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))
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)