klisp

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

commit 9a95a9f6f843044e72cee78d5429d5b0c4481588
parent 9f464f5bd174710f1505ac1a7b9920b30cbc66b1
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Wed, 30 Nov 2011 04:41:43 -0300

Fixed problem with passing values to the root continuation in interpreter arguments.

Diffstat:
Msrc/klisp.c | 73++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 54 insertions(+), 19 deletions(-)

diff --git a/src/klisp.c b/src/klisp.c @@ -34,10 +34,20 @@ #include "kerror.h" #include "krepl.h" #include "ksystem.h" -#include "kghelpers.h" /* for do_return_value, do_pass_value and do_seq */ +#include "kghelpers.h" /* for do_pass_value and do_seq */ static const char *progname = KLISP_PROGNAME; +/* +** Three possible status after an evaluation: +** error: the error continuation was passed a value -> EXIT_FAILURE +** root: the root continuation was passed a value -> status depends on value +** continue: normally completed evaluation, continue with next argument +*/ +#define STATUS_ERROR -1 +#define STATUS_CONTINUE 0 +#define STATUS_ROOT 1 + static void print_usage (void) { fprintf(stderr, @@ -138,7 +148,7 @@ static void show_error(klisp_State *K, TValue obj) { static int report (klisp_State *K, int status) { - if (status != EXIT_SUCCESS) { + if (status == STATUS_ERROR) { const char *msg = "Error!"; k_message(progname, msg); show_error(K, K->next_value); @@ -212,9 +222,25 @@ void do_int_mark_error(klisp_State *K) kapply_cc(K, error_obj); } +void do_int_mark_root(klisp_State *K) +{ + TValue *xparams = K->next_xparams; + TValue obj = K->next_value; + klisp_assert(ttisnil(K->next_env)); + /* + ** xparams[0]: rootp pointer + */ + UNUSED(obj); /* ignore obj */ + bool *rootp = (bool *) pvalue(xparams[0]); + *rootp = false; /* mark that we didn't explicitly call the root cont */ + /* pass #INERT to the root continuation */ + kapply_cc(K, KINERT); +} + static int dostring (klisp_State *K, const char *s, const char *name) { bool errorp = false; /* may be set to true in error handler */ + bool rootp = true; /* may be set to false in continuation */ UNUSED(name); /* could use as filename?? */ /* create a string input port */ @@ -253,11 +279,11 @@ static int dostring (klisp_State *K, const char *s, const char *name) krooted_tvs_push(K, inner_cont); /* This continuation will discard the result of the evaluation - and pass the root continuation #inert instead. This has to do with - the way the exit value of the interpreter is calculated (see man page) + and return #inert instead, it will also signal via rootp = false + that the evaluation didn't explicitly invoke the root continuation */ - TValue discard_cont = kmake_continuation(K, inner_cont, do_return_value, - 1, KINERT); + TValue discard_cont = kmake_continuation(K, inner_cont, do_int_mark_root, + 1, p2tv(&rootp)); krooted_tvs_pop(K); /* pop inner cont */ krooted_tvs_push(K, discard_cont); @@ -278,7 +304,8 @@ static int dostring (klisp_State *K, const char *s, const char *name) klispS_run(K); - int status = errorp? EXIT_FAILURE : EXIT_SUCCESS; + int status = errorp? STATUS_ERROR : + (rootp? STATUS_ROOT : STATUS_CONTINUE); /* get the standard environment again in K->next_env */ K->next_env = env; return report(K, status); @@ -319,6 +346,7 @@ void do_file_read(klisp_State *K) static int dofile(klisp_State *K, const char *name) { bool errorp = false; /* may be set to true in error handler */ + bool rootp = true; /* may be set to false in continuation */ /* create a file input port (unless it's stdin, then just use) */ TValue port; @@ -379,11 +407,11 @@ static int dofile(klisp_State *K, const char *name) /* This continuation will discard the result of the evaluation - and pass the root continuation #inert instead. This has to do with - the way the exit value of the interpreter is calculated (see man page) + and return #inert instead, it will also signal via rootp = false + that the evaluation didn't explicitly invoke the root continuation */ - TValue discard_cont = kmake_continuation(K, inner_cont, do_return_value, - 1, KINERT); + TValue discard_cont = kmake_continuation(K, inner_cont, do_int_mark_root, + 1, p2tv(&rootp)); krooted_tvs_pop(K); /* pop inner cont */ krooted_tvs_push(K, discard_cont); @@ -404,7 +432,8 @@ static int dofile(klisp_State *K, const char *name) klispS_run(K); - int status = errorp? EXIT_FAILURE : EXIT_SUCCESS; + int status = errorp? STATUS_ERROR : + (rootp? STATUS_ROOT : STATUS_CONTINUE); /* get the standard environment again in K->next_env */ K->next_env = env; @@ -544,7 +573,7 @@ static int handle_klispinit(klisp_State *K) const char *init = getenv(KLISP_INIT); int res; if (init == NULL) - res = EXIT_SUCCESS; + res = STATUS_CONTINUE; else res = dostring(K, init, "=" KLISP_INIT); @@ -555,7 +584,7 @@ static int handle_klispinit(klisp_State *K) struct Smain { int argc; char **argv; - int status; + int status; /* STATUS_ROOT, STATUS_ERROR, STATUS_CONTINUE */ }; static void pmain(klisp_State *K) @@ -563,7 +592,10 @@ static void pmain(klisp_State *K) /* This is weird but was done to follow lua scheme */ struct Smain *s = (struct Smain *) pvalue(K->next_value); char **argv = s->argv; - s->status = EXIT_SUCCESS; + s->status = STATUS_CONTINUE; + /* this is needed in case there are no arguments and no init */ + K->next_value = KINERT; + /* There is a standard env in K->next_env, a common one is used for all evaluations (init, expression args, script/repl) */ @@ -582,7 +614,7 @@ static void pmain(klisp_State *K) /* init (eval KLISP_INIT env variable contents) */ s->status = handle_klispinit(K); - if (s->status != EXIT_SUCCESS) + if (s->status != STATUS_CONTINUE) return; bool has_i = false, has_v = false, has_e = false; @@ -603,14 +635,14 @@ static void pmain(klisp_State *K) s->status = runargs(K, argv, (script > 0) ? script : s->argc); - if (s->status != EXIT_SUCCESS) + if (s->status != STATUS_CONTINUE) return; if (script > 0) { s->status = handle_script(K, argv, script); } - if (s->status != EXIT_SUCCESS) + if (s->status != STATUS_CONTINUE) return; if (has_i) { @@ -642,7 +674,8 @@ int main(int argc, char *argv[]) pmain(K); - if (s.status == EXIT_SUCCESS) { + /* convert s.status to either EXIT_SUCCESS or EXIT_FAILURE */ + if (s.status == STATUS_CONTINUE || s.status == STATUS_ROOT) { /* must check value passed to the root continuation to return proper exit status */ if (ttisinert(K->next_value)) { @@ -654,6 +687,8 @@ int main(int argc, char *argv[]) } else { s.status = EXIT_FAILURE; } + } else { /* s.status == STATUS_ERROR */ + s.status = EXIT_FAILURE; } klisp_close(K);