1use super::*;
2
3impl NanValue {
4 pub fn eq_in(self, other: Self, arena: &Arena) -> bool {
5 if self.0 == other.0 {
6 return true;
7 }
8 if self.is_float() != other.is_float() {
9 return false;
10 }
11 if self.is_float() {
12 return self.as_float() == other.as_float();
13 }
14 match (self.wrapper_parts(arena), other.wrapper_parts(arena)) {
15 (Some((self_kind, self_inner)), Some((other_kind, other_inner))) => {
16 return self_kind == other_kind && self_inner.eq_in(other_inner, arena);
17 }
18 (Some(_), None) | (None, Some(_)) => return false,
19 (None, None) => {}
20 }
21 match (self.variant_parts(arena), other.variant_parts(arena)) {
22 (Some((st, sv, sf)), Some((ot, ov, of))) => {
23 return st == ot
24 && sv == ov
25 && sf.len() == of.len()
26 && sf.iter().zip(of).all(|(a, b)| a.eq_in(*b, arena));
27 }
28 (Some(_), None) | (None, Some(_)) => return false,
29 (None, None) => {}
30 }
31 if self.is_string() || other.is_string() {
32 return self.is_string()
33 && other.is_string()
34 && arena.get_string_value(self) == arena.get_string_value(other);
35 }
36 if self.tag() != other.tag() {
37 return false;
38 }
39 match self.tag() {
40 TAG_INT => self.as_int(arena) == other.as_int(arena),
41 TAG_IMMEDIATE | TAG_NONE => false,
42 TAG_STRING => arena.get_string_value(self) == arena.get_string_value(other),
43 TAG_LIST => {
44 let a_len = arena.list_len_value(self);
45 let b_len = arena.list_len_value(other);
46 a_len == b_len
47 && (0..a_len).all(|i| {
48 arena
49 .list_get_value(self, i)
50 .zip(arena.list_get_value(other, i))
51 .is_some_and(|(x, y)| x.eq_in(y, arena))
52 })
53 }
54 TAG_TUPLE => {
55 let a = arena.get_tuple(self.arena_index());
56 let b = arena.get_tuple(other.arena_index());
57 a.len() == b.len() && a.iter().zip(b).all(|(x, y)| x.eq_in(*y, arena))
58 }
59 TAG_VECTOR => {
60 let a = arena.vector_ref_value(self);
61 let b = arena.vector_ref_value(other);
62 a.len() == b.len() && a.iter().zip(b).all(|(x, y)| x.eq_in(*y, arena))
63 }
64 TAG_MAP => {
65 let a = arena.map_ref_value(self);
66 let b = arena.map_ref_value(other);
67 a.len() == b.len()
68 && a.iter()
69 .all(|(k, (_, v1))| b.get(k).is_some_and(|(_, v2)| v1.eq_in(*v2, arena)))
70 }
71 TAG_RECORD => {
72 let (ta, fa) = arena.get_record(self.arena_index());
73 let (tb, fb) = arena.get_record(other.arena_index());
74 ta == tb
75 && fa.len() == fb.len()
76 && fa.iter().zip(fb).all(|(a, b)| a.eq_in(*b, arena))
77 }
78 TAG_VARIANT => {
79 unreachable!("variant comparison handled above")
80 }
81 TAG_SYMBOL => self.bits() == other.bits(),
82 _ => false,
83 }
84 }
85
86 pub fn hash_in<H: std::hash::Hasher>(self, state: &mut H, arena: &Arena) {
87 use std::hash::Hash;
88 if self.is_float() {
89 1u8.hash(state);
90 let f = self.as_float();
91 let bits = if f == 0.0 {
92 0.0f64.to_bits()
93 } else {
94 f.to_bits()
95 };
96 bits.hash(state);
97 return;
98 }
99 if let Some((kind, inner)) = self.wrapper_parts(arena) {
100 match kind {
101 WRAP_SOME => (TAG_SOME as u8).hash(state),
102 WRAP_OK => (TAG_OK as u8).hash(state),
103 WRAP_ERR => (TAG_ERR as u8).hash(state),
104 _ => (0xFFu8).hash(state),
105 }
106 inner.hash_in(state, arena);
107 return;
108 }
109 if let Some((tid, vid, fields)) = self.variant_parts(arena) {
110 (TAG_VARIANT as u8).hash(state);
111 tid.hash(state);
112 vid.hash(state);
113 for field in fields {
114 field.hash_in(state, arena);
115 }
116 return;
117 }
118 if self.is_string() {
119 (TAG_STRING as u8).hash(state);
120 arena.get_string_value(self).hash(state);
121 return;
122 }
123 let tag = self.tag();
124 (tag as u8).hash(state);
125 match tag {
126 TAG_INT => self.as_int(arena).hash(state),
127 TAG_IMMEDIATE => self.payload().hash(state),
128 TAG_NONE => 0u8.hash(state),
129 TAG_STRING => arena.get_string_value(self).hash(state),
130 TAG_LIST => {
131 arena.list_len_value(self).hash(state);
132 for item in arena.list_to_vec_value(self) {
133 item.hash_in(state, arena);
134 }
135 }
136 TAG_TUPLE => {
137 let items = arena.get_tuple(self.arena_index());
138 items.len().hash(state);
139 for item in items {
140 item.hash_in(state, arena);
141 }
142 }
143 TAG_VECTOR => {
144 let items = arena.vector_ref_value(self);
145 items.len().hash(state);
146 for item in items {
147 item.hash_in(state, arena);
148 }
149 }
150 TAG_RECORD => {
151 let (tid, fields) = arena.get_record(self.arena_index());
152 tid.hash(state);
153 for f in fields {
154 f.hash_in(state, arena);
155 }
156 }
157 TAG_VARIANT => {
158 unreachable!("variant hashing handled above")
159 }
160 TAG_SYMBOL => self.bits().hash(state),
161 _ => self.0.hash(state),
162 }
163 }
164
165 pub fn repr(self, arena: &Arena) -> String {
166 if self.is_float() {
167 return self.as_float().to_string();
168 }
169 if let Some((kind, inner)) = self.wrapper_parts(arena) {
170 let ir = inner.repr_inner(arena);
171 return match kind {
172 WRAP_SOME => format!("Option.Some({})", ir),
173 WRAP_OK => format!("Result.Ok({})", ir),
174 WRAP_ERR => format!("Result.Err({})", ir),
175 _ => "??".into(),
176 };
177 }
178 if let Some((tid, vid, fields)) = self.variant_parts(arena) {
179 let vname = arena.get_variant_name(tid, vid);
180 return if fields.is_empty() {
181 vname.to_string()
182 } else {
183 let parts: Vec<_> = fields.iter().map(|v| v.repr_inner(arena)).collect();
184 format!("{}({})", vname, parts.join(", "))
185 };
186 }
187 if self.is_string() {
188 return arena.get_string_value(self).to_string();
189 }
190 match self.tag() {
191 TAG_INT => self.as_int(arena).to_string(),
192 TAG_IMMEDIATE => match self.payload() {
193 IMM_FALSE => "false".into(),
194 IMM_TRUE => "true".into(),
195 IMM_UNIT => "Unit".into(),
196 _ => "??".into(),
197 },
198 TAG_NONE => "Option.None".into(),
199 TAG_STRING => arena.get_string_value(self).to_string(),
200 TAG_LIST => {
201 let parts: Vec<_> = arena
202 .list_to_vec_value(self)
203 .into_iter()
204 .map(|v| v.repr_inner(arena))
205 .collect();
206 format!("[{}]", parts.join(", "))
207 }
208 TAG_TUPLE => {
209 let items = arena.get_tuple(self.arena_index());
210 let parts: Vec<_> = items.iter().map(|v| v.repr_inner(arena)).collect();
211 format!("({})", parts.join(", "))
212 }
213 TAG_VECTOR => {
214 let items = arena.vector_ref_value(self);
215 let parts: Vec<_> = items.iter().map(|v| v.repr_inner(arena)).collect();
216 format!("Vector[{}]", parts.join(", "))
217 }
218 TAG_MAP => {
219 let map = arena.map_ref_value(self);
220 let mut pairs: Vec<_> = map
221 .values()
222 .map(|(k, v)| (k.repr_inner(arena), v.repr_inner(arena)))
223 .collect();
224 pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
225 let parts: Vec<_> = pairs
226 .into_iter()
227 .map(|(k, v)| format!("{}: {}", k, v))
228 .collect();
229 format!("{{{}}}", parts.join(", "))
230 }
231 TAG_RECORD => {
232 let (tid, fields) = arena.get_record(self.arena_index());
233 let name = arena.get_type_name(tid);
234 let fnames = arena.get_field_names(tid);
235 let parts: Vec<_> = fnames
236 .iter()
237 .zip(fields)
238 .map(|(n, v)| format!("{}: {}", n, v.repr_inner(arena)))
239 .collect();
240 format!("{}({})", name, parts.join(", "))
241 }
242 TAG_VARIANT => unreachable!("variant repr handled above"),
243 TAG_SYMBOL => match self.symbol_kind() {
244 SYMBOL_FN => format!("<fn {}>", arena.get_fn(self.symbol_index()).name),
245 SYMBOL_BUILTIN => format!("<builtin {}>", arena.get_builtin(self.symbol_index())),
246 SYMBOL_NAMESPACE => {
247 let (name, _) = arena.get_namespace(self.symbol_index());
248 format!("<type {}>", name)
249 }
250 SYMBOL_NULLARY_VARIANT => unreachable!("variant repr handled above"),
251 _ => "??".into(),
252 },
253 _ => "??".into(),
254 }
255 }
256
257 fn repr_inner(self, arena: &Arena) -> String {
258 if self.is_string() {
259 return format!("\"{}\"", arena.get_string_value(self));
260 }
261 self.repr(arena)
262 }
263
264 pub fn display(self, arena: &Arena) -> Option<String> {
265 if self.is_unit() {
266 None
267 } else {
268 Some(self.repr(arena))
269 }
270 }
271}