From be799b976d6fd58960d0a44e0f389c8f6765e7c0 Mon Sep 17 00:00:00 2001 From: Teddy Date: Thu, 15 Aug 2013 11:17:09 +0800 Subject: tail-rec support for `or` --- builtin.cpp | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/builtin.cpp b/builtin.cpp index 47fdda8..98e7bbc 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -448,26 +448,40 @@ void SpecialOptOr::prepare(Pair *pc) { Pair *SpecialOptOr::call(Pair *args, Environment * &lenvt, Continuation * &cont, EvalObj ** &top_ptr, Pair *pc) { Pair *ret_addr = cont->pc; - if (pc->cdr == empty_list) + Pair *cs = cont->state; + Pair *nexp; + if (pc->cdr == empty_list) // empty list { gc.expose(*top_ptr); *top_ptr++ = gc.attach(new BoolObj(false)); EXIT_CURRENT_EXEC(lenvt, cont, args); return ret_addr->next; } - if (!cont->state) + if (!cs) // spawn the first { - gc.attach(static_cast(*(++top_ptr))); - top_ptr++; - cont->state = TO_PAIR(pc->cdr); - cont->state->next = NULL; - gc.expose(args); - return cont->state; + nexp = cont->state = TO_PAIR(pc->cdr); + if (nexp->cdr == empty_list && !nexp->car->is_simple_obj()) + { + cont->tail = true; + cont->state = NULL; + top_ptr++; + gc.expose(args); + return nexp; + } + else + { + gc.attach(static_cast(*(++top_ptr))); + top_ptr++; + nexp->next = NULL; + gc.expose(args); + return nexp; + } } + EvalObj *ret = TO_PAIR(args->cdr)->car; if (!ret->is_true()) { - if (cont->state->cdr == empty_list) // the last member + if (cs->cdr == empty_list) // the last member { gc.expose(*top_ptr); *top_ptr++ = gc.attach(ret); @@ -476,12 +490,21 @@ Pair *SpecialOptOr::call(Pair *args, Environment * &lenvt, } else { + nexp = TO_PAIR(cs->cdr); + if (nexp->cdr == empty_list && !nexp->car->is_simple_obj()) + { + cont->tail = true; + cont->state = NULL; + top_ptr++; + gc.expose(args); + return nexp; + } gc.attach(static_cast(*(++top_ptr))); top_ptr++; - cont->state = TO_PAIR(cont->state->cdr); - cont->state->next = NULL; + nexp = cont->state = TO_PAIR(cont->state->cdr); + nexp->next = NULL; gc.expose(args); - return cont->state; + return nexp; } } else -- cgit v1.2.3