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:
M | src/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);