diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2024-02-20 16:55:14 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2024-02-20 16:56:09 +0200 |
| commit | 549901c85044b6ccd912688d6be007c2fdacc6c6 (patch) | |
| tree | 15d1123eedb4347472e4b47fec880e2e5b79927e /atk16-asm/asm_pass3.py | |
| parent | abf0594c78087434bced59054896f7f411e18faf (diff) | |
Refactor dir structure
Diffstat (limited to 'atk16-asm/asm_pass3.py')
| -rw-r--r-- | atk16-asm/asm_pass3.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/atk16-asm/asm_pass3.py b/atk16-asm/asm_pass3.py new file mode 100644 index 0000000..9c8cb34 --- /dev/null +++ b/atk16-asm/asm_pass3.py @@ -0,0 +1,78 @@ +from dataclasses import dataclass +from asm_ops import * +from asm_eval import * +from asm_pass2 import * + +@dataclass +class Result3Line: + line_num: int + src_file: str + address: int + parts: list[str] + original_parts: list[str] + +@dataclass +class Result3: + lines: list[Result3Line] + operations: OpExpansionDict + symbols: dict[str, int] + +def pass_3(result2: Result2) -> Result3: + result_lines: list[Result3Line] = [] + symbols: dict[str, int] = {} + address = 0 + + for line in result2.lines: + keyword, *args = line.parts + match keyword: + case "@address": + address = eval_expr(symbols, args[0]) + continue + case "@label": + label = args[0] + if label in symbols: + raise Exception(f"When defining label {label} as {address:>04x}, symbol {label} already defined as {symbols[label]:>04x}") + symbols[args[0]] = address + continue + case "@let": + symbols[args[0]] = eval_expr(symbols, args[1]) + continue + case _: + result_lines.append(Result3Line( + line_num=line.line_num, + src_file=line.src_file, + parts=line.parts, + address=address, + original_parts=line.original_parts, + )) + address += 1 + + result_lines.sort(key=lambda l: l.address) + for result_line in result_lines: + rows_with_same_addr = list(filter(lambda l: l.address == result_line.address, result_lines)) + n = len(rows_with_same_addr) + if n > 1: + formatted = format_overlapping_rows(rows_with_same_addr) + raise Exception(f"Overlapping segments: address 0x{result_line.address:>04x} has conflicting definitions:\n{formatted}") + return Result3( + operations=result2.operations, + lines=result_lines, + symbols=symbols, + ) + +def format_overlapping_rows(rows: list[Result3Line]) -> str: + longest_val = 0 + for row in rows: + joined = " ".join(row.parts) + if len(joined) > longest_val: + longest_val = len(joined) + + first_col_width = longest_val + 4 + + results: list[str] = [] + for row in rows: + joined = " ".join(row.parts) + result = joined + (first_col_width - len(joined)) * " " + f" ({row.src_file}:{row.line_num})" + results.append(result) + + return "\n".join(results) |
