aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-09 16:16:41 +0000
committerGravatar Peter McGoron 2023-02-09 16:16:41 +0000
commitc0770d8ece675f5e6f2249b331c7550933915829 (patch)
tree49ed1779f0941a60ce2941c312d3f53f4ab81616
parenttest refactoring (diff)
add compile t est
Diffstat (limited to '')
-rw-r--r--Makefile2
-rw-r--r--asm/creole.py2
-rw-r--r--asm/ffi.py60
-rw-r--r--asm/test.py44
-rw-r--r--creole.c71
-rw-r--r--creole.h4
6 files changed, 133 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 343c3a4..80cbb1f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,8 @@ asm/libcreole.so: creole.c creole.h
$(CC) -Wall -fPIC -c creole.c -o c_test/creole.o
$(CC) -shared -o asm/libcreole.so c_test/creole.o
+test_asm: asm/libcreole.so
+ cd asm && python3 test.py
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
c_test/creole: c_test/creole.c creole.c creole.h greatest.h
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]),
diff --git a/asm/ffi.py b/asm/ffi.py
index 7468996..cb30ce9 100644
--- a/asm/ffi.py
+++ b/asm/ffi.py
@@ -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()
diff --git a/creole.c b/creole.c
index d2a06cb..78beaa0 100644
--- a/creole.c
+++ b/creole.c
@@ -342,27 +342,17 @@ creole_parse_line(struct creole_ins *ins, struct creole_reader *r)
return CREOLE_COMPILE_OK;
}
-#if 0
-
/**************************************************************************
* High level compiling interface
*************************************************************************/
-static void clear_instruction(struct creole_env *env,
- struct creole_ins *ins)
-{
- memset(ins, 0, sizeof(ins));
- env->prgptr--;
-}
-
static int typecheck(enum creole_word_flag fl, enum creole_arg_type typ)
{
switch (typ) {
- case TYPE_NONE: return 0;
case TYPE_IMM: return fl == CREOLE_IMMEDIATE;
case TYPE_REG: return fl == CREOLE_REGISTER;
case TYPE_VAL: return fl == CREOLE_IMMEDIATE
- | fl == CREOLE_REGISTER;
+ || fl == CREOLE_REGISTER;
case TYPE_LAB: return fl == CREOLE_IMMEDIATE;
default: return 0;
}
@@ -373,65 +363,78 @@ static enum creole_compiler_ret typecheck_ins(struct creole_env *env,
{
unsigned i;
- for (i = 0; i < opcode_info[env->opcode].arglen; i++) {
- if (!typecheck(ins->w[i],
- opcode_info[env->opcode].argtype[i]))
+ for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
+ if (!typecheck(ins->w_flags[i],
+ opcode_info[ins->opcode].argtype[i]))
return CREOLE_TYPE_ERROR;
}
return CREOLE_COMPILE_OK;
}
+static void clear_ins(struct creole_ins *i)
+{
+ i->opcode = 0;
+ i->w[0] = i->w[1] = i->w[2] = i->w_flags[0] =
+ i->w_flags[1] = i->w_flags[2] = 0;
+}
+
static enum creole_compiler_ret
handle_compiletime_immediate(struct creole_env *env,
- struct creole_ins *ins)
+ struct creole_ins *cur_ins)
{
- switch (ins->opcode) {
+ switch (cur_ins->opcode) {
case CREOLE_CLB:
- if (ins->w[0] >= ins->lablen)
+ if (cur_ins->w[0] >= env->lablen)
return CREOLE_LABEL_OVERFLOW;
- ins->lab[ins->w[0]] = env->prgptr;
+ env->lab[cur_ins->w[0]] = env->prgptr;
/* Delete instruction because it is a compile time
* instruction. Place next instruction in its place. */
- clear_instruction(env, ins);
- return CREOLE_COMPILE_OK;
+ clear_ins(cur_ins);
+ return CREOLE_COMPILE_CLEARED_INSTRUCTION;
case CREOLE_NOOP:
- clear_instruction(env, ins);
- return CREOLE_COMPILE_OK;
+ clear_ins(cur_ins);
+ return CREOLE_COMPILE_CLEARED_INSTRUCTION;
default:
- return typecheck_ins(env, ins);
+ return typecheck_ins(env, cur_ins);
}
}
-int creole_compile(struct creole_env *env, struct creole_reader *r)
+enum creole_compiler_ret
+creole_compile(struct creole_env *env, struct creole_reader *r)
{
struct creole_ins *cur_ins = env->prg;
int rcode;
while (env->prgptr < env->prglen) {
- if (!creole_parse_line(cur_ins, r))
- return CREOLE_PARSE_ERROR;
- /* Increase prgptr here. If the instruction is a compile
- * time instruction, then this will be decremented since
- * the instruction will not be executed.
- */
- env->prgptr++;
+ rcode = creole_parse_line(cur_ins, r);
+ if (rcode != CREOLE_COMPILE_OK)
+ return rcode;
rcode = handle_compiletime_immediate(env, cur_ins);
- if (rcode != CREOLE_COMPILE_OK)
+ switch (rcode) {
+ case CREOLE_COMPILE_CLEARED_INSTRUCTION:
+ break;
+ case CREOLE_COMPILE_OK:
+ cur_ins++;
+ env->prgptr++;
+ break;
+ default:
return rcode;
+ }
if (read_eof(r))
break;
- cur_ins += 1;
}
- if (env->prgptr == env->prglen && *line)
+ if (env->prgptr == env->prglen && !read_eof(r))
return CREOLE_PROGRAM_OVERFLOW;
env->prgend = env->prgptr;
env->prgptr = 0;
return CREOLE_COMPILE_OK;
}
+#if 0
+
static creole_word read_word(struct creole_ins *ins, int i)
{
if (env->w_flags[i] == CREOLE_REGISTER)
diff --git a/creole.h b/creole.h
index da6b662..827fe82 100644
--- a/creole.h
+++ b/creole.h
@@ -42,6 +42,8 @@ enum creole_compiler_ret {
CREOLE_LAST_MALFORMED,
CREOLE_LABEL_OVERFLOW,
CREOLE_TYPE_ERROR,
+ CREOLE_COMPILE_CLEARED_INSTRUCTION,
+ CREOLE_PROGRAM_OVERFLOW,
CREOLE_COMPILE_RET_LEN
};
@@ -74,5 +76,7 @@ int creole_encode(creole_word i, unsigned encode_to, unsigned high_bits,
unsigned char buf[7]);
enum creole_compiler_ret
creole_parse_line(struct creole_ins *ins, struct creole_reader *r);
+enum creole_compiler_ret
+creole_compile(struct creole_env *env, struct creole_reader *r);
#endif /* CREOLE_H */