def visit(self, node: VariableNode, scope: Scope): try: typex = scope.find_local(node.lex).type name = self.toVarName(node.lex) return name, Utils.GetType(typex, self.current[TYPE]) except: var_info = scope.find_attribute(node.lex) local_var = self.generateLocalNode(var_info.name) self.saveCilInstruction(CILGetAttribNode( SELF_LOWERCASE, var_info.name, self.current[TYPE].name, local_var, var_info.type.name)) return local_var, Utils.GetType(var_info.type, self.current[TYPE])
def visit(self, node:FuncDeclarationNode, scope:Scope): parent = self.current_type.parent method = self.current_type.get_method(node.id, node.pos) self.current_method = self.current_type.get_method(node.id, node.pos) if parent is not None: try: old_method = parent.get_method(node.id, node.pos) if old_method.return_type.name != method.return_type.name: error_text = SemanticError.WRONG_SIGNATURE_RETURN % (node.id, method.return_type.name, old_method.return_type.name) self.errors.append(SemanticError(*node.type_pos, error_text)) if len(method.param_names) != len(old_method.param_names): error_text = SemanticError.WRONG_NUMBER_PARAM % node.id self.errors.append(SemanticError(*node.pos, error_text)) for (name,param),type1,type2 in zip(node.params, method.param_types, old_method.param_types): if type1.name != type2.name: error_text = SemanticError.WRONG_SIGNATURE_PARAMETER % (name, type1.name, type2.name) self.errors.append(SemanticError(*param.pos, error_text)) except SemanticError: pass result = self.visit(node.body, scope) return_type = Utils.GetType(method.return_type, self.current_type) if not result.conforms_to(return_type): error_text = TypesError.RETURN_TYPE_ERROR % (result.name, return_type.name) self.errors.append(TypesError(*node.type_pos, error_text))
def visit(self, node:InstantiateNode, scope:Scope): try: typex = self.context.get_type(node.lex, node.pos) except SemanticError: typex = ErrorType() error_text = TypesError.NEW_UNDEFINED_CLASS % node.lex self.errors.append(TypesError(*node.pos, error_text)) return Utils.GetType(typex, self.current_type)
def visit(self, node:AssignNode, scope:Scope): var_info = self.find_variable(scope, node.id) var_type = Utils.GetType(var_info.type, self.current_type) typex = self.visit(node.expr, scope) if not typex.conforms_to(var_type): error_text = TypesError.UNCONFORMS_TYPE % (typex.name, node.id, var_type.name) self.errors.append(TypesError(*node.pos, error_text)) return typex
def visit(self, node:VarDeclarationNode, scope:Scope): var_type = self._get_type(node.type, node.type_pos) var_type = Utils.GetType(var_type, self.current_type) if node.expr != None: typex = self.visit(node.expr, scope) if not typex.conforms_to(var_type): error_text = TypesError.UNCONFORMS_TYPE % (typex.name, node.id, var_type.name) self.errors.append(TypesError(*node.type_pos, error_text)) return typex return var_type
def visit(self, node:AttrDeclarationNode, scope:Scope): attr = self.current_type.get_attribute(node.id, node.pos) var_type = Utils.GetType(attr.type, self.current_type) typex = self.visit(node.expr, scope) if not typex.conforms_to(var_type): error_text = TypesError.ATTR_TYPE_ERROR % (typex.name, attr.name, var_type.name) self.errors.append(TypesError(*node.pos, error_text)) return ErrorType() return typex
def visit(self, node: InstantiateNode, scope: Scope): instance = self.generateLocalNode(LOCAL) typex = self.context.get_type(node.lex, node.pos) typex = Utils.GetType(typex, self.current[TYPE]) self.saveCilInstruction(CILAllocateNode(typex.name, instance)) if typex.all_attributes(): self.saveCilInstruction(CILStaticCallNode( typex.name, typex.name, instance, [CILArgNode(instance)], typex.name)) return instance, typex
def visit(self, node: VarDeclarationNode, scope: Scope): var_info = scope.find_variable(node.id) vtype = Utils.GetType(var_info.type, self.current[TYPE]) local_var = self.generateLocalNode(var_info.name) value, typex = self.visit(node.expr, scope) if vtype.name == OBJECT and typex.name in [STRING, INT, BOOL]: self.saveCilInstruction(CILBoxingNode(local_var, typex.name)) else: self.saveCilInstruction(CILAssignNode(local_var, value)) return local_var, vtype
def visit(self, node:BaseCallNode, scope:Scope): obj = self.visit(node.obj, scope) typex = self._get_type(node.type, node.type_pos) if not obj.conforms_to(typex): error_text = TypesError.INCOMPATIBLE_TYPES_DISPATCH % (typex.name, obj.name) self.errors.append(TypesError(*node.type_pos, error_text)) return ErrorType() method = self._get_method(typex, node.id, node.pos) if not isinstance(method, MethodError): self.check_args(method, scope, node.args, node.pos) return Utils.GetType(method.return_type, typex)
def rt_type(self, typex: Type, node): meth = typex.get_method(node.id, node.pos) return Utils.GetType(meth.return_type, self.current[TYPE])
def visit(self, node:VariableNode, scope:Scope): typex = self.find_variable(scope, node.lex).type return Utils.GetType(typex, self.current_type)
def visit(self, node:StaticCallNode, scope:Scope): typex = self.current_type method = self._get_method(typex, node.id, node.pos) if not isinstance(method, MethodError): self.check_args(method, scope, node.args, node.pos) return Utils.GetType(method.return_type, typex)
def visit(self, node:CallNode, scope:Scope): stype = self.visit(node.obj, scope) method = self._get_method(stype, node.id, node.pos) if not isinstance(method, MethodError): self.check_args(method, scope, node.args, node.pos) return Utils.GetType(method.return_type, stype)