klisp

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

commit 7cfeb32417607210301aad01b7b31f5b294a9fa2
parent cbeffb8e1ebdd3b53491b728477ae9d08bf2ac44
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun, 20 Nov 2011 20:41:43 -0300

Some refactoring in preparation for the new improved standalone interpreter.

Diffstat:
Msrc/kerror.c | 6++++--
Msrc/kgcontinuations.c | 4+++-
Msrc/kgerror.c | 20++++++++++----------
Msrc/kgnumbers.c | 2++
Msrc/kgpairs_lists.c | 2++
Msrc/klisp.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/krepl.c | 3++-
Msrc/kstate.c | 33+++++++++++++++++++++++++++++++++
Msrc/kstate.h | 5+++++
9 files changed, 134 insertions(+), 27 deletions(-)

diff --git a/src/kerror.c b/src/kerror.c @@ -102,7 +102,8 @@ void klispE_throw_with_irritants(klisp_State *K, char *msg, TValue irritants) kcall_cont(K, K->error_cont, error_obj); } -void klispE_throw_system_error_with_irritants(klisp_State *K, const char *service, int errnum, TValue irritants) +void klispE_throw_system_error_with_irritants( + klisp_State *K, const char *service, int errnum, TValue irritants) { TValue error_description = klispE_describe_errno(K, service, errnum); krooted_tvs_push(K, error_description); @@ -190,7 +191,8 @@ static const char * const symbolic_error_codes[] = { TValue klispE_describe_errno(klisp_State *K, const char *service, int errnum) { const char *code = NULL; - int tabsize = sizeof(symbolic_error_codes) / sizeof(symbolic_error_codes[0]); + int tabsize = sizeof(symbolic_error_codes) / + sizeof(symbolic_error_codes[0]); if (0 <= errnum && errnum < tabsize) code = symbolic_error_codes[errnum]; if (code == NULL) diff --git a/src/kgcontinuations.c b/src/kgcontinuations.c @@ -344,11 +344,13 @@ void kinit_continuations_ground_env(klisp_State *K) add_applicative(K, ground_env, "continuation->applicative", continuation_applicative, 0); /* 7.2.6 root-continuation */ + klisp_assert(ttiscontinuation(K->root_cont)); add_value(K, ground_env, "root-continuation", K->root_cont); /* 7.2.7 error-continuation */ + klisp_assert(ttiscontinuation(K->error_cont)); add_value(K, ground_env, "error-continuation", - K->root_cont); + K->error_cont); /* 7.3.1 apply-continuation */ add_applicative(K, ground_env, "apply-continuation", apply_continuation, 0); diff --git a/src/kgerror.c b/src/kgerror.c @@ -4,7 +4,6 @@ ** See Copyright Notice in klisp.h */ -#include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -36,7 +35,7 @@ void error_object_message(klisp_State *K, TValue *xparams, TValue ptree, UNUSED(denv); bind_1tp(K, ptree, "error object", ttiserror, error_tv); Error *err_obj = tv2error(error_tv); - assert(ttisstring(err_obj->msg)); + klisp_assert(ttisstring(err_obj->msg)); kapply_cc(K, err_obj->msg); } @@ -49,7 +48,7 @@ void error_object_irritants(klisp_State *K, TValue *xparams, TValue ptree, Error *err_obj = tv2error(error_tv); kapply_cc(K, err_obj->irritants); } - +/* REFACTOR this is the same as do_pass_value */ void do_exception_cont(klisp_State *K, TValue *xparams, TValue obj) { UNUSED(xparams); @@ -57,17 +56,15 @@ void do_exception_cont(klisp_State *K, TValue *xparams, TValue obj) kapply_cc(K, obj); } +/* REFACTOR maybe this should be in kerror.c */ /* Create system-error-continuation. */ void kinit_error_hierarchy(klisp_State *K) { - assert(ttiscontinuation(K->error_cont)); - assert(ttisinert(K->system_error_cont)); + klisp_assert(ttiscontinuation(K->error_cont)); + klisp_assert(ttisinert(K->system_error_cont)); - K->system_error_cont = kmake_continuation(K, K->error_cont, do_exception_cont, 0); - TValue symbol = ksymbol_new(K, "system-error-continuation", KNIL); - krooted_tvs_push(K, symbol); - kadd_binding(K, K->ground_env, symbol, K->system_error_cont); - krooted_tvs_pop(K); + K->system_error_cont = kmake_continuation(K, K->error_cont, + do_exception_cont, 0); } /* init ground */ @@ -80,4 +77,7 @@ void kinit_error_ground_env(klisp_State *K) add_applicative(K, ground_env, "error", r7rs_error, 0); add_applicative(K, ground_env, "error-object-message", error_object_message, 0); add_applicative(K, ground_env, "error-object-irritants", error_object_irritants, 0); + + klisp_assert(ttiscontinuation(K->system_error_cont)); + add_value(K, ground_env, "system-error-continuation", K->system_error_cont); } diff --git a/src/kgnumbers.c b/src/kgnumbers.c @@ -2351,4 +2351,6 @@ void kinit_numbers_ground_env(klisp_State *K) add_applicative(K, ground_env, "sqrt", ksqrt, 0); /* 12.9.6 expt */ add_applicative(K, ground_env, "expt", kexpt, 0); + + /* TODO add some conversion like number->string, string->number */ } diff --git a/src/kgpairs_lists.c b/src/kgpairs_lists.c @@ -1101,4 +1101,6 @@ void kinit_pairs_lists_ground_env(klisp_State *K) add_applicative(K, ground_env, "countable-list?", countable_listp, 0); /* 6.3.10 reduce */ add_applicative(K, ground_env, "reduce", reduce, 0); + + /* TODO add make-list, list-copy and reverse (from r7rs) */ } diff --git a/src/klisp.c b/src/klisp.c @@ -17,20 +17,80 @@ #include "kauxlib.h" #include "kscript.h" +/* TODO this should be moved to a file named like klispconf.h (see lua) */ +/* +@@ KLISP_PROGNAME is the default name for the stand-alone klisp program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define KLISP_PROGNAME "klisp" + +/* +@@ KLISP_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define KLISP_QL(x) "'" x "'" +#define KLISP_QS KLISP_QL("%s") +/* /TODO */ + +static const char *progname = KLISP_PROGNAME; + +static void print_usage (void) { + fprintf(stderr, + "usage: %s [options] [script [args]].\n" + "Available options are:\n" + " -e exp eval string " KLISP_QL("exp") "\n" +// " -l name require library " KLISP_QL("name") "\n" + " -i enter interactive mode after executing " + KLISP_QL("script") "\n" + " -v show version information\n" + " -- stop handling options\n" + " - execute stdin and stop handling options\n" + , + progname); + fflush(stderr); +} + +static void k_message (const char *pname, const char *msg) { + if (pname) + fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); +} + +struct Smain { + int argc; + char **argv; + int status; +}; + int main(int argc, char *argv[]) { - if (argc <= 1) { - klisp_State *K = klispL_newstate(); - klispS_init_repl(K); - klispS_run(K); - klisp_close(K); - return 0; - } else { - klisp_State *K = klispL_newstate(); - kinit_script(K, argc - 1, argv + 1); - klispS_run(K); - int exit_code = K->script_exit_code; - klisp_close(K); - return exit_code; + if (argv[0] && argv[0][0]) + progname = argv[0]; + + klisp_State *K = klispL_newstate(); + + if (K == NULL) { + k_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; } + + /* TODO Here we should load libraries, however we don't have any + non native bindings in the ground environment yet */ + /* RATIONALE I wanted to write all bindings in c, so that I can later on + profile them against non native versions and see how they fare. + Also by writing all in c it's easy to be consistent, especially with + error messages */ + + /* XXX Fix REPL, Fix Script */ + + // klispS_run(K); /* XXX Now this does nothing */ + int exit_code = EXIT_FAILURE; // K->script_exit_code; + klisp_close(K); + + /* TEMP */ + print_usage(); + + return exit_code; } diff --git a/src/krepl.c b/src/krepl.c @@ -43,6 +43,7 @@ void do_repl_read(klisp_State *K, TValue *xparams, TValue obj) UNUSED(obj); /* show prompt */ + /* TODO put this in a variable like in lua */ fprintf(stdout, "klisp> "); TValue port = kcdr(K->kd_in_port_key); @@ -131,7 +132,7 @@ void do_repl_error(klisp_State *K, TValue *xparams, TValue obj) /* FOR NOW used only for irritant list */ TValue port = kcdr(K->kd_error_port_key); - klisp_assert(kfport_file(port) == stderr); + klisp_assert(ttisfport(port) && kfport_file(port) == stderr); /* TEMP: obj should be an error obj */ if (ttiserror(obj)) { diff --git a/src/kstate.c b/src/kstate.c @@ -38,6 +38,7 @@ #include "kbytevector.h" #include "kgpairs_lists.h" /* for creating list_app */ +#include "kerror.h" /* for creating error hierarchy */ #include "kgc.h" /* for memory freeing & gc init */ @@ -238,6 +239,13 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) { /* TODO si */ K->module_params_sym = ksymbol_new(K, "module-parameters", KNIL); + /* Create the root and error continuation (will be added to the + environment in kinit_ground_env) */ + K->root_cont = kmake_continuation(K, KNIL, do_root_exit, 0); + K->error_cont = kmake_continuation(K, K->root_cont, do_error_exit, 0); + /* this must be done before calling kinit_ground_env */ + kinit_error_hierarchy(K); + kinit_ground_env(K); /* set the threshold for gc start now that we have allocated all mem */ @@ -247,6 +255,31 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) { } /* +** Root and Error continuations +*/ +void do_root_exit(klisp_State *K, TValue *xparams, TValue obj) +{ + UNUSED(xparams); + + /* Just save the value and end the loop */ + K->next_value = obj; + /* TEMP the return code is SUCCESS iff obj is inert */ + K->script_exit_code = ttisinert(obj)? EXIT_SUCCESS : EXIT_FAILURE; + K->next_func = NULL; /* force the loop to terminate */ + return; +} + +void do_error_exit(klisp_State *K, TValue *xparams, TValue obj) +{ + UNUSED(xparams); + UNUSED(obj); + + /* TEMP Just pass a value to the root continuation that + would result in an EXIT_FAILURE */ + kapply_cc(K, KFALSE); +} + +/* ** Stacks memory management */ diff --git a/src/kstate.h b/src/kstate.h @@ -142,6 +142,7 @@ struct klisp_State { bool write_displayp; /* script */ + /* REFACTOR rename to exit_code */ int script_exit_code; /* auxiliary stack */ @@ -497,6 +498,10 @@ void klisp_close (klisp_State *K); void do_interception(klisp_State *K, TValue *xparams, TValue obj); +/* for root and error continuations */ +void do_root_exit(klisp_State *K, TValue *xparams, TValue obj); +void do_error_exit(klisp_State *K, TValue *xparams, TValue obj); + /* simple accessors for dynamic keys */ /* XXX: this is ugly but we can't include kpair.h here so... */