aboutsummaryrefslogtreecommitdiffstats
path: root/src/treewalk/environment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/treewalk/environment.c')
-rw-r--r--src/treewalk/environment.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/treewalk/environment.c b/src/treewalk/environment.c
new file mode 100644
index 0000000..dd4a648
--- /dev/null
+++ b/src/treewalk/environment.c
@@ -0,0 +1,72 @@
1#include "environment.h"
2#include "gc.h"
3#include "errors.h"
4
5Environment *
6env_create(Environment *parent) {
7 Environment *env = alloc_env();
8 env->parent = parent;
9 env->marked = false;
10 env->table = ht_init();
11 return env;
12}
13
14void
15env_add_symbol(Environment *env, Object *symbol, Object *value) {
16 if (symbol->type != OBJ_TYPE_SYMBOL) {
17 error_push((Error){
18 .type = ERR_TYPE_RUNTIME,
19 .value = ERR_NOT_A_SYMBOL,
20 .line = 0,
21 .col = 0,
22 });
23 return;
24 }
25 ht_insert(env->table, symbol, value);
26}
27
28Object *
29env_lookup(Environment *env, Object *symbol) {
30 while (env != NULL) {
31 Object *obj = ht_lookup(env->table, symbol);
32 if (obj != NULL) {
33 return obj;
34 }
35 env = env->parent;
36 }
37 return obj_err;
38}
39
40Object *
41env_update(Environment *env, Object *symbol, Object *value) {
42 while (env != NULL) {
43 Object *obj = ht_lookup(env->table, symbol);
44 if (obj != NULL) {
45 ht_insert(env->table, symbol, value);
46 return obj_nil;
47 }
48 env = env->parent;
49 }
50 error_push((Error){
51 .type = ERR_TYPE_RUNTIME,
52 .value = ERR_SYMBOL_NOT_FOUND,
53 });
54 return obj_err;
55}
56
57void
58env_add_or_update_current(Environment *env, Object *symbol, Object *value) {
59 ht_insert(env->table, symbol, value);
60}
61
62Environment *
63env_extend(Environment *parent, Environment *extra) {
64 Environment *env = parent;
65 HashTablePair *pairs = extra->table->pairs;
66 for (size_t i = 0; i < array_cap(pairs); i++) {
67 if (pairs[i].key != NULL) {
68 ht_insert(env->table, pairs[i].key, pairs[i].value);
69 }
70 }
71 return env;
72}