Ejemplo n.º 1
0
    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])
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
    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()
Ejemplo n.º 9
0
    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)
        ]