diff options
| author | 2023-02-09 16:16:41 +0000 | |
|---|---|---|
| committer | 2023-02-09 16:16:41 +0000 | |
| commit | c0770d8ece675f5e6f2249b331c7550933915829 (patch) | |
| tree | 49ed1779f0941a60ce2941c312d3f53f4ab81616 /asm | |
| parent | test refactoring (diff) | |
add compile t est
Diffstat (limited to 'asm')
| -rw-r--r-- | asm/creole.py | 2 | ||||
| -rw-r--r-- | asm/ffi.py | 60 | ||||
| -rw-r--r-- | asm/test.py | 44 |
3 files changed, 90 insertions, 16 deletions
diff --git a/asm/creole.py b/asm/creole.py index c1045c5..1ed25e8 100644 --- a/asm/creole.py +++ b/asm/creole.py @@ -73,7 +73,7 @@ class Instruction: instructions = { "nop" : Instruction(0, []), -"push" : Instruction(1, [ArgType.REG]), +"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]), @@ -3,7 +3,7 @@ from enum import Enum dll = CDLL("./libcreole.so") class CompileRet(Enum): - COMPILE_OK = 0 + OK = 0 OPCODE_READ_ERROR = 1 OPCODE_MALFORMED = 2 ARG_READ_ERROR = 3 @@ -12,6 +12,7 @@ class CompileRet(Enum): LAST_MALFORMED = 6 LABEL_OVERFLOW = 7 TYPE_ERROR = 8 + CLEARED_INSTRUCTION = 9 class CIns(Structure): _fields_ = [("opcode", c_int), @@ -25,17 +26,64 @@ def make_uchar_buf(s): buf = (c_ubyte * len(s))() buf[:] = s[:] return buf +def make_reader(s): + buf = make_uchar_buf(s) + return CReader(buf, len(s)) + +class CEnv(Structure): + _fields_ = [ + ("reg", POINTER(c_uint)), + ("reglen", c_size_t), + ("lab", POINTER(c_size_t)), + ("lablen", c_size_t), + ("stk", POINTER(c_uint)), + ("stkptr", c_size_t), + ("stklen", c_size_t), + ("prg", POINTER(CIns)), + ("prgptr", c_size_t), + ("prgend", c_size_t), + ("prglen", c_size_t) + ] + +class ExecutionEnvironment: + def __init__(self, reglen=32, lablen=32, stklen=4096, prglen=4096): + cenv = CEnv() + cenv.reglen = reglen + cenv.reg = (c_uint * reglen)() + + cenv.lablen = lablen + cenv.lab = (c_size_t * lablen)() + + cenv.stklen = stklen + cenv.stk = (c_uint * stklen)() + cenv.stkptr = 0 + + cenv.prglen = prglen + cenv.prg = (CIns * prglen)() + cenv.prgptr = 0 + cenv.prgend = 0 + + self.cenv = cenv + + def restart(self): + self.cenv.stkptr = 0 + self.cenv.prgptr = 0 + self.cenv.prgend = 0 + + def load(self, prog): + rd = make_reader(prog) + self.restart() + ret = dll.creole_compile(byref(self.cenv), byref(rd)) + return CompileRet(ret) class CParseLineException(Exception): pass def parse_line(line): - buf = make_uchar_buf(line) - - rd = CReader(buf, len(line)) + rd = make_reader(line) ins = CIns() ret = dll.creole_parse_line(byref(ins), byref(rd)) - if ret != 0: - raise CParseLineException(ret) + if ret != CompileRet.OK.value: + raise CParseLineException(CompileRet(ret).name) return (ins.opcode, list(zip(ins.w_flags, ins.w))) diff --git a/asm/test.py b/asm/test.py index b9d6520..06a878f 100644 --- a/asm/test.py +++ b/asm/test.py @@ -7,25 +7,25 @@ class PushTest(unittest.TestCase): p = Program() p.parse_asm_line("push r5") b = p() - self.assertEqual(b, b'\x01\xC2\x80\x00') + self.assertEqual(b, b'\x01\xC2\x85\x00') ins = ffi.parse_line(b) self.assertEqual(ins[0], instructions["push"].opcode) self.assertEqual(ins[1][0], (1,5)) - def test_parse_push_catch_typecheck_push_imm(self): + def test_parse_push_imm(self): p = Program() - with self.assertRaises(TypecheckException) as cm: - p.parse_asm_line("push 0") - self.assertEqual(cm.exception.argtype, ArgType.REG) - self.assertEqual(cm.exception.sarg, '0') - self.assertEqual(cm.exception.i, 0) - self.assertEqual(cm.exception.opcode, 1) + p.parse_asm_line("push 5") + 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[1][0], (0,5)) def test_parse_push_catch_typecheck_push_lab(self): p = Program() with self.assertRaises(TypecheckException) as cm: p.parse_asm_line("push l0") - self.assertEqual(cm.exception.argtype, ArgType.REG) + self.assertEqual(cm.exception.argtype, ArgType.VAL) self.assertEqual(cm.exception.sarg, 'l0') self.assertEqual(cm.exception.i, 0) self.assertEqual(cm.exception.opcode, 1) @@ -52,6 +52,32 @@ class PushTest(unittest.TestCase): b = p() self.assertEqual(b, b'\x01\xFC\x87\xbf\xbf\xbf\xbf\x00') + def test_compile_push(self): + p = Program() + p.parse_asm_line("PUSH r0") + p.parse_asm_line("PUSH r6") + b = p() + + ex = ffi.ExecutionEnvironment() + self.assertEqual(ex.load(b), ffi.CompileRet.OK) + self.assertEqual(ex.cenv.prgend, 2) + + self.assertEqual(ex.cenv.prg[0].opcode, 1) + self.assertEqual(ex.cenv.prg[0].w_flags[0], 1) + self.assertEqual(ex.cenv.prg[0].w_flags[1], 0) + self.assertEqual(ex.cenv.prg[0].w_flags[2], 0) + self.assertEqual(ex.cenv.prg[0].w[0], 0) + self.assertEqual(ex.cenv.prg[0].w[1], 0) + 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[1], 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[1], 0) + self.assertEqual(ex.cenv.prg[1].w[2], 0) + class ProgramTest(unittest.TestCase): def test_two(self): p = Program() |
