Esempio n. 1
0
    def resolve(
        self,
        target: Union[Identifier, NamedAccess],
        method_locals: dict = (),
        current_generics: list = ()
    ) -> Reference:
        """
        Resolve a reference into a Reference object
        :param target: the reference being resolved (can be either an identifier or access object)
        :param method_locals: the locals of the method being compiled
        :return: new Reference
        """
        assert not target.STATIC

        if isinstance(target, Identifier):
            if target in current_generics:
                return Reference(Identifier.object())
            elif target.untyped in self:  # TODO: verify name collisions
                return Reference(target)
            else:
                local = method_locals[target]
                if not local.allowed:
                    raise SelfInStaticMethod(target)
                if local.type not in current_generics and self[
                        local.
                        type].generics and local.source != 'self':  # Check if any generic type parameters have been left unfilled
                    raise UnfilledGenericParameters(target, self[local.type],
                                                    None)
                return LocalReference(method_locals[target], target)
        elif isinstance(target, NamedAccess):
            return self.resolve_named(target, method_locals, current_generics)

        raise Exception("Unknown reference type {}".format(target))
Esempio n. 2
0
    def resolve_named(self,
                      target: Sequence,
                      method_locals=(),
                      current_generics=(),
                      generic_validation=True) -> ElementReference:
        """
        Resolves an identifier pair (a.b) into an element reference
        :param target: the Access object to resolve
        :param method_locals: the current method's locals
        :return: new ElementReference
        """
        assert len(target) == 2

        first, second, local = target[0], target[1], None

        if first.STATIC:
            container = self[first.type]
        elif isinstance(first, IndexedAccess):
            container = self.resolve_indexed(first, method_locals)
        elif first.untyped in current_generics:  # TODO: what about name collisions?
            container = self[Identifier.object(
            )]  # TODO: implement `with type T implement Interface`
        elif first.untyped in self.maps:
            container = self[first]
        elif first in method_locals:
            local = method_locals[first]
            if not local.allowed:
                raise SelfInStaticMethod(target)
            container = self[local.type]
        else:
            raise Exception(
                'Cannot resolve first level access {} (on {}) from {}'.format(
                    first, first.source_ref, method_locals))

        container, element = self.pull(container, second, target)

        remaining_generics = set(container.generics) - set(
            current_generics
        )  # TODO: are we sure generic name conflicts don't prevent this validation?
        if generic_validation and not element.is_complete({
                x: Identifier.invalid()
                for x in remaining_generics
        }):  # Check if any generic type parameters have been left unfilled
            raise UnfilledGenericParameters(target, container, element)

        return ElementReference(container, self.index(container), element,
                                local)