klisp

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

commit 1c712fbdc7a85d2e74442e0d1c07c1eb88710714
parent 1d9aa20ee51615c66af4ebe5ef2201854c15b622
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Fri, 15 Apr 2011 18:31:15 -0300

Added gc rooting to reader. Added two helpers to clear the tvs and vars stacks on error.

Diffstat:
Msrc/kerror.c | 4++--
Msrc/kread.c | 64++++++++++++++++++++++++++++++++++++----------------------------
Msrc/kstate.h | 4++++
Msrc/ktoken.c | 4++++
4 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/src/kerror.c b/src/kerror.c @@ -21,8 +21,8 @@ void clear_buffers(klisp_State *K) K->shared_dict = KNIL; /* is it okay to do this in all cases? */ - K->rooted_tvs_top = 0; - K->rooted_vars_top = 0; + krooted_tvs_clear(K); + krooted_vars_clear(K); } void klispE_throw(klisp_State *K, char *msg) diff --git a/src/kread.c b/src/kread.c @@ -69,6 +69,12 @@ void kread_error(klisp_State *K, char *str) ks_tbclear(K); ks_sclear(K); clear_shared_dict(K); + + /* this is needed because it would be too complicated to + pop manually on each kind of error */ + krooted_tvs_clear(K); + krooted_vars_clear(K); + klispE_throw(K, str); } @@ -95,7 +101,8 @@ TValue try_shared_ref(klisp_State *K, TValue ref_token) return KINERT; } -TValue try_shared_def(klisp_State *K, TValue def_token, TValue value) +/* GC: def token is rooted */ +void try_shared_def(klisp_State *K, TValue def_token, TValue value) { /* IMPLEMENTATION RESTRICTION: only allow fixints in shared tokens */ int32_t ref_num = ivalue(kcdr(def_token)); @@ -105,15 +112,14 @@ TValue try_shared_def(klisp_State *K, TValue def_token, TValue value) if (ref_num == ivalue(kcar(head))) { kread_error(K, "duplicate shared def found"); /* avoid warning */ - return KINERT; + return; } tail = kcdr(tail); } - /* XXX: what happens on out of mem? & gc? (inner cons is not rooted) */ K->shared_dict = kcons(K, kcons(K, kcdr(def_token), value), - K->shared_dict); - return KINERT; + K->shared_dict); /* value is protected by cons */ + return; } /* This overwrites a previouly made def, it is used in '() */ @@ -152,9 +158,13 @@ TValue kread_fsm(klisp_State *K) /* the source code information of that obj */ TValue obj_si; + krooted_vars_push(K, &obj); + krooted_vars_push(K, &obj_si); + while (!(get_state(K) == ST_READ && !read_next_token)) { if (read_next_token) { - TValue tok = ktok_read_token(K); + TValue tok = ktok_read_token(K); /* only root it when necessary */ + if (ttispair(tok)) { /* special token */ switch (chvalue(kcar(tok))) { case '(': { @@ -166,6 +176,7 @@ TValue kread_fsm(klisp_State *K) } /* construct the list with the correct type of pair */ TValue np = kcons_g(K, K->read_mconsp, KINERT, KNIL); + krooted_tvs_push(K, np); /* ** NOTE: the source info of the '(' is temporarily saved ** in np (later it will be replace by the source info @@ -187,6 +198,8 @@ TValue kread_fsm(klisp_State *K) push_data(K, np); push_state(K, ST_FIRST_LIST); read_next_token = true; + + krooted_tvs_pop(K); break; } case ')': { @@ -289,18 +302,15 @@ TValue kread_fsm(klisp_State *K) /* avoid warning */ return KINERT; default: { - TValue res = try_shared_def(K, tok, KNIL); - /* TEMP: while error returns EOF */ - if (ttiseof(res)) { - return res; - } else { - /* token ok, read defined object */ - /* NOTE: save the source info to return it - after the defined object is read */ - push_data(K, kcons(K, tok, ktok_get_source_info(K))); - push_state(K, ST_SHARED_DEF); - read_next_token = true; - } + krooted_tvs_push(K, tok); + try_shared_def(K, tok, KNIL); + /* token ok, read defined object */ + /* NOTE: save the source info to return it + after the defined object is read */ + push_data(K, kcons(K, tok, ktok_get_source_info(K))); + push_state(K, ST_SHARED_DEF); + read_next_token = true; + krooted_tvs_pop(K); } } break; @@ -319,16 +329,11 @@ TValue kread_fsm(klisp_State *K) return KINERT; default: { TValue res = try_shared_ref(K, tok); - /* TEMP: while error returns EOF */ - if (ttiseof(res)) { - return res; - } else { - /* ref ok, process it in next iteration */ - obj = res; - /* NOTE: use source info of ref token */ - obj_si = ktok_get_source_info(K); - read_next_token = false; - } + /* ref ok, process it in next iteration */ + obj = res; + /* NOTE: use source info of ref token */ + obj_si = ktok_get_source_info(K); + read_next_token = false; } } break; @@ -390,6 +395,8 @@ TValue kread_fsm(klisp_State *K) TValue fp = get_data(K); /* replace source info in fp with the saved one */ /* NOTE: the old one will be returned when list is complete */ + /* GC: the way things are done here fp is rooted at all + times */ TValue fp_old_si = kget_source_info(fp); kset_source_info(fp, obj_si); kset_car(fp, obj); @@ -408,6 +415,7 @@ TValue kread_fsm(klisp_State *K) /* get the state out of the way */ pop_state(K); /* construct the list with the correct type of pair */ + /* GC: np is rooted by push_data */ TValue np = kcons_g(K, K->read_mconsp, obj, KNIL); kset_source_info(np, obj_si); kset_cdr(get_data(K), np); diff --git a/src/kstate.h b/src/kstate.h @@ -307,6 +307,8 @@ inline void krooted_tvs_pop(klisp_State *K) --(K->rooted_tvs_top); } +inline void krooted_tvs_clear(klisp_State *K) { K->rooted_tvs_top = 0; } + inline void krooted_vars_push(klisp_State *K, TValue *v) { klisp_assert(K->rooted_vars_top < GC_PROTECT_SIZE); @@ -319,6 +321,8 @@ inline void krooted_vars_pop(klisp_State *K) --(K->rooted_vars_top); } +inline void krooted_vars_clear(klisp_State *K) { K->rooted_vars_top = 0; } + /* dummy functions will be in kpair.h, because we can't include it from here */ diff --git a/src/ktoken.c b/src/ktoken.c @@ -214,6 +214,10 @@ void ktok_error(klisp_State *K, char *str) ks_tbclear(K); ks_sclear(K); clear_shared_dict(K); + + krooted_tvs_clear(K); + krooted_vars_clear(K); + klispE_throw(K, str); }