klisp

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

commit 12857fa47148b10fa3a77f843716904b59935fe8
parent 51adc01edbf2827483c3f3df0c837a6ab9e8e865
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun, 13 Mar 2011 04:24:29 -0300

Bugfix: $lambda was a disaster. Now it correctly takes at least one parameter and does what is should.

Diffstat:
Msrc/kgcombiners.c | 33+++++++++++----------------------
Msrc/kgenv_mut.h | 2+-
Msrc/kghelpers.h | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 86 insertions(+), 31 deletions(-)

diff --git a/src/kgcombiners.c b/src/kgcombiners.c @@ -113,15 +113,16 @@ void unwrap(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) void Slambda(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) { (void) xparams; - bind_al2p(K, "$lambda", ptree, vptree, vpenv, vbody); + bind_al1p(K, "$lambda", ptree, vptree, vbody); /* The ptree & body are copied to avoid mutation */ - vptree = check_copy_ptree(K, "$lambda", vptree, vpenv); + vptree = check_copy_ptree(K, "$lambda", vptree, KIGNORE); /* the body should be a list */ (void)check_list(K, "$lambda", vbody); vbody = copy_es_immutable_h(K, "$lambda", vbody); - TValue new_app = make_applicative(K, do_vau, 4, vptree, vpenv, vbody, denv); + TValue new_app = make_applicative(K, do_vau, 4, vptree, KIGNORE, vbody, + denv); kapply_cc(K, new_app); } @@ -131,26 +132,14 @@ void apply(klisp_State *K, TValue *xparams, TValue ptree, { (void) denv; (void) xparams; - bind_al2p(K, "apply", ptree, app, obj, maybe_env); + bind_al2tp(K, "apply", ptree, + "applicative", ttisapplicative, app, + "any", anytype, obj, + maybe_env); + + TValue env = (get_opt_tpar(K, "apply", K_TENVIRONMENT, &maybe_env))? + maybe_env : kmake_empty_environment(K); - if(!ttisapplicative(app)) { - klispE_throw(K, "apply: Bad type on first argument " - "(expected applicative)"); - return; - } - TValue env; - /* TODO move to an inlinable function */ - if (ttisnil(maybe_env)) { - env = kmake_empty_environment(K); - } else if (ttispair(maybe_env) && ttisnil(kcdr(maybe_env))) { - env = kcar(maybe_env); - if (!ttisenvironment(env)) { - klispE_throw(K, "apply: Bad type on optional argument " - "(expected environment)"); - } - } else { - klispE_throw(K, "apply: Bad ptree structure (in optional argument)"); - } TValue expr = kcons(K, kunwrap(K, app), obj); ktail_eval(K, expr, env); } diff --git a/src/kgenv_mut.h b/src/kgenv_mut.h @@ -220,7 +220,7 @@ inline TValue check_copy_ptree(klisp_State *K, char *name, TValue ptree, /* TODO add symbol name */ ptree_clear_all(K, sym_ls); klispE_throw_extra(K, name, ": same symbol in both ptree and " - "environment parmameter"); + "environment parameter"); } } else if (!ttisignore(penv)) { /* TODO add symbol name */ diff --git a/src/kghelpers.h b/src/kghelpers.h @@ -29,16 +29,19 @@ ** they expand to more than one statement and may evaluate some of ** their arguments more than once */ + +/* XXX: add parens around macro vars!! */ #define bind_1p(K_, n_, ptree_, v_) \ - bind_1tp(K_, n_, ptree_, "any", anytype, v_) + bind_1tp((K_), (n_), (ptree_), "any", anytype, (v_)) #define bind_1tp(K_, n_, ptree_, tstr_, t_, v_) \ TValue v_; \ if (!ttispair(ptree_) || !ttisnil(kcdr(ptree_))) { \ - klispE_throw_extra(K_, n_ , ": Bad ptree (expected one argument)"); \ + klispE_throw_extra((K_), (n_) , \ + ": Bad ptree (expected one argument)"); \ return; \ } \ - v_ = kcar(ptree_); \ + v_ = kcar(ptree_); \ if (!t_(v_)) { \ klispE_throw_extra(K_, n_ , ": Bad type on first argument " \ "(expected " tstr_ ")"); \ @@ -47,7 +50,8 @@ #define bind_2p(K_, n_, ptree_, v1_, v2_) \ - bind_2tp(K_, n_, ptree_, "any", anytype, v1_, "any", anytype, v2_) + bind_2tp((K_), (n_), (ptree_), "any", anytype, (v1_), \ + "any", anytype, (v2_)) #define bind_2tp(K_, n_, ptree_, tstr1_, t1_, v1_, \ tstr2_, t2_, v2_) \ @@ -98,18 +102,80 @@ return; \ } +/* bind at least 1 parameter, like (v1_ . v2_) */ +#define bind_al1p(K_, n_, ptree_, v1_, v2_) \ + bind_al1tp((K_), (n_), (ptree_), "any", anytype, (v1_), (v2_)) + +/* bind at least 1 parameters (with type), like (v1_ . v2_) */ +#define bind_al1tp(K_, n_, ptree_, tstr1_, t1_, v1_, v2_) \ + TValue v1_, v2_; \ + if (!ttispair(ptree_)) { \ + klispE_throw_extra(K_, n_ , ": Bad ptree (expected at least " \ + "one argument)"); \ + return; \ + } \ + v1_ = kcar(ptree_); \ + v2_ = kcdr(ptree_); \ + if (!t1_(v1_)) { \ + klispE_throw_extra(K_, n_, ": Bad type on first argument (expected " \ + tstr1_ ")"); \ + return; \ + } /* bind at least 2 parameters, like (v1_ v2_ . v3_) */ #define bind_al2p(K_, n_, ptree_, v1_, v2_, v3_) \ + bind_al2tp((K_), (n_), (ptree_), "any", anytype, (v1_), \ + "any", anytype, (v2_), (v3_)) + +/* bind at least 2 parameters (with type), like (v1_ v2_ . v3_) */ +#define bind_al2tp(K_, n_, ptree_, tstr1_, t1_, v1_, \ + tstr2_, t2_, v2_, v3_) \ TValue v1_, v2_, v3_; \ - if (!ttispair(ptree_) || !ttispair(kcdr(ptree_))) { \ - klispE_throw_extra(K_, n_, ": Bad ptree (expected at least 2 " \ - "arguments)"); \ + if (!ttispair(ptree_) || !ttispair(kcdr(ptree_))) { \ + klispE_throw_extra(K_, n_ , ": Bad ptree (expected at least " \ + "two arguments)"); \ return; \ } \ v1_ = kcar(ptree_); \ v2_ = kcadr(ptree_); \ - v3_ = kcddr(ptree_) + v3_ = kcddr(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; \ + } + + +/* returns true if the obj pointed by par is a list of one element of + type type, and puts that element in par + returns false if *par is nil + In any other case it throws an error */ +inline bool get_opt_tpar(klisp_State *K, char *name, int32_t type, TValue *par) +{ + if (ttisnil(*par)) { + return false; + } else if (ttispair(*par) && ttisnil(kcdr(*par))) { + *par = kcar(*par); + if (ttype(*par) != type) { + /* TODO show expected type */ + klispE_throw_extra(K, name, ": Bad type on optional argument " + "(expected ?)"); + /* avoid warning */ + return false; + } else { + return true; + } + } else { + klispE_throw(K, "apply: Bad ptree structure (in optional argument)"); + /* avoid warning */ + return false; + } +} + /* TODO: add name and source info */ #define make_operative(K_, fn_, ...) \