6 Env
*new_env(Env
*outer
, MalVal
* binds
, MalVal
*exprs
) {
7 Env
*e
= malloc(sizeof(Env
));
8 e
->table
= g_hash_table_new(g_str_hash
, g_str_equal
);
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
),
19 for (i
=0; i
<binds_len
; i
++) {
20 if (i
> exprs_len
) { break; }
21 if (_nth(binds
, i
)->val
.string
[0] == '&') {
23 env_set(e
, _nth(binds
, i
+1), _slice(exprs
, i
, _count(exprs
)));
26 env_set(e
, _nth(binds
, i
), _nth(exprs
, i
));
29 assert(varargs
|| (binds_len
== exprs_len
),
30 "Arity mismatch: %d formal params vs %d actual params",
31 binds_len
, exprs_len
);
37 Env
*env_find(Env
*env
, MalVal
*key
) {
38 void *val
= g_hash_table_lookup(env
->table
, key
->val
.string
);
41 } else if (env
->outer
) {
42 return env_find(env
->outer
, key
);
48 MalVal
*env_get(Env
*env
, MalVal
*key
) {
49 Env
*e
= env_find(env
, key
);
50 assert(e
, "'%s' not found", key
->val
.string
);
51 return g_hash_table_lookup(e
->table
, key
->val
.string
);
54 Env
*env_set(Env
*env
, MalVal
*key
, MalVal
*val
) {
55 g_hash_table_insert(env
->table
, key
->val
.string
, val
);