fsharp: step5: Added tail call optimization.
[jackhill/mal.git] / fsharp / core.fs
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 toBool b = if b then TRUE else FALSE
9
10 let inline twoNumberOp (f : int64 -> int64 -> Node) = function
11 | [Number(a); Number(b)] -> f a b
12 | [_; _] -> raise <| errArgMismatch ()
13 | _ -> raise <| errArity ()
14
15 let inline twoNodeOp (f : Node -> Node -> Node) = function
16 | [a; b] -> f a b
17 | _ -> raise <| errArity ()
18
19 let add = twoNumberOp (fun a b -> a + b |> Number)
20 let subtract = twoNumberOp (fun a b -> a - b |> Number)
21 let multiply = twoNumberOp (fun a b -> a * b |> Number)
22 let divide = twoNumberOp (fun a b -> a / b |> Number)
23 let lt = twoNodeOp (fun a b -> a < b |> toBool)
24 let le = twoNodeOp (fun a b -> a <= b |> toBool)
25 let ge = twoNodeOp (fun a b -> a >= b |> toBool)
26 let gt = twoNodeOp (fun a b -> a > b |> toBool)
27 let eq = twoNodeOp (fun a b -> a = b |> toBool)
28
29 let list nodes = List(nodes)
30 let isList = function
31 | [List(_)] -> TRUE
32 | [_] -> FALSE
33 | _ -> raise <| errArity ()
34
35 let isEmpty = function
36 | [List([])]
37 | [Vector([||])] -> TRUE
38 | _ -> FALSE
39
40 let count = function
41 | [List(lst)] -> lst |> List.length |> int64 |> Number
42 | [Vector(vec)] -> vec |> Array.length |> int64 |> Number
43 | [Nil] -> ZERO
44 | [_] -> raise <| errArgMismatch ()
45 | _ -> raise <| errArity ()
46
47 let pr_str nodes = nodes |> Printer.pr_str |> String
48 let str nodes = nodes |> Printer.str |> String
49 let prn nodes = nodes |> Printer.prn |> printfn "%s"; Nil
50 let println nodes = nodes |> Printer.println |> printfn "%s"; Nil