def visit(self, node: ast.ClassDeclarationNode, scope: Scope):
        self.current_type = node.id
        init = cil.FunctionNode(name=f'{node.id}__init',
                                params=[],
                                local_vars=[
                                    cil.LocalNode('self'),
                                ],
                                instructions=[
                                    cil.InitNode('self', node.id),
                                ])
        self.root.dot_code.append(init)
        self.current_init = init

        self.current_function = self.current_init
        type_node = self.root.get_type(self.current_type)
        for attr_name in type_node.attributes:
            attr = self.add_local(extract_feat_name(attr_name), internal=False)
            attr_expr, attr_scope = type_node.get_attr_node(attr_name)
            attr_value = self.visit(attr_expr, attr_scope)
            attr_index = type_node.attributes.index(attr_name)
            attr_at = cil.AttributeAt(attr_name, attr_index)
            self.add_inst(cil.SetAttrNode('self', attr_at, attr_value))
            self.add_inst(cil.AssignNode(attr, attr_value))

        for feat in node.features:
            # if isinstance(feat, ast.AttrDeclarationNode):
            #     visited_attrs.append(feat.id)
            #     self.visit(feat, scope)
            if isinstance(feat, ast.FuncDeclarationNode):
                tagged_scope = scope.get_tagged_scope(feat.id)
                self.visit(feat, tagged_scope)

        init.instructions.append(cil.ReturnNode('self'))
 def visit(self, node: ast.BooleanNode, scope: Scope):
     value = self.visit(node.lex == 'true', scope)
     bool_instance = self.add_local('bool_instance')
     self.add_inst(cil.StaticCallNode('Bool__init', bool_instance))
     attr_index = self.root.get_type('Bool').attributes.index('Bool_value')
     attr_at = cil.AttributeAt('Bool_Value', attr_index)
     self.add_inst(cil.SetAttrNode(bool_instance, attr_at, value))
     return bool_instance
 def visit(self, node: ast.IntegerNode, scope: Scope):
     value = self.visit(int(node.lex), scope)
     int_instance = self.add_local('int_instance')
     self.add_inst(cil.StaticCallNode('Int__init', int_instance))
     attr_index = self.root.get_type('Int').attributes.index('Int_value')
     attr_at = cil.AttributeAt('Int_value', attr_index)
     self.add_inst(cil.SetAttrNode(int_instance, attr_at, value))
     return int_instance
 def visit(self, node: ast.AssignNode, scope: Scope):
     expr_dest = self.visit(node.expr, scope)
     self.add_inst(cil.AssignNode(node.id, expr_dest))
     variable = scope.find_variable(node.id)
     if variable.is_attr:
         attr_name = f'{self.current_type}_{node.id}'
         attr_index = self.root.get_type(
             self.current_type).attributes.index(attr_name)
         attr_at = cil.AttributeAt(attr_name, attr_index)
         self.add_inst(cil.SetAttrNode('self', attr_at, value=expr_dest))
     return expr_dest
    def visit(self, node: ast.StringNode, scope: Scope):
        self.add_comment('Instantiating string: ' +
                         (node.lex if len(node.lex) < 20 else node.lex[:15] +
                          '...'))

        value = self.visit(node.lex, scope)
        str_instance = self.add_local('str_instance')
        self.add_inst(cil.StaticCallNode('String__init', str_instance))
        attr_index = self.root.get_type('String').attributes.index(
            'String_value')
        attr_at = cil.AttributeAt('String_value', attr_index)
        self.add_inst(cil.SetAttrNode(str_instance, attr_at, value))
        return str_instance