Travis: add remaining implementations.
[jackhill/mal.git] / fsharp / types.fs
1 module Types
2
3 [<CustomEquality; CustomComparison>]
4 type Node =
5 | Nil
6 | List of Metadata * Node list
7 | Vector of Metadata * Node System.ArraySegment
8 | Map of Metadata * Collections.Map<Node, Node>
9 | Symbol of string
10 | Keyword of string
11 | Number of int64
12 | String of string
13 | Bool of bool
14 | BuiltInFunc of Metadata * int * (Node list -> Node)
15 | Func of Metadata * int * (Node list -> Node) * Node * Node list * EnvChain
16 | Macro of Metadata * int * (Node list -> Node) * Node * Node list * EnvChain
17 | Atom of int * Node Ref
18
19 static member private hashSeq (s : seq<Node>) =
20 let iter st node = (st * 397) ^^^ node.GetHashCode()
21 s |> Seq.fold iter 0
22
23 static member private allEqual (x : seq<Node>) (y : seq<Node>) =
24 use ex = x.GetEnumerator()
25 use ey = y.GetEnumerator()
26 let rec loop () =
27 match ex.MoveNext(), ey.MoveNext() with
28 | false, false -> true
29 | false, true
30 | true, false -> false
31 | true, true ->
32 if ex.Current = ey.Current then
33 loop ()
34 else
35 false
36 loop ()
37
38 static member private allCompare (x : seq<Node>) (y : seq<Node>) =
39 use ex = x.GetEnumerator()
40 use ey = y.GetEnumerator()
41 let rec loop () =
42 match ex.MoveNext(), ey.MoveNext() with
43 | false, false -> 0
44 | false, true -> -1
45 | true, false -> 1
46 | true, true ->
47 let cmp = compare ex.Current ey.Current
48 if cmp = 0 then loop () else cmp
49 loop ()
50
51 static member private rank x =
52 match x with
53 | Nil -> 0
54 | List(_, _) -> 1
55 | Vector(_, _) -> 2
56 | Map(_, _) -> 3
57 | Symbol(_) -> 4
58 | Keyword(_) -> 5
59 | Number(_) -> 6
60 | String(_) -> 7
61 | Bool(_) -> 8
62 | BuiltInFunc(_, _, _)
63 | Func(_, _, _, _, _, _)
64 | Macro(_, _, _, _, _, _) -> 9
65 | Atom(_, _) -> 10
66
67 static member private equals x y =
68 match x, y with
69 | Nil, Nil -> true
70 | List(_, a), List(_, b) -> a = b
71 | List(_, a), Vector(_, b) -> Node.allEqual a b
72 | Vector(_, a), List(_, b) -> Node.allEqual a b
73 | Vector(_, a), Vector(_, b) -> Node.allEqual a b
74 | Map(_, a), Map(_, b) -> a = b
75 | Symbol(a), Symbol(b) -> a = b
76 | Keyword(a), Keyword(b) -> a = b
77 | Number(a), Number(b) -> a = b
78 | String(a), String(b) -> a = b
79 | Bool(a), Bool(b) -> a = b
80 | (BuiltInFunc(_, a, _) | Func(_, a, _, _, _, _) | Macro(_, a, _, _, _, _)),
81 (BuiltInFunc(_, b, _) | Func(_, b, _, _, _, _) | Macro(_, b, _, _, _, _)) ->
82 a = b
83 | Atom(a, _), Atom(b, _) -> a = b
84 | _, _ -> false
85
86 static member private compare x y =
87 match x, y with
88 | Nil, Nil -> 0
89 | List(_, a), List(_, b) -> compare a b
90 | List(_, a), Vector(_, b) -> Node.allCompare a b
91 | Vector(_, a), List(_, b) -> Node.allCompare a b
92 | Vector(_, a), Vector(_, b) -> Node.allCompare a b
93 | Map(_, a), Map(_, b) -> compare a b
94 | Symbol(a), Symbol(b) -> compare a b
95 | Keyword(a), Keyword(b) -> compare a b
96 | Number(a), Number(b) -> compare a b
97 | String(a), String(b) -> compare a b
98 | Bool(a), Bool(b) -> compare a b
99 | (BuiltInFunc(_, a, _) | Func(_, a, _, _, _, _) | Macro(_, a, _, _, _, _)),
100 (BuiltInFunc(_, b, _) | Func(_, b, _, _, _, _) | Macro(_, b, _, _, _, _)) ->
101 compare a b
102 | Atom(a, _), Atom(b, _) -> compare a b
103 | a, b -> compare (Node.rank a) (Node.rank b)
104
105 override x.Equals yobj =
106 match yobj with
107 | :? Node as y -> Node.equals x y
108 | _ -> false
109
110 override x.GetHashCode() =
111 match x with
112 | Nil -> 0
113 | List(_, lst) -> hash lst
114 | Vector(_, vec) -> Node.hashSeq vec
115 | Map(_, map) -> hash map
116 | Symbol(sym) -> hash sym
117 | Keyword(key) -> hash key
118 | Number(num) -> hash num
119 | String(str) -> hash str
120 | Bool(b) -> hash b
121 | BuiltInFunc(_, tag, _) | Func(_, tag, _, _, _, _) | Macro(_, tag, _, _, _, _) ->
122 hash tag
123 | Atom(tag, _) -> hash tag
124
125 interface System.IComparable with
126 member x.CompareTo yobj =
127 match yobj with
128 | :? Node as y -> Node.compare x y
129 | _ -> invalidArg "yobj" "Cannot compare values of different types."
130
131
132 and Env = System.Collections.Generic.Dictionary<string, Node>
133 and EnvChain = Env list
134 and Metadata = Node