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 => self.as_int(arena) == other.as_int(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 => self.as_int(arena).hash(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 => format!("{}", self.as_int(arena)),
231 TAG_IMMEDIATE => match self.payload() {
232 IMM_FALSE => String::from("false"),
233 IMM_TRUE => String::from("true"),
234 IMM_UNIT => String::from("Unit"),
235 _ => String::from("??"),
236 },
237 TAG_NONE => String::from("Option.None"),
238 TAG_STRING => arena.get_string_value(self).to_string(),
239 TAG_LIST => {
240 let parts: Vec<_> = arena
241 .list_to_vec_value(self)
242 .into_iter()
243 .map(|v| v.repr_inner(arena))
244 .collect();
245 format!("[{}]", parts.join(", "))
246 }
247 TAG_TUPLE => {
248 let items = arena.get_tuple(self.arena_index());
249 let parts: Vec<_> = items.iter().map(|v| v.repr_inner(arena)).collect();
250 format!("({})", parts.join(", "))
251 }
252 TAG_VECTOR => {
253 let items = arena.vector_ref_value(self);
254 let parts: Vec<_> = items.iter().map(|v| v.repr_inner(arena)).collect();
255 format!("Vector[{}]", parts.join(", "))
256 }
257 TAG_MAP => {
258 let map = arena.map_ref_value(self);
259 let mut pairs: Vec<_> = map
260 .values()
261 .map(|(k, v)| (k.repr_inner(arena), v.repr_inner(arena)))
262 .collect();
263 pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
264 let parts: Vec<_> = pairs
265 .into_iter()
266 .map(|(k, v)| format!("{}: {}", k, v))
267 .collect();
268 format!("{{{}}}", parts.join(", "))
269 }
270 TAG_RECORD => {
271 let (tid, fields) = arena.get_record(self.arena_index());
272 let name = arena.get_type_name(tid);
273 let fnames = arena.get_field_names(tid);
274 let parts: Vec<_> = fnames
275 .iter()
276 .zip(fields)
277 .map(|(n, v)| format!("{}: {}", n, v.repr_inner(arena)))
278 .collect();
279 format!("{}({})", name, parts.join(", "))
280 }
281 TAG_VARIANT | TAG_INLINE_VARIANT => unreachable!("variant repr handled above"),
282 TAG_SYMBOL => match self.symbol_kind() {
283 SYMBOL_FN => format!("<fn {}>", arena.get_fn(self.symbol_index()).name()),
284 SYMBOL_BUILTIN => format!("<builtin {}>", arena.get_builtin(self.symbol_index())),
285 SYMBOL_NAMESPACE => {
286 let (name, _) = arena.get_namespace(self.symbol_index());
287 format!("<type {}>", name)
288 }
289 SYMBOL_NULLARY_VARIANT => unreachable!("variant repr handled above"),
290 _ => String::from("??"),
291 },
292 _ => String::from("??"),
293 }
294 }
295
296 fn repr_inner<T: ArenaTypes>(self, arena: &Arena<T>) -> String {
297 if self.is_string() {
298 return format!("\"{}\"", arena.get_string_value(self));
299 }
300 self.repr(arena)
301 }
302
303 pub fn display<T: ArenaTypes>(self, arena: &Arena<T>) -> Option<String> {
304 if self.is_unit() {
305 None
306 } else {
307 Some(self.repr(arena))
308 }
309 }
310}