klisp

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

commit 9f464f5bd174710f1505ac1a7b9920b30cbc66b1
parent 083d1496630d0d27dbd673957327cbb122d16a79
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Wed, 30 Nov 2011 04:17:32 -0300

Updated the manual, interpreter tests, bugfix in ktoken, some comments.

Diffstat:
Mdoc/klisp.1 | 16+++++++++++-----
Msrc/klisp.c | 15+++++++++------
Msrc/kread.c | 56++++++++++++++++++++++++++------------------------------
Msrc/kread.h | 4+---
Msrc/krepl.c | 9+++------
Msrc/kstate.h | 14++++++++++----
Msrc/ksystem.win32.c | 6++++++
Msrc/ktoken.c | 23-----------------------
Msrc/ktoken.h | 2+-
Msrc/tests/test-interpreter.sh | 16++++++++++------
10 files changed, 77 insertions(+), 84 deletions(-)

diff --git a/doc/klisp.1 b/doc/klisp.1 @@ -30,7 +30,12 @@ the klisp program in file is loaded and evaluated. All evaluations, including the initialization that is described below, take place in the same -(initially) standard environment. +(initially) standard environment. All values that +result from these evaluation are discarded, but +if the root continuation or error continuation +are passed value, the interpretation of arguments +is interrupted and the EXIT_STATUS is as described +in the corresponding section. The given .I args are available to @@ -42,9 +47,10 @@ then they should be quoted (but note that the quotes will be removed by the shell). The arguments in the returned string start with the string .RI ' script '. -The arguments given in the command line before +All the arguments given in the command line .IR script , -including the name of the interpreter, +including the name of the interpreter, options, +, the script, and its arguments are available via the applicative .RI ' get-interpreter-arguments '. .LP @@ -119,8 +125,8 @@ or reach EOF or if there is no script, .B EXIT_SUCCESS is returned. -If there is an error during the evaluation of -the options, +If the root continuation is passed an object during +init, arguments or script evaluation .B EXIT_FAILURE is returned. If the diff --git a/src/klisp.c b/src/klisp.c @@ -148,7 +148,7 @@ static int report (klisp_State *K, int status) static void print_version(void) { - k_message(NULL, KLISP_RELEASE " " KLISP_COPYRIGHT); + printf("%s\n", KLISP_RELEASE " " KLISP_COPYRIGHT); } /* REFACTOR maybe these should be moved to a general place to be used @@ -541,11 +541,14 @@ static void populate_argument_lists(klisp_State *K, char **argv, int argc, static int handle_klispinit(klisp_State *K) { - const char *init = getenv(KLISP_INIT); - if (init == NULL) - return EXIT_SUCCESS; - else - return dostring(K, init, "=" KLISP_INIT); + const char *init = getenv(KLISP_INIT); + int res; + if (init == NULL) + res = EXIT_SUCCESS; + else + res = dostring(K, init, "=" KLISP_INIT); + + return res; } /* This is weird but was done to follow lua scheme */ diff --git a/src/kread.c b/src/kread.c @@ -539,7 +539,7 @@ TValue kread_fsm(klisp_State *K, bool listp) read_next_token = false; } } - } else { /* if(read_next_token) */ + } else { /* read_next_token == false */ /* process the object just read */ switch(get_state(K)) { case ST_FIRST_EOF_LIST: @@ -676,24 +676,20 @@ TValue kread_fsm(klisp_State *K, bool listp) */ TValue kread(klisp_State *K, bool listp) { - TValue obj; - klisp_assert(ttisnil(K->shared_dict)); - /* WORKAROUND: for repl problem with eofs */ - K->ktok_seen_eof = false; - - obj = kread_fsm(K, listp); - - /* NOTE: clear after function to allow earlier gc */ - clear_shared_dict(K); + TValue obj = kread_fsm(K, listp); + clear_shared_dict(K); /* clear after function to allow earlier gc */ return obj; } /* port is protected from GC in curr_port */ TValue kread_from_port_g(klisp_State *K, TValue port, bool mut, bool listp) { - K->curr_port = port; + if (!tv_equal(port, K->curr_port)) { + K->ktok_seen_eof = false; /* WORKAROUND: for repl problem with eofs */ + K->curr_port = port; + } K->read_mconsp = mut; ktok_set_source_info(K, kport_filename(port), @@ -735,10 +731,10 @@ TValue kread_peek_char_from_port(klisp_State *K, TValue port, bool peek) klisp_assert(kport_is_open(port)); klisp_assert(kport_is_textual(port)); - /* Reset the EOF flag in the tokenizer. The flag is shared, - by operations on all ports. */ - K->ktok_seen_eof = false; - K->curr_port = port; + if (!tv_equal(port, K->curr_port)) { + K->ktok_seen_eof = false; /* WORKAROUND: for repl problem with eofs */ + K->curr_port = port; + } int ch; if (peek) { ch = ktok_peekc(K); @@ -759,10 +755,10 @@ TValue kread_peek_u8_from_port(klisp_State *K, TValue port, bool peek) klisp_assert(kport_is_open(port)); klisp_assert(kport_is_binary(port)); - /* Reset the EOF flag in the tokenizer. The flag is shared, - by operations on all ports. */ - K->ktok_seen_eof = false; - K->curr_port = port; + if (!tv_equal(port, K->curr_port)) { + K->ktok_seen_eof = false; /* WORKAROUND: for repl problem with eofs */ + K->curr_port = port; + } int32_t u8; if (peek) { u8 = ktok_peekc(K); @@ -783,10 +779,10 @@ TValue kread_line_from_port(klisp_State *K, TValue port) klisp_assert(kport_is_open(port)); klisp_assert(kport_is_textual(port)); - /* Reset the EOF flag in the tokenizer. The flag is shared, - by operations on all ports. */ - K->ktok_seen_eof = false; - K->curr_port = port; + if (!tv_equal(port, K->curr_port)) { + K->ktok_seen_eof = false; /* WORKAROUND: for repl problem with eofs */ + K->curr_port = port; + } uint32_t size = MINREADLINEBUFFER; uint32_t i = 0; @@ -830,13 +826,13 @@ TValue kread_line_from_port(klisp_State *K, TValue port) } /* This is needed by the repl to ignore trailing spaces (especially newlines) - that could affect the source info */ -/* XXX This should be replaced somehow, as it doesn't work for sexp and - multi line comments */ -void kread_ignore_whitespace_and_comments_from_port(klisp_State *K, - TValue port) + that could affect the (freshly reset) source info */ +void kread_clear_leading_whitespace_from_port(klisp_State *K, TValue port) { - K->curr_port = port; + if (!tv_equal(port, K->curr_port)) { + K->ktok_seen_eof = false; /* WORKAROUND: for repl problem with eofs */ + K->curr_port = port; + } /* source code info isn't important because it will be reset later */ - ktok_ignore_whitespace_and_comments(K); + ktok_ignore_whitespace(K); } diff --git a/src/kread.h b/src/kread.h @@ -18,9 +18,7 @@ TValue kread_list_from_port(klisp_State *K, TValue port, bool mut); TValue kread_peek_char_from_port(klisp_State *K, TValue port, bool peek); TValue kread_peek_u8_from_port(klisp_State *K, TValue port, bool peek); TValue kread_line_from_port(klisp_State *K, TValue port); -/* XXX soon to be replaced */ -void kread_ignore_whitespace_and_comments_from_port(klisp_State *K, - TValue port); +void kread_clear_leading_whitespace_from_port(klisp_State *K, TValue port); #endif diff --git a/src/krepl.c b/src/krepl.c @@ -45,13 +45,10 @@ void do_repl_read(klisp_State *K) TValue port = kcdr(K->kd_in_port_key); klisp_assert(kfport_file(port) == stdin); -#if 0 /* Let's disable this for now */ - /* workaround to the problem of the dangling '\n' in repl + /* Workaround to the problem of the dangling '\n' in repl (from previous line) */ - kread_ignore_whitespace_and_comments_from_port(K, port); - - kport_reset_source_info(port); -#endif + kread_clear_leading_whitespace_from_port(K, port); + kport_reset_source_info(port); /* always start with a clean source info */ obj = kread_from_port(K, port, true); /* read mutable pairs */ kapply_cc(K, obj); } diff --git a/src/kstate.h b/src/kstate.h @@ -50,12 +50,14 @@ typedef struct stringtable { /* NOTE: when adding TValues here, remember to add them to markroot in kgc.c!! */ +/* TODO split this struct in substructs (e.g. run_context, tokenizer, + gc, etc) */ struct klisp_State { stringtable strt; /* hash table for immutable strings & symbols */ TValue name_table; /* hash tables for naming objects */ TValue cont_name_table; /* hash tables for naming continuation functions*/ - TValue curr_cont; + TValue curr_cont; /* ** If next_env is NIL, then the next_func from a continuation ** and otherwise next_func is from an operative @@ -134,9 +136,10 @@ struct klisp_State { TValue ktok_sexp_comment; /* WORKAROUND for repl */ - bool ktok_seen_eof; + bool ktok_seen_eof; /* to keep track of eofs that later dissapear */ + /* source info tracking */ ksource_info_t ktok_source_info; - /* tokenizer buffer */ + /* tokenizer buffer (XXX this could be done with a string) */ int32_t ktok_buffer_size; int32_t ktok_buffer_idx; char *ktok_buffer; @@ -151,11 +154,13 @@ struct klisp_State { /* writer */ bool write_displayp; - /* auxiliary stack */ + /* auxiliary stack (XXX this could be a vector) */ int32_t ssize; /* total size of array */ int32_t stop; /* top of the stack (all elements are below this index) */ TValue *sbuf; + /* These could be eliminated if a stack was adopted for the c interface */ + /* (like in lua) */ /* TValue stack to protect values from gc, must not grow, otherwise it may call the gc */ int32_t rooted_tvs_top; @@ -166,6 +171,7 @@ struct klisp_State { int32_t rooted_vars_top; TValue *rooted_vars_buf[GC_PROTECT_SIZE]; + /* XXX These should be replaced with calls to krooted_vars_push */ /* These three are useful for constructing lists by means of set-car & set-cdr. The idea is that these dummy pairs start as the head of the list (protecting the entire chain from GC) and at the end of the diff --git a/src/ksystem.win32.c b/src/ksystem.win32.c @@ -61,6 +61,12 @@ bool ksystem_isatty(klisp_State *K, TValue port) * * TEMP: use GetConsoleMode() */ +/* +** Lua uses _isatty in Windows, shouldn't that work? +** e.g. _isatty(_fileno(kport_file(port))) +** I'll try to test it when I have access to a Windows box +** Andres Navarro +*/ DWORD mode; return GetConsoleMode(h, &mode); diff --git a/src/ktoken.c b/src/ktoken.c @@ -532,29 +532,6 @@ void ktok_ignore_whitespace(klisp_State *K) } } -/* XXX temp for repl */ -void ktok_ignore_whitespace_and_comments(klisp_State *K) -{ - /* NOTE: if it's not whitespace do nothing (even on eof) */ - while(true) { - int chi = ktok_peekc(K); - - if (chi == EOF) { - return; - } else { - char ch = (char) chi; - if (ktok_is_whitespace(ch)) { - ktok_getc(K); - } else if (ch == ';') { - ktok_ignore_single_line_comment(K); - } else { - return; - } - } - } -} - - /* ** Delimiter checking */ diff --git a/src/ktoken.h b/src/ktoken.h @@ -33,7 +33,7 @@ inline int ktok_getc(klisp_State *K) { return ktok_peekc_getc(K, false); } inline int ktok_peekc(klisp_State *K) { return ktok_peekc_getc(K, true); } /* needed by the repl */ -void ktok_ignore_whitespace_and_comments(klisp_State *K); +void ktok_ignore_whitespace(klisp_State *K); /* This is needed for string->symbol to check if a symbol has external representation as an identifier */ diff --git a/src/tests/test-interpreter.sh b/src/tests/test-interpreter.sh @@ -145,12 +145,14 @@ check_oi '2' '(display (+ 1 1))' $KLISP - check_o 'abcdef' $KLISP '-e (display "abc")' '-e' '(display "def")' # option: -i +# The interpreter always show name and version +# WAS check_oi 'klisp> ' '' $KLISP -i -check_oi 'klisp> ' '' $KLISP -i +check_oi '/klisp [0-9.][0-9.]* .*\n.*klisp> /' '' $KLISP -i # option: -v -check_o '/klisp [0-9.]+ .*/' $KLISP -v +check_o '/klisp [0-9.][0-9.]* .*/' $KLISP -v # '--' on the command line @@ -169,6 +171,11 @@ check_os '' 0 $KLISP -e '(exit)' check_os '' 0 $KLISP -e '1' check_os '' 3 $KLISP -e '(apply-continuation root-continuation 3)' +## FIX the root continuation should exit without running any more +## arguments, but it doesn't... +check_os '' 0 $KLISP -e '(exit 0)' -e '(exit 1)' +check_os '' 1 $KLISP -e '(exit 1)' -e '(exit 0)' + # KLISP_INIT environment variable export KLISP_INIT='(display "init...")' @@ -192,10 +199,7 @@ check_o '("/dev/null")' $KLISP -e '(write(get-script-arguments))' -- /dev/null # interpreter arguments # (get-interpreter-arguments) returns all command line # arguments. -# -# TODO: The man page says that (interpreter-arguments) -# returns the arguments _before_ the script name. -# + check_o "(\"$KLISP\" \"-e\" \"(write(get-interpreter-arguments))\")" \ $KLISP -e '(write(get-interpreter-arguments))'