klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 828107c7e6d8cc39eb55fce0337f09787852c201
parent 1708898b996f5f0d23ef866d7eeb0548898e8ffc
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sat, 18 Aug 2012 17:20:26 -0300

Refactored do_eval_ls to use the new function reverse_copy_and_encycle.  Argument evaluation is, once again, left to right.

Diffstat:
Msrc/keval.c | 149++++++++++++++-----------------------------------------------------------------
1 file changed, 26 insertions(+), 123 deletions(-)

diff --git a/src/keval.c b/src/keval.c @@ -20,61 +20,9 @@ void do_eval_ls(klisp_State *K); void do_combine_operator(klisp_State *K); void do_combine_operands(klisp_State *K); - /* ** Eval helpers */ - -TValue copy_and_encycle(klisp_State *K, TValue ls, - int32_t apairs, int32_t cpairs) -{ - /* apairs + cpairs > 0 */ - TValue first = kcons(K, kcar(ls), KNIL); - TValue last = first; - krooted_tvs_push(K, first); - ls = kcdr(ls); - bool has_apairs = apairs > 0; - - if (has_apairs) { - --apairs; - while (apairs > 0) { - TValue np = kcons(K, kcar(ls), KNIL); - kset_cdr(last, np); - last = np; - - ls = kcdr(ls); - --apairs; - } - } - - if (cpairs > 0) { - TValue first_c; - if (has_apairs) { - first_c = kcons(K, kcar(ls), KNIL); - kset_cdr(last, first_c); - last = first_c; - ls = kcdr(ls); - --cpairs; - } else { - first_c = first; /* also == to last */ - --cpairs; /* cdr was already done above */ - } - - while (cpairs > 0) { - TValue np = kcons(K, kcar(ls), KNIL); - kset_cdr(last, np); - last = np; - - ls = kcdr(ls); - --cpairs; - } - kset_cdr(last, first_c); - } - - krooted_tvs_pop(K); - return first; -} - void do_eval_ls(klisp_State *K) { TValue *xparams = K->next_xparams; @@ -82,91 +30,44 @@ void do_eval_ls(klisp_State *K) klisp_assert(ttisnil(K->next_env)); /* ** xparams[0]: remaining list - ** xparams[1]: accumulated list - ** xparams[2]: dynamic environment - ** xparams[3]: apairs - ** xparams[4]: cpairs + ** xparams[1]: rem_pairs + ** xparams[2]: accumulated list + ** xparams[3]: dynamic environment + ** xparams[4]: apairs + ** xparams[5]: cpairs */ TValue rest = xparams[0]; - TValue acc = xparams[1]; - TValue env = xparams[2]; - TValue tv_apairs = xparams[3]; - TValue tv_cpairs = xparams[4]; + int32_t rem_pairs = ivalue(xparams[1]); + TValue acc = xparams[2]; + TValue env = xparams[3]; + TValue tv_apairs = xparams[4]; + TValue tv_cpairs = xparams[5]; acc = kcons(K, obj, acc); krooted_tvs_push(K, acc); - if (ttisnil(rest)) { + if (rem_pairs == 0) { /* argument evaluation complete, copy the list and encycle if - needed (the list was reversed again during evaluation, so it - is now in the correct order */ - TValue res = copy_and_encycle(K, acc, ivalue(tv_apairs), - ivalue(tv_cpairs)); + needed (the list was reversed during evaluation, so it should + be reversed first) */ + TValue res = + reverse_copy_and_encycle(K, acc, ivalue(tv_apairs) + + ivalue(tv_cpairs), ivalue(tv_cpairs)); krooted_tvs_pop(K); /* pop acc */ kapply_cc(K, res); } else { /* more arguments need to be evaluated */ /* GC: all objects are rooted at this point */ TValue new_cont = - kmake_continuation(K, kget_cc(K), do_eval_ls, 5, kcdr(rest), - acc, env, tv_apairs, tv_cpairs); + kmake_continuation(K, kget_cc(K), do_eval_ls, 6, kcdr(rest), + i2tv(rem_pairs - 1), acc, env, tv_apairs, + tv_cpairs); krooted_tvs_pop(K); /* pop acc */ kset_cc(K, new_cont); ktail_eval(K, kcar(rest), env); } } -/* TODO: move this to another file, to use it elsewhere */ -static inline void clear_ls_marks(TValue ls) -{ - while (ttispair(ls) && kis_marked(ls)) { - kunmark(ls); - ls = kcdr(ls); - } -} - - -/* operands should be a pair, and should be rooted (GC) */ -TValue check_reverse_copy_list(klisp_State *K, TValue operands, - int32_t *apairs, int32_t *cpairs) -{ - TValue ls = KNIL; - TValue rem_op = operands; - int32_t p = 0; - int32_t c = 0; - - krooted_tvs_push(K, ls); /* put in stack to maintain while invariant */ - - while(ttispair(rem_op) && kis_unmarked(rem_op)) { - kset_mark(rem_op, i2tv(p)); /* remember index */ - ls = kcons(K, kcar(rem_op), ls); - krooted_tvs_pop(K); - krooted_tvs_push(K, ls); - rem_op = kcdr(rem_op); - ++p; - } - - krooted_tvs_pop(K); - - if (ttispair(rem_op)) { /* cyclic list */ - c = p - ivalue(kget_mark(rem_op)); - } else if (ttisnil(rem_op)) { /* regular list */ - /* do nothing */ - } else { /* acyclic list - error */ - clear_ls_marks(operands); - klispE_throw_simple(K, "Not a list in applicative combination"); - return KINERT; - } - clear_ls_marks(operands); - - if (apairs != NULL) - *apairs = p - c; - if (cpairs != NULL) - *cpairs = c; - - return ls; -} - void do_combine_operands(klisp_State *K) { TValue *xparams = K->next_xparams; @@ -190,7 +91,7 @@ void do_combine_operands(klisp_State *K) comb = tv2app(comb)->underlying; ktail_call_si(K, comb, operands, env, si); } else if (ttispair(operands)) { - int32_t apairs, cpairs; + int32_t pairs, apairs, cpairs; TValue comb_cont = kmake_continuation(K, kget_cc(K), do_combine_operator, 3, tv2app(comb)->underlying, env, si); @@ -200,12 +101,14 @@ void do_combine_operands(klisp_State *K) avoid mutation of the structure affecting evaluation; this also allows capturing continuations in the middle of argument evaluation with no additional overhead */ - TValue arg_ls = check_reverse_copy_list(K, operands, - &apairs, &cpairs); + TValue arg_ls = check_copy_list(K, operands, false, + &pairs, &cpairs); + apairs = pairs - cpairs; krooted_tvs_push(K, arg_ls); TValue els_cont = - kmake_continuation(K, comb_cont, do_eval_ls, 5, kcdr(arg_ls), - KNIL, env, i2tv(apairs), i2tv(cpairs)); + kmake_continuation(K, comb_cont, do_eval_ls, 6, kcdr(arg_ls), + i2tv(pairs - 1), KNIL, env, i2tv(apairs), + i2tv(cpairs)); krooted_tvs_pop(K); krooted_tvs_pop(K);