klisp

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

commit 2a62e746ab8ae1896129b6c056461d2229248af8
parent 26f6e0730e24921a4f462215dd02816d9a7eeae8
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Wed, 20 Apr 2011 00:42:09 -0300

Added environments with hashtable bindings. Used only for ground for now. TODO: change nil to some other non user visible value to indicate missing in tables.

Diffstat:
Msrc/kenvironment.c | 58++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/kenvironment.h | 9+++++++++
Msrc/klimits.h | 4++++
Msrc/kobject.h | 2+-
Msrc/kstate.c | 3++-
5 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/src/kenvironment.c b/src/kenvironment.c @@ -13,6 +13,7 @@ #include "kerror.h" #include "kstate.h" #include "kmem.h" +#include "ktable.h" #include "kgc.h" /* keyed dynamic vars */ @@ -84,6 +85,7 @@ TValue kmake_environment(klisp_State *K, TValue parents) /* ** Helper function for kadd_binding and kget_binding, +** Only for list environments, table environments are handled elsewhere ** returns KNIL or a pair with sym as car. */ TValue kfind_local_binding(klisp_State *K, TValue bindings, TValue sym) @@ -109,13 +111,19 @@ TValue kfind_local_binding(klisp_State *K, TValue bindings, TValue sym) right now, but that could change */ void kadd_binding(klisp_State *K, TValue env, TValue sym, TValue val) { - TValue oldb = kfind_local_binding(K, kenv_bindings(K, env), sym); - - if (ttisnil(oldb)) { - TValue new_pair = kcons(K, sym, val); - kenv_bindings(K, env) = kcons(K, new_pair, kenv_bindings(K, env)); + TValue bindings = kenv_bindings(K, env); + if (ttistable(bindings)) { + TValue *cell = klispH_setsym(K, tv2table(bindings), tv2sym(sym)); + *cell = val; } else { - kset_cdr(oldb, val); + TValue oldb = kfind_local_binding(K, bindings, sym); + + if (ttisnil(oldb)) { + TValue new_pair = kcons(K, sym, val); + kenv_bindings(K, env) = kcons(K, new_pair, bindings); + } else { + kset_cdr(oldb, val); + } } } @@ -134,12 +142,26 @@ inline bool try_get_binding(klisp_State *K, TValue env, TValue sym, if (ttisnil(obj)) { continue; } else if (ttisenvironment(obj)) { - TValue oldb = kfind_local_binding(K, kenv_bindings(K, obj), sym); - if (!ttisnil(oldb)) { - /* remember to leave the stack as it was */ - ks_sdiscardn(K, pushed); - *value = kcdr(oldb); - return true; + TValue bindings = kenv_bindings(K, obj); + if (ttistable(bindings)) { + const TValue *cell = klispH_getsym(tv2table(bindings), + tv2sym(sym)); + /* TEMP: for now nil can't be bound in table envs, + only used for ground for now */ + if (cell != &knil) { + /* remember to leave the stack as it was */ + ks_sdiscardn(K, pushed); + *value = *cell; + return true; + } + } else { + TValue oldb = kfind_local_binding(K, bindings, sym); + if (!ttisnil(oldb)) { + /* remember to leave the stack as it was */ + ks_sdiscardn(K, pushed); + *value = kcdr(oldb); + return true; + } } TValue parents = kenv_parents(K, obj); ks_spush(K, parents); @@ -237,3 +259,15 @@ TValue kget_keyed_static_var(klisp_State *K, TValue env, TValue key) return KINERT; } } + +/* environments with hashtable bindings */ +/* TEMP: for now only for ground environment */ +TValue kmake_table_environment(klisp_State *K, TValue parents) +{ + TValue new_env = kmake_environment(K, parents); + krooted_tvs_push(K, new_env); + TValue new_table = klispH_new(K, 0, ENVTABSIZE, K_FLAG_WEAK_NOTHING); + tv2env(new_env)->bindings = new_table; + krooted_tvs_pop(K); + return new_env; +} diff --git a/src/kenvironment.h b/src/kenvironment.h @@ -22,4 +22,13 @@ TValue kmake_keyed_static_env(klisp_State *K, TValue parent, TValue key, TValue val); TValue kget_keyed_static_var(klisp_State *K, TValue env, TValue key); +/* environments with hashtable bindings */ +/* TEMP: for now only for ground environment, have to fix + the fact that KNIL can't be a value in hashtables before + allowing for other environments. Also should have to profile + too see when it makes sense & should add code to all operatives + creating environments to see when it's appropiate or should add code + to add binding to at certain point move over to hashtable */ +TValue kmake_table_environment(klisp_State *K, TValue parents); + #endif diff --git a/src/klimits.h b/src/klimits.h @@ -54,4 +54,8 @@ #define MINSTRTABSIZE 32 #endif +/* starting size for ground environment hashtable */ +/* at last count, there were about 200 bindings in ground env */ +#define ENVTABSIZE 512 + #endif diff --git a/src/kobject.h b/src/kobject.h @@ -339,7 +339,7 @@ typedef struct __attribute__ ((__packed__)) { CommonHeader; TValue mark; /* for cycle/sharing aware algorithms */ TValue parents; /* may be (), a list, or a single env */ - TValue bindings; /* TEMP: for now alist of (binding . value) */ + TValue bindings; /* alist of (binding . value) or table */ /* for keyed static vars */ TValue keyed_node; /* (key . value) pair or KNIL */ /* this is a different field from parents to jump over non keyed diff --git a/src/kstate.c b/src/kstate.c @@ -177,7 +177,8 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) { /* create the ground environment and the eval operative */ K->eval_op = kmake_operative(K, keval_ofn, 0); K->list_app = kmake_applicative(K, list, 0); - K->ground_env = kmake_empty_environment(K); + /* ground environment has a hashtable for bindings */ + K->ground_env = kmake_table_environment(K, KNIL); /* MAYBE: fix it so we can remove module_params_sym from roots */ K->module_params_sym = ksymbol_new(K, "module-parameters");