def visit(self, node, scope): # type: ignore if node.method_info is not None: self.current_method = self.current_type.get_method( node.method_info.name) method_scope = scope.create_child() for pname, ptype in zip(self.current_method.param_names, self.current_method.param_types): try: method_scope.define_variable(pname, ptype) except semantic.BaseSemanticError as e: self.errors.append(e.with_pos(node.lineno, node.columnno)) body = self.visit(node.body, method_scope) if (self.current_method.return_type.name == "SELF_TYPE" and not body.type.conforms_to(self.current_type)): self.errors.append( errors.IncompatibleTypesError( node.lineno, node.columnno, body.type.name, self.current_type.name, )) elif (self.current_method.return_type.name != "SELF_TYPE" and not body.type.conforms_to(self.current_method.return_type)): self.errors.append( errors.IncompatibleTypesError( node.lineno, node.columnno, body.type.name, self.current_method.return_type.name, )) if self.current_type.parent is not None: try: parent_method = self.current_type.parent.get_method( self.current_method.name) except semantic.BaseSemanticError as e: parent_method = None if parent_method is not None and parent_method != self.current_method: self.errors.append( errors.WrongSignatureError(node.lineno, node.columnno, self.current_method.name)) self.current_method = None return type_checked.CoolMethodDeclNode(node.lineno, node.columnno, node.method_info, body)
def visit(self, node, scope): # type: ignore exp = self.visit(node.expr, scope) args = [self.visit(arg, scope) for arg in node.args] try: static_type = self.get_type(node.static_type) method = static_type.get_method(node.id) if not exp.type.conforms_to(static_type): raise semantic.TypeError( f"Expression type {exp.type.name} does not conform to declared static dispatch type {static_type.name}." ) except semantic.BaseSemanticError as e: self.errors.append(e.with_pos(node.lineno, node.columnno)) return type_checked.CoolStaticDispatchNode( node.lineno, node.columnno, exp, ErrorType(), node.id, args, ErrorType(), ) if len(args) != len(method.param_names): self.errors.append( errors.WrongArgsCountError( node.lineno, node.columnno, method.name, len(method.param_names), len(args), )) for arg, ptype in zip(args, method.param_types): if not arg.type.conforms_to(ptype): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, arg.type.name, ptype.name)) # try: # static_type = self.get_type(node.static_type) # if not exp.type.conforms_to(static_type): # self.errors.append( # errors.NotConformsError( # node.lineno, node.columnno, exp.type, static_type # ) # ) # except semantic.BaseSemanticError as e: # self.errors.append(e.with_pos(node.lineno, node.columnno)) return type_checked.CoolStaticDispatchNode( node.lineno, node.columnno, exp, static_type, node.id, args, method.return_type, )
def visit(self, node, scope): # type: ignore exp = self.visit(node.expr, scope) int_type = self.get_type("Int") if not exp.type.conforms_to(int_type): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, exp.type.name, int_type.name)) return type_checked.CoolTildeNode(node.lineno, node.columnno, exp, int_type)
def visit(self, node, scope): # type: ignore exp = self.visit(node.expr, scope) bool_type = self.get_type("Bool") if exp.type != bool_type: self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, exp.type.name, bool_type.name)) return type_checked.CoolNotNode(node.lineno, node.columnno, exp, bool_type)
def visit(self, node, scope): # type: ignore if node.body != [] and node.attr_info is not None: exp = self.visit(node.body, scope) node_type = node.attr_info.type if exp.type.name == "SELF_TYPE" and not self.exp_type.conforms_to( node_type): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, node_type.name, self.exp_type.name)) elif exp.type.name != "SELF_TYPE" and not exp.type.conforms_to( node_type): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, node_type.name, exp.type.name)) return type_built.CoolAttrDeclNode(node.lineno, node.columnno, node.attr_info, exp)
def visit(self, node, scope): # type: ignore conditional = self.visit(node.cond, scope) body = self.visit(node.body, scope) if conditional.type != self.get_type("Bool"): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, conditional.type.name, "Bool")) return type_checked.CoolWhileNode(node.lineno, node.columnno, conditional, body, self.get_type("Object"))
def visit(self, node, scope): # type: ignore try: typex = self.get_type(node.type) except semantic.BaseSemanticError as e: typex = ErrorType() self.errors.append(e.with_pos(node.lineno, node.columnno)) if node.expr == []: right_type = typex right_exp = None # decl_list.append(idx, _type, None) else: right_exp = self.visit(node.expr, scope) right_type = right_exp.type # decl_list.append(idx, _type, right_exp) if typex.name == "SELF_TYPE" and not right_type.conforms_to( self.current_type): self.errors.append( errors.IncompatibleTypesError( node.lineno, node.columnno, right_type.name, self.current_type.name, )) elif typex.name != "SELF_TYPE" and not right_type.conforms_to(typex): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, right_type.name, typex.name)) try: scope.define_variable(node.id, typex, force=True) except semantic.BaseSemanticError as e: self.errors.append(e.with_pos(node.lineno, node.columnno)) return type_checked.CoolLetDeclNode(node.lineno, node.columnno, node.id, right_type, right_exp)
def visit(self, node, scope): # type: ignore conditional = self.visit(node.cond, scope) then_expr = self.visit(node.then_expr, scope) else_expr = self.visit(node.else_expr, scope) bool_type = self.get_type("Bool") if not conditional.type.conforms_to(bool_type): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, conditional.type.name, "Bool")) lca = self.lowest_common_ancestor(then_expr.type, else_expr.type) return type_checked.CoolIfThenElseNode(node.lineno, node.columnno, conditional, then_expr, else_expr, lca)
def visit(self, node, scope): # type: ignore if node.id == "self": self.errors.append( errors.IsReadOnlyError(node.lineno, node.columnno, "self")) try: var = scope.find_variable(node.id) var_type = var.type except semantic.BaseSemanticError as e: self.errors.append(e.with_pos(node.lineno, node.columnno)) var_type = ErrorType() exp = self.visit(node.expr, scope) if not exp.type.conforms_to(var_type): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, exp.type.name, var_type.name)) return type_checked.CoolAssignNode(node.lineno, node.columnno, node.id, exp, exp.type)
def visit(self, node, scope): # type: ignore exp = self.visit(node.expr, scope) args = [self.visit(arg, scope) for arg in node.args] if exp.type.name == "AUTO_TYPE": return type_checked.CoolDispatchNode(node.lineno, node.columnno, exp, node.id, args, exp.type) try: method = exp.type.get_method(node.id) except semantic.BaseSemanticError as e: self.errors.append(e.with_pos(node.lineno, node.columnno)) return type_checked.CoolDispatchNode(node.lineno, node.columnno, exp, node.id, args, ErrorType()) if len(args) != len(method.param_names): self.errors.append( errors.WrongArgsCountError( node.lineno, node.columnno, method.name, len(method.param_names), len(args), )) for arg, ptype in zip(args, method.param_types): args.append(arg) if not arg.type.conforms_to(ptype): self.errors.append( errors.IncompatibleTypesError(node.lineno, node.columnno, arg.type.name, ptype.name)) if method.return_type.name == "SELF_TYPE": return type_checked.CoolDispatchNode(node.lineno, node.columnno, exp, node.id, args, exp.type) return type_checked.CoolDispatchNode(node.lineno, node.columnno, exp, node.id, args, method.return_type)