fsharp: step7: Cleaned up error handling.
[jackhill/mal.git] / fsharp / env.fs
CommitLineData
37bb752e
PS
1module 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