change instructions to be an enum
This commit is contained in:
parent
c0770d8ece
commit
ef84135a2e
|
@ -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,10 +163,12 @@ 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)
|
||||||
|
|
||||||
|
|
10
asm/test.py
10
asm/test.py
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue