Commit | Line | Data |
---|---|---|
37bb752e PS |
1 | module Env |
2 | ||
3 | open Types | |
4 | ||
37bb752e PS |
5 | let makeEmpty () = Env() |
6 | ||
7 | let ofList lst = | |
8 | let env = makeEmpty () | |
9 | let accumulate (e : Env) (k, v) = e.Add(k, v); e | |
10 | List.fold accumulate env lst | |
11 | ||
12 | let set (env : EnvChain) key node = | |
13 | match env with | |
14 | | head::_ -> head.[key] <- node | |
6d809e32 | 15 | | _ -> raise <| Error.noEnvironment () |
37bb752e PS |
16 | |
17 | let rec find (chain : EnvChain) key = | |
18 | match chain with | |
19 | | [] -> None | |
20 | | env::rest -> | |
21 | match env.TryGetValue(key) with | |
22 | | true, v -> Some(v) | |
23 | | false, _ -> find rest key | |
24 | ||
25 | let get chain key = | |
26 | match find chain key with | |
27 | | Some(v) -> v | |
6d809e32 | 28 | | None -> raise <| Error.symbolNotFound key |
37bb752e | 29 | |
8862f80e | 30 | let private getNextValue = |
a836d8f3 | 31 | let counter = ref 0 |
8862f80e PS |
32 | fun () -> System.Threading.Interlocked.Increment(counter) |
33 | ||
34 | let makeBuiltInFunc f = | |
f877bf26 | 35 | Func(getNextValue (), f, Node.NIL, [], []) |
8862f80e PS |
36 | |
37 | let makeFunc f body binds env = | |
38 | Func(getNextValue (), f, body, binds, env) | |
a836d8f3 | 39 | |
37bb752e | 40 | let makeRootEnv () = |
8862f80e | 41 | let wrap name f = name, makeBuiltInFunc f |
37bb752e | 42 | let env = |
aa2e1438 PS |
43 | [ wrap "+" Core.add |
44 | wrap "-" Core.subtract | |
45 | wrap "*" Core.multiply | |
46 | wrap "/" Core.divide | |
47 | wrap "list" Core.list | |
48 | wrap "list?" Core.isList | |
49 | wrap "empty?" Core.isEmpty | |
50 | wrap "count" Core.count | |
51 | wrap "=" Core.eq | |
52 | wrap "<" Core.lt | |
53 | wrap "<=" Core.le | |
54 | wrap ">=" Core.ge | |
55 | wrap ">" Core.gt | |
56 | wrap "pr-str" Core.pr_str | |
57 | wrap "str" Core.str | |
58 | wrap "prn" Core.prn | |
59 | wrap "println" Core.println | |
60 | wrap "read-string" Core.read_str | |
61 | wrap "slurp" Core.slurp | |
62 | wrap "cons" Core.cons | |
63 | wrap "concat" Core.concat ] | |
37bb752e PS |
64 | |> ofList |
65 | [ env ] | |
66 | ||
a97c3028 PS |
67 | let makeNew outer symbols nodes = |
68 | let env = (makeEmpty ())::outer | |
69 | let rec loop symbols nodes = | |
70 | match symbols, nodes with | |
71 | | [Symbol("&"); Symbol(s)], nodes -> | |
72 | set env s (List nodes) | |
73 | env | |
6d809e32 | 74 | | Symbol("&")::_, _ -> raise <| Error.onlyOneSymbolAfterAmp () |
a97c3028 PS |
75 | | Symbol(s)::symbols, n::nodes -> |
76 | set env s n | |
77 | loop symbols nodes | |
78 | | [], [] -> env | |
6d809e32 PS |
79 | | _, [] -> raise <| Error.notEnoughValues () |
80 | | [], _ -> raise <| Error.tooManyValues () | |
81 | | _, _ -> raise <| Error.expectedX "symbol" | |
a97c3028 | 82 | loop symbols nodes |