Esempio n. 1
0
    def compile_target(
            self,
            context: CompilationBuffer) -> Tuple[Reference, CompilationBuffer]:
        assert isinstance(self.target, NamedAccess)

        target_buffer = context.optional(
        )  # This buffer holds a push down operation for the target instance

        if isinstance(self.target[0], CallSite):
            assert not self.stack_target
            inner_target = self.target[0].compile(target_buffer)
            target = context.resolve(
                NamedAccess([inner_target.type, self.target[1]],
                            tokens=self.target))
        else:
            target = context.resolve(self.target.root)

            for ext, _ in self.target.extensions:
                target = context.resolve(
                    NamedAccess([target.type, ext], tokens=self.target))

            if target.kind != Symbol.METHOD:
                raise TargetNotCallable()

            if not target.static and not self.constructing_call and not self.stack_target:
                self.target.compile(target_buffer, without_last=True)

        return target, target_buffer
def test_chained_call():
    call = parse_local('counter.increment().add(10)')
    validate_types(call.arguments, [NumericValue])
    assert call.target == NamedAccess([
        MethodCall(NamedAccess([
            Identifier('counter'), Identifier('increment')
        ])),
        Identifier('add')
    ])
Esempio n. 3
0
    def compile(self, context: CompilationBuffer):
        if not self.values:
            return

        buffer = context.optional()
        ref = self[0].compile(buffer)  # TODO: remove unnecessary recompilation of first element (used to infer type)

        list_type = GenericIdentifier(Identifier('list'), (ref.type,))
        last_call = MethodCall(NamedAccess([list_type, Identifier.constructor()])).deriving_from(self)

        for value in self:  # TODO: validate list is homogeneous, and descend to lowest common type
            last_call = MethodCall(NamedAccess([last_call, Identifier("append")]), ArgumentList([value])).deriving_from(self)

        return last_call.compile(context)
Esempio n. 4
0
    def compile_arguments(self, context: CompilationBuffer,
                          ref: ElementReference):
        argument_selector = ref.element.selector(context)
        compiled_arguments = []

        for idx, arg in enumerate(self.arguments):
            buffer = context.optional()
            compiled_target = arg if self.stack_args and isinstance(
                arg, Reference) else arg.compile(
                    buffer)  # Deals with implicit casts
            argument_selector.constraint(compiled_target)
            compiled_arguments.append(CompiledArgument(compiled_target,
                                                       buffer))

        selected = argument_selector.disambiguate(self.source_ref)
        ref.element = selected.symbol

        for (compiled_target,
             buffer), expected_type in zip(compiled_arguments,
                                           selected.symbol.arguments or []):
            if not argument_selector.inheritance_match(expected_type,
                                                       compiled_target):
                MethodCall(NamedAccess([compiled_target.type, CastTag(expected_type)]), stack_target=True, is_captured=True)\
                    .deriving_from(self)\
                    .compile(buffer)

        return ref, compiled_arguments
Esempio n. 5
0
 def entry(self) -> Reference:
     """
     Get the index of the program's entry point
     """
     return self.resolve(
         NamedAccess([Identifier('Program'),
                      Identifier.constructor()]), {})
Esempio n. 6
0
    def compile(self, context):
        if self.redundant(context):
            return self.value.compile(context)

        return MethodCall(NamedAccess.extend(self.value,
                                             CastTag(self.target_type)),
                          stack_args=self.stack_args,
                          stack_target=self.stack_target).compile(context)
Esempio n. 7
0
 def compile(
     self, context: CompilationBuffer
 ):  # TODO: we should probably reparse the maps into identifiers
     method_call = MethodCall(
         NamedAccess.extend(self.lhs,
                            Identifier(self.operator.serialize())),
         [self.rhs])
     return method_call.compile(context)
Esempio n. 8
0
    def __init__(self, target: Identifier, target_type: Identifier,
                 collection: ValueType):
        super().__init__(None, (target, target_type, collection))

        self.target, self.target_type, self.collection = target, target_type, collection
        self.iterator_id = next(IterationLoop.TRANSIENT_COUNTER)

        self.iterator = self.iterator_container_name[0]
        self.continuation_check = MethodCall(
            NamedAccess.extend(self.iterator,
                               Identifier('has_next'))).deriving_from(self)
        self.continuation_next = MethodCall(
            NamedAccess.extend(self.iterator,
                               Identifier('next'))).deriving_from(self)

        self.value = self.continuation_check

        if isinstance(self.collection, MethodCall):
            self.collection.is_captured = True
Esempio n. 9
0
    def compile(self, context: CompilationBuffer):
        iterator_name, iterator_type = self.iterator_container_name
        AssignmentOperation(
            AssignmentOperation.REASSIGNMENT,
            iterator_name,
            MethodCall(NamedAccess.extend(self.collection,
                                          Identifier('iterator')),
                       is_captured=True).deriving_from(self),
            iterator_type,
        ).deriving_from(self).compile(context)

        super().compile(context)
Esempio n. 10
0
    def finalize(self):
        if not self.is_constructor():
            return super().finalize()

        for descendant in self.descendants:
            if isinstance(
                    descendant,
                    MethodCall) and descendant.target[0] == Identifier.super():
                descendant.replace(
                    AssignmentOperation(
                        AssignmentOperation.REASSIGNMENT,
                        NamedAccess([Identifier.self(),
                                     Identifier.super()]),
                        MethodCall(NamedAccess(
                            [self.parent.extends,
                             Identifier.constructor()]),
                                   descendant.arguments,
                                   is_captured=True).deriving_from(
                                       self)).deriving_from(descendant))

        super().finalize()
Esempio n. 11
0
def validate_method_call(node, target, argument_types):
    assert isinstance(node, MethodCall)
    assert node.target == NamedAccess([Identifier(t) for t in target])
    validate_types(node.arguments, argument_types, MethodCall, lambda x: x.arguments)
Esempio n. 12
0
 def assignment(self, value):
     return MethodCall(NamedAccess.extend(self.target, Identifier('set')), ArgumentList([self.index, value]),
                       is_captured=False) \
         .deriving_from(self)
Esempio n. 13
0
 def compile(self, context: CompilationBuffer):
     return MethodCall(NamedAccess.extend(self.target, Identifier('get')), ArgumentList([self.index])) \
         .deriving_from(self) \
         .compile(context)
Esempio n. 14
0
 def parse_instantiating_call(target: Identifier,
                              arguments: 'ParenthesesVector'):
     return MethodCall(NamedAccess.extend(target, Identifier.constructor()),
                       ArgumentList(arguments))
Esempio n. 15
0
def test_constructing_call():
    method = parse_local('Empty(1)')
    assert method.target == NamedAccess([Identifier('Empty'), Identifier.constructor()])
    validate_types(method.arguments, [NumericValue], MethodCall, lambda x: x.arguments)
    assert method.constructing_call
Esempio n. 16
0
thing A
    does overloaded with Container1 container
    does overloaded with Container2 container
    does overloaded with Container2Child container
    does overloaded with Container1 c1, Container2 c2
    does overloaded with Container1 c1, Container2Child c2

'''

# TODO: verify no cast to base type!
# TODO: we probably don't want implicit casts to text

SYMBOLS = get_symbols(SOURCE_OVERLOADING)
CONTEXT = CompilationContext(SYMBOLS)
BASE = SYMBOLS.resolve(NamedAccess.auto('A.overloaded'))


def get_selection(*target_types):
    selector = BASE.element.selector(CONTEXT)

    for target_type in target_types:
        selector.constraint(Reference(Identifier(target_type)))

    return selector.disambiguate(None)


def verify_selection(target_type, expected_index, expected_match):
    target = get_selection(*target_type)

    assert target.symbol.index == expected_index
Esempio n. 17
0
def test_call_via_indexed_access():
    call = parse_local('a_inst[1].me()')
    assert call.target == NamedAccess([
        IndexedAccess(Identifier('a_inst'), NumericValue(1)),
        Identifier('me')
    ])