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