0554397d741b3695e8348a74db42460194c154d3
[jackhill/mal.git] / fsharp / env.fs
1 module Env
2
3 open Types
4
5 type Env = System.Collections.Generic.Dictionary<string, Node>
6 type EnvChain = Env list
7
8 let errSymbolNotFound s = EvalError(sprintf "'%s' not found" s)
9 let errNoEnvironment () = EvalError("no environment")
10
11 let makeEmpty () = Env()
12
13 let ofList lst =
14 let env = makeEmpty ()
15 let accumulate (e : Env) (k, v) = e.Add(k, v); e
16 List.fold accumulate env lst
17
18 let set (env : EnvChain) key node =
19 match env with
20 | head::_ -> head.[key] <- node
21 | _ -> raise <| errNoEnvironment ()
22
23 let rec find (chain : EnvChain) key =
24 match chain with
25 | [] -> None
26 | env::rest ->
27 match env.TryGetValue(key) with
28 | true, v -> Some(v)
29 | false, _ -> find rest key
30
31 let get chain key =
32 match find chain key with
33 | Some(v) -> v
34 | None -> raise <| errSymbolNotFound key
35
36 let makeRootEnv () =
37 let wrap tag name func = name, Func({ Tag = tag; Name = name; F = func })
38 let env =
39 [ wrap 1 "+" Core.add;
40 wrap 2 "-" Core.subtract;
41 wrap 3 "*" Core.multiply;
42 wrap 4 "/" Core.divide ]
43 |> ofList
44 [ env ]
45
46 let makeNew (env : EnvChain) = (makeEmpty ())::env