Esempio n. 1
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.AllocateNode('Main',
                             self.context.get_type('Main').tag, instance))
        self.register_instruction(
            cil.CallNode(result, 'Main_init', [cil.ArgNode(instance)], "Main"))
        self.register_instruction(
            cil.CallNode(result, self.to_function_name('main', 'Main'),
                         [cil.ArgNode(instance)], "Main"))
        self.register_instruction(cil.ReturnNode(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.define_built_in(scope)

        # Add string equals function
        self.build_string_equals_function(scope)

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

        return cil.ProgramNode(self.dottypes, self.dotdata, self.dotcode)
Esempio n. 2
0
    def visit(self, node, scope):
        self.current_method = self.current_type.get_method(node.id)
        self.dottypes[self.current_type.name].methods[
            node.id] = f'{self.current_type.name}.{node.id}'
        cil_method_name = self.to_function_name(node.id,
                                                self.current_type.name)
        self.current_function = self.register_function(cil_method_name)

        self.register_param(VariableInfo('self', self.current_type))
        for pname, ptype, _, _ in node.params:
            self.register_param(VariableInfo(pname, ptype))

        value = self.visit(node.body, scope)

        self.register_instruction(cil.ReturnNode(value))
        self.current_method = None
Esempio n. 3
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, FuncDeclarationNode)
        ]
        attr_declarations = [
            a for a in node.features if isinstance(a, 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.CallNode(result, f'{node.parent}_init', [cil.ArgNode('self')],
                         node.parent))
        self.register_instruction(cil.ReturnNode(None))

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

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

        self.current_type = None
Esempio n. 4
0
    def build_string_equals_function(self, scope):
        self.current_function = self.register_function('String_equals')
        self.register_param(VariableInfo('str1', None))
        self.register_param(VariableInfo('str2', None))

        str1 = self.define_internal_local(scope=scope, name="str1")
        self.register_instruction(cil.GetAttrNode(
            str1, 'str1', 'value', 'String'))

        str2 = self.define_internal_local(scope=scope, name="str2")
        self.register_instruction(cil.GetAttrNode(
            str2, 'str2', 'value', 'String'))

        result = self.define_internal_local(
            scope=scope, name="comparison_result")
        self.register_instruction(cil.StringEqualsNode(str1, str2, result))
        self.register_instruction(cil.ReturnNode(result))
Esempio n. 5
0
    def define_built_in(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}' 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.ReturnNode(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.LoadStringNode(key_msg, msg))
        self.register_instruction(cil.PrintStringNode(msg))
        type_name = self.define_internal_local(scope=scope, name="type_name")
        self.register_instruction(cil.TypeOfNode('self', type_name))
        self.register_instruction(cil.PrintStringNode(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.LoadStringNode(eol, eol_local))
        self.register_instruction(cil.PrintStringNode(eol_local))
        self.register_instruction(cil.HaltNode())

        # 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.TypeOfNode('self', type_name))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'String_init', [
                                  cil.ArgNode(type_name), cil.ArgNode(instance)], "String"))
        self.register_instruction(cil.ReturnNode(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.CopyNode('self', copy))
        self.register_instruction(cil.ReturnNode(copy))

        # ----------------IO---------------------
        # init
        self.current_function = self.register_function('IO_init')
        self.register_param(VariableInfo('self', None))
        self.register_instruction(cil.ReturnNode(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.GetAttrNode(v, 'x', 'value', 'String'))
        self.register_instruction(cil.PrintStringNode(v))
        self.register_instruction(cil.ReturnNode('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.GetAttrNode(v, 'x', 'value', 'Int'))
        self.register_instruction(cil.PrintIntNode(v))
        self.register_instruction(cil.ReturnNode('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.ReadStringNode(msg))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'String_init', [
                                  cil.ArgNode(msg), cil.ArgNode(instance)], "String"))
        self.register_instruction(cil.ReturnNode(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.ReadIntNode(number))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'Int', self.context.get_type('Int').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'Int_init', [
                                  cil.ArgNode(number), cil.ArgNode(instance)], "Int"))
        self.register_instruction(cil.ReturnNode(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.SetAttrNode('self', 'value', 'v', 'String'))
        self.register_instruction(cil.ReturnNode(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.LengthNode('self', length_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'Int', self.context.get_type('Int').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'Int_init', [
                                  cil.ArgNode(length_result), cil.ArgNode(instance)], "Int"))
        self.register_instruction(cil.ReturnNode(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.GetAttrNode(
            str1, 'self', 'value', 'String'))
        len1 = self.define_internal_local(scope=scope, name="len1")
        self.register_instruction(cil.CallNode(
            len1, 'String.length', [cil.ArgNode('self')], 'String'))

        str2 = self.define_internal_local(scope=scope, name="str2")
        self.register_instruction(
            cil.GetAttrNode(str2, 's', 'value', 'String'))
        len2 = self.define_internal_local(scope=scope, name="len2")
        self.register_instruction(cil.CallNode(
            len2, 'String.length', [cil.ArgNode('s')], 'String'))

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

        concat_result = self.define_internal_local(scope=scope, name="concat")
        self.register_instruction(cil.ConcatNode(
            str1, local_len1, str2, local_len2, concat_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'String_init', [
                                  cil.ArgNode(concat_result), cil.ArgNode(instance)], "String"))
        self.register_instruction(cil.ReturnNode(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.GetAttrNode(i_value, 'i', 'value', 'Int'))
        l_value = self.define_internal_local(scope=scope, name="l_value")
        self.register_instruction(
            cil.GetAttrNode(l_value, 'l', 'value', 'Int'))
        subs_result = self.define_internal_local(
            scope=scope, name="subs_result")
        self.register_instruction(cil.SubStringNode(
            i_value, l_value, 'self', subs_result))
        instance = self.define_internal_local(scope=scope, name="instance")
        self.register_instruction(cil.AllocateNode(
            'String', self.context.get_type('String').tag, instance))
        result_init = self.define_internal_local(
            scope=scope, name="result_init")
        self.register_instruction(cil.CallNode(result_init, 'String_init', [
                                  cil.ArgNode(subs_result), cil.ArgNode(instance)], "String"))
        self.register_instruction(cil.ReturnNode(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.SetAttrNode('self', 'value', 'v', 'Bool'))
        self.register_instruction(cil.ReturnNode(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.SetAttrNode('self', 'value', 'v', 'Int'))
        self.register_instruction(cil.ReturnNode(None))