3 exception ReaderError of string
4 exception EvalError of string
6 [<CustomEquality; CustomComparison>]
10 | Vector of Node System.ArraySegment
11 | Map of Collections.Map<Node, Node>
17 | Func of int * (Node list -> Node) * Node * Node list * EnvChain
19 static member private
hashSeq (s
: seq
<Node>) =
20 let iter st
node = (st
* 397) ^^^ node.GetHashCode()
23 static member private
allEqual (x
: seq
<Node>) (y
: seq
<Node>) =
24 use ex = x
.GetEnumerator()
25 use ey = y
.GetEnumerator()
27 match ex.MoveNext(), ey.MoveNext() with
28 | false, false -> true
30 | true, false -> false
32 if ex.Current = ey.Current then
38 static member private
allCompare (x
: seq
<Node>) (y
: seq
<Node>) =
39 use ex = x
.GetEnumerator()
40 use ey = y
.GetEnumerator()
42 match ex.MoveNext(), ey.MoveNext() with
47 let cmp = compare
ex.Current ey.Current
48 if cmp = 0 then loop
() else cmp
51 static member private
rank x
=
62 | Func(_
, _
, _
, _
, _
) -> 9
64 static member private
equals x y
=
67 | List(a
), List(b
) -> a
= b
68 | List(a
), Vector(b
) -> Node.allEqual a b
69 | Vector(a), List(b
) -> Node.allEqual a b
70 | Vector(a), Vector(b
) -> Node.allEqual a b
71 | Map(a), Map(b
) -> a = b
72 | Symbol(a), Symbol(b
) -> a = b
73 | Keyword(a), Keyword(b
) -> a = b
74 | Number(a), Number(b
) -> a = b
75 | String(a), String(b
) -> a = b
76 | Bool(a), Bool(b
) -> a = b
77 | Func(a, _
, _
, _
, _
), Func(b
, _
, _
, _
, _
) -> a = b
80 static member private
compare x y
=
83 | List(a), List(b
) -> compare a b
84 | List(a), Vector(b
) -> Node.allCompare a b
85 | Vector(a), List(b
) -> Node.allCompare a b
86 | Vector(a), Vector(b
) -> Node.allCompare a b
87 | Map(a), Map(b
) -> compare a b
88 | Symbol(a), Symbol(b
) -> compare a b
89 | Keyword(a), Keyword(b
) -> compare a b
90 | Number(a), Number(b
) -> compare a b
91 | String(a), String(b
) -> compare a b
92 | Bool(a), Bool(b
) -> compare a b
93 | Func(a, _, _, _, _), Func(b
, _, _, _, _) -> compare a b
94 | a, b
-> compare (Node.rank a) (Node.rank b
)
96 override x.Equals yobj =
98 | :? Node as y
-> Node.equals x y
101 override x.GetHashCode() =
104 | List(lst
) -> hash lst
105 | Vector(vec
) -> Node.hashSeq vec
106 | Map(map
) -> hash map
107 | Symbol(sym
) -> hash sym
108 | Keyword(key
) -> hash key
109 | Number(num
) -> hash num
110 | String(str
) -> hash str
112 | Func(tag
, _, _, _, _) -> hash tag
114 interface System.IComparable with
115 member x.CompareTo yobj =
117 | :? Node as y
-> Node.compare x y
118 | _ -> invalidArg
"yobj" "Cannot compare values of different types."
120 static member ofArray arr
= System.ArraySegment(arr
) |> Vector
121 static member toArray
= function
122 | List(lst
) -> Array.ofList
lst
123 | Vector(seg
) -> Array.sub seg
.Array seg
.Offset seg.Count
125 static member length
= function
126 | List(lst) -> List.length
lst
127 | Vector(seg) -> seg.Count
131 and Env = System.Collections.Generic.Dictionary<string, Node>
132 and EnvChain = Env list
134 let TRUE = Bool(true)
135 let SomeTRUE = Some(TRUE)
136 let FALSE = Bool(false)
137 let SomeFALSE = Some(FALSE)
139 let SomeNIL = Some(NIL)
140 let ZERO = Number(0L)
142 (* Active Patterns to help with pattern matching nodes *)
143 let (|Elements|_|) num
node =
144 let rec accumList
acc idx
lst =
145 let len = Array.length
acc
147 | [] when idx
= len -> Some(Elements acc)
148 | h::t
when idx
< len ->
150 accumList
acc (idx
+ 1) t
153 | List(lst) -> accumList
(Array.zeroCreate
num) 0 lst
154 | Vector(seg) when seg.Count = num -> Some(Node.toArray
node)
157 let (|Head|_|) = function
158 | List(h::t
) -> Some(Head(h, List(t
)))
159 | Vector(seg) when seg.Count > 0 ->
160 let h = seg.Array.[seg.Offset]
161 let t = System.ArraySegment(seg.Array, seg.Offset + 1, seg.Count - 1)
166 let (|Empty|_|) = function
167 | List([]) -> Some(Empty)
168 | Vector(seg) when seg.Count = 0 -> Some(Empty)