Beispiel #1
0
 def function_statement(self, tree, scope):
     """
     Create a new scope _without_ a parent scope for this function.
     Prepopulate the scope with symbols from the function arguments.
     """
     scope = Scope.root()
     return_type = NoneType.instance()
     args = {}
     for c in tree.children[2:]:
         if isinstance(c, Tree) and c.data == "typed_argument":
             name = c.child(0)
             e_sym = self.resolver.types(c.types)
             c.expect(
                 e_sym.type() != ObjectType.instance(),
                 "arg_type_no_object",
                 arg=name,
                 type=e_sym.type(),
             )
             sym = Symbol.from_path(name, e_sym.type())
             scope.insert(sym)
             args[sym.name()] = sym
     # add function to the function table
     function_name = tree.child(1).value
     tree.expect(
         self.module.function_table.resolve(function_name) is None,
         "function_redeclaration",
         name=function_name,
     )
     output = tree.function_output
     if output is not None:
         return_type = self.resolver.types(output.types).type()
         tree.expect(return_type != ObjectType.instance(),
                     "return_type_no_object")
     self.module.function_table.insert(function_name, args, return_type)
     return scope, return_type
Beispiel #2
0
    def service_block(self, tree, scope):
        service_name = tree.service.path.child(0).value
        name = scope.resolve(service_name)
        if name is not None and name.type() != ObjectType.instance():
            tree.expect(tree.service.service_fragment.output is None,
                        'mutation_nested')
            tree.expect(tree.nested_block is None, 'mutation_nested')
            # resolve to perform checks
            self.resolver.service(tree.service)
            return

        tree.scope = Scope(parent=scope)
        self.update_scope(tree.scope)

        self.implicit_output(tree)

        output = tree.service.service_fragment.output
        if output is not None:
            output.expect(len(output.children) == 1, 'output_type_only_one',
                          target='service')

            name = output.children[0]
            resolved = tree.scope.resolve(name)
            output.expect(resolved is None, 'output_unique',
                          name=resolved.name() if resolved else None)
            sym = Symbol(name, ObjectType.instance())
            tree.scope.insert(sym)

        if tree.nested_block:
            tree.expect(not self.in_service_block, 'nested_service_block')
            self.in_service_block = True
            for c in tree.nested_block.children:
                self.visit_children(c, scope=tree.scope)
            self.in_service_block = False
Beispiel #3
0
    def service(self, tree):
        # unknown for now
        if tree.service_fragment.output is not None:
            tree.service_fragment.output.expect(
                0, 'service_no_inline_output')

        command = tree.service_fragment.command
        tree.expect(command is not None, 'service_without_command')

        self.check_service_fragment_arguments(tree.service_fragment)

        t = None
        try:
            # check whether variable exists
            t = self.path(tree.path)
        except CompilerError:
            # ignore invalid variables (not existent or invalid)
            # -> must be a service
            return base_symbol(self.resolve_service(tree))

        # variable exists -> event-based service
        if t.type() == ObjectType.instance():
            # In case of event-based service resolve using output_sym.
            return base_symbol(self.resolve_service(tree, t))

        var_name = tree.path.child(0).value
        tree.path.expect(0, 'service_name_not_var', var=var_name)
Beispiel #4
0
 def base_type(self, tree):
     """
     Resolves a base type expression to a type
     """
     assert tree.data == 'base_type'
     tok = tree.first_child()
     if tok.type == 'BOOLEAN_TYPE':
         return base_symbol(BooleanType.instance())
     elif tok.type == 'INT_TYPE':
         return base_symbol(IntType.instance())
     elif tok.type == 'FLOAT_TYPE':
         return base_symbol(FloatType.instance())
     elif tok.type == 'STRING_TYPE':
         return base_symbol(StringType.instance())
     elif tok.type == 'ANY_TYPE':
         return base_symbol(AnyType.instance())
     elif tok.type == 'OBJECT_TYPE':
         return base_symbol(ObjectType.instance())
     elif tok.type == 'FUNCTION_TYPE':
         return base_symbol(AnyType.instance())
     elif tok.type == 'TIME_TYPE':
         return base_symbol(TimeType.instance())
     else:
         assert tok.type == 'REGEXP_TYPE'
         return base_symbol(RegExpType.instance())
Beispiel #5
0
    def service_block(self, tree, scope):
        service_name = tree.service.path.child(0).value
        name = scope.resolve(service_name)
        if name is not None and name.type() != ObjectType.instance():
            tree.expect(tree.service.service_fragment.output is None,
                        'mutation_nested')
            tree.expect(tree.nested_block is None, 'mutation_nested')
            # resolve to perform checks
            self.resolver.service(tree.service)
            return

        tree.scope = Scope(parent=scope)
        with self.create_scope(tree.scope):

            self.implicit_output(tree)

            output = tree.service.service_fragment.output
            if output is not None:
                self.check_output(tree, output, target='service')

            if tree.nested_block:
                tree.expect(not self.in_service_block, 'nested_service_block')
                self.in_service_block = True
                for c in tree.nested_block.children:
                    self.visit_children(c, scope=tree.scope)
                self.in_service_block = False
Beispiel #6
0
    def service_block(self, tree, scope):
        service_name = tree.service.path.child(0).value
        name = scope.resolve(service_name)
        if name is not None and name.type() != ObjectType.instance():
            tree.expect(tree.service.service_fragment.output is None,
                        'mutation_nested')
            tree.expect(tree.nested_block is None, 'mutation_nested')
            # resolve to perform checks
            self.resolver.service(tree.service)
            return

        tree.scope = Scope(parent=scope)

        self.implicit_output(tree)
        output = tree.service.service_fragment.output
        if output is not None:
            self.check_output(tree, output, target='service')

        args = tree.service.service_fragment.arguments
        if args is not None:
            # only look at value nodes (argname, (2) expr, argname, (4) expr)
            for arg in args.children[1::2]:
                self.resolver.expression(arg)

        if tree.nested_block:
            with self.create_scope(tree.scope):
                tree.expect(not self.in_service_block, 'nested_service_block')
                self.in_service_block = True
                for c in tree.nested_block.children:
                    self.visit_children(c, scope=tree.scope)
                self.in_service_block = False
        else:
            tree.service.service_fragment.expect(output is None,
                                                 'service_no_inline_output')
    def resolve_mutation(self, t, tree):
        """
        Resolve a mutation on t with the MutationTable, instantiate it and
        check the caller arguments.
        """
        # a mutation on 'object' returns 'any' (for now)
        if t == ObjectType.instance():
            return AnyType.instance()

        name = tree.mutation_fragment.child(0).value
        args = self.build_arguments(tree.mutation_fragment, name,
                                    fn_type='Mutation')

        # a mutation on 'any' returns 'any'
        overloads = self.mutation_table.resolve(t, name)
        tree.expect(overloads is not None, 'mutation_invalid_name', name=name)
        ms = overloads.match(args.keys())
        if ms is None:
            # if there's only one overload, use this for a better error
            # message
            single = overloads.single()
            if single is None:
                self.show_available_mutation_overloads(tree, overloads)
            else:
                ms = [single]

        if len(ms) > 1:
            # a mutation on any might have matched multiple overloads
            return AnyType.instance()
        else:
            assert len(ms) == 1
            m = ms[0]
            m = m.instantiate(t)
            m.check_call(tree.mutation_fragment, args)
            return m.output()
Beispiel #8
0
    def when_block(self, tree, scope):
        tree.scope = Scope(parent=scope)
        with self.create_scope(tree.scope):
            self.implicit_output(tree)

            output = tree.service.service_fragment.output
            output.expect(len(output.children) == 1,
                          'output_type_only_one',
                          target='when')

            name = output.children[0]
            resolved = tree.scope.resolve(name)
            output.expect(resolved is None,
                          'output_unique',
                          name=resolved.name() if resolved else None)
            sym = Symbol.from_path(name,
                                   ObjectType.instance(),
                                   storage_class=StorageClass.read)
            tree.scope.insert(sym)

            tree.expect(not self.in_when_block, 'nested_when_block')
            self.in_when_block = True
            for c in tree.nested_block.children:
                self.visit_children(c, scope=tree.scope)
            self.in_when_block = False
Beispiel #9
0
 def as_expression(self, tree, expr):
     assert tree.child(1).data == 'as_operator'
     # check for compatibility
     t = self.visitor.types(tree.child(1).types)
     tree.expect(t.type() != ObjectType.instance(), 'object_no_as')
     tree.expect(explicit_cast(expr.type(), t.type()),
                 'type_operation_cast_incompatible',
                 left=expr.type(), right=t.type())
     return t
Beispiel #10
0
 def root(cls):
     """
     Creates a root scope.
     """
     scope = cls(parent=None)
     # insert global symbols
     app = Symbol(name='app', type_=ObjectType.instance())
     scope.insert(app)
     return scope
Beispiel #11
0
    def check_output(self, tree, output, target):
        output.expect(len(output.children) == 1, 'output_type_only_one',
                      target=target)

        name = output.children[0]
        resolved = tree.scope.resolve(name)
        output.expect(resolved is None, 'output_unique',
                      name=resolved.name() if resolved else None)
        sym = Symbol.from_path(name, ObjectType.instance(),
                               storage_class=StorageClass.rebindable())
        tree.scope.insert(sym)