adjust python assembler to new API
This commit is contained in:
parent
83c568c8dd
commit
48827c5b74
2
Makefile
2
Makefile
|
@ -4,7 +4,7 @@ asm/libcreole.so: creole.c creole.h
|
||||||
$(CC) -shared -o asm/libcreole.so c_test/creole.o
|
$(CC) -shared -o asm/libcreole.so c_test/creole.o
|
||||||
|
|
||||||
test_asm: asm/libcreole.so
|
test_asm: asm/libcreole.so
|
||||||
cd asm && python3 test.py
|
cd asm && python3 test.py -f
|
||||||
c_test/encode_decode: c_test/encode_decode.c creole.c creole.h
|
c_test/encode_decode: c_test/encode_decode.c creole.c creole.h
|
||||||
$(CC) c_test/encode_decode.c -Wall -pedantic -std=c89 -g -fopenmp -o c_test/encode_decode
|
$(CC) c_test/encode_decode.c -Wall -pedantic -std=c89 -g -fopenmp -o c_test/encode_decode
|
||||||
# c_test/encode_decode
|
# c_test/encode_decode
|
||||||
|
|
|
@ -65,6 +65,24 @@ class Argument:
|
||||||
""" Returns the high bits that the argument would have
|
""" Returns the high bits that the argument would have
|
||||||
in the opcode. """
|
in the opcode. """
|
||||||
return int(self.sign) << 1 | (self.at == ArgType.REG)
|
return int(self.sign) << 1 | (self.at == ArgType.REG)
|
||||||
|
def __call__(self):
|
||||||
|
l = 2 if self.val < 0x80 else None
|
||||||
|
return encode_pseudo_utf8(self.val, self.high_bits(), l)
|
||||||
|
|
||||||
|
class StringArgument(Argument):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(self, *args, **kwargs)
|
||||||
|
def __bytes__(self):
|
||||||
|
b = bytes()
|
||||||
|
for v in self.val:
|
||||||
|
b = b + Argument(ArgType.IMM, v)()
|
||||||
|
return b
|
||||||
|
|
||||||
|
class LabelArgument(Argument):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(self, *args, **kwargs)
|
||||||
|
def load_label(self, labels):
|
||||||
|
self.val = labels[val]
|
||||||
|
|
||||||
class ArgType(Enum):
|
class ArgType(Enum):
|
||||||
""" Class denoting the type of an argument to an instruction. """
|
""" Class denoting the type of an argument to an instruction. """
|
||||||
|
@ -78,8 +96,17 @@ class ArgType(Enum):
|
||||||
VAL = 3
|
VAL = 3
|
||||||
""" Type that denotes either immediate values or registers. """
|
""" Type that denotes either immediate values or registers. """
|
||||||
|
|
||||||
LAB = 4
|
DAT = 4
|
||||||
""" Type of labels. """
|
""" Type of data label. """
|
||||||
|
|
||||||
|
STR = 5
|
||||||
|
""" Type of a string of 32 bit integers. """
|
||||||
|
|
||||||
|
LAB = 6
|
||||||
|
""" Type of a label (.name). """
|
||||||
|
|
||||||
|
def is_number(t):
|
||||||
|
return t == ArgType.IMM or t == ArgType.REG
|
||||||
|
|
||||||
def gettype(s):
|
def gettype(s):
|
||||||
""" Parses the type of the argument represented as a string
|
""" Parses the type of the argument represented as a string
|
||||||
|
@ -97,14 +124,18 @@ class ArgType(Enum):
|
||||||
:return: The Argument object representing the argument.
|
:return: The Argument object representing the argument.
|
||||||
:raises MalformedArgument:
|
:raises MalformedArgument:
|
||||||
"""
|
"""
|
||||||
if s.isnumeric():
|
if type(s) is list:
|
||||||
|
return StringArgument(ArgType.STR, s)
|
||||||
|
elif s.isnumeric():
|
||||||
return Argument(ArgType.IMM, int(s))
|
return Argument(ArgType.IMM, int(s))
|
||||||
elif s[0] == "-" and s[1:].isnumeric():
|
elif s[0] == "-" and s[1:].isnumeric():
|
||||||
return Argument(ArgType.IMM, word_2c(int(s[1:])), True)
|
return Argument(ArgType.IMM, word_2c(int(s[1:])), True)
|
||||||
elif s[0] == 'r' and s[1:].isnumeric():
|
elif s[0] == 'r' and s[1:].isnumeric():
|
||||||
return Argument(ArgType.REG, int(s[1:]))
|
return Argument(ArgType.REG, int(s[1:]))
|
||||||
elif s[0] == 'l' and s[1:].isnumeric():
|
elif s[0] == 'd' and s[1:].isnumeric():
|
||||||
return Argument(ArgType.LAB, int(s[1:]))
|
return Argument(ArgType.DAT, int(s[1:]))
|
||||||
|
elif s[0] == '.':
|
||||||
|
return Argument(ArgType.LAB, s[1:])
|
||||||
else:
|
else:
|
||||||
raise MalformedArgument(s)
|
raise MalformedArgument(s)
|
||||||
|
|
||||||
|
@ -168,14 +199,14 @@ class Instruction(Enum):
|
||||||
DIV = 5, "_render_default", ArgType.REG, ArgType.VAL, ArgType.VAL
|
DIV = 5, "_render_default", ArgType.REG, ArgType.VAL, ArgType.VAL
|
||||||
SDIV = "DIV", "_render_change_args", ArgType.REG, ArgType.VAL, ArgType.VAL
|
SDIV = "DIV", "_render_change_args", ArgType.REG, ArgType.VAL, ArgType.VAL
|
||||||
SYS = 6, "_render_default", ArgType.VAL
|
SYS = 6, "_render_default", ArgType.VAL
|
||||||
CLB = 7, "_render_default", ArgType.LAB
|
JL = 7, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
JL = 8, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
|
||||||
JLS = "JL", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
JLS = "JL", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
JLE = 9, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
JLE = 8, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
JLES = "JLE", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
JLES = "JLE", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
JE = 10, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
JE = 9, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
J = "JE", "_render_j", ArgType.LAB
|
J = "JE", "_render_j", ArgType.LAB
|
||||||
JNE = 11, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
JNE = 10, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
|
||||||
|
DB = 11, "_render_default", ArgType.DAT, ArgType.STR
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
""" Returns the opcode associated with the Instruction.
|
""" Returns the opcode associated with the Instruction.
|
||||||
|
@ -244,16 +275,14 @@ class Instruction(Enum):
|
||||||
|
|
||||||
def _render_change_args(self, args):
|
def _render_change_args(self, args):
|
||||||
for i in range(0,len(args)):
|
for i in range(0,len(args)):
|
||||||
if args[i].at != ArgType.LAB:
|
if ArgType.is_number(args[i].at):
|
||||||
args[i].sign = True
|
args[i].sign = True
|
||||||
return Instruction[self.opcode].render(args)
|
return Instruction[self.opcode].render(args)
|
||||||
|
|
||||||
def _render_default(self, args):
|
def _render_default(self, args):
|
||||||
b = bytes([self.opcode])
|
b = bytes([self.opcode])
|
||||||
for a in args:
|
for a in args:
|
||||||
l = 2 if a.val < 0x80 else None
|
b = b + a()
|
||||||
bex = encode_pseudo_utf8(a.val, a.high_bits(), l)
|
|
||||||
b = b + bex
|
|
||||||
return b + bytes([0])
|
return b + bytes([0])
|
||||||
|
|
||||||
encoding_types = {
|
encoding_types = {
|
||||||
|
@ -314,12 +343,11 @@ class Line:
|
||||||
raise RangeCheckException(a.at,
|
raise RangeCheckException(a.at,
|
||||||
a.val,
|
a.val,
|
||||||
reglen)
|
reglen)
|
||||||
elif a.at == ArgType.LAB:
|
|
||||||
if a.val < 0 or a.val >= lablen:
|
|
||||||
raise RangeCheckException(a.at,
|
|
||||||
a.val,
|
|
||||||
reglen)
|
|
||||||
|
|
||||||
|
def load_label(self, labels):
|
||||||
|
for a in self.args:
|
||||||
|
if a.at == ArgType.LAB:
|
||||||
|
a.load_label(labels)
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
return self.ins.render(self.args)
|
return self.ins.render(self.args)
|
||||||
|
|
||||||
|
@ -332,10 +360,13 @@ class Program:
|
||||||
self.asm.append(l)
|
self.asm.append(l)
|
||||||
|
|
||||||
def parse_asm_line(self, line):
|
def parse_asm_line(self, line):
|
||||||
line = line.split()
|
line = line.strip().split()
|
||||||
line[0] = line[0].casefold()
|
line[0] = line[0].casefold()
|
||||||
|
if line[0][0] == '.':
|
||||||
|
self.asm.append(line[0][1:])
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# TODO: is there no better way to do this in Python?
|
|
||||||
ins = Instruction[line[0].upper()]
|
ins = Instruction[line[0].upper()]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise InstructionNotFoundException(line[0])
|
raise InstructionNotFoundException(line[0])
|
||||||
|
@ -349,7 +380,12 @@ class Program:
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
b = bytes()
|
b = bytes()
|
||||||
|
labels = {}
|
||||||
for line in self.asm:
|
for line in self.asm:
|
||||||
|
if type(line) is str:
|
||||||
|
labels[line] = len(b)
|
||||||
|
continue
|
||||||
|
line.load_label(labels)
|
||||||
b = b + line()
|
b = b + line()
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
|
77
asm/ffi.py
77
asm/ffi.py
|
@ -24,10 +24,9 @@ class CompileRet(Enum):
|
||||||
ARG_MALFORMED = 4
|
ARG_MALFORMED = 4
|
||||||
LAST_READ_ERROR = 5
|
LAST_READ_ERROR = 5
|
||||||
LAST_MALFORMED = 6
|
LAST_MALFORMED = 6
|
||||||
LABEL_OVERFLOW = 7
|
DATA_OVERFLOW = 7
|
||||||
TYPE_ERROR = 8
|
TYPE_ERROR = 8
|
||||||
CLEARED_INSTRUCTION = 9
|
PROGRAM_OVERFLOW = 9
|
||||||
PROGRAM_OVERFLOW = 10
|
|
||||||
|
|
||||||
class RunRet(Enum):
|
class RunRet(Enum):
|
||||||
CONTINUE = 0
|
CONTINUE = 0
|
||||||
|
@ -35,44 +34,36 @@ class RunRet(Enum):
|
||||||
STOP = 2
|
STOP = 2
|
||||||
STACK_OVERFLOW = 3
|
STACK_OVERFLOW = 3
|
||||||
STACK_UNDERFLOW = 4
|
STACK_UNDERFLOW = 4
|
||||||
LABEL_OVERFLOW = 5
|
DECODE_ERROR = 5
|
||||||
REGISTER_OVERFLOW = 6
|
REGISTER_OVERFLOW = 6
|
||||||
UNKNOWN_OPCODE = 7
|
UNKNOWN_OPCODE = 7
|
||||||
DIVIDE_BY_ZERO = 8
|
DIVIDE_BY_ZERO = 8
|
||||||
HIGH_BIT_MALFORMED = 9
|
HIGH_BIT_MALFORMED = 9
|
||||||
|
JUMP_OVERFLOW = 10
|
||||||
|
|
||||||
def is_halt(self):
|
def is_halt(self):
|
||||||
return not (self == RunRet.CONTINUE or self == RunRet.SYSCALL)
|
return not (self == RunRet.CONTINUE or self == RunRet.SYSCALL)
|
||||||
|
|
||||||
class CIns(Structure):
|
|
||||||
_fields_ = [("opcode", c_int),
|
|
||||||
("w_flags", c_ubyte * 3),
|
|
||||||
("w", c_uint * 3)]
|
|
||||||
|
|
||||||
class CReader(Structure):
|
class CReader(Structure):
|
||||||
_fields_ = [("p", POINTER(c_ubyte)),
|
_fields_ = [("p", POINTER(c_ubyte)),
|
||||||
("left", c_size_t)]
|
("left", c_size_t)]
|
||||||
def make_uchar_buf(s):
|
class Reader:
|
||||||
buf = (c_ubyte * len(s))()
|
def __init__(self, s):
|
||||||
buf[:] = s[:]
|
self.buf = (c_ubyte * len(s))()
|
||||||
return buf
|
self.buf[:] = s[:]
|
||||||
def make_reader(s):
|
self.rd = CReader(self.buf, len(s))
|
||||||
buf = make_uchar_buf(s)
|
|
||||||
return CReader(buf, len(s))
|
|
||||||
|
|
||||||
class CEnv(Structure):
|
class CEnv(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
|
("dats", POINTER(POINTER(c_ubyte))),
|
||||||
|
("datlen", c_size_t),
|
||||||
("reg", POINTER(c_uint)),
|
("reg", POINTER(c_uint)),
|
||||||
("reglen", c_size_t),
|
("reglen", c_size_t),
|
||||||
("lab", POINTER(c_size_t)),
|
|
||||||
("lablen", c_size_t),
|
|
||||||
("stk", POINTER(c_uint)),
|
("stk", POINTER(c_uint)),
|
||||||
("stkptr", c_size_t),
|
("stkptr", c_size_t),
|
||||||
("stklen", c_size_t),
|
("stklen", c_size_t),
|
||||||
("prg", POINTER(CIns)),
|
("r_current", CReader),
|
||||||
("prgptr", c_size_t),
|
("r_start", CReader)
|
||||||
("prgend", c_size_t),
|
|
||||||
("prglen", c_size_t)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
class RegisterOverflowError(Exception):
|
class RegisterOverflowError(Exception):
|
||||||
|
@ -122,38 +113,34 @@ class Environment:
|
||||||
stk = stk - 1
|
stk = stk - 1
|
||||||
return self.cenv.stk[stk]
|
return self.cenv.stk[stk]
|
||||||
|
|
||||||
def __init__(self, prog=None, reglen=32, lablen=32, stklen=4096, prglen=4096):
|
def reset(self):
|
||||||
|
self.cenv.r_current = self.cenv.r_start
|
||||||
|
|
||||||
|
def __init__(self, prog=None, reglen=32, datlen=32, stklen=4096, prglen=4096):
|
||||||
cenv = CEnv()
|
cenv = CEnv()
|
||||||
|
cenv.dats = (POINTER(c_ubyte) * datlen)()
|
||||||
|
cenv.datlen = datlen
|
||||||
|
|
||||||
cenv.reglen = reglen
|
cenv.reglen = reglen
|
||||||
cenv.reg = (c_uint * reglen)()
|
cenv.reg = (c_uint * reglen)()
|
||||||
|
|
||||||
cenv.lablen = lablen
|
|
||||||
cenv.lab = (c_size_t * lablen)()
|
|
||||||
|
|
||||||
cenv.stklen = stklen
|
cenv.stklen = stklen
|
||||||
cenv.stk = (c_uint * stklen)()
|
cenv.stk = (c_uint * stklen)()
|
||||||
cenv.stkptr = 0
|
cenv.stkptr = 0
|
||||||
|
|
||||||
cenv.prglen = prglen
|
|
||||||
cenv.prg = (CIns * prglen)()
|
|
||||||
cenv.prgptr = 0
|
|
||||||
cenv.prgend = 0
|
|
||||||
|
|
||||||
self.cenv = cenv
|
self.cenv = cenv
|
||||||
if prog is not None:
|
if prog is not None:
|
||||||
|
if type(prog) is creole.Program:
|
||||||
|
prog = prog()
|
||||||
r = self.load(prog)
|
r = self.load(prog)
|
||||||
if r is not CompileRet.OK:
|
if r is not CompileRet.OK:
|
||||||
raise CompileError(r)
|
raise CompileError(r)
|
||||||
|
|
||||||
def restart(self):
|
|
||||||
self.cenv.stkptr = 0
|
|
||||||
self.cenv.prgptr = 0
|
|
||||||
self.cenv.prgend = 0
|
|
||||||
|
|
||||||
def load(self, prog):
|
def load(self, prog):
|
||||||
rd = make_reader(prog)
|
self.reader = Reader(prog)
|
||||||
self.restart()
|
self.cenv.r_current = self.reader.rd
|
||||||
ret = dll.creole_compile(byref(self.cenv), byref(rd))
|
self.cenv.r_start = self.cenv.r_current
|
||||||
|
ret = dll.creole_compile(byref(self.cenv), byref(self.cenv.r_current))
|
||||||
return CompileRet(ret)
|
return CompileRet(ret)
|
||||||
|
|
||||||
def syscall(self, sc):
|
def syscall(self, sc):
|
||||||
|
@ -168,15 +155,3 @@ class Environment:
|
||||||
if debug:
|
if debug:
|
||||||
print(self.cenv.reg[0])
|
print(self.cenv.reg[0])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
class CParseLineException(Exception):
|
|
||||||
pass
|
|
||||||
def parse_line(line):
|
|
||||||
rd = make_reader(line)
|
|
||||||
ins = CIns()
|
|
||||||
|
|
||||||
ret = dll.creole_parse_line(byref(ins), byref(rd))
|
|
||||||
|
|
||||||
if ret != CompileRet.OK.value:
|
|
||||||
raise CParseLineException(CompileRet(ret).name)
|
|
||||||
return (ins.opcode, list(zip(ins.w_flags, ins.w)))
|
|
||||||
|
|
27
asm/test.py
27
asm/test.py
|
@ -19,20 +19,13 @@ class PushTest(unittest.TestCase):
|
||||||
def test_parse_push_reg(self):
|
def test_parse_push_reg(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("push r5")
|
p.parse_asm_line("push r5")
|
||||||
b = p()
|
self.assertEqual(p(), b'\x01\xC2\x85\x00')
|
||||||
self.assertEqual(b, b'\x01\xC2\x85\x00')
|
|
||||||
ins = ffi.parse_line(b)
|
|
||||||
self.assertEqual(ins[0], Instruction.PUSH.opcode)
|
|
||||||
self.assertEqual(ins[1][0], (1,5))
|
|
||||||
|
|
||||||
def test_parse_push_imm(self):
|
def test_parse_push_imm(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("push 5")
|
p.parse_asm_line("push 5")
|
||||||
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)
|
|
||||||
self.assertEqual(ins[0], Instruction.PUSH.opcode)
|
|
||||||
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):
|
||||||
p = Program()
|
p = Program()
|
||||||
|
@ -175,7 +168,7 @@ class AddTest(unittest.TestCase):
|
||||||
def test_exec_add(self):
|
def test_exec_add(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
p.parse_asm_line("add r0 1 1")
|
p.parse_asm_line("add r0 1 1")
|
||||||
ex = ffi.Environment(p())
|
ex = ffi.Environment(p)
|
||||||
self.assertEqual(ex(), ffi.RunRet.STOP)
|
self.assertEqual(ex(), ffi.RunRet.STOP)
|
||||||
self.assertEqual(ex.cenv.reg[0], 2)
|
self.assertEqual(ex.cenv.reg[0], 2)
|
||||||
|
|
||||||
|
@ -201,18 +194,18 @@ class AddTest(unittest.TestCase):
|
||||||
def test_exec_add_throw_lab_1(self):
|
def test_exec_add_throw_lab_1(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
with self.assertRaises(TypecheckException) as cm:
|
with self.assertRaises(TypecheckException) as cm:
|
||||||
p.parse_asm_line("add r0 l6 7")
|
p.parse_asm_line("add r0 .label 7")
|
||||||
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
||||||
self.assertEqual(cm.exception.sarg, 'l6')
|
self.assertEqual(cm.exception.sarg, '.label')
|
||||||
self.assertEqual(cm.exception.i, 1)
|
self.assertEqual(cm.exception.i, 1)
|
||||||
self.assertEqual(cm.exception.opcode, 3)
|
self.assertEqual(cm.exception.opcode, 3)
|
||||||
|
|
||||||
def test_exec_add_throw_lab_2(self):
|
def test_exec_add_throw_lab_2(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
with self.assertRaises(TypecheckException) as cm:
|
with self.assertRaises(TypecheckException) as cm:
|
||||||
p.parse_asm_line("add r0 12 l24")
|
p.parse_asm_line("add r0 12 .ab")
|
||||||
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
||||||
self.assertEqual(cm.exception.sarg, 'l24')
|
self.assertEqual(cm.exception.sarg, '.ab')
|
||||||
self.assertEqual(cm.exception.i, 2)
|
self.assertEqual(cm.exception.i, 2)
|
||||||
self.assertEqual(cm.exception.opcode, 3)
|
self.assertEqual(cm.exception.opcode, 3)
|
||||||
|
|
||||||
|
@ -307,18 +300,18 @@ class DivTest(unittest.TestCase):
|
||||||
def test_exec_div_throw_lab_1(self):
|
def test_exec_div_throw_lab_1(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
with self.assertRaises(TypecheckException) as cm:
|
with self.assertRaises(TypecheckException) as cm:
|
||||||
p.parse_asm_line("div r0 l123 456")
|
p.parse_asm_line("div r0 .qqweq 456")
|
||||||
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
||||||
self.assertEqual(cm.exception.sarg, 'l123')
|
self.assertEqual(cm.exception.sarg, '.qqweq')
|
||||||
self.assertEqual(cm.exception.i, 1)
|
self.assertEqual(cm.exception.i, 1)
|
||||||
self.assertEqual(cm.exception.opcode, 5)
|
self.assertEqual(cm.exception.opcode, 5)
|
||||||
|
|
||||||
def test_exec_div_throw_lab_2(self):
|
def test_exec_div_throw_lab_2(self):
|
||||||
p = Program()
|
p = Program()
|
||||||
with self.assertRaises(TypecheckException) as cm:
|
with self.assertRaises(TypecheckException) as cm:
|
||||||
p.parse_asm_line("div r5 1919 l24")
|
p.parse_asm_line("div r5 1919 .24")
|
||||||
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
self.assertEqual(cm.exception.argtype, ArgType.VAL)
|
||||||
self.assertEqual(cm.exception.sarg, 'l24')
|
self.assertEqual(cm.exception.sarg, '.24')
|
||||||
self.assertEqual(cm.exception.i, 2)
|
self.assertEqual(cm.exception.i, 2)
|
||||||
self.assertEqual(cm.exception.opcode, 5)
|
self.assertEqual(cm.exception.opcode, 5)
|
||||||
|
|
||||||
|
|
3
creole.c
3
creole.c
|
@ -380,7 +380,7 @@ parse_line(struct creole_env *env, struct ins *ins, struct creole_reader *r)
|
||||||
return CREOLE_OPCODE_MALFORMED;
|
return CREOLE_OPCODE_MALFORMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode_info[ins->opcode].arglen >= CREOLE_MAX_ARG)
|
if (opcode_info[ins->opcode].arglen > CREOLE_MAX_ARG)
|
||||||
return CREOLE_OPCODE_MALFORMED;
|
return CREOLE_OPCODE_MALFORMED;
|
||||||
for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
|
for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
|
||||||
if (!decode_seq(r, &w))
|
if (!decode_seq(r, &w))
|
||||||
|
@ -446,6 +446,7 @@ creole_compile(struct creole_env *env)
|
||||||
add_to_env(env, &ins);
|
add_to_env(env, &ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->r_current = env->r_start;
|
||||||
return CREOLE_COMPILE_OK;
|
return CREOLE_COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
creole.h
2
creole.h
|
@ -65,7 +65,6 @@ enum creole_compiler_ret {
|
||||||
CREOLE_LAST_MALFORMED,
|
CREOLE_LAST_MALFORMED,
|
||||||
CREOLE_DATA_OVERFLOW,
|
CREOLE_DATA_OVERFLOW,
|
||||||
CREOLE_TYPE_ERROR,
|
CREOLE_TYPE_ERROR,
|
||||||
CREOLE_COMPILE_CLEARED_INSTRUCTION,
|
|
||||||
CREOLE_PROGRAM_OVERFLOW,
|
CREOLE_PROGRAM_OVERFLOW,
|
||||||
CREOLE_COMPILE_RET_LEN
|
CREOLE_COMPILE_RET_LEN
|
||||||
};
|
};
|
||||||
|
@ -114,6 +113,7 @@ enum creole_run_ret creole_reg_read(struct creole_env *env, unsigned reg,
|
||||||
creole_word *w);
|
creole_word *w);
|
||||||
enum creole_run_ret creole_push(struct creole_env *env, creole_word w);
|
enum creole_run_ret creole_push(struct creole_env *env, creole_word w);
|
||||||
enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w);
|
enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w);
|
||||||
|
int creole_jump(struct creole_env *env, creole_word off);
|
||||||
enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc);
|
enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc);
|
||||||
|
|
||||||
#endif /* CREOLE_H */
|
#endif /* CREOLE_H */
|
||||||
|
|
Loading…
Reference in New Issue