summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nandgame/assembler/assembler.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/nandgame/assembler/assembler.py b/nandgame/assembler/assembler.py
new file mode 100644
index 0000000..a622891
--- /dev/null
+++ b/nandgame/assembler/assembler.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+
+import sys
+from typing import Iterable, Tuple
+
+from parser import parser
+from parsetypes import *
+
+
+def check_num_args(instruction: Instruction) -> Tuple[int, int]:
+ return (0, 20)
+
+
+def check_supports_jump(instruction: Instruction) -> bool:
+ return True
+
+
+def check_instructions(
+ instructions: Iterable[Instruction],
+) -> Iterable[ErrorInstruction]:
+ for i in instructions:
+ if isinstance(i, ErrorInstruction):
+ yield i
+ continue
+
+ (min, max) = check_num_args(i)
+ if not (min <= i.num_args <= max):
+ yield ErrorInstruction.from_instruction(
+ i, f"Expected between {min} and {max} args, got {i.num_args}."
+ )
+
+ if not check_supports_jump(i) and i.jumptarget:
+ yield ErrorInstruction.from_instruction(
+ i, f"OPcode got jump, but it's not supported here."
+ )
+
+labels: dict[str,int] = {}
+
+def assemble(program: Iterable[Instruction|JumpTarget]) -> None:
+ pc = 0
+ for ins in program:
+ if isinstance(ins, JumpTarget):
+ pass
+
+with open(sys.argv[1], "rb") as f:
+ data = f.read()
+ data2 = data.decode("ascii")
+ result: list[Instruction | JumpTarget]
+ result = parser.parse(data2, tracking=True)
+ errors = check_instructions(ins for ins in result if isinstance(ins, Instruction))
+ if errors:
+ for e in errors:
+ print(f"On line {e.lineno}: {e.opcode} : {e.error_message}")
+ sys.exit(1)
+ assemble(result)
+
+ pass