klisp

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

commit 099873f65c7bf7613c4113677ec946cb658922cd
parent 12b47c68a0ff6bdca0780d2a94f1102c9d90b5f0
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sat, 12 Mar 2011 20:42:02 -0300

Added encycle! to the ground environment.

Diffstat:
Msrc/kground.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 102 insertions(+), 6 deletions(-)

diff --git a/src/kground.c b/src/kground.c @@ -70,16 +70,35 @@ return; \ } -#define bind_3p(K_, n_, ptree_, v1_, v2_, v3_) \ - TValue v1_, v2_, v3_; \ - if (!ttispair(ptree_) || !ttispair(kcdr(ptree_)) || \ +#define bind_3p(K_, n_, ptree_, v1_, v2_, v3_) \ + bind_3tp(K_, n_, ptree_, "any", anytype, v1_, \ + "any", anytype, v2_, "any", anytype, v3_) + +#define bind_3tp(K_, n_, ptree_, tstr1_, t1_, v1_, \ + tstr2_, t2_, v2_, tstr3_, t3_, v3_) \ + TValue v1_, v2_, v3_; \ + if (!ttispair(ptree_) || !ttispair(kcdr(ptree_)) || \ !ttispair(kcddr (ptree_)) || !ttisnil(kcdddr(ptree_))) { \ klispE_throw_extra(K_, n_, ": Bad ptree (expected three arguments)"); \ return; \ } \ v1_ = kcar(ptree_); \ v2_ = kcadr(ptree_); \ - v3_ = kcaddr(ptree_) + v3_ = kcaddr(ptree_); \ + if (!t1_(v1_)) { \ + klispE_throw_extra(K_, n_, ": Bad type on first argument (expected " \ + tstr1_ ")"); \ + return; \ + } else if (!t2_(v2_)) { \ + klispE_throw_extra(K_, n_, ": Bad type on second argument (expected " \ + tstr2_ ")"); \ + return; \ + } else if (!t3_(v3_)) { \ + klispE_throw_extra(K_, n_, ": Bad type on third argument (expected " \ + tstr3_ ")"); \ + return; \ + } + /* bind at least 2 parameters, like (v1_ v2_ . v3_) */ #define bind_al2p(K_, n_, ptree_, v1_, v2_, v3_) \ @@ -1377,6 +1396,9 @@ void get_list_metrics(klisp_State *K, TValue *xparams, TValue ptree, } /* 5.7.2 list-tail */ +/* ASK John: can the object be a cyclic list? the wording of the report + seems to indicate that can't be the case, but it makes sense here + (cf $encycle!) to allow cyclic lists, so that's what I do */ void list_tail(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) { @@ -1409,7 +1431,81 @@ void list_tail(klisp_State *K, TValue *xparams, TValue ptree, */ /* 5.8.1 encycle! */ -/* TODO */ +/* ASK John: can the object be a cyclic list of length less than k1+k2? + the wording of the report seems to indicate that can't be the case, + and here it makes sense to forbid it because otherwise the list-metrics + of the result would differ with the expected ones (cf list-tail). + So here an error is signaled if the improper list cyclic with less pairs + than needed */ +void encycleB(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv) +{ + (void) denv; + (void) xparams; + /* XXX: should be integer instead of fixint, but that's all + we have for now */ + bind_3tp(K, "encycle!", ptree, "any", anytype, obj, + "finite integer", ttisfixint, tk1, + "finite integer", ttisfixint, tk2); + + int32_t k1 = ivalue(tk1); + int32_t k2 = ivalue(tk2); + + if (k1 < 0 || k2 < 0) { + klispE_throw(K, "encycle!: negative index"); + return; + } + + TValue tail = obj; + + while(k1) { + if (!ttispair(tail)) { + unmark_list(K, obj); + klispE_throw(K, "encycle!: non pair found while traversing " + "object"); + return; + } else if (kis_marked(tail)) { + unmark_list(K, obj); + klispE_throw(K, "encycle!: too few pairs in cyclic list"); + return; + } + kmark(tail); + tail = kcdr(tail); + --k1; + } + + TValue fcp = tail; + + /* if k2 == 0 do nothing (but this still checks that the obj + has at least k1 pairs */ + if (k2 != 0) { + --k2; /* to have cycle length k2 we should discard k2-1 pairs */ + while(k2) { + if (!ttispair(tail)) { + unmark_list(K, obj); + klispE_throw(K, "encycle!: non pair found while traversing " + "object"); + return; + } else if (kis_marked(tail)) { + unmark_list(K, obj); + klispE_throw(K, "encycle!: too few pairs in cyclic list"); + return; + } + kmark(tail); + tail = kcdr(tail); + --k2; + } + if (!kis_mutable(tail)) { + unmark_list(K, obj); + klispE_throw(K, "encycle!: immutable pair"); + return; + } else { + kset_cdr(tail, fcp); + } + } + unmark_list(K, obj); + kapply_cc(K, KINERT); +} /* ** 5.9 Combiners @@ -1697,7 +1793,7 @@ TValue kmake_ground_env(klisp_State *K) */ /* 5.8.1 encycle! */ - /* TODO */ + add_applicative(K, ground_env, "encycle!", encycleB, 0); /* ** 5.9 Combiners