Commit | Line | Data |
---|---|---|
ea81a808 JM |
1 | // Node vs browser behavior |
2 | var env = {}; | |
3 | if (typeof module === 'undefined') { | |
4 | var exports = env; | |
5 | } | |
6 | ||
7 | // Env implementation | |
8 | function Env(outer, binds, exprs) { | |
9 | this.data = {}; | |
10 | this.outer = outer || null; | |
11 | ||
12 | if (binds && exprs) { | |
13 | // Returns a new Env with symbols in binds bound to | |
14 | // corresponding values in exprs | |
15 | // TODO: check types of binds and exprs and compare lengths | |
16 | for (var i=0; i<binds.length;i++) { | |
17 | if (binds[i].value === "&") { | |
18 | // variable length arguments | |
19 | this.data[binds[i+1].value] = Array.prototype.slice.call(exprs, i); | |
20 | break; | |
21 | } else { | |
22 | this.data[binds[i].value] = exprs[i]; | |
23 | } | |
24 | } | |
25 | } | |
26 | return this; | |
27 | } | |
28 | Env.prototype.find = function (key) { | |
b8ee29b2 JM |
29 | if (!key.constructor || key.constructor.name !== 'Symbol') { |
30 | throw new Error("env.find key must be a symbol") | |
31 | } | |
32 | if (key.value in this.data) { return this; } | |
ea81a808 JM |
33 | else if (this.outer) { return this.outer.find(key); } |
34 | else { return null; } | |
35 | }; | |
b8ee29b2 JM |
36 | Env.prototype.set = function(key, value) { |
37 | if (!key.constructor || key.constructor.name !== 'Symbol') { | |
38 | throw new Error("env.set key must be a symbol") | |
39 | } | |
40 | this.data[key.value] = value; | |
41 | return value; | |
42 | }; | |
ea81a808 | 43 | Env.prototype.get = function(key) { |
b8ee29b2 JM |
44 | if (!key.constructor || key.constructor.name !== 'Symbol') { |
45 | throw new Error("env.get key must be a symbol") | |
46 | } | |
ea81a808 | 47 | var env = this.find(key); |
b8ee29b2 JM |
48 | if (!env) { throw new Error("'" + key.value + "' not found"); } |
49 | return env.data[key.value]; | |
ea81a808 JM |
50 | }; |
51 | ||
52 | exports.Env = env.Env = Env; |