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:
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);