klisp

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

commit 43f04b6fed44c6bd24db6337830ced33a2165e91
parent 260533a3faf987c5cddaa543ae9e56c6e7770acd
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Tue, 15 Mar 2011 00:43:20 -0300

Added guard-continuation to the ground environment. NOTE: the mechanism to handle the guards isn't there yet, but the guard list are checked and properly copied.

Diffstat:
Msrc/kapplicative.h | 2+-
Msrc/kgcombiners.c | 4++--
Msrc/kgcontinuations.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/kgcontinuations.h | 3++-
Msrc/kground.c | 3++-
Msrc/kobject.h | 13+++++++++++++
6 files changed, 125 insertions(+), 7 deletions(-)

diff --git a/src/kapplicative.h b/src/kapplicative.h @@ -13,5 +13,5 @@ TValue kwrap(klisp_State *K, TValue underlying); TValue kmake_applicative(klisp_State *K, TValue name, TValue si, TValue underlying); -#define kunwrap(K_, app_) (tv2app(app_)->underlying) +#define kunwrap(app_) (tv2app(app_)->underlying) #endif diff --git a/src/kgcombiners.c b/src/kgcombiners.c @@ -102,7 +102,7 @@ void unwrap(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) (void) denv; (void) xparams; bind_1tp(K, "unwrap", ptree, "applicative", ttisapplicative, app); - TValue underlying = kunwrap(K, app); + TValue underlying = kunwrap(app); kapply_cc(K, underlying); } @@ -140,7 +140,7 @@ void apply(klisp_State *K, TValue *xparams, TValue ptree, TValue env = (get_opt_tpar(K, "apply", K_TENVIRONMENT, &maybe_env))? maybe_env : kmake_empty_environment(K); - TValue expr = kcons(K, kunwrap(K, app), obj); + TValue expr = kcons(K, kunwrap(app), obj); ktail_eval(K, expr, env); } diff --git a/src/kgcontinuations.c b/src/kgcontinuations.c @@ -46,7 +46,7 @@ void do_extended_cont(klisp_State *K, TValue *xparams, TValue obj) ** xparams[1]: environment */ TValue app = xparams[0]; - TValue underlying = kunwrap(K, app); + TValue underlying = kunwrap(app); TValue env = xparams[1]; TValue expr = kcons(K, underlying, obj); @@ -73,8 +73,111 @@ void extend_continuation(klisp_State *K, TValue *xparams, TValue ptree, kapply_cc(K, new_cont); } +/* Helpers for guard-continuation (& guard-dynamic-extent) */ + +/* this is used for inner & outer continuations, it just + passes the value. xparams is not actually empty, it contains + the entry/exit guards, but they are used only in + continuation->applicative (that is during abnormal passes) */ +void pass_value(klisp_State *K, TValue *xparams, TValue obj) +{ + UNUSED(xparams); + kapply_cc(K, obj); +} + +#define singly_wrapped(obj_) (ttisapplicative(obj_) && \ + ttisoperative(kunwrap(obj_))) + +/* this unmarks root before throwing any error */ +/* TODO: this isn't very clean, refactor */ +inline TValue check_copy_single_entry(klisp_State *K, char *name, + TValue obj, TValue root) +{ + if (!ttispair(obj) || !ttispair(kcdr(obj)) || + !ttisnil(kcddr(obj))) { + unmark_list(K, root); + klispE_throw_extra(K, name , ": Bad entry (expected " + "list of length 2)"); + return KINERT; + } + TValue cont = kcar(obj); + TValue app = kcadr(obj); + + if (!ttiscontinuation(cont)) { + unmark_list(K, root); + klispE_throw_extra(K, name, ": Bad type on first element (expected " + "continuation)"); + return KINERT; + } else if (!singly_wrapped(app)) { + unmark_list(K, root); + klispE_throw_extra(K, name, ": Bad type on second element (expected " + "singly wrapped applicative)"); + return KINERT; + } + + /* GC: save intermediate pair */ + return kcons(K, cont, kcons(K, app, KNIL)); +} + +/* the guards are probably generated on the spot so we don't check + for immutability and copy it anyways */ +TValue check_copy_guards(klisp_State *K, char *name, TValue obj) +{ + if (ttisnil(obj)) { + return obj; + } else { + TValue dummy = kcons(K, KINERT, KNIL); + TValue last_pair = dummy; + TValue tail = obj; + + while(ttispair(tail) && !kis_marked(tail)) { + /* this will clear the marks and throw an error if the structure + is incorrect */ + TValue entry = check_copy_single_entry(K, name, kcar(tail), obj); + TValue new_pair = kcons(K, entry, KNIL); + kmark(tail); + kset_cdr(last_pair, new_pair); + last_pair = new_pair; + tail = kcdr(tail); + } + + /* dont close the cycle (if there is one) */ + unmark_list(K, obj); + + if (!ttispair(tail) && !ttisnil(tail)) { + klispE_throw_extra(K, name , ": expected list"); + return KINERT; + } + return kcdr(dummy); + } +} + /* 7.2.4 guard-continuation */ -/* TODO */ +void guard_continuation(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv) +{ + UNUSED(denv); + UNUSED(xparams); + + bind_3tp(K, "guard-continuation", ptree, "any", anytype, entry_guards, + "continuation", ttiscontinuation, cont, + "any", anytype, exit_guards); + + entry_guards = check_copy_guards(K, "guard-continuation: entry guards", + entry_guards); + exit_guards = check_copy_guards(K, "guard-continuation: exit guards", + exit_guards); + + TValue outer_cont = kmake_continuation(K, cont, KNIL, KNIL, pass_value, + 1, entry_guards); + /* mark it as an outer continuation */ + kset_outer_cont(outer_cont); + TValue inner_cont = kmake_continuation(K, outer_cont, KNIL, KNIL, + pass_value, 1, exit_guards); + /* mark it as an outer continuation */ + kset_inner_cont(inner_cont); + kapply_cc(K, inner_cont); +} /* helper for continuation->applicative */ diff --git a/src/kgcontinuations.h b/src/kgcontinuations.h @@ -29,7 +29,8 @@ void extend_continuation(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); /* 7.2.4 guard-continuation */ -/* TODO */ +void guard_continuation(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv); /* 7.2.5 continuation->applicative */ void continuation_applicative(klisp_State *K, TValue *xparams, TValue ptree, diff --git a/src/kground.c b/src/kground.c @@ -359,7 +359,8 @@ void kinit_ground_env(klisp_State *K) add_applicative(K, ground_env, "extend-continuation", extend_continuation, 0); /* 7.2.4 guard-continuation */ - /* TODO */ + add_applicative(K, ground_env, "guard-continuation", guard_continuation, + 0); /* 7.2.5 continuation->applicative */ add_applicative(K, ground_env, "continuation->applicative", diff --git a/src/kobject.h b/src/kobject.h @@ -419,6 +419,19 @@ extern char *ktv_names[]; #define gch_get_flags(o_) (obj2gch(o_)->flags) #define tv_get_flags(o_) (gch_get_flags(tv2gch(o_))) +/* Flags for marking continuations */ +#define K_FLAG_OUTER 0x01 +#define K_FLAG_INNER 0x02 +#define K_FLAG_DYNAMIC 0x04 + +#define kset_inner_cont(c_) (tv_get_flags(c_) |= K_FLAG_INNER) +#define kset_outer_cont(c_) (tv_get_flags(c_) |= K_FLAG_OUTER) +#define kset_dyn_cont(c_) (tv_get_flags(c_) |= K_FLAG_DYNAMIC) + +#define kis_inner_cont(c_) ((tv_get_flags(c_) & K_FLAG_INNER) != 0) +#define kis_outer_cont(c_) ((tv_get_flags(c_) & K_FLAG_OUTER) != 0) +#define kis_dyn_cont(c_) ((tv_get_flags(c_) & K_FLAG_DYNAMIC) != 0) + #define K_FLAG_IMMUTABLE 0x01 #define kis_mutable(o_) ((tv_get_flags(o_) & K_FLAG_IMMUTABLE) == 0) #define kis_immutable(o_) (!kis_mutable(o_))