Commit | Line | Data |
---|---|---|
21986733 DM |
1 | require, "hash.i" |
2 | require, "types.i" | |
3 | ||
4 | struct Env { | |
5 | pointer outer | |
6 | Hash data | |
7 | } | |
8 | ||
9 | func env_new(outer_ptr, binds=, exprs=) | |
10 | { | |
11 | env = Env(outer=outer_ptr, data=hash_new()) | |
12 | for (i = 1; i <= numberof(binds); ++i) { | |
13 | if (binds(i)->val == "&") { | |
14 | rest_args = numberof(exprs) >= i ? exprs(i:) : [] | |
15 | env_set, env, binds(i + 1)->val, MalList(val=&rest_args) | |
16 | break | |
17 | } else { | |
18 | env_set, env, binds(i)->val, *exprs(i) | |
19 | } | |
20 | } | |
21 | return env | |
22 | } | |
23 | ||
24 | func env_find(env, key) | |
25 | { | |
26 | if (hash_has_key(env.data, key)) return env | |
27 | if (is_void(*env.outer)) return nil | |
28 | return env_find(*env.outer, key) | |
29 | } | |
30 | ||
31 | func env_get(env, key) | |
32 | { | |
33 | found_env = env_find(env, key) | |
34 | if (is_void(found_env)) return MalError(message=("'" + key + "' not found")) | |
35 | return hash_get(found_env.data, key) | |
36 | } | |
37 | ||
38 | func env_set(&env, key, val) | |
39 | { | |
40 | d = env.data | |
41 | hash_set, d, key, val | |
42 | env.data = d | |
43 | return val | |
44 | } |