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