klisp

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

commit 252802e64cf2670540276320c09c5a631f3c3ad2
parent bc11d230ec4342dc8997eb367d6aaf89d0391c02
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun, 20 Nov 2011 23:31:15 -0300

Added -e argument handling (string evaluation)

Diffstat:
Msrc/kenvironment.c | 2+-
Msrc/kerror.h | 1+
Msrc/kgc.c | 4+++-
Msrc/kgcontinuations.h | 1-
Msrc/kgenvironments.c | 4+++-
Msrc/kgports.c | 4+++-
Msrc/klisp.c | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/kread.c | 2+-
Msrc/kstate.c | 14+++++++-------
9 files changed, 171 insertions(+), 19 deletions(-)

diff --git a/src/kenvironment.c b/src/kenvironment.c @@ -314,7 +314,7 @@ TValue kget_keyed_static_var(klisp_State *K, TValue env, TValue key) } /* environments with hashtable bindings */ -/* TEMP: for now only for ground environment */ +/* TEMP: for now only for ground & std environments */ TValue kmake_table_environment(klisp_State *K, TValue parents) { TValue new_env = kmake_environment(K, parents); diff --git a/src/kerror.h b/src/kerror.h @@ -13,6 +13,7 @@ #include "klisp.h" #include "kstate.h" +#include "kpair.h" /* for klist */ TValue klispE_new(klisp_State *K, TValue who, TValue cont, TValue msg, TValue irritants); diff --git a/src/kgc.c b/src/kgc.c @@ -581,7 +581,7 @@ static void markroot (klisp_State *K) { K->grayagain = NULL; K->weak = NULL; - /* TEMP: this is quite awfull, think of other way to do this */ + /* TEMP: this is quite awful, think of other way to do this */ /* MAYBE: some of these could be FIXED */ markvalue(K, K->name_table); markvalue(K, K->cont_name_table); @@ -612,6 +612,8 @@ static void markroot (klisp_State *K) { markvalue(K, K->ktok_sexp_comment); markvalue(K, K->shared_dict); + markvalue(K, K->curr_port); + /* Mark all objects in the auxiliary stack, (all valid indexes are below top), all the objects in the two protected areas, and the three dummy pairs */ diff --git a/src/kgcontinuations.h b/src/kgcontinuations.h @@ -62,7 +62,6 @@ void kgexit(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); void do_extended_cont(klisp_State *K, TValue *xparams, TValue obj); -void do_pass_value(klisp_State *K, TValue *xparams, TValue obj); /* init ground */ void kinit_continuations_ground_env(klisp_State *K); diff --git a/src/kgenvironments.c b/src/kgenvironments.c @@ -313,7 +313,9 @@ void make_kernel_standard_environment(klisp_State *K, TValue *xparams, UNUSED(denv); check_0p(K, ptree); - TValue new_env = kmake_environment(K, K->ground_env); + /* std environments have hashtable for bindings */ + TValue new_env = kmake_table_environment(K, K->ground_env); +// TValue new_env = kmake_environment(K, K->ground_env); kapply_cc(K, new_env); } diff --git a/src/kgports.c b/src/kgports.c @@ -704,7 +704,9 @@ void get_module(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) TValue port = kmake_fport(K, filename, false, false); krooted_tvs_push(K, port); - TValue env = kmake_environment(K, K->ground_env); + /* std environments have hashtable for bindings */ + TValue env = kmake_table_environment(K, K->ground_env); +// TValue env = kmake_environment(K, K->ground_env); krooted_tvs_push(K, env); if (get_opt_tpar(K, maybe_env, "environment", ttisenvironment)) { diff --git a/src/klisp.c b/src/klisp.c @@ -15,8 +15,19 @@ #include "klisp.h" #include "kstate.h" #include "kauxlib.h" + +#include "kstring.h" +#include "kcontinuation.h" +#include "koperative.h" +#include "kenvironment.h" +#include "kport.h" +#include "kread.h" +#include "kerror.h" +#include "kgcontinuations.h" /* for do_pass_value */ #include "kscript.h" +/* TODO update dependencies in makefile */ + /* 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. @@ -60,11 +71,139 @@ static void k_message (const char *pname, const char *msg) fflush(stderr); } +static int report (klisp_State *K, int status) { + if (status && !lua_isnil(L, -1)) { +/* TODO show error */ + const char *msg = "Error! \n"; + k_message(progname, msg) + } + return status; +} + static void print_version (void) { k_message(NULL, KLISP_RELEASE " " KLISP_COPYRIGHT); } +/* REFACTOR maybe these should be moved to a general place to be used + from any program */ +void do_str_eval(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: dynamic environment + */ + TValue denv = xparams[0]; + ktail_eval(K, obj, denv); +} + +void do_str_read(klisp_State *K, TValue *xparams, TValue obj) +{ + /* + ** xparams[0]: port + */ + TValue port = xparams[0]; + UNUSED(obj); + /* read just one value (as mutable data) */ + TValue obj1 = kread_from_port(K, port, true); + + if (ttiseof(obj1)) { + klispE_throw_simple_with_irritants(K, "No object could be read", + 1, port); + return; + } + + krooted_tvs_push(K, obj1); + TValue obj2 = kread_from_port(K, port, true); + krooted_tvs_pop(K); + + if (!ttiseof(obj2)) { + klispE_throw_simple_with_irritants(K, "More than one expression read", + 1, port); + return; + } + + /* all ok, just one exp read */ + kapply_cc(K, obj1); +} + +void do_int_mark_error(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv) +{ + /* + ** xparams[0]: errorp pointer + */ + UNUSED(denv); + bool *errorp = (bool *) pvalue(xparams[0]); + *errorp = true; + /* ptree is (object divert) */ + TValue error_obj = kcar(ptree); + /* pass the error along after setting the flag */ + kapply_cc(K, error_obj); +} + +static int dostring (klisp_State *K, const char *s, const char *name) +{ + bool errorp = false; /* may be set to true in error handler */ + + UNUSED(name); /* could use as filename?? */ + /* create a string input port */ + TValue str = kstring_new_b(K, s); + krooted_tvs_push(K, str); + TValue port = kmake_mport(K, str, false, false); + krooted_tvs_pop(K); + krooted_tvs_push(K, port); + + /* create the guard set error flag after errors */ + TValue exit_int = kmake_operative(K, do_int_mark_error, + 1, p2tv(&errorp)); + krooted_tvs_push(K, exit_int); + TValue exit_guard = kcons(K, K->error_cont, exit_int); + krooted_tvs_pop(K); /* already in guard */ + krooted_tvs_push(K, exit_guard); + TValue exit_guards = kcons(K, exit_guard, KNIL); + krooted_tvs_pop(K); /* alread in guards */ + krooted_tvs_push(K, exit_guards); + + TValue entry_guards = KNIL; + + /* this is needed for interception code */ + TValue env = kmake_empty_environment(K); + krooted_tvs_push(K, env); + TValue outer_cont = kmake_continuation(K, K->root_cont, + do_pass_value, 2, entry_guards, env); + kset_outer_cont(outer_cont); + krooted_tvs_push(K, outer_cont); + TValue inner_cont = kmake_continuation(K, outer_cont, + do_pass_value, 2, exit_guards, env); + kset_inner_cont(inner_cont); + krooted_tvs_pop(K); krooted_tvs_pop(K); krooted_tvs_pop(K); + + /* only port remains in the root stack */ + krooted_tvs_push(K, inner_cont); + + /* XXX This should probably be an extra param to the function */ + env = K->next_env; /* this is the standard env that should be used for + evaluation */ + TValue eval_cont = kmake_continuation(K, inner_cont, do_str_eval, + 1, env); + krooted_tvs_pop(K); /* pop inner cont */ + krooted_tvs_push(K, eval_cont); + TValue read_cont = kmake_continuation(K, eval_cont, do_str_read, + 1, port); + krooted_tvs_pop(K); /* pop eval cont */ + krooted_tvs_pop(K); /* pop port */ + kset_cc(K, read_cont); /* this will protect all conts from gc */ + klispS_apply_cc(K, KINERT); + + klispS_run(K); + + int status = errorp? 1 : 0; + + /* get the standard environment again in K->next_env */ + K->next_env = env; + return report(K, status); +} + /* check that argument has no extra characters at the end */ #define notail(x) {if ((x)[2] != '\0') return -1;} @@ -105,6 +244,11 @@ static int collectargs (char **argv, bool *pi, bool *pv, bool *pe) static int runargs (klisp_State *K, char **argv, int n) { + /* There is a standard env in K->next_env, a common one is used for all + evaluations (init, expression args, script/repl) */ + TValue env = K->next_env; + UNUSED(env); + for (int i = 1; i < n; i++) { if (argv[i] == NULL) continue; @@ -118,10 +262,8 @@ static int runargs (klisp_State *K, char **argv, int n) chunk = argv[++i]; klisp_assert(chunk != NULL); - /* TODO do string */ - UNUSED(K); -// if (dostring(L, chunk, "=(command line)") != 0) -// return 1; + if (dostring(K, chunk, "=(command line)") != 0) + return 1; break; } // case 'l': /* no libraries for now */ @@ -142,9 +284,13 @@ struct Smain { static int pmain (klisp_State *K) { /* This is weird but was done to follow lua scheme */ - struct Smain *s = (struct Smain *) pvalue(K->next_obj); + struct Smain *s = (struct Smain *) pvalue(K->next_value); char **argv = s->argv; + /* There is a standard env in K->next_env, a common one is used for all + evaluations (init, expression args, script/repl) */ + //TValue env = K->next_env; + if (argv[0] && argv[0][0]) progname = argv[0]; @@ -204,7 +350,7 @@ int main(int argc, char *argv[]) /* This is weird but was done to follow lua scheme */ s.argc = argc; s.argv = argv; - K->next_obj = p2tv(&s); + K->next_value = p2tv(&s); status = pmain(K); klisp_close(K); diff --git a/src/kread.c b/src/kread.c @@ -559,7 +559,7 @@ TValue kread(klisp_State *K) return obj; } - +/* port is protected from GC in curr_port */ TValue kread_from_port(klisp_State *K, TValue port, bool mut) { K->curr_port = port; diff --git a/src/kstate.c b/src/kstate.c @@ -38,7 +38,7 @@ #include "kbytevector.h" #include "kgpairs_lists.h" /* for creating list_app */ -#include "kerror.h" /* for creating error hierarchy */ +#include "kgerror.h" /* for creating error hierarchy */ #include "kgc.h" /* for memory freeing & gc init */ @@ -248,6 +248,9 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) { kinit_ground_env(K); + /* create a std environment and leave it in K->next_env */ + K->next_env = kmake_table_environment(K, K->ground_env); + /* set the threshold for gc start now that we have allocated all mem */ K->GCthreshold = 4*K->totalbytes; @@ -263,8 +266,6 @@ void do_root_exit(klisp_State *K, TValue *xparams, TValue obj) /* 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; } @@ -272,11 +273,9 @@ void do_root_exit(klisp_State *K, TValue *xparams, TValue obj) 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); + /* TEMP Just pass the error to the root continuation */ + kapply_cc(K, obj); } /* @@ -589,6 +588,7 @@ void klispS_run(klisp_State *K) (*fn)(K, K->next_xparams, K->next_value, K->next_env); } } + /* K->next_func is NULL, this means we should exit already */ break; } }