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