klisp

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

commit 1f3aab1d158d6149314883a315a38bc2380ebf6f
parent bb68806dbb11377290da23374a20b8c03b809fc0
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Mon, 28 Mar 2011 14:55:57 -0300

Added some preliminary work for the $let family of operatives.

Diffstat:
Msrc/Makefile | 2+-
Msrc/kgenvironments.c | 99++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/kgenvironments.h | 5++++-
Msrc/kground.c | 3+--
4 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -102,7 +102,7 @@ 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 \ klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \ - kenvironment.h + kenvironment.h kgenv_mut.h kgpair_mut.h kgenv_mut.o: kgenv_mut.c kgenv_mut.h kghelpers.h kstate.h \ klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \ kenvironment.h diff --git a/src/kgenvironments.c b/src/kgenvironments.c @@ -20,6 +20,9 @@ #include "kghelpers.h" #include "kgenvironments.h" +#include "kgenv_mut.h" /* for check_ptree */ +#include "kgpair_mut.h" /* for copy_es_immutable_h */ +/* MAYBE: move the above to kghelpers.h */ /* 4.8.1 environment? */ /* uses typep */ @@ -68,8 +71,102 @@ void make_environment(klisp_State *K, TValue *xparams, TValue ptree, } } +/* Helpers for all the let family */ + +/* +** The split-let-bindings function has two cases: +** the 'lets' with a star ($let* and $letrec) allow repeated symbols +** in different bidings (each binding is a different ptree whereas +** in $let, $letrec, $let-redirect and $let-safe, all the bindings +** are collected in a single ptree). +** In both cases the value returned is a list of cars of bindings and +** exprs is modified to point to a list of cadrs of bindings. +** The ptrees are copied as by copy-es-immutable (as with $vau & $lambda) +** If bindings is not finite (or not a list) an error is signaled. +*/ + +TValue split_check_let_bindings(klisp_State *K, char *name, TValue bindings, + TValue *exprs, bool starp) +{ + TValue dummy_cars = kcons(K, KNIL, KNIL); + TValue last_car_pair = dummy_cars; + TValue dummy_cadrs = kcons(K, KNIL, KNIL); + TValue last_cadr_pair = dummy_cadrs; + + TValue tail = bindings; + + while(ttispair(tail) && !kis_marked(tail)) { + kmark(tail); + TValue first = kcar(tail); + if (!ttispair(first) || !ttispair(kcdr(first)) || + !ttisnil(kcddr(first))) { + unmark_list(K, bindings); + klispE_throw_extra(K, name, ": bad structure in bindings"); + return KNIL; + } + + TValue new_car = kcons(K, kcar(first), KNIL); + kset_cdr(last_car_pair, new_car); + last_car_pair = new_car; + TValue new_cadr = kcons(K, kcadr(first), KNIL); + kset_cdr(last_cadr_pair, new_cadr); + last_cadr_pair = new_cadr; + + tail = kcdr(tail); + } + + unmark_list(K, bindings); + + if (!ttispair(tail) && !ttisnil(tail)) { + klispE_throw_extra(K, name, ": expected list"); + return KNIL; + } else if(ttispair(tail)) { + klispE_throw_extra(K, name , ": expected finite list"); + return KNIL; + } else { + *exprs = kcdr(dummy_cadrs); + TValue res; + if (starp) { + /* all bindings are consider individual ptrees in these 'let's, + replace each ptree with its copy (after checking of course) */ + tail = kcdr(dummy_cars); + while(!ttisnil(tail)) { + TValue first = kcar(tail); + TValue copy = check_copy_ptree(K, name, first, KIGNORE); + kset_car(tail, copy); + tail = kcdr(tail); + } + res = kcdr(dummy_cars); + } else { + /* all bindings are consider one ptree in these 'let's */ + res = check_copy_ptree(K, name, kcdr(dummy_cars), KIGNORE); + } + return res; + } +} + /* 5.10.1 $let */ -/* TODO */ +/* TEMP: for now this only checks the parameters and makes copies */ +/* XXX: it doesn't do any evaluation or env creation */ +void Slet(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) +{ + /* + ** xparams[0]: symbol name + */ + UNUSED(denv); + char *name = ksymbol_buf(xparams[0]); + bind_al1p(K, name, ptree, bindings, body); + + TValue exprs; + TValue btree = split_check_let_bindings(K, name, bindings, &exprs, false); + int32_t dummy; + UNUSED(check_list(K, name, true, body, &dummy)); + body = copy_es_immutable_h(K, name, body, false); + + /* XXX */ + TValue res = kcons(K, btree, kcons(K, exprs, body)); + kapply_cc(K, res); +} /* 6.7.1 $binds? */ /* TODO */ diff --git a/src/kgenvironments.h b/src/kgenvironments.h @@ -32,8 +32,11 @@ void eval(klisp_State *K, TValue *xparams, TValue ptree, void make_environment(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); +/* Helpers for all $let family */ +TValue split_check_let_bindings(klisp_State *K, char *name, TValue bindings, + TValue *exprs, bool starp); /* 5.10.1 $let */ -/* TODO */ +void Slet(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); /* 6.7.1 $binds? */ /* TODO */ diff --git a/src/kground.c b/src/kground.c @@ -337,8 +337,7 @@ void kinit_ground_env(klisp_State *K) */ /* 5.10.1 $let */ - /* TODO */ - + add_operative(K, ground_env, "$let", Slet, 1, symbol); /* **