def visit(self, node: ConditionalNode, scope: Scope): ''' IF cond GOTO true result = <false.expr> GOTO end LABEL true result = <true.expr> LABEL end ''' cond, _ = self.visit(node.cond, scope) true_label = cil.LabelNode(f"true__{self.idx}") end_label = cil.LabelNode(f"end__{self.idx}") result = self.define_internal_local() self.register_instruction(cil.GotoIfNode(cond, true_label.label)) false_expr, ftypex = self.visit(node.else_stm, scope) self.register_instruction(cil.AssignNode(result, false_expr)) self.register_instruction(cil.GotoNode(end_label.label)) self.register_instruction(true_label) true_expr, ttypex = self.visit(node.stm, scope) self.register_instruction(cil.AssignNode(result, true_expr)) self.register_instruction(end_label) return result, get_common_basetype([ttypex, ftypex])
def visit(self, node: FuncDeclarationNode, scope: Scope): self.current_method = self.current_type.get_method(node.id, node.pos) name = self.to_function_name(node.id, self.current_type.name) self.current_function = self.register_function(name) # Handle PARAMS self.register_param('self', self.current_type.name) for p_name, p_type in node.params: self.register_param(p_name, p_type.value) value, typex = self.visit(node.body, scope) if not isinstance(value, str): result = self.define_internal_local() self.register_instruction(cil.AssignNode(result, value)) else: result = value # Boxing if necessary if (typex.name == 'Int' or typex.name == 'String' or typex.name == 'Bool' ) and self.current_method.return_type.name == 'Object': self.register_instruction(cil.BoxingNode(result, typex.name)) # Handle RETURN self.register_instruction(cil.ReturnNode(result)) self.current_method = None
def visit(self, node: CaseNode, scope: Scope): expr, typex = self.visit(node.expr, scope) result = self.define_internal_local() end_label = cil.LabelNode(f'end__{self.idx}') error_label = cil.LabelNode(f'error__{self.idx}') isvoid = self.check_void(expr) self.register_instruction(cil.GotoIfNode(isvoid, error_label.label)) try: new_scope = scope.expr_dict[node] except: new_scope = scope sorted_case_list = self.sort_option_nodes_by_type(node.case_list) for i, case in enumerate(sorted_case_list): next_label = cil.LabelNode(f'next__{self.idx}_{i}') expr_i = self.visit(case, new_scope.create_child(), expr, next_label, typex) self.register_instruction(cil.AssignNode(result, expr_i)) self.register_instruction(cil.GotoNode(end_label.label)) self.register_instruction(next_label) # Si llegó aquí es porque no matcheó nunca self.register_instruction(cil.ErrorNode('case_error')) self.register_instruction(error_label) self.register_instruction(cil.ErrorNode('case_void_error')) self.register_instruction(end_label) return result, typex
def visit(self, node: BlockNode, scope: Scope): value = None for exp in node.expr_list: value, typex = self.visit(exp, scope) result = self.define_internal_local() self.register_instruction(cil.AssignNode(result, value)) return result, typex
def visit(self, node: AssignNode, scope: Scope): var_info = scope.find_local(node.id) value, typex = self.visit(node.expr, scope) if var_info is None: var_info = scope.find_attribute(node.id) attributes = [ attr.name for attr, a_type in self.current_type.all_attributes() ] if var_info.type.name == 'Object' and typex.name in [ 'String', 'Bool', 'Int' ]: value = self.define_internal_local() self.register_instruction(cil.BoxingNode(value, typex.name)) self.register_instruction( cil.SetAttribNode('self', var_info.name, self.current_type.name, value)) else: local_name = self.to_var_name(var_info.name) if var_info.type.name == 'Object' and typex.name in [ 'String', 'Bool', 'Int' ]: self.register_instruction( cil.BoxingNode(local_name, typex.name)) else: self.register_instruction(cil.AssignNode(local_name, value)) return value, typex
def visit(self, node: VarDeclarationNode, scope: Scope): var_info = scope.find_variable(node.id) vtype = get_type(var_info.type, self.current_type) local_var = self.register_local(var_info.name) value, typex = self.visit(node.expr, scope) if vtype.name == 'Object' and typex.name in ['String', 'Int', 'Bool']: self.register_instruction(cil.BoxingNode(local_var, typex.name)) else: self.register_instruction(cil.AssignNode(local_var, value)) return local_var, vtype
def visit(self, node: OptionNode, scope: Scope, expr, next_label, type_e): aux = self.define_internal_local() self.register_instruction(cil.ConformsNode(aux, expr, node.typex)) self.register_instruction(cil.GotoIfFalseNode(aux, next_label.label)) local_var = self.register_local(node.id) typex = self.context.get_type(node.typex, node.type_pos) scope.define_variable(node.id, typex) if typex.name == 'Object' and type_e.name in ['String', 'Int', 'Bool']: self.register_instruction(cil.BoxingNode(local_var, type_e.name)) else: self.register_instruction(cil.AssignNode(local_var, expr)) expr_i, type_expr = self.visit(node.expr, scope) return expr_i
def visit(self, node: WhileNode, scope: Scope): ''' LABEL start IF NOT <cond> GOTO end res = <expr> GOTO start LABEL end ''' start_label = cil.LabelNode(f'start__{self.idx}') end_label = cil.LabelNode(f'end__{self.idx}') result = self.define_internal_local() self.register_instruction(cil.VoidConstantNode(result)) self.register_instruction(start_label) cond, _ = self.visit(node.cond, scope) self.register_instruction(cil.GotoIfFalseNode(cond, end_label.label)) expr, typex = self.visit(node.expr, scope) self.register_instruction(cil.AssignNode(result, expr)) self.register_instruction(cil.GotoNode(start_label.label)) self.register_instruction(end_label) return result, ObjectType()
def create_built_in(self): # ---------------------------------- Object Functions ---------------------------------- # f1_params = [ParamNode("self", 'Object')] f1_localVars = [LocalNode("local_abort_Object_self_0")] f1_intructions = [ cil.AssignNode(f1_localVars[0].name, f1_params[0].name, self.index), cil.ExitNode(f1_params[0].name, idx=self.index) ] f1 = FunctionNode("function_abort_Object", f1_params, f1_localVars, f1_intructions) f2_params = [ParamNode("self", 'Object')] f2_localVars = [LocalNode("local_type_name_Object_result_0")] f2_intructions = [ cil.TypeOfNode(f2_params[0].name, f2_localVars[0].name, self.index), cil.ReturnNode(f2_localVars[0].name, self.index) ] f2 = FunctionNode("function_type_name_Object", f2_params, f2_localVars, f2_intructions) f3_params = [ParamNode("self", 'Object')] f3_localVars = [LocalNode("local_copy_Object_result_0")] f3_intructions = [ cil.CopyNode(f3_localVars[0].name, f3_params[0].name, self.index), cil.ReturnNode(f3_localVars[0].name, self.index) ] f3 = FunctionNode("function_copy_Object", f3_params, f3_localVars, f3_intructions) # ---------------------------------- IO Functions ---------------------------------- # f4_params = [ParamNode("self", 'IO'), ParamNode("word", 'String')] f4_localVars = [LocalNode("local_out_string_String_self_0")] f4_intructions = [ cil.AssignNode(f4_localVars[0].name, f4_params[0].name, self.index), cil.OutStringNode(f4_params[1].name, self.index), cil.ReturnNode(f4_localVars[0].name, self.index) ] f4 = FunctionNode("function_out_string_IO", f4_params, f4_localVars, f4_intructions) f5_params = [ParamNode("self", 'IO'), ParamNode("number", 'Int')] f5_localVars = [LocalNode("local_out_int_IO_self_0")] f5_intructions = [ cil.AssignNode(f5_localVars[0].name, f5_params[0].name, self.index), cil.OutIntNode(f5_params[1].name, self.index), cil.ReturnNode(f5_localVars[0].name, self.index) ] f5 = FunctionNode("function_out_int_IO", f5_params, f5_localVars, f5_intructions) f6_params = [ParamNode("self", 'IO')] f6_localVars = [LocalNode("local_in_int_IO_result_0")] f6_intructions = [ cil.ReadIntNode(f6_localVars[0].name, self.index), cil.ReturnNode(f6_localVars[0].name, self.index) ] f6 = FunctionNode("function_in_int_IO", f6_params, f6_localVars, f6_intructions) f7_params = [ParamNode("self", 'IO')] f7_localVars = [LocalNode("local_in_string_IO_result_0")] f7_intructions = [ cil.ReadStringNode(f7_localVars[0].name, self.index), cil.ReturnNode(f7_localVars[0].name, self.index) ] f7 = FunctionNode("function_in_string_IO", f7_params, f7_localVars, f7_intructions) # ---------------------------------- String Functions ---------------------------------- # f8_params = [ParamNode("self", 'String')] f8_localVars = [LocalNode("local_length_String_result_0")] f8_intructions = [ cil.LengthNode(f8_localVars[0].name, f8_params[0].name, self.index), cil.ReturnNode(f8_localVars[0].name, self.index) ] f8 = FunctionNode("function_length_String", f8_params, f8_localVars, f8_intructions) f9_params = [ParamNode("self", 'String'), ParamNode("word", 'String')] f9_localVars = [LocalNode("local_concat_String_result_0")] f9_intructions = [ cil.ConcatNode(f9_localVars[0].name, f9_params[0].name, f9_params[1].name, self.index), cil.ReturnNode(f9_localVars[0].name, self.index) ] f9 = FunctionNode("function_concat_String", f9_params, f9_localVars, f9_intructions) f10_params = [ ParamNode("self", 'String'), ParamNode("begin", 'Int'), ParamNode("end", 'Int') ] f10_localVars = [LocalNode("local_substr_String_result_0")] f10_intructions = [ cil.SubstringNode(f10_localVars[0].name, f10_params[0].name, f10_params[1].name, f10_params[2].name, self.index), cil.ReturnNode(f10_localVars[0].name, self.index) ] f10 = FunctionNode("function_substr_String", f10_params, f10_localVars, f10_intructions) f11_params = [ParamNode("self", 'String')] f11_localVars = [LocalNode("local_type_name_String_result_0")] f11_intructions = [ cil.LoadNode(f11_localVars[0].name, 'type_String', self.index), cil.ReturnNode(f11_localVars[0].name, self.index) ] f11 = FunctionNode("function_type_name_String", f11_params, f11_localVars, f11_intructions) f12_params = [ParamNode("self", 'String')] f12_localVars = [LocalNode("local_copy_String_result_0")] f12_intructions = [ cil.ConcatNode(f12_localVars[0].name, f12_params[0].name, None, self.index), cil.ReturnNode(f12_localVars[0].name, self.index) ] f12 = FunctionNode("function_copy_String", f12_params, f12_localVars, f12_intructions) f17_params = [ParamNode("self", 'String')] f17_localVars = [LocalNode('local_abort_String_msg_0')] f17_intructions = [ cil.LoadNode(f17_params[0].name, 'string_abort'), cil.OutStringNode(f17_params[0].name, self.index), cil.ExitNode(f17_params[0].name, idx=self.index) ] f17 = FunctionNode("function_abort_String", f17_params, f17_localVars, f17_intructions) # ---------------------------------- Int Functions ---------------------------------- # f13_params = [ParamNode("self", 'Int')] f13_localVars = [LocalNode("local_type_name_Int_result_0")] f13_intructions = [ cil.LoadNode(f13_localVars[0].name, 'type_Int', self.index), cil.ReturnNode(f13_localVars[0].name, self.index) ] f13 = FunctionNode("function_type_name_Int", f13_params, f13_localVars, f13_intructions) f14_params = [ParamNode("self", 'Int')] f14_localVars = [LocalNode("local_copy_Int_result_0")] f14_intructions = [ cil.AssignNode(f14_localVars[0].name, f14_params[0].name), cil.ReturnNode(f14_localVars[0].name, self.index) ] f14 = FunctionNode("function_copy_Int", f14_params, f14_localVars, f14_intructions) f18_params = [ParamNode("self", 'Int')] f18_localVars = [LocalNode('local_abort_Int_msg_0')] f18_intructions = [ cil.LoadNode(f18_params[0].name, 'int_abort'), cil.OutStringNode(f18_params[0].name, self.index), cil.ExitNode(f18_params[0].name, idx=self.index) ] f18 = FunctionNode("function_abort_Int", f18_params, f18_localVars, f18_intructions) # ---------------------------------- Bool Functions ---------------------------------- # f15_params = [ParamNode("self", 'Bool')] f15_localVars = [LocalNode("local_type_name_Bool_result_0")] f15_intructions = [ cil.LoadNode(f15_localVars[0].name, 'type_Bool', self.index), cil.ReturnNode(f15_localVars[0].name, self.index) ] f15 = FunctionNode("function_type_name_Bool", f15_params, f15_localVars, f15_intructions) f16_params = [ParamNode("self", 'Bool')] f16_localVars = [LocalNode("local_copy_result_Bool_0")] f16_intructions = [ cil.AssignNode(f16_localVars[0].name, f16_params[0].name), cil.ReturnNode(f16_localVars[0].name, self.index) ] f16 = FunctionNode("function_copy_Bool", f16_params, f16_localVars, f16_intructions) f19_params = [ParamNode("self", 'Bool')] f19_localVars = [LocalNode('local_abort_Bool_msg_0')] f19_intructions = [ cil.LoadNode(f19_params[0].name, 'bool_abort'), cil.OutStringNode(f19_params[0].name, self.index), cil.ExitNode(f19_params[0].name, idx=self.index) ] f19 = FunctionNode("function_abort_Bool", f19_params, f19_localVars, f19_intructions) self.dotcode += [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19 ] object_methods = [('abort', f1.name), ('type_name', f2.name), ('copy', f3.name)] string_methods = [('length', f8.name), ('concat', f9.name), ('substr', f10.name), ('abort', f17.name), ('type_name', f11.name), ('copy', f12.name)] io_methods = [('out_string', f4.name), ('out_int', f5.name), ('in_int', f6.name), ('in_string', f7.name)] int_methods = [('abort', f18.name), ('type_name', f13.name), ('copy', f14.name)] bool_methods = [('abort', f19.name), ('type_name', f15.name), ('copy', f16.name)] self.dottypes += [ TypeNode("Object", [], object_methods), TypeNode("IO", [], object_methods + io_methods), TypeNode("String", [], string_methods), TypeNode('Int', [], int_methods), TypeNode('Bool', [], bool_methods) ]