DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / c / env.c
CommitLineData
ea81a808
JM
1#include <stdlib.h>
2#include "types.h"
3
4// Env
5
6Env *new_env(Env *outer, MalVal* binds, MalVal *exprs) {
6b3ecaa7 7 Env *e = MAL_GC_MALLOC(sizeof(Env));
ea81a808
JM
8 e->table = g_hash_table_new(g_str_hash, g_str_equal);
9 e->outer = outer;
10
11 if (binds && exprs) {
12 assert_type(binds, MAL_LIST|MAL_VECTOR,
13 "new_env called with non-sequential bindings");
14 assert_type(exprs, MAL_LIST|MAL_VECTOR,
15 "new_env called with non-sequential expressions");
16 int binds_len = _count(binds),
17 exprs_len = _count(exprs),
18 varargs = 0, i;
19 for (i=0; i<binds_len; i++) {
20 if (i > exprs_len) { break; }
21 if (_nth(binds, i)->val.string[0] == '&') {
22 varargs = 1;
b8ee29b2 23 env_set(e, _nth(binds, i+1), _slice(exprs, i, _count(exprs)));
ea81a808
JM
24 break;
25 } else {
b8ee29b2 26 env_set(e, _nth(binds, i), _nth(exprs, i));
ea81a808
JM
27 }
28 }
29 assert(varargs || (binds_len == exprs_len),
30 "Arity mismatch: %d formal params vs %d actual params",
31 binds_len, exprs_len);
32
33 }
34 return e;
35}
36
b8ee29b2
JM
37Env *env_find(Env *env, MalVal *key) {
38 void *val = g_hash_table_lookup(env->table, key->val.string);
ea81a808
JM
39 if (val) {
40 return env;
41 } else if (env->outer) {
42 return env_find(env->outer, key);
43 } else {
44 return NULL;
45 }
46}
47
b8ee29b2 48MalVal *env_get(Env *env, MalVal *key) {
ea81a808 49 Env *e = env_find(env, key);
b8ee29b2
JM
50 assert(e, "'%s' not found", key->val.string);
51 return g_hash_table_lookup(e->table, key->val.string);
ea81a808
JM
52}
53
b8ee29b2
JM
54Env *env_set(Env *env, MalVal *key, MalVal *val) {
55 g_hash_table_insert(env->table, key->val.string, val);
ea81a808
JM
56 return env;
57}