change instructions to be an enum

This commit is contained in:
Peter McGoron 2023-02-09 16:32:32 +00:00
parent c0770d8ece
commit ef84135a2e
2 changed files with 25 additions and 25 deletions

View File

@ -50,13 +50,23 @@ class TypecheckException(Exception):
self.opcode = opcode self.opcode = opcode
def __str__(self): def __str__(self):
return f'opcode {self.opcode} has invalid value {self.sarg} (expected {self.argtype} in position {self.i}' return f'opcode {self.opcode} has invalid value {self.sarg} (expected {self.argtype} in position {self.i}'
class Instruction: class Instruction(Enum):
def __init__(self, opcode, argtypes): 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: if opcode > 0x7F or opcode < 0:
raise OpcodeException(opcode) raise OpcodeException(opcode)
self.opcode = opcode self.opcode = opcode
self.argtypes = argtypes self.argtypes = args
def typecheck(self, sargs): def typecheck(self, sargs):
rargs = [] rargs = []
if len(sargs) != len(self.argtypes): if len(sargs) != len(self.argtypes):
@ -71,18 +81,6 @@ class Instruction:
rargs.append(t) rargs.append(t)
return rargs 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 = { encoding_types = {
# start mask A B # start mask A B
2: (0x7F, 0xC0, 7), 2: (0x7F, 0xC0, 7),
@ -165,12 +163,14 @@ class Program:
def parse_asm_line(self, line): def parse_asm_line(self, line):
line = line.split() line = line.split()
line[0] = line[0].casefold() 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]) raise InstructionNotFoundException(line[0])
else:
ins = instructions[line[0]] args_w_type = ins.typecheck(line[1:])
args_w_type = ins.typecheck(line[1:]) self.asm_push_line(ins.opcode, args_w_type)
self.asm_push_line(ins.opcode, args_w_type)
def __call__(self): def __call__(self):
b = bytes() b = bytes()

View File

@ -9,7 +9,7 @@ class PushTest(unittest.TestCase):
b = p() b = p()
self.assertEqual(b, b'\x01\xC2\x85\x00') self.assertEqual(b, b'\x01\xC2\x85\x00')
ins = ffi.parse_line(b) 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)) self.assertEqual(ins[1][0], (1,5))
def test_parse_push_imm(self): def test_parse_push_imm(self):
@ -18,7 +18,7 @@ class PushTest(unittest.TestCase):
b = p() b = p()
self.assertEqual(b, b'\x01\xC0\x85\x00') self.assertEqual(b, b'\x01\xC0\x85\x00')
ins = ffi.parse_line(b) 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)) self.assertEqual(ins[1][0], (0,5))
def test_parse_push_catch_typecheck_push_lab(self): def test_parse_push_catch_typecheck_push_lab(self):
@ -55,7 +55,7 @@ class PushTest(unittest.TestCase):
def test_compile_push(self): def test_compile_push(self):
p = Program() p = Program()
p.parse_asm_line("PUSH r0") p.parse_asm_line("PUSH r0")
p.parse_asm_line("PUSH r6") p.parse_asm_line("PUSH 6")
b = p() b = p()
ex = ffi.ExecutionEnvironment() 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[0].w[2], 0)
self.assertEqual(ex.cenv.prg[1].opcode, 1) 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[1], 0)
self.assertEqual(ex.cenv.prg[1].w_flags[2], 0) self.assertEqual(ex.cenv.prg[1].w_flags[2], 0)
self.assertEqual(ex.cenv.prg[1].w[0], 6) self.assertEqual(ex.cenv.prg[1].w[0], 6)
@ -109,7 +109,7 @@ class ProgramTest(unittest.TestCase):
p = Program() p = Program()
p.parse_asm_line("add r1 23 3648") p.parse_asm_line("add r1 23 3648")
ins = ffi.parse_line(p()) 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][0], (1,1))
self.assertEqual(ins[1][1], (0,23)) self.assertEqual(ins[1][1], (0,23))
self.assertEqual(ins[1][2], (0,3648)) self.assertEqual(ins[1][2], (0,3648))