Пример #1
0
    def visit(self, node: COOL_AST.LetNode, scope):
        let_scope = scope.create_child()
        for var_name, var_type, var_expr in node.var_list:
            if var_expr is not None:
                var_expr_value = self.visit(var_expr, let_scope)
            else:
                instance = None
                if var_type in ['Int', 'Bool']:
                    instance = self.define_internal_local(scope=let_scope, name="instance")
                    self.register_instruction(
                        CIL_AST.Allocate(var_type, self.context.get_type(var_type).tag, instance))
                    value = self.define_internal_local(scope=let_scope, name="value")
                    self.register_instruction(CIL_AST.LoadInt(0, value))
                    result_init = self.define_internal_local(scope=let_scope, name="result_init")
                    self.register_instruction(
                        CIL_AST.Call(result_init, f'{var_type}_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)],
                                     var_type))
                elif var_type == 'String':
                    instance = self.define_internal_local(scope=let_scope, name="instance")
                    self.register_instruction(
                        CIL_AST.Allocate(var_type, self.context.get_type(var_type).tag, instance))
                    value = self.define_internal_local(scope=let_scope, name="value")
                    self.register_instruction(CIL_AST.LoadStr('empty_str', value))
                    result_init = self.define_internal_local(scope=let_scope, name="result_init")
                    self.register_instruction(
                        CIL_AST.Call(result_init, f'{var_type}_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)],
                                     var_type))
                var_expr_value = instance
            let_var = self.define_internal_local(scope=let_scope, name=var_name, cool_var_name=var_name)
            self.register_instruction(CIL_AST.Assign(let_var, var_expr_value))

        body_value = self.visit(node.body, let_scope)
        result_local = self.define_internal_local(scope=scope, name="let_result")
        self.register_instruction(CIL_AST.Assign(result_local, body_value))
        return result_local
Пример #2
0
    def visit(self, node, scope):
        instance = None

        if node.type in ['Int', 'Bool']:
            instance = self.define_internal_local(scope=scope, name="instance")
            self.register_instruction(CIL_AST.Allocate(node.type, self.context.get_type(node.type).tag, instance))
            value = self.define_internal_local(scope=scope, name="value")
            self.register_instruction(CIL_AST.LoadInt(0, value))
            result_init = self.define_internal_local(scope=scope, name="result_init")
            self.register_instruction(
                CIL_AST.Call(result_init, f'{node.type}_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)], node.type))
        elif node.type == 'String':
            instance = self.define_internal_local(scope=scope, name="instance")
            self.register_instruction(CIL_AST.Allocate(node.type, self.context.get_type(node.type).tag, instance))
            value = self.define_internal_local(scope=scope, name="value")
            self.register_instruction(CIL_AST.LoadStr('empty_str', value))
            result_init = self.define_internal_local(scope=scope, name="result_init")
            self.register_instruction(
                CIL_AST.Call(result_init, f'{node.type}_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)], node.type))

        if node.val is None:
            self.register_instruction(CIL_AST.SetAttr('self', node.id, instance, self.current_type.name))
        else:
            expr = self.visit(node.val, scope)
            self.register_instruction(CIL_AST.SetAttr('self', node.id, expr, self.current_type.name))
Пример #3
0
    def visit(self, node, scope=None):
        scope = Scope()
        self.current_function = self.register_function('main')
        instance = self.define_internal_local(scope=scope, name="instance")
        result = self.define_internal_local(scope=scope, name="result")
        self.register_instruction(CIL_AST.Allocate('Main', self.context.get_type('Main').tag, instance))
        self.register_instruction(CIL_AST.Call(result, 'Main_init', [CIL_AST.Arg(instance)], "Main"))
        self.register_instruction(
            CIL_AST.Call(result, self.to_function_name('main', 'Main'), [CIL_AST.Arg(instance)], "Main"))
        self.register_instruction(CIL_AST.Return(None))
        self.current_function = None

        self.register_data('Abort called from class ')
        self.register_data('\n')
        self.dotdata['empty_str'] = ''

        # Add built-in types in .TYPES section
        self.register_builtin_types(scope)

        # Add string equals function
        self.build_string_equals_function(scope)

        for klass in node.declarations:
            self.visit(klass, scope.create_child())

        return CIL_AST.Program(self.dottypes, self.dotdata, self.dotcode)
Пример #4
0
    def visit(self, node: COOL_AST.InstantiateNode, scope):
        result_local = self.define_internal_local(scope=scope, name="result")
        result_init = self.define_internal_local(scope=scope, name="init")

        if node.lex == "SELF_TYPE":
            self.register_instruction(CIL_AST.Allocate(self.current_type.name, self.current_type.tag, result_local))
            self.register_instruction(
                CIL_AST.Call(result_init, f'{self.current_type.name}_init', [result_local], self.current_type.name))
        else:
            self.register_instruction(CIL_AST.Allocate(node.lex, self.context.get_type(node.lex).tag, result_local))
            self.register_instruction(
                CIL_AST.Call(result_init, f'{node.lex}_init', [CIL_AST.Arg(result_local)], self.current_type.name))

        return result_local
Пример #5
0
    def visit(self, node: COOL_AST.ArithBinaryNode, scope):
        result_local = self.define_internal_local(scope=scope, name="result")
        op_local = self.define_internal_local(scope=scope, name="op")
        left_local = self.define_internal_local(scope=scope, name="left")
        right_local = self.define_internal_local(scope=scope, name="right")

        left_value = self.visit(node.left, scope)
        right_value = self.visit(node.right, scope)

        self.register_instruction(CIL_AST.GetAttr(left_local, left_value, "value", node.left.computed_type.name))
        self.register_instruction(CIL_AST.GetAttr(right_local, right_value, "value", node.right.computed_type.name))

        if isinstance(node, COOL_AST.PlusNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "+"))
        elif isinstance(node, COOL_AST.MinusNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "-"))
        elif isinstance(node, COOL_AST.StarNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "*"))
        elif isinstance(node, COOL_AST.DivNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "/"))

        # Allocate Int result
        self.register_instruction(CIL_AST.Allocate('Int', self.context.get_type('Int').tag, result_local))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'Int_init', [CIL_AST.Arg(op_local), CIL_AST.Arg(result_local)], "Int"))
        return result_local
Пример #6
0
    def visit(self, node, scope):
        self.current_type = self.context.get_type(node.id)

        # Handle all the .TYPE section
        cil_type = self.register_type(self.current_type.name)
        cil_type.attributes = [f'{attr.name}' for c, attr in self.current_type.get_all_attributes()]
        cil_type.methods = {f'{m}': f'{c}.{m}' for c, m in self.current_type.get_all_methods()}

        scope.define_cil_local("self", self.current_type.name, self.current_type)

        func_declarations = [f for f in node.features if isinstance(f, COOL_AST.ClassDeclarationNode)]
        attr_declarations = [a for a in node.features if isinstance(a, COOL_AST.AttrDeclarationNode)]
        for attr in attr_declarations:
            scope.define_cil_local(attr.id, attr.id, node.id)

        # -------------------------Init---------------------------------
        self.current_function = self.register_function(f'{node.id}_init')
        self.register_param(VariableInfo('self', None))

        # Init parents recursively
        result = self.define_internal_local(scope=scope, name="result")
        self.register_instruction(CIL_AST.Call(result, f'{node.parent}_init', [CIL_AST.Arg('self')], node.parent))
        self.register_instruction(CIL_AST.Return(None))

        for attr in attr_declarations:
            self.visit(attr, scope)
        # ---------------------------------------------------------------
        self.current_function = None

        for feature in func_declarations:
            self.visit(feature, scope.create_child())

        self.current_type = None
Пример #7
0
 def visit(self, node: COOL_AST.ConstantNumNode, scope):
     instance = self.define_internal_local(scope=scope, name="instance")
     self.register_instruction(CIL_AST.Allocate('Int', self.context.get_type('Int').tag, instance))
     value = self.define_internal_local(scope=scope, name="value")
     self.register_instruction(CIL_AST.LoadInt(node.lex, value))
     result_init = self.define_internal_local(scope=scope, name="result_init")
     self.register_instruction(
         CIL_AST.Call(result_init, 'Int_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)], "Int"))
     return instance
Пример #8
0
 def visit(self, node: COOL_AST.IsVoidNode, scope):
     expre_value = self.visit(node.expr, scope)
     result_local = self.define_internal_local(scope=scope, name="isvoid_result")
     self.register_instruction(CIL_AST.IsVoid(result_local, expre_value))
     instance = self.define_internal_local(scope=scope, name="instance")
     self.register_instruction(CIL_AST.Allocate('Bool', self.context.get_type('Bool').tag, instance))
     result_init = self.define_internal_local(scope=scope, name="result_init")
     self.register_instruction(
         CIL_AST.Call(result_init, 'Bool_init', [CIL_AST.Arg(result_local), CIL_AST.Arg(instance)], "Bool"))
     return instance
Пример #9
0
 def visit(self, node: COOL_AST.BoolNode, scope):
     boolean = 0
     if str(node.lex) == "True":
         boolean = 1
     instance = self.define_internal_local(scope=scope, name="instance")
     self.register_instruction(CIL_AST.Allocate('Bool', self.context.get_type('Bool').tag, instance))
     value = self.define_internal_local(scope=scope, name="value")
     self.register_instruction(CIL_AST.LoadInt(boolean, value))
     result_init = self.define_internal_local(scope=scope, name="result_init")
     self.register_instruction(
         CIL_AST.Call(result_init, 'Bool_init', [CIL_AST.Arg(value), CIL_AST.Arg(instance)], "Bool"))
     return instance
Пример #10
0
    def visit(self, node: COOL_AST.BooleanBinaryNode, scope):
        result_local = self.define_internal_local(scope=scope, name="result")
        op_local = self.define_internal_local(scope=scope, name="op")
        left_local = self.define_internal_local(scope=scope, name="left")
        right_local = self.define_internal_local(scope=scope, name="right")

        left_value = self.visit(node.left, scope)
        right_value = self.visit(node.right, scope)

        self.register_instruction(CIL_AST.GetAttr(left_local, left_value, "value", node.left.computed_type.name))
        self.register_instruction(CIL_AST.GetAttr(right_local, right_value, "value", node.right.computed_type.name))

        if isinstance(node, COOL_AST.LessNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "<"))
        elif isinstance(node, COOL_AST.LessNode):
            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "<="))
        elif isinstance(node, COOL_AST.EqualNode):
            if node.left.computed_type.name == 'String':
                self.register_instruction(
                    CIL_AST.Call(op_local, 'String_equals', [CIL_AST.Arg(right_value), CIL_AST.Arg(left_value)],
                                 'String'))
            elif node.left.computed_type.name in ['Int', 'Bool']:
                self.register_instruction(
                    CIL_AST.GetAttr(left_local, left_value, "value", node.left.computed_type.name))
                self.register_instruction(
                    CIL_AST.GetAttr(right_local, right_value, "value", node.right.computed_type.name))
            else:
                self.register_instruction(CIL_AST.Assign(left_local, left_value))
                self.register_instruction(CIL_AST.Assign(right_local, right_value))

            self.register_instruction(CIL_AST.BinaryOperator(op_local, left_local, right_local, "="))

        # Allocate Bool result
        self.register_instruction(CIL_AST.Allocate('Bool', self.context.get_type('Bool').tag, result_local))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'Bool_init', [CIL_AST.Arg(op_local), CIL_AST.Arg(result_local)], "Bool"))
        return result_local
Пример #11
0
    def visit(self, node: COOL_AST.StringNode, scope):
        str_name = ""
        for s in self.dotdata.keys():
            if self.dotdata[s] == node.lex:
                str_name = s
                break
        if str_name == "":
            str_name = self.register_data(node.lex)

        result_local = self.define_internal_local(scope=scope)
        self.register_instruction(CIL_AST.LoadStr(str_name, result_local))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'String_init', [CIL_AST.Arg(result_local), CIL_AST.Arg(instance)], "String"))
        return instance
Пример #12
0
    def visit(self, node: COOL_AST.NotNode, scope):
        result_local = self.define_internal_local(scope=scope, name="result")
        op_local = self.define_internal_local(scope=scope, name="op")
        expr_local = self.define_internal_local(scope=scope)

        expr_value = self.visit(node.expr, scope)

        self.register_instruction(CIL_AST.GetAttr(expr_local, expr_value, "value", node.expr.computed_type.name))
        self.register_instruction(CIL_AST.UnaryOperator(op_local, expr_local, "not"))

        # Allocate Bool result
        self.register_instruction(CIL_AST.Allocate('Bool', self.context.get_type('Bool').tag, result_local))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'Bool_init', [CIL_AST.Arg(op_local), CIL_AST.Arg(result_local)], "Bool"))

        return result_local
Пример #13
0
    def register_builtin_types(self, scope):
        for t in ['Object', 'Int', 'String', 'Bool', 'IO']:
            builtin_type = self.context.get_type(t)
            cil_type = self.register_type(t)
            cil_type.attributes = [f'{attr.name}' for attr in builtin_type.attributes]
            cil_type.methods = {f'{m}': f'{c}.{m}' for c, m in builtin_type.get_all_methods()}
            if t in ['Int', 'String', 'Bool']:
                cil_type.attributes.append('value')

        # ----------------Object---------------------
        # init
        self.current_function = self.register_function('Object_init')
        self.register_param(VariableInfo('self', None))
        self.register_instruction(CIL_AST.Return(None))

        # abort
        self.current_function = self.register_function(self.to_function_name('abort', 'Object'))
        self.register_param(VariableInfo('self', None))
        msg = self.define_internal_local(scope=scope, name="msg")
        key_msg = ''
        for s in self.dotdata.keys():
            if self.dotdata[s] == 'Abort called from class ':
                key_msg = s
        self.register_instruction(CIL_AST.LoadStr(key_msg, msg))
        self.register_instruction(CIL_AST.PrintString(msg))
        type_name = self.define_internal_local(scope=scope, name="type_name")
        self.register_instruction(CIL_AST.TypeOf('self', type_name))
        self.register_instruction(CIL_AST.PrintString(type_name))
        eol_local = self.define_internal_local(scope=scope, name="eol")
        for s in self.dotdata.keys():
            if self.dotdata[s] == '\n':
                eol = s
        self.register_instruction(CIL_AST.LoadStr(eol, eol_local))
        self.register_instruction(CIL_AST.PrintString(eol_local))
        self.register_instruction(CIL_AST.Halt())

        # type_name
        self.current_function = self.register_function(self.to_function_name('type_name', 'Object'))
        self.register_param(VariableInfo('self', None))
        type_name = self.define_internal_local(scope=scope, name="type_name")
        self.register_instruction(CIL_AST.TypeOf('self', type_name))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'String_init', [CIL_AST.Arg(type_name), CIL_AST.Arg(instance)], "String"))
        self.register_instruction(CIL_AST.Return(instance))

        # copy
        self.current_function = self.register_function(self.to_function_name('copy', 'Object'))
        self.register_param(VariableInfo('self', None))
        copy = self.define_internal_local(scope=scope, name="copy")
        self.register_instruction(CIL_AST.Copy('self', copy))
        self.register_instruction(CIL_AST.Return(copy))

        # ----------------IO---------------------
        # init
        self.current_function = self.register_function('IO_init')
        self.register_param(VariableInfo('self', None))
        self.register_instruction(CIL_AST.Return(None))

        # out_string
        self.current_function = self.register_function(self.to_function_name('out_string', 'IO'))
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('x', None))
        v = self.define_internal_local(scope=scope, name="v")
        self.register_instruction(CIL_AST.GetAttr(v, 'x', 'value', 'String'))
        self.register_instruction(CIL_AST.PrintString(v))
        self.register_instruction(CIL_AST.Return('self'))

        # out_int
        self.current_function = self.register_function(self.to_function_name('out_int', 'IO'))
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('x', None))
        v = self.define_internal_local(scope=scope, name="v")
        self.register_instruction(CIL_AST.GetAttr(v, 'x', 'value', 'Int'))
        self.register_instruction(CIL_AST.PrintInteger(v))
        self.register_instruction(CIL_AST.Return('self'))

        # in_string
        self.current_function = self.register_function(self.to_function_name('in_string', 'IO'))
        self.register_param(VariableInfo('self', None))
        msg = self.define_internal_local(scope=scope, name="read_str")
        self.register_instruction(CIL_AST.ReadString(msg))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'String_init', [CIL_AST.Arg(msg), CIL_AST.Arg(instance)], "String"))
        self.register_instruction(CIL_AST.Return(instance))

        # in_int
        self.current_function = self.register_function(self.to_function_name('in_int', 'IO'))
        self.register_param(VariableInfo('self', None))
        number = self.define_internal_local(scope=scope, name="read_int")
        self.register_instruction(CIL_AST.ReadInteger(number))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('Int', self.context.get_type('Int').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'Int_init', [CIL_AST.Arg(number), CIL_AST.Arg(instance)], "Int"))
        self.register_instruction(CIL_AST.Return(instance))

        # ----------------String---------------------
        # init
        self.current_function = self.register_function('String_init')
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('v', None))
        self.register_instruction(CIL_AST.SetAttr('self', 'value', 'v', 'String'))
        self.register_instruction(CIL_AST.Return(None))

        # length
        self.current_function = self.register_function(self.to_function_name('length', 'String'))
        self.register_param(VariableInfo('self', None))
        length_result = self.define_internal_local(scope=scope, name="length")
        self.register_instruction(CIL_AST.Length('self', length_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('Int', self.context.get_type('Int').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'Int_init', [CIL_AST.Arg(length_result), CIL_AST.Arg(instance)], "Int"))
        self.register_instruction(CIL_AST.Return(instance))

        # concat
        self.current_function = self.register_function(self.to_function_name('concat', 'String'))
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('s', None))

        str1 = self.define_internal_local(scope=scope, name="str1")
        self.register_instruction(CIL_AST.GetAttr(str1, 'self', 'value', 'String'))
        len1 = self.define_internal_local(scope=scope, name="len1")
        self.register_instruction(CIL_AST.Call(len1, 'String.length', [CIL_AST.Arg('self')], 'String'))

        str2 = self.define_internal_local(scope=scope, name="str2")
        self.register_instruction(CIL_AST.GetAttr(str2, 's', 'value', 'String'))
        len2 = self.define_internal_local(scope=scope, name="len2")
        self.register_instruction(CIL_AST.Call(len2, 'String.length', [CIL_AST.Arg('s')], 'String'))

        local_len1 = self.define_internal_local(scope=scope, name="local_len1")
        self.register_instruction(CIL_AST.GetAttr(local_len1, len1, 'value', 'Int'))
        local_len2 = self.define_internal_local(scope=scope, name="local_len2")
        self.register_instruction(CIL_AST.GetAttr(local_len2, len2, 'value', 'Int'))

        concat_result = self.define_internal_local(scope=scope, name="concat")
        self.register_instruction(CIL_AST.Concat(str1, local_len1, str2, local_len2, concat_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'String_init', [CIL_AST.Arg(concat_result), CIL_AST.Arg(instance)], "String"))
        self.register_instruction(CIL_AST.Return(instance))

        # substr
        self.current_function = self.register_function(self.to_function_name('substr', 'String'))
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('i', None))
        self.register_param(VariableInfo('l', None))
        i_value = self.define_internal_local(scope=scope, name="i_value")
        self.register_instruction(CIL_AST.GetAttr(i_value, 'i', 'value', 'Int'))
        l_value = self.define_internal_local(scope=scope, name="l_value")
        self.register_instruction(CIL_AST.GetAttr(l_value, 'l', 'value', 'Int'))
        subs_result = self.define_internal_local(scope=scope, name="subs_result")
        self.register_instruction(CIL_AST.SubStr(i_value, l_value, 'self', subs_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(CIL_AST.Allocate('String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(scope=scope, name="result_init")
        self.register_instruction(
            CIL_AST.Call(result_init, 'String_init', [CIL_AST.Arg(subs_result), CIL_AST.Arg(instance)], "String"))
        self.register_instruction(CIL_AST.Return(instance))

        # ----------------Bool---------------------
        # init
        self.current_function = self.register_function('Bool_init')
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('v', None))
        self.register_instruction(CIL_AST.SetAttr('self', 'value', 'v', 'Bool'))
        self.register_instruction(CIL_AST.Return(None))

        # ----------------Int---------------------
        # init
        self.current_function = self.register_function('Int_init')
        self.register_param(VariableInfo('self', None))
        self.register_param(VariableInfo('v', None))
        self.register_instruction(CIL_AST.SetAttr('self', 'value', 'v', 'Int'))
        self.register_instruction(CIL_AST.Return(None))