test refactoring
This commit is contained in:
parent
606814c4c0
commit
e044a7b457
|
@ -24,16 +24,32 @@ class ArgType(Enum):
|
||||||
def typecheck(self, s):
|
def typecheck(self, s):
|
||||||
t = ArgType.gettype(s)
|
t = ArgType.gettype(s)
|
||||||
if self == ArgType.VAL:
|
if self == ArgType.VAL:
|
||||||
return t[0] == ArgType.REG or t[0] == ArgType.IMM
|
if t[0] == ArgType.REG or t[0] == ArgType.IMM:
|
||||||
|
return t
|
||||||
else:
|
else:
|
||||||
return t[0] == self
|
return None
|
||||||
|
elif t[0] == self:
|
||||||
|
return t
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
class OpcodeException(Exception):
|
class OpcodeException(Exception):
|
||||||
pass
|
pass
|
||||||
class TypecheckLenException(Exception):
|
class TypecheckLenException(Exception):
|
||||||
pass
|
def __init__(self, opcode, insargs, argtypelen):
|
||||||
|
self.opcode = opcode
|
||||||
|
self.insargs = insargs
|
||||||
|
self.argtypelen = argtypelen
|
||||||
|
def __str__(self):
|
||||||
|
return f'arguments {insargs} to opcode {self.opcode} not length {self.argtypelen}'
|
||||||
class TypecheckException(Exception):
|
class TypecheckException(Exception):
|
||||||
pass
|
def __init__(self, argtype, sarg, i, opcode):
|
||||||
|
self.argtype = argtype
|
||||||
|
self.sarg = sarg
|
||||||
|
self.i = i
|
||||||
|
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:
|
class Instruction:
|
||||||
def __init__(self, opcode, argtypes):
|
def __init__(self, opcode, argtypes):
|
||||||
if opcode > 0x7F or opcode < 0:
|
if opcode > 0x7F or opcode < 0:
|
||||||
|
@ -44,12 +60,15 @@ class Instruction:
|
||||||
def typecheck(self, sargs):
|
def typecheck(self, sargs):
|
||||||
rargs = []
|
rargs = []
|
||||||
if len(sargs) != len(self.argtypes):
|
if len(sargs) != len(self.argtypes):
|
||||||
raise TypecheckLenException(sargs, self.argtypes)
|
raise TypecheckLenException(self.opcode, sargs,
|
||||||
|
len(self.argtypes))
|
||||||
for i in range(0, len(sargs)):
|
for i in range(0, len(sargs)):
|
||||||
if not self.argtypes[i].typecheck(sargs[i]):
|
t = self.argtypes[i].typecheck(sargs[i])
|
||||||
|
if t is None:
|
||||||
raise TypecheckException(self.argtypes[i],
|
raise TypecheckException(self.argtypes[i],
|
||||||
sargs[i])
|
sargs[i],
|
||||||
rargs.append(ArgType.gettype(sargs[i]))
|
i, self.opcode)
|
||||||
|
rargs.append(t)
|
||||||
return rargs
|
return rargs
|
||||||
|
|
||||||
instructions = {
|
instructions = {
|
||||||
|
|
12
asm/ffi.py
12
asm/ffi.py
|
@ -1,6 +1,18 @@
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
|
from enum import Enum
|
||||||
dll = CDLL("./libcreole.so")
|
dll = CDLL("./libcreole.so")
|
||||||
|
|
||||||
|
class CompileRet(Enum):
|
||||||
|
COMPILE_OK = 0
|
||||||
|
OPCODE_READ_ERROR = 1
|
||||||
|
OPCODE_MALFORMED = 2
|
||||||
|
ARG_READ_ERROR = 3
|
||||||
|
ARG_MALFORMED = 4
|
||||||
|
LAST_READ_ERROR = 5
|
||||||
|
LAST_MALFORMED = 6
|
||||||
|
LABEL_OVERFLOW = 7
|
||||||
|
TYPE_ERROR = 8
|
||||||
|
|
||||||
class CIns(Structure):
|
class CIns(Structure):
|
||||||
_fields_ = [("opcode", c_int),
|
_fields_ = [("opcode", c_int),
|
||||||
("w_flags", c_ubyte * 3),
|
("w_flags", c_ubyte * 3),
|
||||||
|
|
56
asm/test.py
56
asm/test.py
|
@ -2,17 +2,57 @@ from creole import *
|
||||||
import unittest
|
import unittest
|
||||||
import ffi
|
import ffi
|
||||||
|
|
||||||
class ProgramTest(unittest.TestCase):
|
class PushTest(unittest.TestCase):
|
||||||
def test_oneline(self):
|
def test_parse_push_reg(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("PUSH r0")
|
p.parse_asm_line("push r5")
|
||||||
b = p()
|
b = p()
|
||||||
self.assertEqual(b, b'\x01\xC2\x80\x00')
|
self.assertEqual(b, b'\x01\xC2\x80\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):
|
||||||
|
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)
|
||||||
|
|
||||||
|
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.sarg, 'l0')
|
||||||
|
self.assertEqual(cm.exception.i, 0)
|
||||||
|
self.assertEqual(cm.exception.opcode, 1)
|
||||||
|
|
||||||
|
def test_parse_push_catch_typecheck_argument_overflow(self):
|
||||||
|
p = Program()
|
||||||
|
with self.assertRaises(TypecheckLenException) as cm:
|
||||||
|
p.parse_asm_line("push r1 r2")
|
||||||
|
self.assertEqual(cm.exception.opcode, 1)
|
||||||
|
self.assertEqual(cm.exception.insargs, ["r1", "r2"])
|
||||||
|
self.assertEqual(cm.exception.argtypelen, 1)
|
||||||
|
|
||||||
|
def test_parse_push_catch_typecheck_argument_underflow(self):
|
||||||
|
p = Program()
|
||||||
|
with self.assertRaises(TypecheckLenException) as cm:
|
||||||
|
p.parse_asm_line("push")
|
||||||
|
self.assertEqual(cm.exception.opcode, 1)
|
||||||
|
self.assertEqual(cm.exception.insargs, [])
|
||||||
|
self.assertEqual(cm.exception.argtypelen, 1)
|
||||||
|
|
||||||
def test_large_reg(self):
|
def test_large_reg(self):
|
||||||
p = Program(regnum=0x8000000)
|
p = Program(regnum=0x8000000)
|
||||||
p.parse_asm_line("PUSH r134217727")
|
p.parse_asm_line("PUSH r134217727")
|
||||||
b = p()
|
b = p()
|
||||||
self.assertEqual(b, b'\x01\xFC\x87\xbf\xbf\xbf\xbf\x00')
|
self.assertEqual(b, b'\x01\xFC\x87\xbf\xbf\xbf\xbf\x00')
|
||||||
|
|
||||||
|
class ProgramTest(unittest.TestCase):
|
||||||
def test_two(self):
|
def test_two(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("PUSH r1")
|
p.parse_asm_line("PUSH r1")
|
||||||
|
@ -39,12 +79,14 @@ class ProgramTest(unittest.TestCase):
|
||||||
b = p()
|
b = p()
|
||||||
self.assertEqual(b, b_ex)
|
self.assertEqual(b, b_ex)
|
||||||
|
|
||||||
def test_parse_reg(self):
|
def test_parse_imm(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("push r5")
|
p.parse_asm_line("add r1 23 3648")
|
||||||
ins = ffi.parse_line(p())
|
ins = ffi.parse_line(p())
|
||||||
self.assertEqual(ins[0], instructions["push"].opcode)
|
self.assertEqual(ins[0], instructions["add"].opcode)
|
||||||
self.assertEqual(ins[1][0], (1,5))
|
self.assertEqual(ins[1][0], (1,1))
|
||||||
|
self.assertEqual(ins[1][1], (0,23))
|
||||||
|
self.assertEqual(ins[1][2], (0,3648))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue