Compare commits
No commits in common. "c_turmit" and "master" have entirely different histories.
13 changed files with 30 additions and 1678 deletions
9
Makefile
9
Makefile
|
|
@ -1,9 +0,0 @@
|
|||
all: libs
|
||||
|
||||
libs:
|
||||
make -C libs
|
||||
|
||||
.PHONY: libs clean
|
||||
|
||||
clean:
|
||||
make -C libs clean
|
||||
3
gte.sh
3
gte.sh
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
PYTHONPATH=":`pwd`/libs" /usr/bin/env python3 -m gte "$@"
|
||||
|
|
@ -16,22 +16,18 @@ logger = logging.getLogger()
|
|||
logger.debug('Logger started')
|
||||
|
||||
from . import turmit, rpnlib
|
||||
#from .turmit import Turmit
|
||||
from cturmit import CTurmit as Turmit
|
||||
from .turmit import Turmit
|
||||
from .world import World, LivingTurmit, eval_prog
|
||||
from .mutator import mutate
|
||||
|
||||
parser = argparse.ArgumentParser(description='Genetic Turmit Evolver')
|
||||
|
||||
parser.add_argument('-L', '--list-op', action="store_const", default=False,
|
||||
const=True, help="List operations and exit")
|
||||
|
||||
subparsers = parser.add_subparsers(help='sub-commands help')
|
||||
|
||||
parser_evolve = subparsers.add_parser('evolve', help='evolving help')
|
||||
|
||||
parser_evolve.add_argument('--steps', '-s', type=int, metavar='N',
|
||||
default=None, help="Number of steps")
|
||||
default=30000, help="Number of steps")
|
||||
|
||||
parser_evolve.add_argument('--repeat-eval', '-R', type=int, metavar='N',
|
||||
default=5)
|
||||
|
|
@ -113,26 +109,10 @@ parser_gen.add_argument('--no-diagonals', '-d', action='store_const',
|
|||
parser_gen.add_argument('--threads', '-t', type=int, metavar='N',
|
||||
default=os.cpu_count()-1,
|
||||
help="Animation writting threads")
|
||||
parser_gen.add_argument('--buffer-min', '-b', type=int, metavar='N',
|
||||
default=10,
|
||||
help="Start populating animation buffer when this \
|
||||
amount of images are in the buffer")
|
||||
parser_gen.add_argument('--buffer-max', '-B', type=int, metavar='N',
|
||||
default=100,
|
||||
help="Start a buffer flush when this amount of images \
|
||||
are in the buffer")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list_op:
|
||||
from . import rpnlib
|
||||
print("Operations list & aliases :")
|
||||
for i, opname in enumerate(rpnlib._op_list):
|
||||
alias = rpnlib._op_alias[opname] if opname in rpnlib._op_alias else ""
|
||||
print("\t%02X: %8s\t%s" % (i, opname, alias))
|
||||
exit(0)
|
||||
|
||||
elif 'pool_size' in args:
|
||||
if 'pool_size' in args:
|
||||
# Evolver
|
||||
if args.prog is None:
|
||||
prog = rpnlib.RpnExpr.random(args.prog_size)
|
||||
|
|
@ -204,8 +184,10 @@ elif 'pool_size' in args:
|
|||
# Displaying eval results
|
||||
logger.info('Generation evaluating ended in %.2fs' % (genstop - genstart))
|
||||
|
||||
scores = sorted(scores, key=lambda x: x[0], reverse=True)
|
||||
|
||||
if args.target is None:
|
||||
scores = sorted(scores, key=lambda x: x[0], reverse=True)
|
||||
else:
|
||||
scores = sorted(scores, key=lambda x: abs(x[0] - args.target),)
|
||||
for i, (score, prog, sinfo) in enumerate(scores):
|
||||
logger.info('P%d %.3f:(D:%.3f,F:%.3f) : "%s"' % (i, score,
|
||||
sinfo['D'],
|
||||
|
|
@ -242,7 +224,7 @@ elif 'pool_size' in args:
|
|||
logger.debug('P%d : %s' % (pid, str(prog)))
|
||||
generation += 1
|
||||
exit(0)
|
||||
elif 'output_dir' in args:
|
||||
else:
|
||||
# Generate
|
||||
if args.output_dir is not None:
|
||||
from PIL import Image
|
||||
|
|
@ -251,12 +233,10 @@ elif 'output_dir' in args:
|
|||
im.save(fname)
|
||||
logger.debug('Image %s saved in %.3fs' % (fname,
|
||||
time.time() - st1))
|
||||
del(im)
|
||||
|
||||
write_pool = Pool(args.threads)
|
||||
async_res = []
|
||||
img_count = 0
|
||||
img_total = args.steps if args.anim_div <=1 else args.steps / (args.anim_div - 1)
|
||||
w = World(args.world_height, args.world_width, gray=args.gray)
|
||||
prog = rpnlib.RpnExpr.from_string(args.prog)
|
||||
turmits = [LivingTurmit(world=w, prog=prog, diag=not args.no_diagonals)
|
||||
|
|
@ -266,7 +246,7 @@ elif 'output_dir' in args:
|
|||
start = time.time()
|
||||
for step in range(args.steps):
|
||||
if step % 512 == 1:
|
||||
msg = 'Step %d/%d avg: %dus/step fractdim=%.3f'
|
||||
msg = 'Step %d/%d %dus/step fractdim=%.3f'
|
||||
msg %= (step, args.steps,
|
||||
((time.time() - start)*1000000)//step//len(turmits),
|
||||
w.fractdim())
|
||||
|
|
@ -281,23 +261,14 @@ elif 'output_dir' in args:
|
|||
fname = os.path.join(args.output_dir, fname)
|
||||
im = Image.fromarray(np.uint8(w._val))
|
||||
async_res.append(write_pool.apply_async(save_pool, (im, fname)))
|
||||
if len(async_res) > args.buffer_max:
|
||||
logger.debug('Flushing animation on disk to empty RAM')
|
||||
while len(async_res) > args.buffer_min:
|
||||
while async_res[0].ready():
|
||||
async_res[0].get()
|
||||
async_res.pop(0)
|
||||
msg = '%d/%d images written at avg %.0f img/s ETL : %ds'
|
||||
img_prog = img_count - args.buffer_min
|
||||
img_pers = img_prog/((time.time() - start))
|
||||
etl = (img_total - img_prog) // img_pers
|
||||
msg %= (img_prog, img_total, img_pers, etl)
|
||||
logger.info(msg)
|
||||
while async_res[0].ready():
|
||||
async_res[0].get()
|
||||
async_res.pop(0)
|
||||
|
||||
if args.output_dir is not None:
|
||||
while len(async_res) and async_res[0].ready():
|
||||
while async_res[0].ready():
|
||||
async_res[0].get()
|
||||
async_res.pop(0)
|
||||
sync_res.pop(0)
|
||||
write_pool.close()
|
||||
logger.info('Waiting for animation to be written on disk')
|
||||
img_st1 = None
|
||||
|
|
@ -347,8 +318,5 @@ elif 'output_dir' in args:
|
|||
|
||||
w.save(args.output)
|
||||
logger.info('Image saved in %s' % args.output)
|
||||
else:
|
||||
parser.print_help()
|
||||
exit(1)
|
||||
|
||||
exit(0)
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ class Turmit(object):
|
|||
# @note This limit is handled by @ref rpnlib.RpnOp()
|
||||
self._signed_int = True
|
||||
|
||||
self._stack_max = 0xFFF
|
||||
|
||||
if 'max_int' in kwargs:
|
||||
v = kwargs['max_int']
|
||||
if v < 1:
|
||||
|
|
@ -275,7 +273,7 @@ class Turmit(object):
|
|||
'''
|
||||
|
||||
stksz = len(self._stack)
|
||||
new_sz %= self._stack_max
|
||||
new_sz %= 0xFFF
|
||||
if new_sz < 2:
|
||||
new_sz = 2
|
||||
if new_sz > stksz:
|
||||
|
|
@ -426,11 +424,11 @@ class Turmit(object):
|
|||
Condition type is encoded on an int :
|
||||
- 0b0000 : je
|
||||
- 0b0001 : jne
|
||||
- 0b0010 : jl
|
||||
- 0b0011 : jle
|
||||
- 0b0010 : jle
|
||||
- 0b0011 : jl
|
||||
- 0b0100 : jg
|
||||
- 0b0101 : jge
|
||||
- 0b0110 : jmp
|
||||
- 0b0110 : jne
|
||||
- 0b0111 : jmp
|
||||
|
||||
@param a int : operand
|
||||
|
|
|
|||
65
gte/world.py
65
gte/world.py
|
|
@ -12,8 +12,7 @@ import time
|
|||
import numpy as np
|
||||
from random import randint
|
||||
|
||||
#from .turmit import Turmit
|
||||
from cturmit import CTurmit as Turmit
|
||||
from .turmit import Turmit
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
|
@ -26,8 +25,7 @@ def eval_prog(args):
|
|||
w = World(args.world_height, args.world_width, gray=True)
|
||||
logger.debug('Running P%d run#%d %s' % (progid, trynum, prog))
|
||||
w.raz()
|
||||
base = LivingTurmit(world=w, prog=prog, diag=not args.no_diagonals)
|
||||
turmits = [ LivingTurmit(world=w, turmit=base)
|
||||
turmits = [LivingTurmit(world=w, prog=prog, diag=not args.no_diagonals)
|
||||
for _ in range(args.turmit_count)]
|
||||
|
||||
start = time.time()
|
||||
|
|
@ -35,49 +33,24 @@ def eval_prog(args):
|
|||
steps = args.steps
|
||||
else:
|
||||
steps = args.steps - int((args.steps / 1.5) // (args.repeat_eval - trynum))
|
||||
|
||||
if not steps: # 0 or None
|
||||
pfdim = 0
|
||||
dfdim = 1
|
||||
steps = 0
|
||||
lim_reach = 0
|
||||
retry_lim = 0
|
||||
while lim_reach < 2 and steps < 0x40000:
|
||||
for _ in range(3000):
|
||||
for turmit in turmits:
|
||||
turmit()
|
||||
steps += 0x1000
|
||||
cfdim = w.fractdim() # delta fdim on not targeted dim
|
||||
dfdim = cfdim - pfdim
|
||||
pfdim = cfdim
|
||||
if abs(dfdim) < 0.001:
|
||||
lim_reach += 1
|
||||
else:
|
||||
retry_lim += 1
|
||||
if retry_lim < 3:
|
||||
lim_reach = 0
|
||||
else:
|
||||
for step in range(steps):
|
||||
for turmit in turmits:
|
||||
turmit()
|
||||
for step in range(steps):
|
||||
for turmit in turmits:
|
||||
turmit()
|
||||
stop = time.time()
|
||||
|
||||
score_dir = sum([t.dirvar() for t in turmits]) / len(turmits)
|
||||
score_deter = sum([t.determinist() for t in turmits]) / len(turmits)
|
||||
score_fract, raw_fract = w.fractdim_target(args.target)
|
||||
score_fract = w.fractdim()
|
||||
score = (score_dir * score_fract) * (score_deter * 0.2 + 0.8)
|
||||
sinfo = {'F':score_fract, 'D':score_dir}
|
||||
#score = sum([score_fract] + [score_dir] * 4) / 5
|
||||
if not args.quiet:
|
||||
tall = time.time() - startall
|
||||
msg = 'G%d P%d R%d: %d steps scores %.3f:(D:%.3f,F:%.3f,'
|
||||
msg = 'G%d P%d R%d: %d steps scores %.3f:(D:%.3f,F:%.3f,Dtr:%.3f) in %.3fs (%dus per step)\t%s'
|
||||
msg %= (generation, progid, trynum, steps, score, score_dir,
|
||||
score_fract)
|
||||
if args.target:
|
||||
msg += 'RawF:%.3f,' % raw_fract
|
||||
msg += 'Dtr:%.3f) in %.3fs (%dus per step)\t%s'
|
||||
msg %= (score_deter, tall,
|
||||
((stop - start)*1000000)//steps//len(turmits), str(prog))
|
||||
score_fract, score_deter, tall,
|
||||
((stop - start)*1000000)//steps//len(turmits),
|
||||
str(prog))
|
||||
logger.info(msg)
|
||||
return progid, score, sinfo
|
||||
|
||||
|
|
@ -125,16 +98,6 @@ class World(object):
|
|||
''' @brief Save as an image '''
|
||||
scipy.misc.imsave(filename, self._val)
|
||||
|
||||
def fractdim_target(self, target, threshold=None):
|
||||
res = self.fractdim(threshold)
|
||||
if target:
|
||||
ret = (2.0 - (abs(target - res))*5)
|
||||
if ret < 0:
|
||||
ret = 0.0
|
||||
return (ret, res)
|
||||
else:
|
||||
return (res, res)
|
||||
|
||||
def fractdim(self, threshold=None):
|
||||
''' @return Minkowski–Bouligand dimension (computed) '''
|
||||
if not self._gray:
|
||||
|
|
@ -206,8 +169,6 @@ class LivingTurmit(Turmit):
|
|||
''' @brief Represent a Turmit with coordinates in a world '''
|
||||
|
||||
def __init__(self, world, color = None, x=None, y=None, diag=True, **kwargs):
|
||||
if 'prog' in kwargs:
|
||||
kwargs['prog'] = str(kwargs['prog']).lower()
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if not isinstance(world, World):
|
||||
|
|
@ -267,7 +228,6 @@ class LivingTurmit(Turmit):
|
|||
r = g = b = self._world[self._y][self._x]
|
||||
else:
|
||||
r,g,b = self._world[self._y][self._x]
|
||||
r = int(r); g=int(g); b=int(b)
|
||||
tdir = super().__call__(x=self._x, y=self._y, r=r, g=g, b=b)
|
||||
self.move(tdir)
|
||||
|
||||
|
|
@ -293,10 +253,7 @@ class LivingTurmit(Turmit):
|
|||
''' @brief Process a determinit score : determinist_expr / total expr
|
||||
@return float in [0.0..1.0]
|
||||
'''
|
||||
try:
|
||||
return (self._determin_score + 1) / self._steps
|
||||
except AttributeError:
|
||||
return 1
|
||||
return (self._determin_score + 1) / self._steps
|
||||
|
||||
def dirvar(self):
|
||||
''' @brief Process @ref _dirvar to return a direction variation
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
PYTHON=/usr/bin/python3
|
||||
#CFLAGS=-Wall -Werror -O0 -g
|
||||
CFLAGS=-Wall -Werror
|
||||
CC=gcc $(CFLAGS)
|
||||
|
||||
all: cturmit*.so
|
||||
|
||||
cturmit*.so: setup.py build/lib.*/cturmit*.so
|
||||
cp build/lib.*/cturmit*.so ./
|
||||
|
||||
build/lib.*/cturmit*.so: cturmit.c cturmit.h turmit.c turmit.h
|
||||
make clean; CFLAGS="$(CFLAGS)" $(PYTHON) setup.py --verbose build
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
-rm -Rf build cturmit*.so
|
||||
352
libs/cturmit.c
352
libs/cturmit.c
|
|
@ -1,352 +0,0 @@
|
|||
#include "cturmit.h"
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_cturmit(void)
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
CTurmitType.tp_new = PyType_GenericNew;
|
||||
if (PyType_Ready(&CTurmitType) < 0)
|
||||
return NULL;
|
||||
|
||||
m = PyModule_Create(&cturmitmodule);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(&CTurmitType);
|
||||
PyModule_AddObject(m, "CTurmit", (PyObject *)&CTurmitType);
|
||||
return m;
|
||||
}
|
||||
|
||||
static int
|
||||
CTurmit_init(CTurmit *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
size_t sz;
|
||||
char err_msg[128];
|
||||
ssize_t arg_stk_sz, arg_int_max;
|
||||
char *arg_expr;
|
||||
int i, ret;
|
||||
CTurmit *turmit;
|
||||
PyObject *stack_size, *int_max, *expr, *keys, *asc_str;
|
||||
PyObject *errtype, *errvalue, *errbck;
|
||||
|
||||
PyErr_Fetch(&errtype, &errvalue, &errbck);
|
||||
turmit = (CTurmit*)PyMapping_GetItemString(kwds, "turmit");
|
||||
if(turmit)
|
||||
{
|
||||
Py_XDECREF(errtype);
|
||||
Py_XDECREF(errvalue);
|
||||
Py_XDECREF(errbck);
|
||||
ret = _CTurmit_copy_init(self, turmit);
|
||||
Py_DECREF(turmit);
|
||||
return ret;
|
||||
}
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
|
||||
stack_size = int_max = expr = NULL;
|
||||
self->turmit = NULL;
|
||||
|
||||
//Checking arguments
|
||||
if((sz = PySequence_Length(args)) >= 0)
|
||||
{
|
||||
if(sz > 1)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128, "1 positional argument expected \
|
||||
but %ld found", sz);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
stack_size = PySequence_GetItem(args, 0);
|
||||
}
|
||||
if(!stack_size)
|
||||
{
|
||||
stack_size = PyMapping_GetItemString(kwds, "stack_size");
|
||||
PyMapping_DelItemString(kwds, "stack_size");
|
||||
}
|
||||
if(stack_size)
|
||||
{
|
||||
if(!PyLong_CheckExact(stack_size))
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
Py_DECREF(stack_size);
|
||||
snprintf(err_msg, 128,
|
||||
"stack_size expected to be an integer");
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
arg_stk_sz = PyLong_AsSsize_t(stack_size);
|
||||
Py_DECREF(stack_size);
|
||||
if(arg_stk_sz == (size_t)-1 && PyErr_Occurred())
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"size_t overflow with stack_size");
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_stk_sz = 8;
|
||||
}
|
||||
|
||||
int_max = PyMapping_GetItemString(kwds, "max_int");
|
||||
PyMapping_DelItemString(kwds, "max_int");
|
||||
if(int_max)
|
||||
{
|
||||
if(!PyLong_CheckExact(int_max))
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"int_max expected to be an integer");
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
arg_int_max = PyLong_AsSsize_t(int_max);
|
||||
Py_DECREF(int_max);
|
||||
if(arg_int_max == (size_t)-1 && PyErr_Occurred())
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"size_t overflow with stack_size");
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_int_max = 0x10000;
|
||||
}
|
||||
|
||||
expr = PyMapping_GetItemString(kwds, "prog");
|
||||
PyMapping_DelItemString(kwds, "prog");
|
||||
if(expr)
|
||||
{
|
||||
if(!PyUnicode_Check(expr) && !(expr = PyObject_Str(expr)))
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"prog expected to be a string !");
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
asc_str = PyUnicode_AsASCIIString(expr);
|
||||
Py_DECREF(expr);
|
||||
if(!asc_str)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"prog expected to be an ASCII string");
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
arg_expr = (char*)PyBytes_AsString(asc_str);
|
||||
Py_DECREF(asc_str);
|
||||
if(!arg_expr)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"Unable to convert prog to Cstring");
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_expr = "";
|
||||
}
|
||||
|
||||
if(PyMapping_Length(kwds) > 0)
|
||||
{
|
||||
keys = PyMapping_Keys(kwds);
|
||||
strncpy(err_msg, "Unrecognized arguments : '", 128);
|
||||
for(i=0; i<PyList_Size(keys); i++)
|
||||
{
|
||||
asc_str = PyUnicode_AsASCIIString(
|
||||
PyList_GetItem(keys, i));
|
||||
strncat(err_msg,
|
||||
(char*)PyBytes_AsString(asc_str),127);
|
||||
strncat(err_msg, "', '", 127);
|
||||
}
|
||||
Py_DECREF(keys);
|
||||
strncat(err_msg, "'", 128);
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
self->turmit = turmit_alloc(arg_stk_sz, arg_int_max, arg_expr,
|
||||
TURMIT_AUTOCOMP);
|
||||
if(self->turmit->err)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128,
|
||||
"Unable to compile '%s' err : %s", arg_expr,
|
||||
self->turmit->err_str);
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
err_msg);
|
||||
goto cturmit_init_error;
|
||||
}
|
||||
Py_XDECREF(errtype);
|
||||
Py_XDECREF(errvalue);
|
||||
Py_XDECREF(errbck);
|
||||
return 0;
|
||||
|
||||
cturmit_init_error:
|
||||
Py_XDECREF(errtype);
|
||||
Py_XDECREF(errvalue);
|
||||
Py_XDECREF(errbck);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
CTurmit_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
CTurmit *self;
|
||||
self = (CTurmit *)type->tp_alloc(type, 0);
|
||||
if(self != NULL) {
|
||||
//do stuff
|
||||
}
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
void
|
||||
CTurmit_dealloc(CTurmit *self)
|
||||
{
|
||||
if(self->turmit) { turmit_free(self->turmit); }
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static int _CTurmit_copy_init(CTurmit *self, CTurmit *t)
|
||||
{
|
||||
self->turmit = turmit_copy(t->turmit);
|
||||
if(!self->turmit)
|
||||
{
|
||||
//set error
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* CTurmit_call(PyObject *func, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
turmit_int res;
|
||||
PyObject *arg;
|
||||
CTurmit *self;
|
||||
turmit_int exec_args[5];
|
||||
char *argsname[5] = {"x", "y", "r", "g", "b"}; // see TURMIT_VAR_L
|
||||
char err_msg[64];
|
||||
int i;
|
||||
PyObject *errtype, *errvalue, *errbck;
|
||||
|
||||
self = (CTurmit*)func;
|
||||
|
||||
PyErr_Fetch(&errtype, &errvalue, &errbck);
|
||||
|
||||
for(i=0; i<5; i++)
|
||||
{
|
||||
arg = PyMapping_GetItemString(kwds, argsname[i]);
|
||||
if(PyErr_Occurred())
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 64, "Argument %s missing",
|
||||
argsname[i]);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
exec_args[i] = PyLong_AsUnsignedLongLong(arg);
|
||||
if(PyErr_Occurred())
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 64, "An integer is required for %s",
|
||||
argsname[i]);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
err_msg);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
Py_DECREF(arg);
|
||||
}
|
||||
res = turmit_exec(self->turmit, exec_args);
|
||||
return PyLong_FromUnsignedLongLong(res);
|
||||
}
|
||||
|
||||
PyObject* CTurmit__push(CTurmit* self, PyObject *args)
|
||||
{
|
||||
char err_msg[128];
|
||||
size_t sz;
|
||||
turmit_int ival;
|
||||
PyObject *val;
|
||||
PyObject *errtype, *errvalue, *errbck;
|
||||
|
||||
PyErr_Fetch(&errtype, &errvalue, &errbck);
|
||||
|
||||
if((sz = PySequence_Length(args)) >= 0)
|
||||
{
|
||||
if(sz > 1)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
snprintf(err_msg, 128, "1 positional argument expected \
|
||||
but %ld found", sz);
|
||||
PyErr_SetString(PyExc_TypeError, err_msg);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
val = PySequence_GetItem(args, 0);
|
||||
}
|
||||
if(!val)
|
||||
{
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Argument val is missing");
|
||||
Py_RETURN_NONE;
|
||||
|
||||
}
|
||||
ival = PyLong_AsSize_t(val);
|
||||
if(ival == (size_t)-1 && PyErr_Occurred()) { Py_RETURN_NONE; }
|
||||
SPUSH(self->turmit, ival);
|
||||
PyErr_Restore(errtype, errvalue, errbck);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* CTurmit__pop(CTurmit* self)
|
||||
{
|
||||
return PyLong_FromUnsignedLongLong(SPOP(self->turmit));
|
||||
}
|
||||
|
||||
PyObject* CTurmit_get_shead(CTurmit *self, void *ref)
|
||||
{
|
||||
return PyLong_FromUnsignedLongLong(SCUR(self->turmit));
|
||||
}
|
||||
|
||||
PyObject* CTurmit_get__cur(CTurmit *self, void *ref)
|
||||
{
|
||||
return PyLong_FromSsize_t(self->turmit->stack_cur);
|
||||
}
|
||||
|
||||
PyObject* CTurmit_get__stack(CTurmit *self, void *ref)
|
||||
{
|
||||
size_t i;
|
||||
PyObject *res;
|
||||
|
||||
res = PyList_New(self->turmit->stack_sz);
|
||||
|
||||
for(i=0; i<self->turmit->stack_sz;i++)
|
||||
{
|
||||
PyList_SET_ITEM(res, i,
|
||||
PyLong_FromUnsignedLongLong(self->turmit->stack[i]));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
205
libs/cturmit.h
205
libs/cturmit.h
|
|
@ -1,205 +0,0 @@
|
|||
#include<Python.h>
|
||||
#include"structmember.h"
|
||||
|
||||
#include "turmit.h"
|
||||
|
||||
/** @brief Python module containing CTurmit python class */
|
||||
|
||||
static PyModuleDef cturmitmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"cturmit",
|
||||
"Module implementing turmits in C",
|
||||
-1,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
}; /*<! Module description */
|
||||
|
||||
/*
|
||||
class CTurmit definitions
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PyObject VAR_HEAD;
|
||||
|
||||
turmit_t *turmit; /*<! Ref to a turmit_t from libs/turmit.h */
|
||||
} CTurmit; /*<! CTurmit struct */
|
||||
|
||||
static PyMemberDef CTurmit_members[] = {
|
||||
{NULL} /* Sentinel */
|
||||
}; /*<! CTurmit member attribute description */
|
||||
|
||||
|
||||
/* Other methods */
|
||||
#define TURMIT_PYOP(NAME) PyObject* CTurmit_op_##NAME(CTurmit* self) {\
|
||||
turmit_op_##NAME(self->turmit);\
|
||||
Py_RETURN_NONE;\
|
||||
}
|
||||
#define TURMIT_PYOPDEF(NAME) {#NAME, (PyCFunction)CTurmit_op_##NAME, \
|
||||
METH_NOARGS, NULL}
|
||||
|
||||
/** @brief Push a python integer on the CTurmit stack
|
||||
* @param self the CTurmit instance
|
||||
* @param PyObject* list of *args arguments. Should contain a single integer
|
||||
* argument to be pushed on the stack
|
||||
* @return Python None
|
||||
* @throws TypeError if bad arguments
|
||||
*/
|
||||
PyObject* CTurmit__push(CTurmit* self, PyObject *args);
|
||||
/**@brief Pop a python integer from the CTurmit stack
|
||||
* @return a python integer returned from PyLong_FromUnsignedLongLong()
|
||||
*/
|
||||
PyObject* CTurmit__pop(CTurmit* self);
|
||||
/* Adding method to call turmit_t operations on the stack
|
||||
* @param self CTurmit* (see TURMIT_PYOP macro) the method takes no args
|
||||
* except self
|
||||
*/
|
||||
TURMIT_PYOP(mem_sz)
|
||||
TURMIT_PYOP(add)
|
||||
TURMIT_PYOP(sub)
|
||||
TURMIT_PYOP(bin_and)
|
||||
TURMIT_PYOP(dup)
|
||||
TURMIT_PYOP(lshift)
|
||||
TURMIT_PYOP(mod)
|
||||
TURMIT_PYOP(mul)
|
||||
TURMIT_PYOP(div)
|
||||
TURMIT_PYOP(bin_or)
|
||||
TURMIT_PYOP(bin_xor)
|
||||
TURMIT_PYOP(pop)
|
||||
TURMIT_PYOP(swp)
|
||||
TURMIT_PYOP(jmp)
|
||||
TURMIT_PYOP(jz)
|
||||
TURMIT_PYOP(jcmp)
|
||||
|
||||
static PyMethodDef CTurmit_methods[] = {
|
||||
{"_push", (PyCFunction)CTurmit__push, METH_KEYWORDS | METH_VARARGS,
|
||||
"Push a value on the stack"},
|
||||
{"_pop", (PyCFunction)CTurmit__pop, METH_NOARGS,
|
||||
"Pop a value from the stack"},
|
||||
TURMIT_PYOPDEF(mem_sz),
|
||||
TURMIT_PYOPDEF(add),
|
||||
TURMIT_PYOPDEF(sub),
|
||||
TURMIT_PYOPDEF(bin_and),
|
||||
TURMIT_PYOPDEF(dup),
|
||||
TURMIT_PYOPDEF(lshift),
|
||||
TURMIT_PYOPDEF(mod),
|
||||
TURMIT_PYOPDEF(mul),
|
||||
TURMIT_PYOPDEF(div),
|
||||
TURMIT_PYOPDEF(bin_or),
|
||||
TURMIT_PYOPDEF(bin_xor),
|
||||
TURMIT_PYOPDEF(pop),
|
||||
TURMIT_PYOPDEF(swp),
|
||||
TURMIT_PYOPDEF(jmp),
|
||||
TURMIT_PYOPDEF(jz),
|
||||
TURMIT_PYOPDEF(jcmp),
|
||||
{NULL} /* Sentinel */
|
||||
}; /*<! Static CTurmit method mapping */
|
||||
|
||||
/*
|
||||
Getter & setter definition
|
||||
|
||||
Note : no setter, this methods are implemented for read only access
|
||||
to some @ref turmit_t attributes
|
||||
*/
|
||||
|
||||
/**@brief Returns current value on the top of the stack
|
||||
* @note mapped as "shead" attribute
|
||||
* @retrun a python int
|
||||
*/
|
||||
PyObject* CTurmit_get_shead(CTurmit *self, void *ref);
|
||||
/**@brief Returns current position of the stack head
|
||||
* @note mapped as "_cur" attribute
|
||||
* @retrun a python int
|
||||
*/
|
||||
PyObject* CTurmit_get__cur(CTurmit *self, void *ref);
|
||||
/**@brief Returns a python representation of the stack
|
||||
*@return a python list containing python int
|
||||
*/
|
||||
PyObject* CTurmit_get__stack(CTurmit *self, void *ref);
|
||||
|
||||
static struct PyGetSetDef CTurmit_getset[] = {
|
||||
{"shead", (getter)CTurmit_get_shead, NULL, NULL, NULL},
|
||||
{"_cur", (getter)CTurmit_get__cur, NULL, NULL, NULL},
|
||||
{"_stack", (getter)CTurmit_get__stack, NULL, NULL, NULL},
|
||||
{NULL} /* Sentinel */
|
||||
};/*<! Getter mapping */
|
||||
|
||||
/**@brief Utility method that handle CTurmit instanciation copying an existing
|
||||
* CTurmit instance
|
||||
* @param self Python self CTurmit, the CTurmit to copy
|
||||
* @param t the destination CTurmit
|
||||
* @return 0 if no error else -1
|
||||
* @todo set error to throw python exception if error
|
||||
*/
|
||||
static int _CTurmit_copy_init(CTurmit *self, CTurmit *t);
|
||||
|
||||
/**@brief Python CTurmit.__new__() method
|
||||
* @param type Python type
|
||||
* @param args Python *args positional args list
|
||||
* @param kwds Python **kwargs named args dict
|
||||
* @return a CTurmit with memory allocated for the instance
|
||||
*/
|
||||
static PyObject *
|
||||
CTurmit_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
||||
|
||||
/**@brief CTurmit.__init__(self, stack_size=8, max_int=0x10000, prog="", turmit=None) method
|
||||
* @param CTurmit* self
|
||||
* @param PyObject* can contain an interger representing stack size
|
||||
* @param Pyobject* contains kwargs. Can be : stack_size, max_int, prog
|
||||
*/
|
||||
static int
|
||||
CTurmit_init(CTurmit *self, PyObject *args, PyObject *kwds);
|
||||
|
||||
/**@brief CTurmit.__del__(self) method
|
||||
* @param self The CTurmit instance
|
||||
*/
|
||||
void
|
||||
CTurmit_dealloc(CTurmit *self);
|
||||
|
||||
/**@brief CTurmit.__call__(self, x, y, r, g, b) method
|
||||
* @param args python positional arguments list
|
||||
* @param kwds python named arguments dict
|
||||
*/
|
||||
PyObject* CTurmit_call(PyObject *func, PyObject *args, PyObject *kwds);
|
||||
|
||||
static PyTypeObject CTurmitType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cturmit.CTurmit", /* tp_name */
|
||||
sizeof(CTurmit), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)CTurmit_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
CTurmit_call, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
"CTurmit objects", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
CTurmit_methods, /* tp_methods */
|
||||
CTurmit_members, /* tp_members */
|
||||
CTurmit_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)CTurmit_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
CTurmit_new, /* tp_new */
|
||||
}; /*<! CTurmit object mapping */
|
||||
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
from distutils.core import setup, Extension
|
||||
|
||||
module1 = Extension('cturmit',
|
||||
sources = ['cturmit.c', 'turmit.c'])
|
||||
|
||||
|
||||
setup(
|
||||
name = "Cturmit",
|
||||
version = '1.0',
|
||||
description = 'Turmit implementation in c',
|
||||
ext_modules = [module1]
|
||||
)
|
||||
458
libs/turmit.c
458
libs/turmit.c
|
|
@ -1,458 +0,0 @@
|
|||
#include "turmit.h"
|
||||
|
||||
TURMIT_OP(mem_sz)
|
||||
{
|
||||
turmit_int *new;
|
||||
turmit_int new_sz, old_sz, new_blc, old_blc;
|
||||
|
||||
old_sz = turmit->stack_sz;
|
||||
old_blc = (old_sz / TURMIT_STACK_GROW) + 1;
|
||||
|
||||
new_sz = SPOP(turmit);
|
||||
new_sz %= TURMIT_STACK_MAX;
|
||||
new_sz = new_sz<2?2:new_sz;
|
||||
new_blc = (new_sz / TURMIT_STACK_GROW) + 1;
|
||||
|
||||
if(new_blc != old_blc)
|
||||
{
|
||||
new = realloc(turmit->stack,
|
||||
sizeof(turmit_int) * (new_blc * TURMIT_STACK_GROW));
|
||||
if(!new) {
|
||||
perror("Unable to reallocate memory for stack");
|
||||
return;
|
||||
}
|
||||
turmit->stack = new;
|
||||
}
|
||||
turmit->stack_sz = new_sz;
|
||||
turmit->stack_cur %= new_sz;
|
||||
if(old_sz < new_sz)
|
||||
{
|
||||
bzero(turmit->stack + old_sz,
|
||||
sizeof(turmit_int) * (new_sz - old_sz));
|
||||
}
|
||||
}
|
||||
|
||||
TURMIT_OP(add)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
SPUSH(turmit, a+b);
|
||||
}
|
||||
|
||||
TURMIT_OP(sub)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
if(turmit->flags & TURMIT_SIGNED)
|
||||
{
|
||||
fprintf(stderr, "Signed int not implemented\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
SPUSH(turmit, a>b?(turmit->int_max - a) + b:b - a);
|
||||
}
|
||||
}
|
||||
|
||||
TURMIT_OP(bin_and)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
SPUSH(turmit, b & a);
|
||||
}
|
||||
|
||||
TURMIT_OP(dup)
|
||||
{
|
||||
turmit_int a = SCUR(turmit);
|
||||
SPUSH(turmit, a);
|
||||
}
|
||||
|
||||
TURMIT_OP(lshift)
|
||||
{
|
||||
turmit_int a,b;
|
||||
a = SPOP(turmit); b = SPOP(turmit);
|
||||
SPUSH(turmit, b << a);
|
||||
}
|
||||
|
||||
TURMIT_OP(mod)
|
||||
{
|
||||
turmit_int a,b;
|
||||
a = SPOP(turmit); b = SPOP(turmit);
|
||||
a = !a?0:b%a;
|
||||
SPUSH(turmit, a);
|
||||
}
|
||||
|
||||
TURMIT_OP(mul)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
SPUSH(turmit, a*b);
|
||||
}
|
||||
|
||||
TURMIT_OP(div)
|
||||
{
|
||||
turmit_int a, b;
|
||||
a = SPOP(turmit);
|
||||
b = SPOP(turmit);
|
||||
SPUSH(turmit, a==0?0:b/a);
|
||||
}
|
||||
|
||||
TURMIT_OP(bin_or)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
SPUSH(turmit, a | b);
|
||||
}
|
||||
|
||||
TURMIT_OP(bin_xor)
|
||||
{
|
||||
turmit_int a = SPOP(turmit), b = SPOP(turmit);
|
||||
SPUSH(turmit, a ^ b);
|
||||
}
|
||||
|
||||
TURMIT_OP(pop)
|
||||
{
|
||||
SPOP(turmit);
|
||||
}
|
||||
|
||||
TURMIT_OP(swp)
|
||||
{
|
||||
turmit_int a, b;
|
||||
a = SPOP(turmit);
|
||||
b = SPOP(turmit);
|
||||
SPUSH(turmit, a);
|
||||
SPUSH(turmit, b);
|
||||
}
|
||||
|
||||
TURMIT_OP(jmp)
|
||||
{
|
||||
turmit_int a;
|
||||
a = SPOP(turmit);
|
||||
TURMIT_JMP(turmit, a);
|
||||
}
|
||||
|
||||
TURMIT_OP(jz)
|
||||
{
|
||||
turmit_int a, b;
|
||||
a = SPOP(turmit);
|
||||
b = SPOP(turmit);
|
||||
if(b == 0)
|
||||
{
|
||||
TURMIT_JMP(turmit, a);
|
||||
}
|
||||
}
|
||||
|
||||
TURMIT_OP(jcmp)
|
||||
{
|
||||
turmit_int a, b, cnd, offset;
|
||||
offset = SPOP(turmit);
|
||||
cnd = SPOP(turmit);
|
||||
b = SPOP(turmit);
|
||||
a = SPOP(turmit);
|
||||
if(((cnd & 7) == 0 && a != b) || (cnd > 6) || ((cnd & 1) && a == b) ||
|
||||
((cnd & 7) > 2 && a < b) || ((cnd & 7) > 4 && a > b))
|
||||
{
|
||||
TURMIT_JMP(turmit, offset);
|
||||
}
|
||||
}
|
||||
|
||||
turmit_t *turmit_alloc(ssize_t stack_sz, ssize_t int_max, const char *expr,
|
||||
unsigned char flags)
|
||||
{
|
||||
turmit_t *res;
|
||||
|
||||
res = malloc(sizeof(struct turmit_s));
|
||||
if(!res)
|
||||
{
|
||||
perror("Unable to allocate memory for turmit");
|
||||
return NULL;
|
||||
}
|
||||
return turmit_init(res, stack_sz, int_max, expr, flags);
|
||||
}
|
||||
|
||||
turmit_t *turmit_init(turmit_t *turmit, ssize_t stack_sz, ssize_t int_max,
|
||||
const char *expr, unsigned char flags)
|
||||
{
|
||||
turmit->expr = strndup(expr, TURMIT_EXPR_MAX_SZ);
|
||||
turmit->flags = flags;
|
||||
turmit->int_max = int_max;
|
||||
turmit->op_expr = NULL;
|
||||
turmit->op_expr_sz = 0;
|
||||
turmit->op_cur = 0;
|
||||
turmit->op_end = 0;
|
||||
turmit->stack_sz = stack_sz;
|
||||
turmit->stack_cur = turmit->stack_sz - 1;
|
||||
turmit->err = 0;
|
||||
turmit->err_str = NULL;
|
||||
turmit->stack = malloc(sizeof(turmit_int) *
|
||||
((turmit->stack_sz / TURMIT_STACK_GROW)+1) * TURMIT_STACK_GROW);
|
||||
|
||||
if(!turmit->stack)
|
||||
{
|
||||
perror("Unable to allocate turmit's stack's memory");
|
||||
return turmit;
|
||||
}
|
||||
bzero(turmit->stack, sizeof(turmit_int) * turmit->stack_sz);
|
||||
|
||||
if(turmit->flags & TURMIT_AUTOCOMP)
|
||||
{
|
||||
turmit_compile(turmit);
|
||||
}
|
||||
return turmit;
|
||||
}
|
||||
|
||||
turmit_t *turmit_copy(turmit_t *turmit)
|
||||
{
|
||||
turmit_t *res;
|
||||
turmit_int stack_blck;
|
||||
|
||||
res = malloc(sizeof(turmit_t));
|
||||
if(!res)
|
||||
{
|
||||
perror("Unable to allocate memory for copy");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(res, turmit, sizeof(turmit_t));
|
||||
if(turmit->expr)
|
||||
{
|
||||
res->expr = strdup(turmit->expr);
|
||||
}
|
||||
if(turmit->stack)
|
||||
{
|
||||
stack_blck = (res->stack_sz / TURMIT_STACK_GROW) + 1;
|
||||
res->stack = malloc(
|
||||
sizeof(turmit_int) * stack_blck * TURMIT_STACK_GROW);
|
||||
memcpy(res->stack, turmit->stack,
|
||||
sizeof(turmit_int) * stack_blck * TURMIT_STACK_GROW);
|
||||
}
|
||||
if(turmit->op_expr)
|
||||
{
|
||||
res->op_expr = malloc(sizeof(turmit_op_t) * res->op_expr_sz);
|
||||
if(!res->op_expr)
|
||||
{
|
||||
perror("Unable to allocate memory for expression");
|
||||
return res;
|
||||
}
|
||||
memcpy(res->op_expr, turmit->op_expr,
|
||||
sizeof(turmit_op_t) * res->op_expr_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void turmit_clean(turmit_t *turmit)
|
||||
{
|
||||
if(turmit->stack) { free(turmit->stack); }
|
||||
if(turmit->err_str) { free(turmit->err_str); }
|
||||
if(turmit->expr) { free(turmit->expr); }
|
||||
if(turmit->op_expr) { free(turmit->op_expr); }
|
||||
|
||||
}
|
||||
|
||||
void turmit_free(turmit_t *turmit)
|
||||
{
|
||||
turmit_clean(turmit);
|
||||
free(turmit);
|
||||
}
|
||||
|
||||
turmit_int turmit_exec(turmit_t *turmit, const turmit_int args[5])
|
||||
{
|
||||
turmit_op_t *op;
|
||||
|
||||
turmit->op_cur = 0;
|
||||
turmit->op_end = 0;
|
||||
while(!turmit->op_end && turmit->op_cur < turmit->op_expr_sz)
|
||||
{
|
||||
op = &(turmit->op_expr[turmit->op_cur]);
|
||||
switch(op->value)
|
||||
{
|
||||
case TURMIT_SYM_OP:
|
||||
op->op.op(turmit);
|
||||
break;
|
||||
case TURMIT_SYM_VAL:
|
||||
SPUSH(turmit, op->op.val);
|
||||
break;
|
||||
case TURMIT_SYM_VAR:
|
||||
SPUSH(turmit, args[op->op.var]);
|
||||
break;
|
||||
default:
|
||||
// Null sym encountered. This sould NOT append
|
||||
fprintf(stderr, "Warning NULL sym encountered\n");
|
||||
turmit->op_cur = turmit->op_expr_sz;
|
||||
break;
|
||||
}
|
||||
//_turmit_stack_dump(turmit);
|
||||
turmit->op_cur++;
|
||||
}
|
||||
return SCUR(turmit);
|
||||
}
|
||||
|
||||
int turmit_compile(turmit_t *turmit)
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmissing-braces"
|
||||
turmit_sym_t tsym[] = TURMIT_OP_LST;
|
||||
#pragma GCC diagnostic pop
|
||||
char *cur, *endptr;
|
||||
turmit_sym_t *isym;
|
||||
ssize_t opcur;
|
||||
turmit_op_t *pret;
|
||||
long int iret;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
turmit->op_expr_sz = 64;
|
||||
turmit->op_expr = malloc(sizeof(turmit_op_t) * turmit->op_expr_sz);
|
||||
bzero(turmit->op_expr, sizeof(turmit_op_t) * turmit->op_expr_sz);
|
||||
opcur = 0;
|
||||
|
||||
cur = turmit->expr;
|
||||
while(*cur != '\0')
|
||||
{
|
||||
if(opcur >= turmit->op_expr_sz - 1)
|
||||
{ //more space needed
|
||||
turmit->op_expr_sz += 64;
|
||||
pret = realloc(turmit->op_expr,
|
||||
sizeof(turmit_op_t) * turmit->op_expr_sz);
|
||||
if(!pret)
|
||||
{
|
||||
perror("Unable to allocate memory");
|
||||
goto turmit_compile_err;
|
||||
}
|
||||
bzero(pret + opcur - 1,
|
||||
64 * sizeof(turmit_op_t));
|
||||
turmit->op_expr = pret;
|
||||
}
|
||||
//Checking for separators
|
||||
if(*cur == ' ' || *cur == '\t' || *cur == ' ')
|
||||
{
|
||||
cur++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Checking for variables
|
||||
for(i=0; TURMIT_VAR_L[i] != '\0'; i++)
|
||||
{
|
||||
if(tolower(*cur) == TURMIT_VAR_L[i])
|
||||
{
|
||||
turmit->op_expr[opcur].op.var = i;
|
||||
turmit->op_expr[opcur].value = TURMIT_SYM_VAR;
|
||||
opcur++;
|
||||
cur++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(TURMIT_VAR_L[i] != '\0') { continue; }
|
||||
|
||||
//Checking for values
|
||||
//hex
|
||||
if(strncasecmp("0x", cur, 2) == 0)
|
||||
{
|
||||
cur+= 2;
|
||||
errno = 0;
|
||||
iret = strtol(cur, &endptr, 16);
|
||||
err = errno;
|
||||
if(err || endptr == cur)
|
||||
{
|
||||
fprintf(stderr, "Invalid constant %s : %s\n",
|
||||
cur-2, strerror(err));
|
||||
goto turmit_compile_err;
|
||||
}
|
||||
turmit->op_expr[opcur].op.val = iret;
|
||||
turmit->op_expr[opcur].value = TURMIT_SYM_VAL;
|
||||
opcur++;
|
||||
cur = endptr;
|
||||
continue;
|
||||
}
|
||||
//decimal
|
||||
if(*cur <= '9' && *cur >= '0')
|
||||
{
|
||||
iret = strtol(cur, &endptr, 10);
|
||||
err = errno;
|
||||
if(err || endptr == cur)
|
||||
{
|
||||
fprintf(stderr, "Invalid constant %s : %s\n",
|
||||
cur, strerror(err));
|
||||
goto turmit_compile_err;
|
||||
}
|
||||
turmit->op_expr[opcur].op.val = iret;
|
||||
turmit->op_expr[opcur].value = TURMIT_SYM_VAL;
|
||||
opcur++;
|
||||
cur = endptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Checking for op
|
||||
isym = tsym;
|
||||
while(isym->str != NULL)
|
||||
{
|
||||
endptr = cur;
|
||||
if(strncasecmp(isym->str, cur, strlen(isym->str)) == 0)
|
||||
{
|
||||
endptr = cur+strlen(isym->str);
|
||||
}
|
||||
else if(isym->alias && strncmp(cur, isym->alias,
|
||||
strlen(isym->alias)) == 0)
|
||||
{
|
||||
endptr = cur+strlen(isym->alias);
|
||||
}
|
||||
if(cur != endptr)
|
||||
{
|
||||
cur = endptr;
|
||||
turmit->op_expr[opcur].op.op = isym->op_fun;
|
||||
turmit->op_expr[opcur].value = TURMIT_SYM_OP;
|
||||
opcur++;
|
||||
break;
|
||||
}
|
||||
isym++;
|
||||
}
|
||||
if(isym->str != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//unrecognized symbol :'(
|
||||
turmit->err = 1;
|
||||
if(turmit->err_str) { free(turmit->err_str); }
|
||||
turmit->err_str = malloc(sizeof(char) * 256);
|
||||
if(!turmit->err_str)
|
||||
{
|
||||
perror("Unable to allocate memory for error string");
|
||||
return -1;
|
||||
}
|
||||
snprintf(turmit->err_str, 256,
|
||||
"Error compiling prog starting at : '%s'", cur);
|
||||
goto turmit_compile_err;
|
||||
}
|
||||
if(!opcur)
|
||||
{ //empty expression
|
||||
turmit->op_expr_sz = 0;
|
||||
free(turmit->op_expr);
|
||||
turmit->op_expr = NULL;
|
||||
return 0;
|
||||
}
|
||||
turmit->op_expr_sz = opcur;
|
||||
pret = realloc(turmit->op_expr,
|
||||
sizeof(turmit_op_t) * turmit->op_expr_sz);
|
||||
if(!pret)
|
||||
{
|
||||
perror("Unable to shrink op_expr");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
turmit->op_expr = pret;
|
||||
}
|
||||
return 0;
|
||||
|
||||
turmit_compile_err:
|
||||
free(turmit->op_expr);
|
||||
turmit->op_expr = NULL;
|
||||
turmit->op_expr_sz = 0;
|
||||
turmit->op_cur = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _turmit_stack_dump(turmit_t *turmit)
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr, "Stack cur = %lu\n[", turmit->stack_cur);
|
||||
for(i=0; i<turmit->stack_sz; i++)
|
||||
{
|
||||
fprintf(stderr,"%llu, ", turmit->stack[i]);
|
||||
}
|
||||
fprintf(stderr, "]\n");
|
||||
}
|
||||
|
||||
196
libs/turmit.h
196
libs/turmit.h
|
|
@ -1,196 +0,0 @@
|
|||
#ifndef _TURMIT_H_
|
||||
#define _TURMIT_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/**@Todo For the moment there is no way to track wether a variable is used
|
||||
* or not in result processing */
|
||||
|
||||
typedef unsigned long long int turmit_int;
|
||||
typedef struct turmit_op_s turmit_op_t;
|
||||
typedef struct turmit_s turmit_t;
|
||||
typedef struct turmit_sym_s turmit_sym_t;
|
||||
typedef void (*turmit_op_f)(turmit_t*);
|
||||
|
||||
#define SCUR(t) (t->stack[t->stack_cur])
|
||||
#define SDEC(t) (t->stack_cur = (t->stack_cur>0?t->stack_cur:t->stack_sz) -1)
|
||||
#define SINC(t) (t->stack_cur = (t->stack_cur + 1) % t->stack_sz)
|
||||
#define SPOP(t) (__SPOP(t))
|
||||
#define SPUSH(t, v) (t->stack[SINC(t)] = v % t->int_max)
|
||||
|
||||
#define TURMIT_JMP(t, v) (((t->op_expr_sz - t->op_cur) <= v)?\
|
||||
(t->op_end=1):\
|
||||
(t->op_cur += (v>0?v-1:0) ))
|
||||
|
||||
#define TURMIT_STACK_GROW 0xFF
|
||||
#define TURMIT_STACK_MAX 0xFFF
|
||||
#define TURMIT_EXPR_MAX_SZ 0xFFFFFFFF
|
||||
|
||||
#define TURMIT_LAZY 0
|
||||
#define TURMIT_AUTOCOMP 1
|
||||
#define TURMIT_UNSIGNED 0
|
||||
#define TURMIT_SIGNED 2
|
||||
|
||||
#define TURMIT_OK 0
|
||||
#define TURMIT_ERROR -1
|
||||
|
||||
#define TURMIT_SYM_OP 1
|
||||
#define TURMIT_SYM_VAL 2
|
||||
#define TURMIT_SYM_VAR 3
|
||||
|
||||
#define TURMIT_VAR_L "xyrgb"
|
||||
|
||||
#define TURMIT_OPSYM(NAME) {#NAME, NULL, turmit_op_##NAME}
|
||||
#define TURMIT_OPSYMALIAS(NAME, alias) {#NAME, alias, turmit_op_##NAME}
|
||||
|
||||
// OPSYMALIAS has to be first !
|
||||
#define TURMIT_OP_LST {\
|
||||
TURMIT_OPSYMALIAS(add, "+"),\
|
||||
TURMIT_OPSYMALIAS(sub, "-"),\
|
||||
TURMIT_OPSYMALIAS(mul, "*"),\
|
||||
TURMIT_OPSYMALIAS(div, "/"),\
|
||||
TURMIT_OPSYMALIAS(mod, "%"),\
|
||||
TURMIT_OPSYMALIAS(bin_or, "|"),\
|
||||
TURMIT_OPSYMALIAS(bin_and, "&"),\
|
||||
TURMIT_OPSYMALIAS(bin_xor, "^"),\
|
||||
TURMIT_OPSYMALIAS(lshift, "<<"),\
|
||||
TURMIT_OPSYM(mem_sz),\
|
||||
TURMIT_OPSYM(dup),\
|
||||
TURMIT_OPSYM(pop),\
|
||||
TURMIT_OPSYM(swp),\
|
||||
TURMIT_OPSYM(jmp),\
|
||||
TURMIT_OPSYM(jz),\
|
||||
TURMIT_OPSYM(jcmp),\
|
||||
NULL,\
|
||||
}
|
||||
|
||||
struct turmit_sym_s
|
||||
{
|
||||
char *str;
|
||||
char *alias;
|
||||
turmit_op_f op_fun;
|
||||
};
|
||||
|
||||
union turmit_op_u
|
||||
{
|
||||
turmit_op_f op;
|
||||
turmit_int val;
|
||||
short var; /*!< interpreted % 5 */
|
||||
};
|
||||
|
||||
struct turmit_op_s
|
||||
{
|
||||
union turmit_op_u op;
|
||||
/** 0 for NULL, 1 if operation pointer, 2 if value, 3 if variable */
|
||||
short value;
|
||||
};
|
||||
|
||||
struct turmit_s
|
||||
{
|
||||
char *expr;
|
||||
unsigned char flags;
|
||||
ssize_t int_max;
|
||||
|
||||
turmit_op_t *op_expr;
|
||||
ssize_t op_expr_sz;
|
||||
ssize_t op_cur;
|
||||
short op_end;
|
||||
|
||||
ssize_t stack_sz;
|
||||
turmit_int *stack;
|
||||
ssize_t stack_cur;
|
||||
|
||||
/**@brief 0 if no error
|
||||
* @note only for compilation error for the moment
|
||||
*/
|
||||
char err;
|
||||
char *err_str;
|
||||
};
|
||||
|
||||
inline static turmit_int __SPOP(turmit_t *t) {
|
||||
turmit_int r = t->stack[t->stack_cur];
|
||||
SDEC(t);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#define TURMIT_OP(NAME) void turmit_op_##NAME (turmit_t *turmit)
|
||||
|
||||
/**@brief Allocate memory and initialise a turmit
|
||||
* @param const char* The turmit expression
|
||||
* @param unsigned char One of TURMIT_LAZY or TURMIT_AUTOCOMP.
|
||||
* @return A pointer on the new turmit
|
||||
*/
|
||||
turmit_t *turmit_alloc(ssize_t stack_sz, ssize_t int_max, const char *expr,
|
||||
unsigned char flags);
|
||||
|
||||
/**@brief Initialize a turmit
|
||||
* @param turmit_t* The turmit to initialize
|
||||
* @param const char* The turmit expression
|
||||
* @param unsigned char One of TURMIT_LAZY or TURMIT_AUTOCOMP.
|
||||
* @return The pointer on the turmit
|
||||
*/
|
||||
turmit_t *turmit_init(turmit_t *turmit, ssize_t stack_sz, ssize_t int_max,
|
||||
const char *expr, unsigned char flags);
|
||||
|
||||
turmit_t *turmit_copy(turmit_t *turmit);
|
||||
|
||||
void turmit_clean(turmit_t *turmit);
|
||||
|
||||
/**@brief Free memory of a turmit
|
||||
* @param turmit the turmit to free
|
||||
*/
|
||||
void turmit_free(turmit_t *turmit);
|
||||
|
||||
/**@brief Exec a turmit expr
|
||||
* @param turmit_t* Concerned turmit
|
||||
* @param turmit_int* Arguments ( see @ref TURMIT_VAL_L )
|
||||
* @return Processed value
|
||||
*/
|
||||
turmit_int turmit_exec(turmit_t *turmit, const turmit_int args[5]);
|
||||
|
||||
/**@brief Populate turmit_t.op_expr and set op_expr_sz
|
||||
* @return 0 if no errors
|
||||
*/
|
||||
int turmit_compile(turmit_t *turmit);
|
||||
|
||||
void _turmit_stack_dump(turmit_t *turmit);
|
||||
|
||||
TURMIT_OP(mem_sz);
|
||||
|
||||
TURMIT_OP(add);
|
||||
|
||||
TURMIT_OP(sub);
|
||||
|
||||
TURMIT_OP(bin_and);
|
||||
|
||||
TURMIT_OP(dup);
|
||||
|
||||
TURMIT_OP(lshift);
|
||||
|
||||
TURMIT_OP(mod);
|
||||
|
||||
TURMIT_OP(mul);
|
||||
|
||||
TURMIT_OP(div);
|
||||
|
||||
TURMIT_OP(bin_or);
|
||||
|
||||
TURMIT_OP(bin_xor);
|
||||
|
||||
TURMIT_OP(pop);
|
||||
|
||||
TURMIT_OP(swp);
|
||||
|
||||
TURMIT_OP(jmp);
|
||||
|
||||
TURMIT_OP(jz);
|
||||
|
||||
TURMIT_OP(jcmp);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
PYTHONPATH=":`pwd`/libs" python3 -m unittest $@
|
||||
python3 -m unittest $@
|
||||
|
|
|
|||
|
|
@ -1,319 +0,0 @@
|
|||
import unittest
|
||||
import inspect
|
||||
|
||||
from cturmit import CTurmit as Turmit
|
||||
from gte.rpnlib import _op_list
|
||||
|
||||
class TurmitTestCase(unittest.TestCase):
|
||||
|
||||
def test_init(self):
|
||||
''' Test Turmit class __init__ '''
|
||||
t = Turmit(42)
|
||||
self.assertEqual(len(t._stack), 42)
|
||||
self.assertEqual(t.shead, 0)
|
||||
self.assertEqual(len(t._stack) - 1 , t._cur)
|
||||
|
||||
def test_init_args(self):
|
||||
''' Test Turmit __init__ arguments '''
|
||||
t = Turmit()
|
||||
t = Turmit(prog = 'G R B 44 MOD ADD 43 MOD ADD 42 MOD')
|
||||
t = Turmit(prog = 'G R B ADD ADD 42 MOD', max_int = 0xFFFF,
|
||||
stack_size=42)
|
||||
|
||||
def test_call(self):
|
||||
''' Test Turmit.__call__ '''
|
||||
t = Turmit(prog = 'G R B ADD ADD 42 MOD', max_int = 0xFFFF,
|
||||
stack_size=42)
|
||||
r = t(x=1, y=2, r=255, g=255, b=255)
|
||||
self.assertEqual(r, 9)
|
||||
r = t(x=2, y=2, r=255, g=0, b=0)
|
||||
self.assertEqual(r, 3)
|
||||
|
||||
def test_copy(self):
|
||||
t = Turmit(prog = 'G R B ADD ADD 42 MOD', max_int = 0xFFFF,
|
||||
stack_size=42)
|
||||
t2 = Turmit(turmit=t)
|
||||
r = t2(x=1, y=2, r=255, g=255, b=255)
|
||||
self.assertEqual(r, 9)
|
||||
r = t2(x=2, y=2, r=255, g=0, b=0)
|
||||
self.assertEqual(r, 3)
|
||||
|
||||
|
||||
def test_init_badargs(self):
|
||||
''' Test Turmit __init__ bad arguments '''
|
||||
with self.assertRaises(RuntimeError):
|
||||
t = Turmit(foobar=42)
|
||||
with self.assertRaises(ValueError):
|
||||
t = Turmit(prog='foobar')
|
||||
|
||||
|
||||
class TurmitExprCompileTestCase(unittest.TestCase):
|
||||
''' Tests compilatin capabilities of cturmit '''
|
||||
|
||||
def test_values(self):
|
||||
progs = ('1', '0x1', '9', '0x9', '0xf', '0xF', '0x1FFF', '0xFFF1',
|
||||
'12345');
|
||||
for prog in progs:
|
||||
t = Turmit(prog=prog)
|
||||
|
||||
def test_var(self):
|
||||
progs = ('x', 'y', 'r', 'g', 'b')
|
||||
for prog in progs:
|
||||
t = Turmit(prog=prog)
|
||||
|
||||
|
||||
class TurmitOperationTestCase(unittest.TestCase):
|
||||
|
||||
def test_push(self):
|
||||
''' Test Turmit _push() method '''
|
||||
t = Turmit()
|
||||
t._push(1)
|
||||
self.assertEqual(t.shead, 1)
|
||||
t._push(2)
|
||||
self.assertEqual(t.shead, 2)
|
||||
|
||||
def _rpn(self, rpn, narg = 2):
|
||||
if rpn not in _op_list:
|
||||
raise unittest.SkipTest('"%s" not implemented' % rpn)
|
||||
method, wrapped = _op_list[rpn]
|
||||
if narg != len(inspect.signature(method).parameters) - 1:
|
||||
self.fail('Expected %s to take %d arguments, but Turmit.%s() takes \
|
||||
%d arguments' % (rpn, narg, rpn, len(inspect.signature(method).parameters) - 1))
|
||||
|
||||
def test_add(self):
|
||||
''' Test turmit add method '''
|
||||
self._rpn('add')
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(8)
|
||||
t.add()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 50)
|
||||
|
||||
t._push(42)
|
||||
t._push(8)
|
||||
t.add()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 50)
|
||||
|
||||
t.add()
|
||||
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 100)
|
||||
|
||||
def test_mem_sz(self):
|
||||
''' Test turmit mem_sz() operation '''
|
||||
self._rpn('mem_sz', 1)
|
||||
|
||||
t = Turmit(8)
|
||||
self.assertEqual(len(t._stack), 8)
|
||||
|
||||
t._push(42)
|
||||
t.mem_sz()
|
||||
self.assertEqual(len(t._stack), 42)
|
||||
self.assertEqual(t._cur, 7)
|
||||
|
||||
t._push(42)
|
||||
t._push(8)
|
||||
t.mem_sz()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
def test_sub(self):
|
||||
''' Test turmit sub() method '''
|
||||
self._rpn('sub')
|
||||
|
||||
t = Turmit(max_int=0xFFFF)
|
||||
|
||||
t._push(50)
|
||||
t._push(8)
|
||||
|
||||
t.sub()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
t._push(50)
|
||||
t._push(8)
|
||||
t.sub()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
t.sub()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 0)
|
||||
|
||||
t._push(8)
|
||||
t._push(50)
|
||||
t.sub()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 0xFFFF + (8 - 50))
|
||||
|
||||
def test_mul(self):
|
||||
''' Test turmit mul() method '''
|
||||
self._rpn('mul')
|
||||
|
||||
t = Turmit()
|
||||
|
||||
t._push(7)
|
||||
t._push(6)
|
||||
|
||||
t.mul()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
t._push(7)
|
||||
t._push(6)
|
||||
t.mul()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
t.mul()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 42 *42)
|
||||
|
||||
def test_div(self):
|
||||
''' Test turmit division capabilities '''
|
||||
self._rpn('div')
|
||||
|
||||
t = Turmit()
|
||||
|
||||
t._push(43)
|
||||
t._push(7)
|
||||
|
||||
t.div()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 6)
|
||||
|
||||
def test_mod(self):
|
||||
''' Test turmit mod() method '''
|
||||
self._rpn('mod')
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(4)
|
||||
|
||||
t.mod()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 2)
|
||||
|
||||
def test_pow(self):
|
||||
''' Test turmit pow() method '''
|
||||
self._rpn('pow')
|
||||
|
||||
t = Turmit()
|
||||
t._push(2)
|
||||
t._push(4)
|
||||
|
||||
t.pow()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 16)
|
||||
|
||||
def test_sqrt(self):
|
||||
''' Test turmit sqrt() method '''
|
||||
self._rpn('sqrt', 1)
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
|
||||
t.sqrt()
|
||||
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 6)
|
||||
|
||||
def test_and(self):
|
||||
''' Test turmit binary and() method '''
|
||||
self._rpn('bin_and')
|
||||
|
||||
t = Turmit()
|
||||
t._push(10)
|
||||
t._push(42)
|
||||
|
||||
t.bin_and()
|
||||
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 10)
|
||||
|
||||
def test_or(self):
|
||||
''' Test turmit binary or() method '''
|
||||
self._rpn('bin_or')
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(7)
|
||||
|
||||
t.bin_or()
|
||||
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 47)
|
||||
|
||||
def test_xor(self):
|
||||
''' Test turmit binary xor() method '''
|
||||
self._rpn('bin_xor')
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(11)
|
||||
|
||||
t.bin_xor()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 33)
|
||||
|
||||
def test_rshift(self):
|
||||
''' Test turmit rshift method '''
|
||||
self._rpn('rshift')
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(2)
|
||||
|
||||
t.rshift()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 10)
|
||||
|
||||
def test_lshift(self):
|
||||
''' Test turmit lshift method '''
|
||||
self._rpn('lshift')
|
||||
|
||||
t = Turmit()
|
||||
t._push(10)
|
||||
t._push(2)
|
||||
t.lshift()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 40)
|
||||
|
||||
def test_dup(self):
|
||||
''' Test turmit dup() method '''
|
||||
self._rpn('dup', 1)
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t.dup()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 42)
|
||||
|
||||
def test_pop(self):
|
||||
''' Test turmit pop() method '''
|
||||
self._rpn('pop', 1)
|
||||
|
||||
t = Turmit()
|
||||
t._push(10)
|
||||
t._push(2)
|
||||
t.pop()
|
||||
self.assertEqual(t._cur, 0)
|
||||
self.assertEqual(t.shead, 10)
|
||||
t.pop()
|
||||
self.assertEqual(t._cur, len(t._stack) - 1)
|
||||
|
||||
def test_swp(self):
|
||||
''' Test turmit swp() method '''
|
||||
self._rpn('swp', 2)
|
||||
|
||||
t = Turmit()
|
||||
t._push(42)
|
||||
t._push(1337)
|
||||
t.swp()
|
||||
self.assertEqual(t._cur, 1)
|
||||
self.assertEqual(t.shead, 42)
|
||||
t._pop()
|
||||
self.assertEqual(t.shead, 1337)
|
||||
Loading…
Add table
Add a link
Reference in a new issue