Exemple #1
0
 def test_source(self):
   """
   Make sure that the given source file is parsed and emitted correctly.
   To do this, we parse & emit two times. The first and second emission, should
   be exactly the same.
   """
   input   = open(file).read()
   output1 = api.load(input).accept(Dumper())
   output2 = api.load(output1).accept(Dumper())
   if output1 != output2:
     for line in unified_diff(output1.split("\n"), output2.split("\n")):
       print_stderr(line)
     assert False, "Roundtripping of " + file + "failed."
Exemple #2
0
    def test_property_as_obj_for_method_call(self):
        src = """module test
function t1(node) {
  node.queue.remove()
}"""
        model = api.load(src)
        self.assertEqual(model.accept(Dumper()), src)
Exemple #3
0
    def after_visit_Parameter(self, parameter):
        if not isinstance(parameter.type, UnknownType): return

        parents = list(reversed(self.stack))
        function = parents[1]
        env = parents[2]

        if isinstance(env, Module):
            # case 2: it's a global function declaration, but with a reference
            #         from the first case, so we try to convert the environment
            #         to an ExecutionStrategy
            for execution in env.executions:
                func = execution.executed
                if isinstance(func,
                              FunctionExp) and func.name == function.name:
                    env = execution
                    break
            else:
                # case 3: it's a global function and is referenced from another
                # function. Here we have no reference to use to infer the type. This
                # will be handled by the calling side, who will infer its argument types
                # upon these parameters
                pass

        # we reached this point so we found an env that can tell us the signature
        # of our function
        if isinstance(env, ExecutionStrategy):
            # case 1: function declaration for exection in an ExecutionStrategy =>
            #         it's a handler and we should be able to match the function's
            #         signature to that of the scope of the strategy
            # An ExecutionStrategy can have an event (When) or not (Every)
            # An event is a FunctionExp executed within the Scope.
            if isinstance(env, When):
                func = env.scope.get_function(env.event.name)
            else:
                func = env.scope.get_function()
            type = None
            try:
                # try to extract the param information for the same indexed parameter
                index = function.parameters.index(parameter)
                type = func.parameters[index].type
            except:
                pass
            if not type is None:
                self.success(
                    "Found ExecutionStrategy with Scope providing info. " +
                    "Inferring parameter", parameter.name, "to",
                    type.accept(Dumper()))
                parameter.type = type
            else:
                self.fail("Couldn't extract parameter typing info from " + \
                          "ExecutionStrategy environment for parameter",
                          parameter.name)
Exemple #4
0
    def after_visit_ListLiteralExp(self, lst):
        if not isinstance(lst.type, ManyType): return
        if not isinstance(lst.type.subtype, UnknownType): return

        # determine the best matching type of the expressions in the list
        type = UnknownType()
        has_atoms = False
        for exp in lst.expressions:
            # no AtomType, it is converted to different other types on need-to basis
            if isinstance(exp.type, AtomType):
                has_atoms = True
                continue
            # init on first non-UnknownType
            if isinstance(type, UnknownType):
                type = exp.type
                next
            # make sure that all types are compatible with detected type
            # when we're dealing with ManyType, look into subtype
            if isinstance(type, ManyType):
                type_class = type.subtype.__class__.__name__
                next_class = type.subtype.__class__.__name__
            else:
                type_class = type.__class__.__name__
                next_class = exp.type.__class__.__name__
            # if we're already dealing with bytes, we can always convert to byte
            if type_class == "ByteType": continue
            # otherwise: lower the type restrictions
            if next_class == "ByteType":
                type = exp.type
                continue
            # if there the same, obviously
            if type_class == next_class: continue
            # self.fail("Couldn't determine best matching type for ListLiteral.",
            #           "Ended up with", type_class, "and", next_class)
            # TODO: undo this short-cut someday ;-)
            # we can't easily come to a single type to deal with this, and further on
            # during code generation we will handle these situations differently
            # anyway, so let's mark it as MixedType for now
            type = MixedType()
            break

        if has_atoms and isinstance(type, UnknownType):
            type = AtomType()

        # type is best matching type for all expressions in ListLiteral
        # apply it to the subtype of the ListLiteral's ManyType
        lst.type.subtype = type
        self.success(
            "Inferred type of ListLiteral from list's expressions' types.",
            "Inferred type to", lst.type.accept(Dumper()))
Exemple #5
0
 def after_visit_Constant(self, constant):
     """
 Infers the type of the constant if it is unknown. 
 """
     if isinstance(constant.type, UnknownType):
         try:
             new_type = {
                 'IntegerLiteralExp': IntegerType,
                 'FloatLiteralExp': FloatType,
                 'BooleanLiteralExp': BooleanType
             }[constant.value.__class__.__name__]
             self.success("unknown constant type for", constant.name, \
                          "inferred to", new_type().accept(Dumper()))
             constant.type = new_type()
         except KeyError:
             self.fail("Failed to infer constant type based on value of " + \
                       constant.name)
Exemple #6
0
    def after_visit_VariableExp(self, variable):
        # original : self._type = UnknownType()
        # we need to move up the stack to find the declaration and reuse that;
        # variables can be declared in FunctionDecl, might be a Constant, or as
        # part of an assignment, then we can also reuse the type of the value part
        # of the assignment

        # simplest case, it's in the environment
        if variable.name in self.env:
            variable.type = self.env[variable.name].type
            self.success("VariableExp referenced the environment.",
                         variable.name, "Inferred type to", variable.type)
            # the type might be Unknown, but inference below should fix this
            if not isinstance(variable.type, UnknownType):
                # we might have got type information, but maybe it's incomplete
                if isinstance(variable.type, ObjectType):
                    if variable.type.provides.values() == []:
                        # we don't do typedefs (yet), be we have domains that export custom
                        # object-types, let's see if OUR module's domain exports it
                        # TODO: add utility functions/properties for this to SemanticChecker
                        #       e.g: self.my_module().domains
                        for domain in self.stack[1].domains:
                            try:
                                variable.type = domain.get_type(
                                    variable.type.name)
                                self.success(
                                    "Retrieved missing type information from domain",
                                    domain.name, variable.type.name)
                                return
                            except:
                                pass
                            self.fail(
                                "Couldn't retrieve custom object-type info from domain",
                                variable.type.name)
                return

        parents = list(reversed(self.stack))

        # TODO: too specific (for contains) AND wrong !! :-(
        # special case: if the VarExp is part of a ListLiteral as argument to
        # FuncCallExp that is part of a CaseStmt, it takes the subtype of the
        # Manytype that the Provided method carries.
        if isinstance(parents[1], ListLiteralExp) and \
           isinstance(parents[2], FunctionCallExp) and \
           isinstance(parents[3], CaseStmt):
            variable.type = parents[3].expression.type.provides[
                parents[2].name].parameters[0].type.subtype
            self.success("VariableExp ", variable.name,
                         "is a VariableDecl for data of type",
                         variable.type.accept(Dumper()))
            return

        # a VarExp in a consequences Stmt of a CaseStmt can look for a same-name
        # VarExp in the corresponding cases FunctionCallExp of the CaseStmt
        for index in range(0, len(parents)):
            if isinstance(parents[index], CaseStmt):
                case = parents[index]
                consequence = parents[index - 1]
                consequence_index = case.consequences.index(consequence)
                functioncall = case.cases[consequence_index]
                for argument in functioncall.arguments:
                    if isinstance(
                            argument,
                            VariableExp) and argument.name == variable.name:
                        self.success("Found CaseFuncCall with decl for",
                                     variable.name, "Inferring to",
                                     str(parameter.type))
                        variable.type = parameter.type
                        return
                    if isinstance(argument, ListLiteralExp):
                        for item in argument.expressions:
                            if isinstance(item, VariableExp
                                          ) and item.name == variable.name:
                                self.success(
                                    "Found CaseFuncCall in list with decl for",
                                    variable.name, "Inferring to",
                                    str(item.type))
                                variable.type = item.type
                                return
Exemple #7
0
def dump_foo(args, model=None):
    if model is None: model = load(args)
    if args.verbose: print "foo: generating FOO"
    print model.accept(Dumper())
Exemple #8
0
# expressions.py
# author: Christophe VG

# unit tests for foo-lang expressions

import unittest

from foo_lang.semantic.model import *

from foo_lang.semantic.dumper import Dumper
dumper = Dumper()


def dump(model):
    return model.accept(dumper)


class TestExpressions(unittest.TestCase):
    def test_and_exp(self):
        exp = AndExp(BooleanLiteralExp("true"), BooleanLiteralExp("false"))
        self.assertEqual(dump(exp), "( true and false )")

    def test_or_exp(self):
        exp = OrExp(BooleanLiteralExp("true"), BooleanLiteralExp("false"))
        self.assertEqual(dump(exp), "( true or false )")

    def test_eq_exp(self):
        exp = EqualsExp(BooleanLiteralExp("true"), BooleanLiteralExp("false"))
        self.assertEqual(dump(exp), "( true == false )")

    def test_ne_exp(self):