klisp

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

commit e859df58d8b166c487b00ce322dff629dce63af5
parent c9bda1d52762c113481d855f395f3c41170367c3
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun,  6 Mar 2011 02:05:48 -0300

Added applicatives and their rule of evaluation. eval is, more or less, complete.

Diffstat:
Msrc/Makefile | 6++++--
Asrc/kapplicative.c | 28++++++++++++++++++++++++++++
Asrc/kapplicative.h | 17+++++++++++++++++
Msrc/klisp.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/kobject.h | 6++++++
5 files changed, 170 insertions(+), 10 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -9,7 +9,7 @@ MYLIBS= CORE_O= kobject.o ktoken.o kpair.o kstring.o ksymbol.o kread.o \ kwrite.o kstate.o kmem.o kerror.o kauxlib.o kenvironment.o \ - kcontinuation.o koperative.o + kcontinuation.o koperative.o kapplicative.o KRN_T= klisp KRN_O= klisp.o @@ -34,7 +34,8 @@ clean: .PHONY: all default o clean klisp.o: klisp.c klisp.h kobject.h kread.h kwrite.h klimits.h kstate.h kmem.h \ - kerror.h kauxlib.h koperative.h kenvironment.h kcontinuation.h + kerror.h kauxlib.h koperative.h kenvironment.h kcontinuation.h \ + kapplicative.h koperative.h kobject.o: kobject.c kobject.h ktoken.o: ktoken.c ktoken.h kobject.h kstate.h kpair.h kstring.h ksymbol.h \ kerror.h @@ -52,3 +53,4 @@ kenvironment.o: kenvironment.c kenvironment.h kpair.h kobject.h kerror.h \ kmem.h kstate.h kcontinuation.o: kcontinuation.c kcontinuation.h kmem.h kstate.h kobject.h koperative.o: koperative.c koperative.h kmem.h kstate.h kobject.h +kapplicative.o: kapplicative.c kapplicative.h kmem.h kstate.h kobject.h diff --git a/src/kapplicative.c b/src/kapplicative.c @@ -0,0 +1,28 @@ +/* +** kapplicative.c +** Kernel Applicatives +** See Copyright Notice in klisp.h +*/ + +#include "kobject.h" +#include "kstate.h" +#include "kapplicative.h" +#include "kmem.h" + +TValue kwrap(klisp_State *K, TValue underlying) +{ + return kmake_applicative(K, KNIL, KNIL, underlying); +} + +TValue kmake_applicative(klisp_State *K, TValue name, TValue si, + TValue underlying) +{ + Applicative *new_app = klispM_new(K, Applicative); + new_app->next = NULL; + new_app->gct = 0; + new_app->tt = K_TAPPLICATIVE; + new_app->name = name; + new_app->si = si; + new_app->underlying = underlying; + return gc2app(new_app); +} diff --git a/src/kapplicative.h b/src/kapplicative.h @@ -0,0 +1,17 @@ +/* +** kapplicative.h +** Kernel Applicatives +** See Copyright Notice in klisp.h +*/ + +#ifndef kapplicative_h +#define kapplicative_h + +#include "kobject.h" +#include "kstate.h" + +TValue kwrap(klisp_State *K, TValue underlying); +TValue kmake_applicative(klisp_State *K, TValue name, TValue si, + TValue underlying); + +#endif diff --git a/src/klisp.c b/src/klisp.c @@ -24,6 +24,7 @@ #include "kcontinuation.h" #include "kenvironment.h" #include "koperative.h" +#include "kapplicative.h" #include "kpair.h" #include "ksymbol.h" #include "kerror.h" @@ -40,24 +41,110 @@ void exit_fn(klisp_State *K, TValue *xparams, TValue obj) return; } -/* eval helper */ +/* eval helpers */ +void eval_ls_cfn(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: this argument list pair + ** xparams[1]: dynamic environment + ** xparams[2]: first-cycle-pair/NIL + ** xparams[3]: combiner + */ + TValue apair = xparams[0]; + TValue rest = kcdr(apair); + TValue env = xparams[1]; + TValue tail = xparams[2]; + TValue combiner = xparams[3]; + + /* save the result of last evaluation and continue with next pair */ + kset_car(apair, obj); + if (ttisnil(rest)) { + /* argument evaluation complete */ + /* this is necessary to recreate the cycle in operand list */ + kset_cdr(apair, tail); + kapply_cc(K, combiner); + } else { + /* more arguments need to be evaluated */ + TValue new_cont = kmake_continuation(K, kget_cc(K), KNIL, KNIL, + &eval_ls_cfn, 4, rest, env, + tail, combiner); + kset_cc(K, new_cont); + ktail_call(K, K->eval_op, kcar(rest), env); + } +} + +inline void clear_ls_marks(TValue ls) +{ + while (ttispair(ls) && kis_marked(ls)) { + kunmark(ls); + ls = kcdr(ls); + } +} + +/* operands should be a pair */ +inline TValue make_arg_ls(klisp_State *K, TValue operands, TValue *tail) +{ + TValue arg_ls = kcons(K, kcar(operands), KNIL); + TValue last_pair = arg_ls; + kset_mark(operands, last_pair); + TValue rem_op = kcdr(operands); + + while(ttispair(rem_op) && kis_unmarked(rem_op)) { + TValue new_pair = kcons(K, kcar(rem_op), KNIL); + kset_mark(rem_op, new_pair); + kset_cdr(last_pair, new_pair); + last_pair = new_pair; + rem_op = kcdr(rem_op); + } + + if (ttispair(rem_op)) { + /* cyclical list */ + *tail = kget_mark(rem_op); + } else if (ttisnil(rem_op)) { + *tail = KNIL; + } else { + clear_ls_marks(operands); + klispE_throw(K, "Not a list in applicative combination", true); + return KINERT; + } + clear_ls_marks(operands); + return arg_ls; +} + void combine_cfn(klisp_State *K, TValue *xparams, TValue obj) { /* - ** tparams[0]: operand list - ** tparams[1]: dynamic environment + ** xparams[0]: operand list + ** xparams[1]: dynamic environment */ TValue operands = xparams[0]; TValue env = xparams[1]; switch(ttype(obj)) { - case K_TAPPLICATIVE: - /* TODO */ - kapply_cc(K, KINERT); - break; + case K_TAPPLICATIVE: { + if (ttisnil(operands)) { + /* no arguments => no evaluation, just call the operative */ + /* NOTE: the while is needed because it may be multiply wrapped */ + while(ttisapplicative(obj)) + obj = tv2app(obj)->underlying; + ktail_call(K, obj, operands, env); + } else if (ttispair(operands)) { + /* make a copy of the operands (for storing arguments) */ + TValue tail; + TValue arg_ls = make_arg_ls(K, operands, &tail); + + TValue comb_cont = kmake_continuation( + K, kget_cc(K), KNIL, KNIL, &combine_cfn, 2, arg_ls, env); + + TValue els_cont = kmake_continuation( + K, comb_cont, KNIL, KNIL, &eval_ls_cfn, + 4, arg_ls, env, tail, tv2app(obj)->underlying); + kset_cc(K, els_cont); + ktail_call(K, K->eval_op, kcar(arg_ls), env); + } + } case K_TOPERATIVE: ktail_call(K, obj, operands, env); - break; default: klispE_throw(K, "Not a combiner in combiner position", true); return; @@ -141,6 +228,7 @@ void match_cfn(klisp_State *K, TValue *xparams, TValue obj) /* the underlying function of a simple define */ void def_ofn(klisp_State *K, TValue *xparams, TValue obj, TValue env) { + (void) xparams; if (!ttispair(obj) || !ttispair(kcdr(obj)) || !ttisnil(kcdr(kcdr(obj)))) { klispE_throw(K, "Bad syntax ($define!)", true); return; @@ -159,6 +247,19 @@ void def_ofn(klisp_State *K, TValue *xparams, TValue obj, TValue env) } } +/* the underlying function of cons */ +void cons_ofn(klisp_State *K, TValue *xparams, TValue obj, TValue env) +{ + if (!ttispair(obj) || !ttispair(kcdr(obj)) || !ttisnil(kcdr(kcdr(obj)))) { + klispE_throw(K, "Bad syntax (cons)", true); + return; + } + TValue car = kcar(obj); + TValue cdr = kcar(kcdr(obj)); + TValue new_pair = kcons(K, car, cdr); + kapply_cc(K, new_pair); +} + int main(int argc, char *argv[]) { printf("Read/Write Test\n"); @@ -168,9 +269,15 @@ int main(int argc, char *argv[]) /* set up the continuations */ K->eval_op = kmake_operative(K, KNIL, KNIL, eval_ofn, 0); TValue ground_env = kmake_empty_environment(K); + TValue g_define = kmake_operative(K, KNIL, KNIL, def_ofn, 0); TValue s_define = ksymbol_new(K, "$define!"); kadd_binding(K, ground_env, s_define, g_define); + + TValue g_cons = kwrap(K, kmake_operative(K, KNIL, KNIL, cons_ofn, 0)); + TValue s_cons = ksymbol_new(K, "cons"); + kadd_binding(K, ground_env, s_cons, g_cons); + TValue std_env = kmake_environment(K, ground_env); TValue root_cont = kmake_continuation(K, KNIL, KNIL, KNIL, exit_fn, 0); diff --git a/src/kobject.h b/src/kobject.h @@ -178,6 +178,10 @@ typedef struct __attribute__ ((__packed__)) GCheader { #define ttisstring(o) (tbasetype_(o) == K_TAG_STRING) #define ttissymbol(o) (tbasetype_(o) == K_TAG_SYMBOL) #define ttispair(o) (tbasetype_(o) == K_TAG_PAIR) +#define ttisoperative(o) (tbasetype_(o) == K_TAG_OPERATIVE) +#define ttisapplicative(o) (tbasetype_(o) == K_TAG_APPLICATIVE) +#define ttisenvironment(o) (tbasetype_(o) == K_TAG_ENVIRONMENT) +#define ttiscontinuation(o) (tbasetype_(o) == K_TAG_CONTINUATION) /* @@ -357,6 +361,7 @@ const TValue keminf; #define gc2env(o_) (gc2tv(K_TAG_ENVIRONMENT, o_)) #define gc2cont(o_) (gc2tv(K_TAG_CONTINUATION, o_)) #define gc2op(o_) (gc2tv(K_TAG_OPERATIVE, o_)) +#define gc2app(o_) (gc2tv(K_TAG_APPLICATIVE, o_)) /* Macro to convert a TValue into a specific heap allocated object */ #define tv2pair(v_) ((Pair *) gcvalue(v_)) @@ -365,6 +370,7 @@ const TValue keminf; #define tv2env(v_) ((Environment *) gcvalue(v_)) #define tv2cont(v_) ((Continuation *) gcvalue(v_)) #define tv2op(v_) ((Operative *) gcvalue(v_)) +#define tv2app(v_) ((Applicative *) gcvalue(v_)) #define tv2mgch(v_) ((MGCheader *) gcvalue(v_))