klisp

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

commit 83e77d19e575de757dcb77ebc3a9c46dbfa99775
parent d5d07dd34404ab2c979a80c7065fe1157c0f1e85
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Mon, 21 Nov 2011 01:58:56 -0300

Added a list read to kread.c, updated load and get-module to use it.

Diffstat:
Msrc/kgports.c | 37+++++--------------------------------
Msrc/kread.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/kread.h | 1+
3 files changed, 110 insertions(+), 44 deletions(-)

diff --git a/src/kgports.c b/src/kgports.c @@ -551,36 +551,6 @@ void call_with_file(klisp_State *K, TValue *xparams, TValue ptree, /* helpers for load */ -/* read all expressions in a file, as immutable pairs */ -/* GC: assume port is rooted */ -TValue read_all_expr(klisp_State *K, TValue port) -{ - /* GC: root dummy and obj */ - TValue tail = kget_dummy1(K); - TValue obj = KINERT; - krooted_vars_push(K, &obj); - - while(true) { - obj = kread_from_port(K, port, false); /* read immutable pairs */ - if (ttiseof(obj)) { - krooted_vars_pop(K); - return kcutoff_dummy1(K); - } else { - TValue new_pair = kimm_cons(K, obj, KNIL); -#if KTRACK_SI - /* put the source info */ - /* XXX: should first read all comments and whitespace, - then save the source info, then read the object and - lastly put the saved source info on the new pair... - For now this will do, but it's not technically correct */ - kset_source_info(K, new_pair, ktry_get_si(K, obj)); -#endif - kset_cdr_unsafe(K, tail, new_pair); - tail = new_pair; - } - } -} - /* interceptor for errors during reading */ void do_int_close_file(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) @@ -663,7 +633,8 @@ void load(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) current continuation as parent GC: root this obj */ kset_cc(K, guarded_cont); /* implicit rooting */ - TValue ls = read_all_expr(K, port); /* any error will close the port */ + /* any error will close the port */ + TValue ls = kread_list_from_port(K, port, false); /* immutable pairs */ /* now the sequence of expresions should be evaluated in denv and #inert returned after all are done */ @@ -723,7 +694,9 @@ void get_module(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) TValue guarded_cont = make_guarded_read_cont(K, kget_cc(K), port); kset_cc(K, guarded_cont); /* implicit roooting */ - TValue ls = read_all_expr(K, port); /* any error will close the port */ + + /* any error will close the port */ + TValue ls = kread_list_from_port(K, port, false); /* use immutable pairs */ /* now the sequence of expresions should be evaluated in the created env and the environment returned after all are done */ diff --git a/src/kread.c b/src/kread.c @@ -35,12 +35,18 @@ ** info as above (but no pair with last pair). ** ST_SHARED_DEF: a pair with car: shared def token and cdr: source ** info of the shared def token. -** +** ST_SEXP_COMMENT: the source info of the comment token +** ST_FIRST_EOF_LIST: first pair of the list (with source info, start of file) +** ST_MIDDLE_EOF_LIST: two elements, first below, second on top: +** - a pair with car: first pair of the list (with source info corrected +** to car of list) and cdr: source info of the start of file. +** - last pair of the list so far. */ typedef enum { ST_READ, ST_SHARED_DEF, ST_LAST_ILIST, ST_PAST_LAST_ILIST, - ST_FIRST_LIST, ST_MIDDLE_LIST, ST_SEXP_COMMENT + ST_FIRST_LIST, ST_MIDDLE_LIST, ST_SEXP_COMMENT, ST_FIRST_EOF_LIST, + ST_MIDDLE_EOF_LIST } state_t; #define push_state(kst_, st_) (ks_spush(kst_, (i2tv((int32_t)(st_))))) @@ -151,15 +157,43 @@ void change_shared_def(klisp_State *K, TValue def_token, TValue value) /* ** Reader FSM */ + +/* +** listp: +** false: read one value +** true: read all values as a list +*/ + /* TEMP: For now we'll use just one big function */ -TValue kread_fsm(klisp_State *K) +TValue kread_fsm(klisp_State *K, bool listp) { /* TODO add more specific sexp comment error msgs */ /* TODO replace some read errors with asserts where appropriate */ klisp_assert(ks_sisempty(K)); klisp_assert(ttisnil(K->shared_dict)); + push_state(K, ST_READ); + if (listp) { /* read a list of values */ + /* create the first pair */ + TValue np = kcons_g(K, K->read_mconsp, KINERT, KNIL); + krooted_tvs_push(K, np); + /* + ** NOTE: the source info of the start of file is temporarily + ** saved in np (later it will be replace by the source info + ** of the car of the list) + */ + TValue si = ktok_get_source_info(K); + krooted_tvs_push(K, si); +#if KTRACK_SI + kset_source_info(K, np, si); +#endif + krooted_tvs_pop(K); + push_data(K, np); + krooted_tvs_pop(K); + push_state(K, ST_FIRST_EOF_LIST); + } + /* read next token or process obj */ bool read_next_token = true; /* the obj just read/completed */ @@ -235,6 +269,7 @@ TValue kread_fsm(klisp_State *K) obj_si = kget_source_info(K, fp_with_old_si); #else UNUSED(fp_with_old_si); + obj_si = KNIL; #endif read_next_token = false; break; @@ -269,6 +304,8 @@ TValue kread_fsm(klisp_State *K) /* avoid warning */ return KINERT; case ST_READ: + case ST_FIRST_EOF_LIST: + case ST_MIDDLE_EOF_LIST: kread_error(K, "unmatched closing paren found"); /* avoid warning */ return KINERT; @@ -308,6 +345,8 @@ TValue kread_fsm(klisp_State *K) /* avoid warning */ return KINERT; case ST_READ: + case ST_FIRST_EOF_LIST: + case ST_MIDDLE_EOF_LIST: kread_error(K, "dot found outside list"); /* avoid warning */ return KINERT; @@ -393,10 +432,37 @@ TValue kread_fsm(klisp_State *K) " comment", last_sexp_comment_si); /* avoid warning */ return KINERT; + case ST_FIRST_EOF_LIST: { + pop_state(K); + TValue fp_with_old_si = get_data(K); + pop_data(K); + obj = KNIL; + #if KTRACK_SI + obj_si = kget_source_info(K, fp_with_old_si); + #else + UNUSED(fp_with_old_si); + obj_si = KNIL; + #endif + read_next_token = false; + break; + } + case ST_MIDDLE_EOF_LIST: { + pop_state(K); + /* discard info on last pair */ + pop_data(K); + pop_state(K); + TValue fp_old_si = get_data(K); + pop_data(K); + /* list read ok, process it in next iteration */ + obj = kcar(fp_old_si); + obj_si = kcdr(fp_old_si); + read_next_token = false; + break; + } case ST_READ: - /* will exit in next loop */ obj = tok; obj_si = ktok_get_source_info(K); + /* will exit in next loop */ read_next_token = false; break; case ST_FIRST_LIST: @@ -436,7 +502,9 @@ TValue kread_fsm(klisp_State *K) } else { /* if(read_next_token) */ /* process the object just read */ switch(get_state(K)) { + case ST_FIRST_EOF_LIST: case ST_FIRST_LIST: { + state_t state = get_state(K); /* get the state out of the way */ pop_state(K); TValue fp = get_data(K); @@ -462,13 +530,22 @@ TValue kread_fsm(klisp_State *K) push_data(K, kcons (K, fp, fp_old_si)); krooted_tvs_pop(K); krooted_tvs_pop(K); - push_state(K, ST_FIRST_LIST); + push_state(K, state); push_data(K, fp); - push_state(K, ST_MIDDLE_LIST); + if (state == ST_FIRST_LIST) { + push_state(K, ST_MIDDLE_LIST); + } else { + push_state(K, ST_MIDDLE_EOF_LIST); + /* shared dict must be cleared after every element + of an eof list */ + clear_shared_dict(K); + } read_next_token = true; break; } - case ST_MIDDLE_LIST: { + case ST_MIDDLE_LIST: + case ST_MIDDLE_EOF_LIST: { + state_t state = get_state(K); /* get the state out of the way */ pop_state(K); /* construct the list with the correct type of pair */ @@ -482,7 +559,12 @@ TValue kread_fsm(klisp_State *K) /* replace last pair of the (still incomplete) read next obj */ pop_data(K); push_data(K, np); - push_state(K, ST_MIDDLE_LIST); + push_state(K, state); + if (state == ST_MIDDLE_EOF_LIST) { + /* shared dict must be cleared after every element + of an eof list */ + clear_shared_dict(K); + } krooted_tvs_pop(K); read_next_token = true; break; @@ -543,7 +625,7 @@ TValue kread_fsm(klisp_State *K) /* ** Reader Main Function */ -TValue kread(klisp_State *K) +TValue kread(klisp_State *K, bool listp) { TValue obj; @@ -551,7 +633,7 @@ TValue kread(klisp_State *K) /* WORKAROUND: for repl problem with eofs */ K->ktok_seen_eof = false; - obj = kread_fsm(K); + obj = kread_fsm(K, listp); /* NOTE: clear after function to allow earlier gc */ clear_shared_dict(K); @@ -560,7 +642,7 @@ TValue kread(klisp_State *K) } /* port is protected from GC in curr_port */ -TValue kread_from_port(klisp_State *K, TValue port, bool mut) +TValue kread_from_port_g(klisp_State *K, TValue port, bool mut, bool listp) { K->curr_port = port; K->read_mconsp = mut; @@ -568,13 +650,23 @@ TValue kread_from_port(klisp_State *K, TValue port, bool mut) ktok_set_source_info(K, kport_filename(port), kport_line(port), kport_col(port)); - TValue obj = kread(K); + TValue obj = kread(K, listp); kport_update_source_info(port, K->ktok_source_info.line, K->ktok_source_info.col); return obj; } +TValue kread_from_port(klisp_State *K, TValue port, bool mut) +{ + return kread_from_port_g(K, port, mut, false); +} + +TValue kread_list_from_port(klisp_State *K, TValue port, bool mut) +{ + return kread_from_port_g(K, port, mut, true); +} + TValue kread_peek_char_from_port(klisp_State *K, TValue port, bool peek) { /* Reset the EOF flag in the tokenizer. The flag is shared, diff --git a/src/kread.h b/src/kread.h @@ -14,6 +14,7 @@ ** Reader interface */ TValue kread_from_port(klisp_State *K, TValue port, bool mut); +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);