コード例 #1
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
 def _visit_func_decl(self, node: ASTNode):
     # Only for member function
     node.record = Record(
         node.children[0].token.lexeme,
         SymbolType(node.children[2].token.lexeme, []),
         RecordType.FUNCTION,
         node.children[0].token.location,
         params=[param.record for param in node.children[1].children],
     )
コード例 #2
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
 def _visit_func_param(self, node: ASTNode):
     node.record = Record(
         node.children[1].token.lexeme,  # ID
         SymbolType(
             node.children[0].token.lexeme,
             [child.token for child in node.children[2].children],
         ),
         RecordType.PARAM,
         node.children[1].token.location,
     )
コード例 #3
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
 def _visit_var_decl(self, node: ASTNode):
     node.record = Record(
         node.children[1].token.lexeme,  # ID
         SymbolType(
             node.children[0].token.lexeme,
             [child.token for child in node.children[2].children],
         ),
         None,
         node.children[1].token.location,
     )
コード例 #4
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
 def _visit_main(self, node: ASTNode):
     table = SymbolTable("main")
     for child in node.children[0].children:  # Locals
         table.insert(child.record)
     node.record = Record(
         "main",
         SymbolType("void", []),
         RecordType.FUNCTION,
         node.token.location,
         params=[],
         table=table,
     )
コード例 #5
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
    def _visit_func_def(self, node: ASTNode):
        name = node.children[1].token.lexeme
        table = SymbolTable(name, is_function=True)
        params = [param.record for param in node.children[2].children]
        for param in params:
            table.insert(param)

        for child in node.children[4].children:  # Locals
            table.insert(child.record)

        node.record = Record(
            name,
            SymbolType(node.children[3].token.lexeme, []),
            RecordType.FUNCTION,
            node.children[1].token.location,
            params=params,
            table=table,
        )

        scope = node.children[0].token
        if scope:
            parent = BaseType(scope.lexeme).table
            if not parent:
                self.error(
                    'Use of undeclared class "{name}"'.format(
                        name=scope.lexeme),
                    scope.location,
                )
                return
            records = parent.entries.get(name, [])
            record = next(
                (r for r in records if r.record_type == RecordType.FUNCTION
                 and equal_params(r.params, params)
                 and r.type.base is node.record.type.base),
                None,
            )
            if not record:
                self.error(
                    'Member function "{scope}::{name}{type}" is defined but has not been declared'
                    .format(scope=scope.lexeme,
                            name=name,
                            type=node.record.format_type()),
                    scope.location,
                )
                return
            record.table = table  # Attach table on existing record in the class table
            table.inherits = [BaseType(scope.lexeme)]
            table.name = scope.lexeme + "::" + table.name
            node.record = record
        else:
            GLOBALS.insert(node.record)
コード例 #6
0
ファイル: table_builder.py プロジェクト: Lercerss/COMP442
    def _visit_class_decl(self, node: ASTNode):
        name = node.children[0].token.lexeme
        table = SymbolTable(
            name,
            [
                BaseType(inherit.token.lexeme)
                for inherit in node.children[1].children
            ],
        )

        for child in node.children[2].children:  # Members
            table.insert(child.record)
        node.record = Record(name,
                             None,
                             RecordType.CLASS,
                             node.children[0].token.location,
                             table=table)
コード例 #7
0
    def _type_for_data_member(
        self,
        node: ASTNode,
        types: List[SymbolType],
        records: List[Record],
        is_first: bool,
    ) -> SymbolType:
        token = node.children[0].token
        record = next(
            (r for r in records if r.record_type in DATA_RECORD_TYPES),
            None,
        )
        if record is None:
            self.error(
                'Use of undeclared {type} "{name}"'.format(
                    type="local variable" if is_first else "data member",
                    name=token.lexeme,
                ),
                token.location,
            )
            return None

        index_types = types or []
        if len(index_types) > len(record.type.dims) or any(
                type_ != SymbolType(INT, []) for type_ in index_types):
            self.error(
                'Invalid indexing for "{name}", type is "{type}"'.format(
                    name=token.lexeme, type=record.format_type()),
                token.location,
            )
            return None

        if index_types:
            # Reserve space for offset calculation
            node.temp_record = Record("", SymbolType(INT, []), RecordType.TEMP,
                                      None)
            self.scope.insert(node.temp_record)

        node.record = record
        return SymbolType(record.type.base,
                          record.type.dims[len(index_types):])
コード例 #8
0
 def _temp_record(self, type_, node):
     if type_:
         node.record = Record("", type_, RecordType.TEMP, None)
         self.scope.insert(node.record)
コード例 #9
0
ファイル: code_gen.py プロジェクト: Lercerss/COMP442
    def _visit_var(self, node: ASTNode):
        first_record = node.children[0].record
        record = Record(
            "",
            first_record.type,
            RecordType.TEMP,
            first_record.location,
        )
        if first_record.record_type == RecordType.DATA:
            node.temp_record = Record(
                "",
                first_record.type,
                RecordType.TEMP,
                first_record.location,
            )
            node.temp_record.offset = 8

        for child in node.children:
            if child.node_type == GroupNodeType.DATA_MEMBER:
                record.offset += child.record.offset
                index_list = child.children[1]
                if index_list.children:
                    # Array indexing
                    offset_code = []
                    with self.register() as ofs_reg, self.register(
                    ) as tmp_reg:
                        op, start_addr = "addi", ["r14", str(-record.offset)]
                        if node.temp_record:
                            op, start_addr = (
                                "lw",
                                [str(-node.temp_record.offset) + "(r14)"],
                            )
                        elif child.record.is_pointer():
                            op, start_addr = "lw", [
                                child.record.memory_location()
                            ]

                        _add_line(offset_code, op, [ofs_reg, *start_addr])
                        for i, index in enumerate(index_list.children):
                            node.code += index.code
                            self.load_in_reg(offset_code, index, tmp_reg)
                            _add_line(
                                offset_code,
                                "muli",
                                [
                                    tmp_reg,
                                    tmp_reg,
                                    str(child.record.type.mul_for_dim(i)),
                                ],
                            )
                            _add_line(offset_code, "sub",
                                      [ofs_reg, ofs_reg, tmp_reg])

                        _add_line(
                            offset_code,
                            "sw",
                            [child.temp_record.memory_location(), ofs_reg],
                        )
                    node.code += offset_code
                    record.offset = 0
                    node.temp_record = child.temp_record
            else:
                offset = 8  # Leave space for return value and r15 in stack frame
                offset += self.scope.current_size()

                if "::" in child.record.table.name:
                    # Add `this` pointer
                    with self.register() as register:
                        if node.temp_record:
                            _add_line(
                                node.code,
                                "lw",
                                [register,
                                 node.temp_record.memory_location()],
                            )
                            _add_line(
                                node.code,
                                "addi",
                                [register, register,
                                 str(-record.offset)],
                            )
                        else:
                            _add_line(
                                node.code,
                                "addi",
                                [register, "r14",
                                 str(-record.offset)],
                            )
                        _add_line(
                            node.code,
                            "sw",
                            [str(-offset) + "(r14)", register],
                        )
                    offset += 4

                for arg in child.children[1].children:  # Handle arguments
                    node.code += arg.code
                    with self.register() as register:
                        if arg.record and arg.record.type.is_complex():
                            # Pass complex arguments as pointers
                            _add_line(
                                node.code,
                                "addi",
                                [register, "r14",
                                 str(-arg.record.offset)],
                            )
                        else:
                            self.load_in_reg(node.code, arg, register)
                        _add_line(
                            node.code,
                            "sw",
                            [str(-offset) + "(r14)", register],
                        )
                        if arg.record:
                            if arg.record.type.is_complex():
                                offset += 4
                            else:
                                offset += arg.record.type.size
                        else:  # Literal
                            # TODO Handle float literal
                            offset += 4

                with self.new_frame(node.code):  # Call function
                    _add_line(
                        node.code,
                        "jl",
                        [
                            "r15",
                            self.get_mangled(child.record.table.name, "func")
                        ],
                    )

                with self.register() as register:  # Retrieve return value
                    _add_line(
                        node.code,
                        "lw",
                        [register,
                         str(-self.scope.current_size()) + "(r14)"],
                    )
                    _add_line(node.code, "sw",
                              [child.record.memory_location(), register])
                record.offset = child.record.offset

        node.record = record