aboutsummaryrefslogtreecommitdiffstats
path: root/asm/ffi.py
blob: 39d9800f5d70e3d35523049372d9a1d88cd18678 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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

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)

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)))