def object_copy(self):
        self.params.append(ParamNode("self"))
        copy_local = self.define_internal_local()
        self.register_instruction(
            AllocateNode(self.current_type.name, copy_local))

        for attr in self.attrs[self.current_type.name].keys():
            attr_copy_local = self.define_internal_local()
            attr_name = (self.to_attr_name(self.current_type.name, attr)
                         if self.current_type.name
                         not in ["Int", "String", "Bool"] else attr)
            self.register_instruction(
                GetAttribNode(
                    attr_copy_local,
                    "self",
                    attr_name,
                    self.current_type.name,
                ))
            self.register_instruction(
                SetAttribNode(
                    copy_local,
                    attr_name,
                    attr_copy_local,
                    self.current_type.name,
                ))

        self.register_instruction(ReturnNode(copy_local))
    def string_length(self):
        self.params.append(ParamNode("self"))

        result = self.define_internal_local()

        self.register_instruction(LengthNode(result, "self"))
        self.register_instruction(ReturnNode(result))
    def visit(self, node, return_var=None):
        self.current_function = self.register_function(
            self.to_function_name(f"{node.id}_constructor",
                                  self.current_type.name))

        self.params.append(ParamNode("self"))

        # Assign init_expr if not None
        if node.init_exp:
            init_expr_value = self.define_internal_local()
            self.visit(node.init_exp, init_expr_value)
            self.register_instruction(ReturnNode(init_expr_value))

        else:  # Assign default value
            default_var = self.define_internal_local()
            self.register_instruction(DefaultValueNode(default_var, node.type))
            self.register_instruction(ReturnNode(default_var))

        self.current_function = None
    def string_concat(self):
        self.params.append(ParamNode("self"))
        other_arg = VariableInfo("other_arg")
        self.register_param(other_arg)

        ret_vinfo = self.define_internal_local()

        self.register_instruction(ConcatNode(ret_vinfo, "self",
                                             other_arg.name))
        self.register_instruction(ReturnNode(ret_vinfo))
    def string_substr(self):
        self.params.append(ParamNode("self"))
        idx_arg = VariableInfo("idx_arg")
        self.register_param(idx_arg)
        length_arg = VariableInfo("length_arg")
        self.register_param(length_arg)

        ret_vinfo = self.define_internal_local()

        self.register_instruction(
            SubstringNode(ret_vinfo, "self", idx_arg.name, length_arg.name))
        self.register_instruction(ReturnNode(ret_vinfo))
    def add_builtin_constructors(self):
        builtin_types = ["Object", "IO", "Int", "Bool", "String"]
        for typex in builtin_types:
            self.current_function = FunctionNode(
                self.to_function_name("constructor", typex), [], [], [])
            self.params.append(ParamNode("self"))
            # instance = self.define_internal_local()
            # self.register_instruction(AllocateNode(typex, instance))
            self.register_instruction(ReturnNode("self"))
            self.code.append(self.current_function)

        self.current_function = None
 def object_type_name(self):
     self.params.append(ParamNode("self"))
     self.data.append(
         DataNode(f"type_name_{self.current_type.name}",
                  f"{self.current_type.name}"))
     type_name = self.define_internal_local()
     self.register_instruction(
         LoadNode(
             type_name,
             VariableInfo(
                 f"type_name_{self.current_type.name}",
                 None,
                 f"{self.current_type.name}",
             ),
         ))
     self.register_instruction(ReturnNode(type_name))
    def build_constructor(self, node):
        self.current_function = self.register_function(
            self.to_function_name("constructor", node.id))

        self.params.append(ParamNode("self"))
        self.current_type.define_method("constructor", [], [], "Object")

        for attr, (_, typex) in self.attrs[self.current_type.name].items():
            instance = self.define_internal_local()
            self.register_instruction(ArgNode("self"))
            self.register_instruction(
                StaticCallNode(
                    self.to_function_name(f"{attr}_constructor", typex),
                    instance))
            self.register_instruction(
                SetAttribNode("self", self.to_attr_name(node.id, attr),
                              instance, node.id))

        self.register_instruction(ReturnNode("self"))
    def visit(self, node, return_var=None):
        self.current_method = self.current_type.get_method(node.id)

        # Add function to .CODE
        self.current_function = self.register_function(
            self.to_function_name(node.id, self.current_type.name))

        # Add params
        self.current_function.params.append(ParamNode("self"))
        for pname, _ in node.params:
            self.register_param(VariableInfo(pname))

        # Body
        value = self.define_internal_local()
        self.visit(node.body, value)

        # Return
        if isinstance(self.current_method.return_type, VoidType):
            value = None

        self.register_instruction(ReturnNode(value))

        self.current_method = None
        self.current_function = None
 def io_inint(self):
     self.params.append(ParamNode("self"))
     ret_vinfo = self.define_internal_local()
     self.register_instruction(ReadIntNode(ret_vinfo))
     self.register_instruction(ReturnNode(ret_vinfo))
 def io_outint(self):
     self.params.append(ParamNode("self"))
     int_arg = VariableInfo("int")
     self.register_param(int_arg)
     self.register_instruction(PrintIntNode(int_arg.name))
     self.register_instruction(ReturnNode("self"))
 def io_outstring(self):
     self.params.append(ParamNode("self"))
     str_arg = VariableInfo("str")
     self.register_param(str_arg)
     self.register_instruction(PrintStrNode(str_arg.name))
     self.register_instruction(ReturnNode("self"))