def visit(self, node, scope): if node.obj == None: obj_type = self.current_type elif isinstance(node.obj, tuple): self.visit(node.obj[0], scope) child_type = self.update_type(node.obj[0].inferenced_type) try: obj_type = self.context.get_type(node.obj[1], selftype=False, autotype=False) if isinstance(child_type, AutoType): child_type.set_upper_limmit([obj_type]) except SemanticError: obj_type = ErrorType() else: self.visit(node.obj, scope) obj_type = self.update_type(node.obj.inferenced_type) methods = None try: methods = [(obj_type, obj_type.get_method(node.id))] except SemanticError as err: if isinstance(obj_type, AutoType): result = self.context.get_method_by_name( node.id, len(node.args)) types = [typex for _, typex in result] obj_type.set_upper_limmit(types) if len(obj_type.upper_limmit): methods = [(t, t.get_method(node.id)) for t in obj_type.upper_limmit] else: self.AddError(err) node.inferenced_obj_type = obj_type if methods: type_set = set() heads = [] for typex, method in methods: ret_type = method.return_type ret_type = typex if isinstance(ret_type, SelfType) else ret_type heads, type_set = smart_add(type_set, heads, ret_type) if len(node.args) == len(method.param_types): for i in range(len(node.args)): arg, param_type = node.args[i], method.param_types[i] self.visit(arg, scope) arg_type = self.update_type(arg.inferenced_type) arg_type = conforms(arg_type, param_type) if isinstance(param_type, AutoType): param_type = conforms(param_type, arg_type) method.param_types[i] = param_type self.update_graph(arg_type, param_type) arg.inferenced_type = arg_type node.inferenced_type = AutoType(node.id, heads, type_set) else: node.inferenced_type = ErrorType()
def visit(self, node, scope): if isinstance(node.inferenced_type, ErrorType): return if node.obj == None: obj_type = self.current_type elif isinstance(node.obj, tuple): self.visit(node.obj[0], scope) child_type = self.update_type(node.obj[0].inferenced_type) try: obj_type = self.context.get_type(node.obj[1], selftype=False, autotype=False) if isinstance(child_type, AutoType): child_type.set_upper_limmit([obj_type]) except SemanticError: obj_type = ErrorType() else: self.visit(node.obj, scope) obj_type = self.update_type(node.obj.inferenced_type) method = None try: method = obj_type.get_method(node.id) except SemanticError: if isinstance(obj_type, AutoType): result = self.context.get_method_by_name( node.id, len(node.args)) valid = [] for meth, typex in result: if typex in obj_type.type_set: valid.append((meth, typex)) if len(valid) > 1: error = f"Method \"{node.id}\" found in {len(valid)} unrelated types:\n" error += " -Found in: " error += ", ".join(typex.name for _, typex in valid) self.AddError(error) obj_type = ErrorType() elif len(valid) == 0: self.AddError( f"There is no method called {node.id} which takes {len(node.args)} paramters." ) obj_type == ErrorType() else: method, types = valid[0] obj_type.set_upper_limmit([types]) node.inferenced_obj_type = self.compare_types(node.inferenced_obj_type, obj_type) if method: type_set = set() heads = [] ret_type = self.update_type(method.return_type) heads, type_set = smart_add(type_set, heads, ret_type) if len(node.args) == len(method.param_types): for i in range(len(node.args)): arg, param_type = node.args[i], method.param_types[i] arg_infer = arg.inferenced_type self.visit(arg, scope) arg_type = self.update_type(arg.inferenced_type) arg_type = conforms(arg_type, param_type) if isinstance(param_type, AutoType): param_type = conforms(param_type, arg_type) method.param_types[i] = self.compare_types( method.param_types[i], param_type) arg.inferenced_type = self.compare_types( arg_infer, arg_type) inferred = node.inferenced_type if isinstance(ret_type, AutoType) and is_subset( inferred, ret_type): method.return_type.set_upper_limmit(heads) node.inferenced_type = self.compare_types( inferred, method.return_type) elif is_subset(ret_type, inferred): node.inferenced_type = self.compare_types(inferred, ret_type) else: node.inferenced_type = ErrorType()