diff options
Diffstat (limited to 'src/bootstrap/environment.c')
-rw-r--r-- | src/bootstrap/environment.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c new file mode 100644 index 0000000..1bbe844 --- /dev/null +++ b/src/bootstrap/environment.c | |||
@@ -0,0 +1,106 @@ | |||
1 | // | ||
2 | // Environment. | ||
3 | // | ||
4 | |||
5 | typedef struct EnvEntry { | ||
6 | Object *symbol; | ||
7 | Object *value; | ||
8 | } EnvEntry; | ||
9 | |||
10 | typedef struct Environment { | ||
11 | struct Environment *parent; | ||
12 | EnvEntry *buf; | ||
13 | size_t size; | ||
14 | size_t cap; | ||
15 | } Environment; | ||
16 | |||
17 | static Environment *global_env; | ||
18 | |||
19 | #define ENV_BUF_CAP 8 | ||
20 | |||
21 | Environment * | ||
22 | env_create(Environment *parent) { | ||
23 | Environment *env = malloc(sizeof(Environment)); | ||
24 | env->parent = parent; | ||
25 | env->buf = NULL; | ||
26 | env->size = 0; | ||
27 | env->cap = ENV_BUF_CAP; | ||
28 | return env; | ||
29 | } | ||
30 | |||
31 | void | ||
32 | env_add_symbol(Environment *env, Object *symbol, Object *value) { | ||
33 | if (symbol->type != OBJ_TYPE_SYMBOL) { | ||
34 | error_push((Error){ | ||
35 | .type = ERR_TYPE_RUNTIME, | ||
36 | .value = ERR_NOT_A_SYMBOL, | ||
37 | .line = 0, | ||
38 | .col = 0, | ||
39 | }); | ||
40 | return; | ||
41 | } | ||
42 | if (env->buf == NULL) { | ||
43 | env->size = 0; | ||
44 | env->cap = ENV_BUF_CAP; | ||
45 | env->buf = malloc(env->cap * sizeof(EnvEntry)); | ||
46 | } else if (env->size == env->cap) { | ||
47 | env->cap *= 2; | ||
48 | env->buf = realloc(env->buf, env->cap * sizeof(EnvEntry)); | ||
49 | } | ||
50 | env->buf[env->size++] = (EnvEntry){symbol, value}; | ||
51 | } | ||
52 | |||
53 | bool | ||
54 | obj_eq(Object *a, Object* b) { | ||
55 | if (a->type != b->type) { | ||
56 | return false; | ||
57 | } | ||
58 | switch (a->type) { | ||
59 | case OBJ_TYPE_FIXNUM: { | ||
60 | return a->fixnum == b->fixnum; | ||
61 | } break; | ||
62 | case OBJ_TYPE_STRING: { | ||
63 | if (a->string_n != b->string_n) { | ||
64 | return false; | ||
65 | } | ||
66 | for (size_t i = 0; i < a->string_n; i++) { | ||
67 | if (a->string[i] != b->string[i]) { | ||
68 | return false; | ||
69 | } | ||
70 | } | ||
71 | } break; | ||
72 | case OBJ_TYPE_SYMBOL: { | ||
73 | if (a->symbol_n != b->symbol_n) { | ||
74 | return false; | ||
75 | } | ||
76 | for (size_t i = 0; i < a->symbol_n; i++) { | ||
77 | if (a->symbol[i] != b->symbol[i]) { | ||
78 | return false; | ||
79 | } | ||
80 | } | ||
81 | } break; | ||
82 | case OBJ_TYPE_PAIR: { | ||
83 | // TODO: needs evaluation of parameters... | ||
84 | } break; | ||
85 | default: { | ||
86 | return a == b; | ||
87 | } break; | ||
88 | } | ||
89 | return true; | ||
90 | } | ||
91 | |||
92 | Object * | ||
93 | env_lookup(Environment *env, Object *symbol) { | ||
94 | while (env != NULL) { | ||
95 | for (size_t i = 0; i < env->size; i++) { | ||
96 | EnvEntry entry = env->buf[i]; | ||
97 | if (obj_eq(symbol, entry.symbol)) { | ||
98 | return entry.value; | ||
99 | } | ||
100 | } | ||
101 | env = env->parent; | ||
102 | } | ||
103 | return obj_err; | ||
104 | } | ||
105 | |||
106 | // TODO: Free env function. | ||