Commit | Line | Data |
---|---|---|
f877bf26 PS |
1 | module Node |
2 | ||
3 | open Types | |
4 | ||
5 | let TRUE = Bool(true) | |
6 | let SomeTRUE = Some(TRUE) | |
7 | let FALSE = Bool(false) | |
8 | let SomeFALSE = Some(FALSE) | |
9 | let NIL = Nil | |
10 | let SomeNIL = Some(NIL) | |
11 | let ZERO = Number(0L) | |
12 | ||
a71aefe1 PS |
13 | let makeVector seg = Vector(NIL, seg) |
14 | let makeList lst = List(NIL, lst) | |
15 | let makeMap map = Map(NIL, map) | |
16 | ||
17 | let EmptyLIST = [] |> makeList | |
18 | let EmptyVECTOR = System.ArraySegment([| |]) |> makeVector | |
19 | let EmptyMAP = Map.empty |> makeMap | |
20 | ||
21 | let ofArray arr = System.ArraySegment(arr) |> makeVector | |
f877bf26 PS |
22 | |
23 | let toArray = function | |
a71aefe1 PS |
24 | | List(_, lst) -> Array.ofList lst |
25 | | Vector(_, seg) -> Array.sub seg.Array seg.Offset seg.Count | |
f877bf26 PS |
26 | | node -> [| node |] |
27 | ||
28 | let length = function | |
a71aefe1 PS |
29 | | List(_, lst) -> List.length lst |
30 | | Vector(_, seg) -> seg.Count | |
31 | | Map(_, m) -> m.Count | |
f877bf26 PS |
32 | | _ -> 1 |
33 | ||
34 | (* Active Patterns to help with pattern matching nodes *) | |
35 | let inline (|Elements|_|) num node = | |
36 | let rec accumList acc idx lst = | |
37 | let len = Array.length acc | |
38 | match lst with | |
39 | | [] when idx = len -> Some(Elements acc) | |
40 | | h::t when idx < len -> | |
41 | acc.[idx] <- h | |
42 | accumList acc (idx + 1) t | |
43 | | _ -> None | |
44 | match node with | |
a71aefe1 PS |
45 | | List(_, lst) -> accumList (Array.zeroCreate num) 0 lst |
46 | | Vector(_, seg) when seg.Count = num -> Some(toArray node) | |
f877bf26 PS |
47 | | _ -> None |
48 | ||
49 | let inline (|Cons|_|) node = | |
50 | match node with | |
a71aefe1 PS |
51 | | List(_, h::t) -> Some(Cons(h, makeList t)) |
52 | | Vector(_, seg) when seg.Count > 0 -> | |
f877bf26 PS |
53 | let h = seg.Array.[seg.Offset] |
54 | let t = System.ArraySegment(seg.Array, seg.Offset + 1, seg.Count - 1) | |
a71aefe1 | 55 | |> makeVector |
f877bf26 PS |
56 | Some(Cons(h, t)) |
57 | | _ -> None | |
58 | ||
59 | let inline (|Empty|_|) node = | |
60 | match node with | |
a71aefe1 PS |
61 | | List(_, []) -> Some(Empty) |
62 | | Vector(_, seg) when seg.Count = 0 -> Some(Empty) | |
f877bf26 PS |
63 | | _ -> None |
64 | ||
65 | let inline (|Pair|_|) node = | |
66 | match node with | |
a71aefe1 PS |
67 | | List(_, a::b::t) -> Some(a, b, makeList t) |
68 | | List(_, []) -> None | |
69 | | List(_, _) -> raise <| Error.expectedEvenNodeCount () | |
70 | | Vector(_, seg) -> | |
f877bf26 PS |
71 | match seg.Count with |
72 | | 0 -> None | |
6d809e32 | 73 | | 1 -> raise <| Error.expectedEvenNodeCount () |
f877bf26 PS |
74 | | _ -> |
75 | let a = seg.Array.[seg.Offset] | |
76 | let b = seg.Array.[seg.Offset + 1] | |
77 | let t = System.ArraySegment(seg.Array, seg.Offset + 2, seg.Count - 2) | |
a71aefe1 | 78 | |> makeVector |
f877bf26 PS |
79 | Some(a, b, t) |
80 | | _ -> None | |
224d2396 PS |
81 | |
82 | let inline (|Seq|_|) node = | |
83 | match node with | |
a71aefe1 PS |
84 | | List(_, lst) -> Some(Seq.ofList lst) |
85 | | Vector(_, seg) -> Some(seg :> Node seq) | |
224d2396 | 86 | | _ -> None |