Commit | Line | Data |
---|---|---|
8f1ee487 PS |
1 | module Eval |
2 | ||
3 | open Types | |
4 | ||
5 | type Env = Map<string, Node> | |
6 | ||
1e4687b4 | 7 | let errExpected tok = EvalError(sprintf "expected %s" tok) |
8f1ee487 | 8 | |
a836d8f3 | 9 | let iterPairs f (source : seq<_>) = |
0756d620 PS |
10 | use iter = source.GetEnumerator() |
11 | let rec loop () = | |
12 | if iter.MoveNext() then | |
13 | let first = iter.Current | |
14 | if not (iter.MoveNext()) then raise <| errExpected "even node count" | |
15 | let second = iter.Current | |
16 | f first second | |
17 | loop () | |
18 | loop () | |
19 | ||
8f1ee487 | 20 | let rec eval_ast env = function |
37bb752e | 21 | | Symbol(sym) -> Env.get env sym |
8f1ee487 PS |
22 | | List(lst) -> lst |> List.map (eval env) |> List |
23 | | Vector(arr) -> arr |> Array.map (eval env) |> Vector | |
24 | | Map(map) -> map |> Map.map (fun k v -> eval env v) |> Map | |
25 | | node -> node | |
26 | ||
1e4687b4 PS |
27 | and defBang env = function |
28 | | sym::node::[] -> | |
29 | match sym with | |
37bb752e PS |
30 | | Symbol(sym) -> |
31 | let node = eval env node | |
32 | Env.set env sym node | |
33 | node | |
1e4687b4 PS |
34 | | _ -> raise <| errExpected "symbol" |
35 | | _ -> raise <| Core.errArity () | |
36 | ||
0756d620 PS |
37 | and setBinding env first second = |
38 | let s = match first with | |
39 | | Symbol(s) -> s | |
40 | | _ -> raise <| errExpected "symbol" | |
41 | let form = eval env second | |
42 | Env.set env s form | |
1e4687b4 PS |
43 | |
44 | and letStar env = function | |
45 | | bindings::form::[] -> | |
46 | let newEnv = Env.makeNew env | |
0756d620 | 47 | let binder = setBinding newEnv |
1e4687b4 | 48 | match bindings with |
a836d8f3 PS |
49 | | List(lst) -> lst |> iterPairs binder |
50 | | Vector(vec) -> vec |> iterPairs binder | |
1e4687b4 PS |
51 | | _ -> raise <| errExpected "list or vector" |
52 | eval newEnv form | |
53 | | _ -> raise <| Core.errArity () | |
37bb752e | 54 | |
8f1ee487 | 55 | and eval env = function |
1e4687b4 PS |
56 | | List(Symbol("def!")::rest) -> defBang env rest |
57 | | List(Symbol("let*")::rest) -> letStar env rest | |
8f1ee487 PS |
58 | | List(_) as node -> |
59 | let resolved = node |> eval_ast env | |
60 | match resolved with | |
61 | | List(Func({F = f})::rest) -> f rest | |
1e4687b4 | 62 | | _ -> raise <| errExpected "function" |
8f1ee487 | 63 | | node -> node |> eval_ast env |