115 lines
2.4 KiB
Python
115 lines
2.4 KiB
Python
from ctypes import *
|
|
from enum import Enum
|
|
dll = CDLL("./libcreole.so")
|
|
|
|
class CompileRet(Enum):
|
|
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
|
|
CLEARED_INSTRUCTION = 9
|
|
PROGRAM_OVERFLOW = 10
|
|
|
|
class RunRet(Enum):
|
|
CONTINUE = 0
|
|
SYSCALL = 1
|
|
STOP = 2
|
|
STACK_OVERFLOW = 3
|
|
STACK_UNDERFLOW = 4
|
|
RUN_LABEL_OVERFLOW = 5
|
|
REGISTER_OVERFLOW = 6
|
|
UNKNOWN_OPCODE = 7
|
|
|
|
def is_halt(self):
|
|
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):
|
|
_fields_ = [("p", POINTER(c_ubyte)),
|
|
("left", c_size_t)]
|
|
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 Environment:
|
|
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)
|
|
|
|
def syscall(self, sc):
|
|
pass
|
|
def __call__(self):
|
|
sc = c_size_t()
|
|
ret = RunRet.CONTINUE
|
|
while not ret.is_halt():
|
|
ret = RunRet(dll.creole_step(byref(self.cenv), byref(sc)))
|
|
if ret == RunRet.SYSCALL:
|
|
self.syscall(sc)
|
|
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)))
|