diff --git a/asm/creole.py b/asm/creole.py index 1ed25e8..1d105a1 100644 --- a/asm/creole.py +++ b/asm/creole.py @@ -50,13 +50,23 @@ class TypecheckException(Exception): self.opcode = opcode def __str__(self): return f'opcode {self.opcode} has invalid value {self.sarg} (expected {self.argtype} in position {self.i}' -class Instruction: - def __init__(self, opcode, argtypes): +class Instruction(Enum): + NOP = 0 + PUSH = 1, ArgType.VAL + POP = 2, ArgType.REG + ADD = 3, ArgType.VAL, ArgType.VAL, ArgType.VAL + MUL = 4, ArgType.VAL, ArgType.VAL, ArgType.VAL + DIV = 5, ArgType.VAL, ArgType.VAL, ArgType.VAL + JL = 6, ArgType.LAB, ArgType.VAL, ArgType.VAL + CLB = 7, ArgType.LAB + SYS = 8, ArgType.VAL + + def __init__(self, opcode, *args): if opcode > 0x7F or opcode < 0: raise OpcodeException(opcode) self.opcode = opcode - self.argtypes = argtypes + self.argtypes = args def typecheck(self, sargs): rargs = [] if len(sargs) != len(self.argtypes): @@ -71,18 +81,6 @@ class Instruction: rargs.append(t) return rargs -instructions = { -"nop" : Instruction(0, []), -"push" : Instruction(1, [ArgType.VAL]), -"pop" : Instruction(2, [ArgType.REG]), -"add" : Instruction(3, [ArgType.VAL, ArgType.VAL, ArgType.VAL]), -"mul" : Instruction(4, [ArgType.VAL, ArgType.VAL, ArgType.VAL]), -"div" : Instruction(5, [ArgType.VAL, ArgType.VAL, ArgType.VAL]), -"jl" : Instruction(6, [ArgType.LAB, ArgType.VAL, ArgType.VAL]), -"clb" : Instruction(7, [ArgType.LAB]), -"sys" : Instruction(8, [ArgType.VAL]) -} - encoding_types = { # start mask A B 2: (0x7F, 0xC0, 7), @@ -165,12 +163,14 @@ class Program: def parse_asm_line(self, line): line = line.split() line[0] = line[0].casefold() - if line[0] not in instructions: + try: + # TODO: is there no better way to do this in Python? + ins = getattr(Instruction, line[0].upper()) + except Exception as e: raise InstructionNotFoundException(line[0]) - else: - ins = instructions[line[0]] - args_w_type = ins.typecheck(line[1:]) - self.asm_push_line(ins.opcode, args_w_type) + + args_w_type = ins.typecheck(line[1:]) + self.asm_push_line(ins.opcode, args_w_type) def __call__(self): b = bytes() diff --git a/asm/test.py b/asm/test.py index 06a878f..640f3bf 100644 --- a/asm/test.py +++ b/asm/test.py @@ -9,7 +9,7 @@ class PushTest(unittest.TestCase): b = p() self.assertEqual(b, b'\x01\xC2\x85\x00') ins = ffi.parse_line(b) - self.assertEqual(ins[0], instructions["push"].opcode) + self.assertEqual(ins[0], Instruction.PUSH.opcode) self.assertEqual(ins[1][0], (1,5)) def test_parse_push_imm(self): @@ -18,7 +18,7 @@ class PushTest(unittest.TestCase): b = p() self.assertEqual(b, b'\x01\xC0\x85\x00') ins = ffi.parse_line(b) - self.assertEqual(ins[0], instructions["push"].opcode) + self.assertEqual(ins[0], Instruction.PUSH.opcode) self.assertEqual(ins[1][0], (0,5)) def test_parse_push_catch_typecheck_push_lab(self): @@ -55,7 +55,7 @@ class PushTest(unittest.TestCase): def test_compile_push(self): p = Program() p.parse_asm_line("PUSH r0") - p.parse_asm_line("PUSH r6") + p.parse_asm_line("PUSH 6") b = p() ex = ffi.ExecutionEnvironment() @@ -71,7 +71,7 @@ class PushTest(unittest.TestCase): self.assertEqual(ex.cenv.prg[0].w[2], 0) self.assertEqual(ex.cenv.prg[1].opcode, 1) - self.assertEqual(ex.cenv.prg[1].w_flags[0], 1) + self.assertEqual(ex.cenv.prg[1].w_flags[0], 0) self.assertEqual(ex.cenv.prg[1].w_flags[1], 0) self.assertEqual(ex.cenv.prg[1].w_flags[2], 0) self.assertEqual(ex.cenv.prg[1].w[0], 6) @@ -109,7 +109,7 @@ class ProgramTest(unittest.TestCase): p = Program() p.parse_asm_line("add r1 23 3648") ins = ffi.parse_line(p()) - self.assertEqual(ins[0], instructions["add"].opcode) + self.assertEqual(ins[0], Instruction.ADD.opcode) self.assertEqual(ins[1][0], (1,1)) self.assertEqual(ins[1][1], (0,23)) self.assertEqual(ins[1][2], (0,3648))