klisp

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

commit b4b80374ad6c5875f11f158df8e063d23ca773a7
parent 9ad171b1c2435c8b4609a3879183ebdc473d9e7c
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun,  6 Mar 2011 23:51:19 -0300

Errors now use continuations. Improved repl code. Moved ground env init to a new file.

Diffstat:
Msrc/Makefile | 16++++++++++------
Msrc/kenvironment.c | 2+-
Msrc/kerror.c | 47++++++++++++++++++++++++++++++++++++-----------
Msrc/kerror.h | 5++---
Msrc/keval.c | 4++--
Asrc/kground.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/kground.h | 14++++++++++++++
Msrc/klisp.c | 96+++----------------------------------------------------------------------------
Msrc/kmem.c | 8++++++--
Msrc/kmem.h | 8++++----
Msrc/kread.c | 2+-
Msrc/krepl.c | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/krepl.h | 4+---
Msrc/kstate.c | 185+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/kstate.h | 8++++++--
Msrc/ktoken.c | 2+-
Msrc/kwrite.c | 2+-
17 files changed, 343 insertions(+), 218 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -9,7 +9,8 @@ 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 kapplicative.o keval.o krepl.o + kcontinuation.o koperative.o kapplicative.o keval.o krepl.o \ + kground.o KRN_T= klisp KRN_O= klisp.o @@ -25,7 +26,7 @@ all: $(ALL_T) o: $(ALL_O) $(KRN_T): $(ALL_O) - $(CC) -o $@ $(MYLDFLAGS) $(ALL_O) $(LIBS) + $(CC) $(CFLAGS) -o $@ $(MYLDFLAGS) $(ALL_O) $(LIBS) clean: $(RM) $(ALL_T) $(ALL_O) @@ -46,9 +47,10 @@ ksymbol.o: ksymbol.c ksymbol.h kobject.h kpair.h kstate.h kmem.h klisp.h kread.o: kread.c kread.h kobject.h ktoken.h kpair.h kstate.h kerror.h klisp.h kwrite.o: kwrite.c kwrite.h kobject.h kpair.h kstring.h kstate.h kerror.h \ klisp.h -kstate.o: kstate.c kstate.h klisp.h kobject.h kmem.h kstring.h klisp.h +kstate.o: kstate.c kstate.h klisp.h kobject.h kmem.h kstring.h klisp.h \ + kground.h kmem.o: kmem.c kmem.h klisp.h kerror.h klisp.h -kerror.o: kerror.c kerror.h klisp.h kstate.h klisp.h +kerror.o: kerror.c kerror.h klisp.h kstate.h klisp.h kmem.h kstring.h kauxlib.o: kauxlib.c kauxlib.h klisp.h kstate.h klisp.h kenvironment.o: kenvironment.c kenvironment.h kpair.h kobject.h kerror.h \ kmem.h kstate.h klisp.h @@ -61,4 +63,6 @@ kapplicative.o: kapplicative.c kapplicative.h kmem.h kstate.h kobject.h \ keval.o: keval.c keval.h kcontinuation.h kenvironment.h kstate.h kobject.h \ kpair.h kerror.h klisp.h krepl.o: krepl.c krepl.h kcontinuation.h kstate.h kobject.h keval.h klisp.h \ - kread.h kwrite.h -\ No newline at end of file + kread.h kwrite.h kenvironment.h +kground.o: kground.c kground.h kstate.h kobject.h klisp.h kenvironment.h \ + kpair.h kapplicative.h koperative.h ksymbol.h kerror.h +\ No newline at end of file diff --git a/src/kenvironment.c b/src/kenvironment.c @@ -77,7 +77,7 @@ TValue kget_binding(klisp_State *K, TValue env, TValue sym) env = kenv_parents(K, env); } - klispE_throw_extra(K, "Unbound symbol", ksymbol_buf(sym), true); + klispE_throw_extra(K, "Unbound symbol", ksymbol_buf(sym)); /* avoid warning */ return KINERT; } diff --git a/src/kerror.c b/src/kerror.c @@ -1,23 +1,48 @@ #include <stdio.h> +#include <string.h> #include <stdlib.h> -#include <stdbool.h> -#include <setjmp.h> #include "klisp.h" #include "kstate.h" +#include "kmem.h" +#include "kstring.h" -void klispE_throw(klisp_State *K, char *msg, bool can_cont) +void clear_buffers(klisp_State *K) { - fprintf(stderr, "\n*ERROR*: %s\n", msg); - K->error_can_cont = can_cont; - longjmp(K->error_jb, 1); + /* XXX: clear stack and char buffer, clear shared dict */ + /* TODO: put these in handlers for read-token, read and write */ + ks_sclear(K); + ks_tbclear(K); + K->shared_dict = KNIL; +} + +void klispE_throw(klisp_State *K, char *msg) +{ + TValue error_msg = kstring_new(K, msg, strlen(msg)); + /* TEMP */ + clear_buffers(K); + + kcall_cont(K, K->error_cont, error_msg); } /* TEMP: for throwing with extra msg info */ -void klispE_throw_extra(klisp_State *K, char *msg, char *extra_msg, - bool can_cont) { - fprintf(stderr, "\n*ERROR*: %s %s\n", msg, extra_msg); - K->error_can_cont = can_cont; - longjmp(K->error_jb, 1); +void klispE_throw_extra(klisp_State *K, char *msg, char *extra_msg) { + /* TODO */ + int32_t l1 = strlen(msg); + int32_t l2 = strlen(extra_msg); + + int32_t tl = l1+l2+1; + + char *msg_buf = klispM_malloc(K, tl+1); + strcpy(msg_buf, msg); + msg_buf[l1] = ' '; + strcpy(msg_buf+l1+1, extra_msg); + + TValue error_msg = kstring_new(K, msg_buf, tl); + klispM_freemem(K, msg_buf, tl+1); + + clear_buffers(K); + + kcall_cont(K, K->error_cont, error_msg); } diff --git a/src/kerror.h b/src/kerror.h @@ -13,9 +13,8 @@ #include "klisp.h" #include "kstate.h" -void klispE_throw(klisp_State *K, char *msg, bool can_cont); +void klispE_throw(klisp_State *K, char *msg); /* TEMP: for throwing with extra msg info */ -void klispE_throw_extra(klisp_State *K, char *msg, char *extra_msg, - bool can_cont); +void klispE_throw_extra(klisp_State *K, char *msg, char *extra_msg); #endif diff --git a/src/keval.c b/src/keval.c @@ -78,7 +78,7 @@ inline TValue make_arg_ls(klisp_State *K, TValue operands, TValue *tail) *tail = KNIL; } else { clear_ls_marks(operands); - klispE_throw(K, "Not a list in applicative combination", true); + klispE_throw(K, "Not a list in applicative combination"); return KINERT; } clear_ls_marks(operands); @@ -120,7 +120,7 @@ void combine_cfn(klisp_State *K, TValue *xparams, TValue obj) case K_TOPERATIVE: ktail_call(K, obj, operands, env); default: - klispE_throw(K, "Not a combiner in combiner position", true); + klispE_throw(K, "Not a combiner in combiner position"); return; } } diff --git a/src/kground.c b/src/kground.c @@ -0,0 +1,84 @@ +/* +** kground.h +** Bindings in the ground environment +** See Copyright Notice in klisp.h +*/ + +/* TODO: split in different files for each module */ +#include "kstate.h" +#include "kobject.h" +#include "kground.h" +#include "kpair.h" +#include "kenvironment.h" +#include "kcontinuation.h" +#include "ksymbol.h" +#include "koperative.h" +#include "kapplicative.h" +#include "kerror.h" + +/* define helper */ +void match_cfn(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** tparams[0]: ptree + ** tparams[1]: dynamic environment + */ + TValue ptree = xparams[0]; + TValue env = xparams[1]; + + /* TODO: allow general parameter trees */ + if (!ttisignore(ptree)) { + kadd_binding(K, env, ptree, obj); + } + kapply_cc(K, KINERT); +} + +/* 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!)"); + return; + } + TValue ptree = kcar(obj); + TValue exp = kcar(kcdr(obj)); + /* TODO: allow general ptrees */ + if (!ttissymbol(ptree) && !ttisignore(ptree)) { + klispE_throw(K, "Not a symbol or ignore ($define!)"); + return; + } else { + TValue new_cont = kmake_continuation(K, kget_cc(K), KNIL, KNIL, + &match_cfn, 2, ptree, env); + kset_cc(K, new_cont); + ktail_call(K, K->eval_op, exp, 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)"); + return; + } + TValue car = kcar(obj); + TValue cdr = kcar(kcdr(obj)); + TValue new_pair = kcons(K, car, cdr); + kapply_cc(K, new_pair); +} + +TValue kmake_ground_env(klisp_State *K) +{ + 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); + + return ground_env; +} diff --git a/src/kground.h b/src/kground.h @@ -0,0 +1,14 @@ +/* +** kground.h +** Bindings in the ground environment +** See Copyright Notice in klisp.h +*/ + +#ifndef kground_h +#define kground_h + +#include "kstate.h" + +TValue kmake_ground_env(klisp_State *K); + +#endif diff --git a/src/klisp.c b/src/klisp.c @@ -31,110 +31,20 @@ #include "ksymbol.h" #include "kerror.h" - -/* define helper */ -void match_cfn(klisp_State *K, TValue *xparams, TValue obj) -{ - /* - ** tparams[0]: ptree - ** tparams[1]: dynamic environment - */ - TValue ptree = xparams[0]; - TValue env = xparams[1]; - - /* TODO: allow general parameter trees */ - if (!ttisignore(ptree)) { - kadd_binding(K, env, ptree, obj); - } - kapply_cc(K, KINERT); -} - -/* 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; - } - TValue ptree = kcar(obj); - TValue exp = kcar(kcdr(obj)); - /* TODO: allow general ptrees */ - if (!ttissymbol(ptree) && !ttisignore(ptree)) { - klispE_throw(K, "Not a symbol or ignore ($define!)", true); - return; - } else { - TValue new_cont = kmake_continuation(K, kget_cc(K), KNIL, KNIL, - &match_cfn, 2, ptree, env); - kset_cc(K, new_cont); - ktail_call(K, K->eval_op, exp, 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"); klisp_State *K = klispL_newstate(); - - /* set up the continuations */ - K->eval_op = kmake_operative(K, KNIL, KNIL, keval_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); - TValue loop_cont = kmake_continuation( - K, root_cont, KNIL, KNIL, &loop_fn, 1, std_env); - TValue eval_cont = kmake_continuation( - K, loop_cont, KNIL, KNIL, &eval_cfn, 1, std_env); - - kset_cc(K, eval_cont); - /* NOTE: this will take effect only in the while (K->next_func) loop */ - klispS_apply_cc(K, kread(K)); + kinit_repl(K); int ret_value = 0; bool done = false; while(!done) { if (setjmp(K->error_jb)) { - /* error signaled */ - if (K->error_can_cont) { - /* XXX: clear stack and char buffer, clear shared dict */ - /* TODO: put these in handlers for read-token, read and write */ - ks_sclear(K); - ks_tbclear(K); - K->shared_dict = KNIL; - - kset_cc(K, eval_cont); - /* NOTE: this will take effect only in the while (K->next_func) loop */ - klispS_apply_cc(K, kread(K)); - } else { - printf("Aborting...\n"); - ret_value = 1; - done = true; - } + /* continuation called */ + /* TEMP: do nothing, the loop will call the continuation */ } else { /* all ok, continue with next func */ while (K->next_func) { diff --git a/src/kmem.c b/src/kmem.c @@ -10,6 +10,7 @@ */ #include <stddef.h> +#include <stdio.h> #include <assert.h> #include "klisp.h" @@ -43,8 +44,11 @@ void *klispM_realloc_ (klisp_State *K, void *block, size_t osize, size_t nsize) klisp_assert((osize == 0) == (block == NULL)); block = (*K->frealloc)(K->ud, block, osize, nsize); - if (block == NULL && nsize > 0) - klispE_throw(K, MEMERRMSG, false); + if (block == NULL && nsize > 0) { + /* TODO: make this a catchable error */ + fprintf(stderr, MEMERRMSG); + abort(); + } klisp_assert((nsize == 0) == (block == NULL)); K->totalbytes = (K->totalbytes - osize) + nsize; return block; diff --git a/src/kmem.h b/src/kmem.h @@ -17,11 +17,11 @@ #define MEMERRMSG "not enough memory" -#define klispM_freemem(L, b, s) klispM_realloc_(L, (b), (s), 0) -#define klispM_free(L, b) klispM_realloc_(L, (b), sizeof(*(b)), 0) +#define klispM_freemem(K, b, s) klispM_realloc_(K, (b), (s), 0) +#define klispM_free(K, b) klispM_realloc_(K, (b), sizeof(*(b)), 0) -#define klispM_malloc(L,t) klispM_realloc_(L, NULL, 0, (t)) -#define klispM_new(L,t) cast(t *, klispM_malloc(L, sizeof(t))) +#define klispM_malloc(K,t) klispM_realloc_(K, NULL, 0, (t)) +#define klispM_new(K,t) cast(t *, klispM_malloc(K, sizeof(t))) void *klispM_realloc_ (klisp_State *K, void *block, size_t oldsize, size_t size); diff --git a/src/kread.c b/src/kread.c @@ -67,7 +67,7 @@ void kread_error(klisp_State *K, char *str) { /* clear the stack */ ks_sclear(K); - klispE_throw(K, str, true); + klispE_throw(K, str); } /* diff --git a/src/krepl.c b/src/krepl.c @@ -10,9 +10,11 @@ #include "kstate.h" #include "kobject.h" #include "kcontinuation.h" +#include "kenvironment.h" #include "kerror.h" -#include "kwrite.h" #include "kread.h" +#include "kwrite.h" +#include "kstring.h" #include "krepl.h" /* the exit continuation, it exits the loop */ @@ -27,6 +29,18 @@ void exit_fn(klisp_State *K, TValue *xparams, TValue obj) return; } +/* the underlying function of the read cont */ +void read_fn(klisp_State *K, TValue *xparams, TValue obj) +{ + (void) obj; + (void) xparams; + + /* show prompt */ + fprintf(stdout, "klisp> "); + obj = kread(K); + kapply_cc(K,obj); +} + /* the underlying function of the eval cont */ void eval_cfn(klisp_State *K, TValue *xparams, TValue obj) { @@ -38,6 +52,21 @@ void eval_cfn(klisp_State *K, TValue *xparams, TValue obj) ktail_call(K, K->eval_op, obj, denv); } +void loop_fn(klisp_State *K, TValue *xparams, TValue obj); + +/* this is called from both loop_fn and error_fn */ +inline void create_loop(klisp_State *K, TValue denv) +{ + TValue loop_cont = kmake_continuation( + K, K->root_cont, KNIL, KNIL, &loop_fn, 1, denv); + TValue eval_cont = kmake_continuation( + K, loop_cont, KNIL, KNIL, &eval_cfn, 1, denv); + TValue read_cont = kmake_continuation( + K, eval_cont, KNIL, KNIL, &read_fn, 0); + kset_cc(K, read_cont); + kapply_cc(K, KINERT); +} + /* the underlying function of the write & loop cont */ void loop_fn(klisp_State *K, TValue *xparams, TValue obj) { @@ -51,13 +80,40 @@ void loop_fn(klisp_State *K, TValue *xparams, TValue obj) kwrite(K, obj); knewline(K); TValue denv = xparams[0]; - - TValue loop_cont = kmake_continuation( - K, kget_cc(K), KNIL, KNIL, &loop_fn, 1, denv); - TValue eval_cont = kmake_continuation( - K, loop_cont, KNIL, KNIL, &eval_cfn, 1, denv); - kset_cc(K, eval_cont); - TValue robj = kread(K); - kapply_cc(K, robj); + create_loop(K, denv); } } + +/* the underlying function of the error cont */ +void error_fn(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: dynamic environment + */ + /* TEMP: obj should be a string */ + /* TODO: create some kind of error object */ + char *str = ttisstring(obj)? + kstring_buf(obj) : "not a string passed to error continuation"; + + fprintf(stderr, "\n*ERRROR*: %s\n", str); + + TValue denv = xparams[0]; + create_loop(K, denv); +} + +/* call this to init the repl in a newly created klisp state */ +void kinit_repl(klisp_State *K) +{ + TValue std_env = kmake_environment(K, K->ground_env); + + /* set up the continuations */ + TValue root_cont = kmake_continuation(K, KNIL, KNIL, KNIL, + exit_fn, 0); + TValue error_cont = kmake_continuation(K, KNIL, KNIL, KNIL, + error_fn, 1, std_env); + + K->root_cont = root_cont; + K->error_cont = error_cont; + + create_loop(K, std_env); +} diff --git a/src/krepl.h b/src/krepl.h @@ -11,8 +11,6 @@ #include "kstate.h" #include "kobject.h" -void loop_fn(klisp_State *K, TValue *xparams, TValue obj); -void eval_cfn(klisp_State *K, TValue *xparams, TValue obj); -void exit_fn(klisp_State *K, TValue *xparams, TValue obj); +void kinit_repl(klisp_State *K); #endif diff --git a/src/kstate.c b/src/kstate.c @@ -9,102 +9,129 @@ */ #include <stddef.h> +#include <setjmp.h> #include "klisp.h" #include "kstate.h" +#include "kobject.h" #include "kstring.h" #include "kpair.h" #include "kmem.h" +#include "keval.h" +#include "koperative.h" +#include "kground.h" + /* ** State creation and destruction */ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) { - klisp_State *K; - void *k = (*f)(ud, NULL, 0, state_size()); - if (k == NULL) return NULL; - void *s = (*f)(ud, NULL, 0, KS_ISSIZE * sizeof(TValue)); - if (s == NULL) { - (*f)(ud, k, state_size(), 0); - return NULL; - } - void *b = (*f)(ud, NULL, 0, KS_ITBSIZE); - if (b == NULL) { - (*f)(ud, k, state_size(), 0); - (*f)(ud, s, KS_ISSIZE * sizeof(TValue), 0); - return NULL; - } - - K = (klisp_State *) k; - - K->symbol_table = KNIL; - /* TODO: create a continuation */ - K->curr_cont = KNIL; - - K->next_func = NULL; - K->next_value = KINERT; - K->next_env = KNIL; - K->next_xparams = NULL; - - K->eval_op = KINERT; - - K->frealloc = f; - K->ud = ud; - - /* current input and output */ - K->curr_in = stdin; - K->curr_out = stdout; - K->filename_in = "*STDIN*"; - K->filename_out = "*STDOUT*"; - - /* TODO: more gc info */ - K->totalbytes = KS_ISSIZE + state_size(); - - /* TEMP: err */ - /* do nothing for now */ - - /* initialize strings */ - /* Empty string */ - /* TODO: make it uncollectible */ - K->empty_string = kstring_new_empty(K); - - /* initialize tokenizer */ - - /* WORKAROUND: for stdin line buffering & reading of EOF */ - K->ktok_seen_eof = false; - - ks_tbsize(K) = KS_ITBSIZE; - ks_tbidx(K) = 0; /* buffer is empty */ - ks_tbuf(K) = (char *)b; - - /* Special Tokens */ - K->ktok_lparen = kcons(K, ch2tv('('), KNIL); - K->ktok_rparen = kcons(K, ch2tv(')'), KNIL); - K->ktok_dot = kcons(K, ch2tv('.'), KNIL); - - /* TEMP: For now just hardcode it to 8 spaces tab-stop */ - K->ktok_source_info.tab_width = 8; - K->ktok_source_info.filename = "*STDIN*"; - ktok_init(K); - ktok_reset_source_info(K); - - /* initialize reader */ - K->shared_dict = KNIL; - - /* initialize writer */ - - /* initialize temp stack */ - K->ssize = KS_ISSIZE; - K->stop = 0; /* stack is empty */ - K->sbuf = (TValue *)s; - - return K; + klisp_State *K; + void *k = (*f)(ud, NULL, 0, state_size()); + if (k == NULL) return NULL; + void *s = (*f)(ud, NULL, 0, KS_ISSIZE * sizeof(TValue)); + if (s == NULL) { + (*f)(ud, k, state_size(), 0); + return NULL; + } + void *b = (*f)(ud, NULL, 0, KS_ITBSIZE); + if (b == NULL) { + (*f)(ud, k, state_size(), 0); + (*f)(ud, s, KS_ISSIZE * sizeof(TValue), 0); + return NULL; + } + + K = (klisp_State *) k; + + K->symbol_table = KNIL; + /* TODO: create a continuation */ + K->curr_cont = KNIL; + + K->next_func = NULL; + K->next_value = KINERT; + K->next_env = KNIL; + K->next_xparams = NULL; + + K->eval_op = KINERT; + K->ground_env = KINERT; + + K->frealloc = f; + K->ud = ud; + + /* current input and output */ + K->curr_in = stdin; + K->curr_out = stdout; + K->filename_in = "*STDIN*"; + K->filename_out = "*STDOUT*"; + + /* TODO: more gc info */ + K->totalbytes = KS_ISSIZE + state_size(); + + /* TEMP: err */ + /* do nothing for now */ + + /* initialize strings */ + /* Empty string */ + /* TODO: make it uncollectible */ + K->empty_string = kstring_new_empty(K); + + /* initialize tokenizer */ + + /* WORKAROUND: for stdin line buffering & reading of EOF */ + K->ktok_seen_eof = false; + + ks_tbsize(K) = KS_ITBSIZE; + ks_tbidx(K) = 0; /* buffer is empty */ + ks_tbuf(K) = (char *)b; + + /* Special Tokens */ + K->ktok_lparen = kcons(K, ch2tv('('), KNIL); + K->ktok_rparen = kcons(K, ch2tv(')'), KNIL); + K->ktok_dot = kcons(K, ch2tv('.'), KNIL); + + /* TEMP: For now just hardcode it to 8 spaces tab-stop */ + K->ktok_source_info.tab_width = 8; + K->ktok_source_info.filename = "*STDIN*"; + ktok_init(K); + ktok_reset_source_info(K); + + /* initialize reader */ + K->shared_dict = KNIL; + + /* initialize writer */ + + /* initialize temp stack */ + K->ssize = KS_ISSIZE; + K->stop = 0; /* stack is empty */ + K->sbuf = (TValue *)s; + + /* create the ground environment and the eval operative */ + K->eval_op = kmake_operative(K, KNIL, KNIL, keval_ofn, 0); + K->ground_env = kmake_ground_env(K); + + return K; } void klisp_close (klisp_State *K) { /* TODO: free memory for all objects */ klispM_freemem(K, ks_sbuf(K), ks_ssize(K)); + klispM_freemem(K, ks_tbuf(K), ks_tbsize(K)); /* NOTE: this needs to be done "by hand" */ (*(K->frealloc))(K->ud, K, state_size(), 0); } + + +void kcall_cont(klisp_State *K, TValue dst_cont, TValue obj) +{ + /* TODO: interceptions */ + Continuation *cont = tv2cont(dst_cont); + K->next_func = cont->fn; + K->next_value = obj; + /* NOTE: this is needed to differentiate a return from a tail call */ + K->next_env = KNIL; + K->next_xparams = cont->extra; + K->curr_cont = cont->parent; + + longjmp(K->error_jb, 1); +} diff --git a/src/kstate.h b/src/kstate.h @@ -51,6 +51,9 @@ struct klisp_State { TValue *next_xparams; TValue eval_op; /* the operative for evaluation */ + TValue ground_env; + TValue root_cont; + TValue error_cont; klisp_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to `frealloc' */ @@ -58,9 +61,8 @@ struct klisp_State { /* TODO: gc info */ int32_t totalbytes; - /* TEMP:error handling */ + /* TEMP: error handling */ jmp_buf error_jb; - bool error_can_cont; /* can continue after error? */ /* standard input and output */ /* TODO: eventually these should be ports */ @@ -268,5 +270,7 @@ inline void klispS_tail_call(klisp_State *K, TValue top, TValue ptree, #define ktail_call(K_, op_, p_, e_) \ klispS_tail_call((K_), (op_), (p_), (e_)); return +void kcall_cont(klisp_State *K, TValue cont, TValue obj); + #endif diff --git a/src/ktoken.c b/src/ktoken.c @@ -222,7 +222,7 @@ void ktok_error(klisp_State *K, char *str) { /* clear the buffer before throwing an error */ ks_tbclear(K); - klispE_throw(K, str, true); + klispE_throw(K, str); } diff --git a/src/kwrite.c b/src/kwrite.c @@ -32,7 +32,7 @@ void kwrite_error(klisp_State *K, char *msg) { - klispE_throw(K, msg, true); + klispE_throw(K, msg); } /*