11 Env
*new_env(Env
*outer
, MalVal
* binds
, MalVal
*exprs
) {
12 Env
*e
= malloc(sizeof(Env
));
13 e
->table
= g_hash_table_new(g_str_hash
, g_str_equal
);
17 assert_type(binds
, MAL_LIST
|MAL_VECTOR
,
18 "new_env called with non-sequential bindings");
19 assert_type(exprs
, MAL_LIST
|MAL_VECTOR
,
20 "new_env called with non-sequential expressions");
21 int binds_len
= _count(binds
),
22 exprs_len
= _count(exprs
),
24 for (i
=0; i
<binds_len
; i
++) {
25 if (i
> exprs_len
) { break; }
26 if (_nth(binds
, i
)->val
.string
[0] == '&') {
28 env_set(e
, _nth(binds
, i
+1)->val
.string
, _slice(exprs
, i
, _count(exprs
)));
31 env_set(e
, _nth(binds
, i
)->val
.string
, _nth(exprs
, i
));
34 assert(varargs
|| (binds_len
== exprs_len
),
35 "Arity mismatch: %d formal params vs %d actual params",
36 binds_len
, exprs_len
);
42 Env
*env_find(Env
*env
, char *key
) {
43 void *val
= g_hash_table_lookup(env
->table
, key
);
46 } else if (env
->outer
) {
47 return env_find(env
->outer
, key
);
53 MalVal
*env_get(Env
*env
, char *key
) {
54 Env
*e
= env_find(env
, key
);
55 assert(e
, "'%s' not found", key
);
56 return g_hash_table_lookup(e
->table
, key
);
59 Env
*env_set(Env
*env
, char *key
, MalVal
*val
) {
60 g_hash_table_insert(env
->table
, key
, val
);