Commit | Line | Data |
---|---|---|
6c47cf67 PS |
1 | module Core |
2 | ||
3 | open Types | |
4 | ||
5 | let errArity () = EvalError("arity: wrong number of arguments") | |
6 | let errArgMismatch () = EvalError("argument mismatch") | |
7 | ||
8 | let inline toNumber node = | |
9 | match node with | |
10 | | Number(n) -> n | |
11 | | _ -> raise <| errArgMismatch () | |
12 | ||
13 | let inline makeNumFolder op = | |
14 | (fun state node -> op state (node |> toNumber)) | |
15 | ||
16 | let add nodes = | |
17 | let addNode = makeNumFolder (+) | |
18 | nodes |> Seq.fold addNode 0L |> Number | |
19 | ||
20 | let subtract nodes = | |
21 | let subtractNode = makeNumFolder (-) | |
22 | match nodes with | |
23 | | [] -> raise <| errArity () | |
24 | | Number(first)::[] -> Number(-first) | |
25 | | Number(first)::rest -> rest |> Seq.fold subtractNode first |> Number | |
26 | | _ -> raise <| errArgMismatch () | |
27 | ||
28 | let multiply nodes = | |
29 | let multiplyNode = makeNumFolder ( * ) | |
30 | nodes |> Seq.fold multiplyNode 1L |> Number | |
31 | ||
32 | let divide nodes = | |
33 | let divideNode = makeNumFolder (/) | |
34 | match nodes with | |
35 | | [] -> raise <| errArity () | |
36 | | Number(first)::[] -> 1L / first |> Number | |
37 | | Number(first)::rest -> rest |> Seq.fold divideNode first |> Number | |
38 | | _ -> raise <| errArgMismatch () |