klisp

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

commit 300079e1e735a79bb35dcf24bd5d42a612575759
parent 3b841c58a968ec6c43a3d405d2b9bfaaf20dae68
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Mon,  4 Apr 2011 15:56:46 -0300

Added filter to the ground environment.

Diffstat:
Msrc/Makefile | 3++-
Msrc/kghelpers.h | 4++++
Msrc/kgpairs_lists.c | 142++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/kgpairs_lists.h | 2+-
Msrc/kground.c | 2+-
5 files changed, 149 insertions(+), 4 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -98,7 +98,8 @@ kgsymbols.o: kgsymbols.c kgsymbols.c kghelpers.h kstate.h klisp.h \ kgcontrol.o: kgcontrol.c kgcontrol.c kghelpers.h kstate.h klisp.h \ kobject.h kerror.h kpair.h kcontinuation.h kgpairs_lists.o: kgpairs_lists.c kgpairs_lists.h kghelpers.h kstate.h klisp.h \ - kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h kgequalp.h + kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h kgequalp.h \ + kenvironment.h kgpair_mut.o: kgpair_mut.c kgpair_mut.h kghelpers.h kstate.h klisp.h \ kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h kgeqp.h kgenvironments.o: kgenvironments.c kgenvironments.h kghelpers.h kstate.h \ diff --git a/src/kghelpers.h b/src/kghelpers.h @@ -249,6 +249,10 @@ int32_t check_list(klisp_State *K, char *name, bool allow_infp, */ +/* REFACTOR: return the number of pairs and cycle pairs in two extra params */ +/* TODO: add check_copy_typed_list */ +/* TODO: remove inline */ + /* check that obj is a list and make a copy if it is not immutable */ inline TValue check_copy_list(klisp_State *K, char *name, TValue obj) { diff --git a/src/kgpairs_lists.c b/src/kgpairs_lists.c @@ -15,6 +15,7 @@ #include "kpair.h" #include "kstring.h" #include "kcontinuation.h" +#include "kenvironment.h" #include "ksymbol.h" #include "kerror.h" @@ -317,8 +318,147 @@ void list_neighbors(klisp_State *K, TValue *xparams, TValue ptree, kapply_cc(K, kcdr(dummy)); } +/* Helpers for filter */ + +/* For acyclic input lists: Return the filtered list */ +void do_ret_cdr(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: (dummy . complete-ls) + */ + UNUSED(obj); + kapply_cc(K, kcdr(xparams[0])); +} + +/* For cyclic input list: If the result cycle is non empty, + close it and return filtered list */ +void do_filter_encycle(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: (dummy . complete-ls) + ** xparams[1]: last non-cycle pair + */ + /* obj: ((last-evaled . rem-ls) . last-pair) */ + TValue last_pair = kcdr(obj); + TValue last_non_cycle_pair = xparams[1]; + + if (tv_equal(last_pair, last_non_cycle_pair)) { + /* no cycle in result, so put the nil at the end. + this is necessary because it is now pointing + to the first cycle pair */ + kset_cdr(last_non_cycle_pair, KNIL); + } else { + /* There are pairs in the cycle, so close it */ + TValue first_cycle_pair = kcdr(last_non_cycle_pair); + TValue last_cycle_pair = last_pair; + kset_cdr(last_cycle_pair, first_cycle_pair); + } + + kapply_cc(K, kcdr(xparams[0])); +} + +void do_filter(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: app + ** xparams[1]: (last-evaled . rem-ls) + ** xparams[2]: last-pair in result list + ** xparams[3]: n + */ + TValue app = xparams[0]; + TValue ls = xparams[1]; + TValue last_pair = xparams[2]; + int32_t n = ivalue(xparams[3]); + + if (!ttisboolean(obj)) { + klispE_throw(K, "filter: expected boolean result"); + return; + } + + if (kis_false(obj)) { + kset_cdr(last_pair, kcdr(ls)); + } else { + last_pair = ls; + } + + if (n == 0) { + /* pass the rest of the list and last pair for cycle handling */ + kapply_cc(K, kcons(K, ls, last_pair)); + } else { + TValue new_n = i2tv(n-1); +/* The car of ls here contains the last evaluated object. So the next + obj to be tested is actually the cadr of ls. */ + TValue first = kcadr(ls); + ls = kcdr(ls); + TValue new_env = kmake_empty_environment(K); + /* have to unwrap the applicative to extra evaluation of first */ + TValue new_expr = kcons(K, kunwrap(app), kcons(K, first, KNIL)); + TValue new_cont = + kmake_continuation(K, kget_cc(K), KNIL, KNIL, do_filter, 4, app, + ls, last_pair, new_n); + kset_cc(K, new_cont); + ktail_eval(K, new_expr, new_env); + } +} + +void do_filter_cycle(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: (dummy . complete-ls) + ** xparams[1]: app + ** xparams[2]: cpairs + */ + + TValue dummy = xparams[0]; + TValue app = xparams[1]; + TValue cpairs = xparams[2]; + + /* obj: ((last-acyclic obj . cycle) . last-result-pair) */ + TValue ls = kcar(obj); + TValue last_pair = kcdr(obj); + + /* this continuation will close the cycle and return the list */ + TValue encycle_cont = + kmake_continuation(K, kget_cc(K), KNIL, KNIL, do_filter_encycle, 2, + dummy, last_pair); + + /* schedule the filtering of the elements of the cycle */ + TValue new_cont = + kmake_continuation(K, encycle_cont, KNIL, KNIL, do_filter, 4, app, + ls, last_pair, cpairs); + kset_cc(K, new_cont); + /* this will be like a nop (the cdr of last-pair will be setted, but it + will get rewritten later), and will continue with do_filter */ + kapply_cc(K, KFALSE); +} + /* 6.3.5 filter */ -/* TODO */ +void filter(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) +{ + UNUSED(xparams); + bind_2tp(K, "filter", ptree, "applicative", ttisapplicative, app, + "any", anytype, ls); + /* copy the list to allow filtering by mutating pairs and + to avoid changes made by the applicative to alter the + structure of ls */ + /* REFACTOR: do this in a single pass */ + int32_t cpairs; + int32_t pairs = check_list(K, "filter", true, ls, &cpairs); + ls = check_copy_list(K, "filter", ls); + /* add dummy pair to allow set-cdr! to filter out any pair */ + ls = kcons(K, KINERT, ls); + + TValue ret_cont = (cpairs == 0)? + kmake_continuation(K, kget_cc(K), KNIL, KNIL, do_ret_cdr, 1, ls) + : kmake_continuation(K, kget_cc(K), KNIL, KNIL, do_filter_cycle, 3, + ls, app, i2tv(cpairs)); + TValue new_cont = + kmake_continuation(K, ret_cont, KNIL, KNIL, do_filter, 4, app, + ls, ls, i2tv(pairs-cpairs)); + kset_cc(K, new_cont); + /* this will be a nop, and will continue with do_filter */ + kapply_cc(K, KFALSE); +} /* 6.3.6 assoc */ void assoc(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) diff --git a/src/kgpairs_lists.h b/src/kgpairs_lists.h @@ -68,7 +68,7 @@ void list_neighbors(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); /* 6.3.5 filter */ -/* TODO */ +void filter(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); /* 6.3.6 assoc */ void assoc(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); diff --git a/src/kground.c b/src/kground.c @@ -389,7 +389,7 @@ void kinit_ground_env(klisp_State *K) add_applicative(K, ground_env, "list-neighbors", list_neighbors, 0); /* 6.3.5 filter */ - /* TODO */ + add_applicative(K, ground_env, "filter", filter, 0); /* 6.3.6 assoc */ add_applicative(K, ground_env, "assoc", assoc, 0);