1use std::cmp::Ordering;
2use std::fmt;
3use std::sync::{Arc, Mutex};
4
5use crate::collections::{
6 PersistentArrayMap, PersistentHashMap, PersistentHashSet, PersistentList, PersistentQueue,
7 PersistentVector, SortedMap, SortedSet, TransientMap, TransientSet, TransientVector,
8};
9use crate::error::ExceptionInfo;
10use crate::hash::{
11 ClojureHash, hash_combine_ordered, hash_combine_unordered, hash_i64, hash_string, hash_u128,
12};
13use crate::keyword::Keyword;
14use crate::regex::Matcher;
15use crate::resource::ResourceHandle;
16use crate::symbol::Symbol;
17use crate::types::{
18 Agent, Atom, BoundFn, CljxCons, CljxFn, CljxFuture, CljxPromise, Delay, LazySeq, MultiFn,
19 Namespace, NativeFn, Protocol, ProtocolFn, Var, Volatile,
20};
21use cljrs_gc::{GcPtr, MarkVisitor, Trace};
22use num_bigint::BigInt;
23use num_traits::ToPrimitive;
24use regex::Regex;
25
26#[derive(Debug)]
28pub struct ObjectArray(pub Mutex<Vec<Value>>);
29
30impl ObjectArray {
31 pub fn new(v: Vec<Value>) -> Self {
32 Self(Mutex::new(v))
33 }
34}
35
36impl Trace for ObjectArray {
37 fn trace(&self, visitor: &mut MarkVisitor) {
38 {
39 let guard = self.0.lock().unwrap();
40 for v in guard.iter() {
41 v.trace(visitor);
42 }
43 }
44 }
45}
46
47#[derive(Clone, Debug)]
52pub enum Value {
53 Nil,
55 Bool(bool),
56 Long(i64),
57 Double(f64),
58 BigInt(GcPtr<BigInt>),
59 BigDecimal(GcPtr<bigdecimal::BigDecimal>),
60 Ratio(GcPtr<num_rational::Ratio<BigInt>>),
61 Char(char),
62 Str(GcPtr<String>),
63 Uuid(u128),
64 Pattern(GcPtr<Regex>),
65 Matcher(GcPtr<Matcher>),
66
67 Symbol(GcPtr<Symbol>),
69 Keyword(GcPtr<Keyword>),
70
71 List(GcPtr<PersistentList>),
73 Vector(GcPtr<PersistentVector>),
74 Map(MapValue),
77 Set(SetValue),
78 Queue(GcPtr<PersistentQueue>),
79
80 TransientMap(GcPtr<TransientMap>),
82 TransientSet(GcPtr<TransientSet>),
83 TransientVector(GcPtr<TransientVector>),
84
85 IntArray(GcPtr<Mutex<Vec<i32>>>),
87 LongArray(GcPtr<Mutex<Vec<i64>>>),
88 ShortArray(GcPtr<Mutex<Vec<i16>>>),
89 ByteArray(GcPtr<Mutex<Vec<i8>>>),
90 FloatArray(GcPtr<Mutex<Vec<f32>>>),
91 DoubleArray(GcPtr<Mutex<Vec<f64>>>),
92 BooleanArray(GcPtr<Mutex<Vec<bool>>>),
93 CharArray(GcPtr<Mutex<Vec<char>>>),
94 ObjectArray(GcPtr<ObjectArray>),
95
96 NativeFunction(GcPtr<NativeFn>),
98 Fn(GcPtr<CljxFn>),
99 Macro(GcPtr<CljxFn>),
100 BoundFn(GcPtr<BoundFn>),
101
102 Var(GcPtr<Var>),
104 Atom(GcPtr<Atom>),
105
106 Reduced(Box<Value>),
108
109 Namespace(GcPtr<Namespace>),
111
112 LazySeq(GcPtr<LazySeq>),
115 Cons(GcPtr<CljxCons>),
117
118 Protocol(GcPtr<Protocol>),
120 ProtocolFn(GcPtr<ProtocolFn>),
121 MultiFn(GcPtr<MultiFn>),
122
123 Volatile(GcPtr<Volatile>),
125 Delay(GcPtr<Delay>),
126 Promise(GcPtr<CljxPromise>),
127 Future(GcPtr<CljxFuture>),
128 Agent(GcPtr<Agent>),
129
130 TypeInstance(GcPtr<TypeInstance>),
132
133 NativeObject(GcPtr<crate::native_object::NativeObjectBox>),
135
136 Resource(ResourceHandle),
138
139 WithMeta(Box<Value>, Box<Value>),
142
143 Error(GcPtr<ExceptionInfo>),
145}
146
147#[derive(Clone, Debug)]
149pub enum MapValue {
150 Array(GcPtr<PersistentArrayMap>),
151 Hash(GcPtr<PersistentHashMap>),
152 Sorted(GcPtr<SortedMap>),
153}
154
155impl MapValue {
156 pub fn empty() -> Self {
157 MapValue::Array(GcPtr::new(PersistentArrayMap::empty()))
158 }
159
160 pub fn from_pairs(pairs: Vec<(Value, Value)>) -> Self {
167 use crate::collections::array_map::AssocResult;
168
169 match PersistentArrayMap::from_pairs(pairs) {
171 AssocResult::Array(m) => MapValue::Array(GcPtr::new(m)),
172 AssocResult::Promote(pairs) => {
173 MapValue::Hash(GcPtr::new(PersistentHashMap::from_pairs(pairs)))
174 }
175 }
176 }
177
178 pub fn from_flat_entries(entries: Vec<Value>) -> Self {
183 debug_assert!(entries.len().is_multiple_of(2));
184 let pairs: Vec<(Value, Value)> = entries
186 .chunks(2)
187 .map(|chunk| (chunk[0].clone(), chunk[1].clone()))
188 .collect();
189 Self::from_pairs(pairs)
190 }
191
192 pub fn get(&self, key: &Value) -> Option<Value> {
193 match self {
194 MapValue::Array(m) => m.get().get(key).cloned(),
195 MapValue::Hash(m) => m.get().get(key).cloned(),
196 MapValue::Sorted(m) => m.get().get(key).cloned(),
197 }
198 }
199
200 pub fn count(&self) -> usize {
201 match self {
202 MapValue::Array(m) => m.get().count(),
203 MapValue::Hash(m) => m.get().count(),
204 MapValue::Sorted(m) => m.get().count(),
205 }
206 }
207
208 pub fn assoc(&self, k: Value, v: Value) -> Self {
209 match self {
210 MapValue::Array(m) => match m.get().assoc(k, v) {
211 crate::collections::array_map::AssocResult::Array(new_m) => {
212 MapValue::Array(GcPtr::new(new_m))
213 }
214 crate::collections::array_map::AssocResult::Promote(pairs) => {
215 let hm = PersistentHashMap::from_pairs(pairs);
216 MapValue::Hash(GcPtr::new(hm))
217 }
218 },
219 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().assoc(k, v))),
220 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().assoc(k, v))),
221 }
222 }
223
224 pub fn dissoc(&self, key: &Value) -> Self {
225 match self {
226 MapValue::Array(m) => MapValue::Array(GcPtr::new(m.get().dissoc(key))),
227 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().dissoc(key))),
228 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().dissoc(key))),
229 }
230 }
231
232 pub fn contains_key(&self, key: &Value) -> bool {
233 match self {
234 MapValue::Array(m) => m.get().contains_key(key),
235 MapValue::Hash(m) => m.get().contains_key(key),
236 MapValue::Sorted(m) => m.get().contains_key(key),
237 }
238 }
239
240 pub fn for_each<F: FnMut(&Value, &Value)>(&self, mut f: F) {
242 match self {
243 MapValue::Array(m) => {
244 for (k, v) in m.get().iter() {
245 f(k, v);
246 }
247 }
248 MapValue::Hash(m) => {
249 for (k, v) in m.get().iter() {
250 f(k, v);
251 }
252 }
253 MapValue::Sorted(m) => {
254 for (k, v) in m.get().iter() {
255 f(k, v);
256 }
257 }
258 }
259 }
260
261 pub fn iter(&self) -> Box<dyn Iterator<Item = (&Value, &Value)> + '_> {
263 match self {
264 MapValue::Array(m) => Box::new(m.get().iter()),
265 MapValue::Hash(m) => Box::new(m.get().iter()),
266 MapValue::Sorted(m) => Box::new(m.get().iter()),
267 }
268 }
269}
270
271#[derive(Clone, Debug)]
273pub enum SetValue {
274 Hash(GcPtr<PersistentHashSet>),
275 Sorted(GcPtr<SortedSet>),
276}
277
278impl SetValue {
279 pub fn empty() -> Self {
280 Self::Hash(GcPtr::new(PersistentHashSet::empty()))
281 }
282
283 pub fn count(&self) -> usize {
284 match self {
285 SetValue::Hash(m) => m.get().count(),
286 SetValue::Sorted(m) => m.get().count(),
287 }
288 }
289
290 pub fn is_empty(&self) -> bool {
291 match self {
292 SetValue::Hash(m) => m.get().is_empty(),
293 SetValue::Sorted(m) => m.get().is_empty(),
294 }
295 }
296
297 pub fn contains(&self, key: &Value) -> bool {
298 match self {
299 SetValue::Hash(m) => m.get().contains(key),
300 SetValue::Sorted(m) => m.get().contains(key),
301 }
302 }
303
304 pub fn conj(&self, value: Value) -> Self {
305 match self {
306 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().conj(value))),
307 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().conj(value))),
308 }
309 }
310
311 pub fn conj_mut(&mut self, value: Value) -> &mut Self {
312 match self {
313 SetValue::Hash(m) => {
314 m.get_mut().conj_mut(value);
315 }
316 SetValue::Sorted(s) => {
317 s.get_mut().conj_mut(value);
318 }
319 }
320 self
321 }
322
323 pub fn disj(&self, value: &Value) -> Self {
324 match self {
325 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().disj(value))),
326 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().disj(value))),
327 }
328 }
329
330 pub fn iter(&self) -> Box<dyn Iterator<Item = &Value> + '_> {
331 match self {
332 SetValue::Hash(s) => Box::new(s.get().iter()),
333 SetValue::Sorted(s) => Box::new(s.get().iter()),
334 }
335 }
336}
337
338impl cljrs_gc::Trace for SetValue {
339 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
340 use cljrs_gc::GcVisitor as _;
341 match self {
342 SetValue::Hash(s) => visitor.visit(s),
343 SetValue::Sorted(s) => visitor.visit(s),
344 }
345 }
346}
347
348impl Eq for Value {}
351
352impl PartialEq for Value {
353 fn eq(&self, other: &Self) -> bool {
354 if let Value::WithMeta(inner, _) = self {
356 return inner.as_ref() == other;
357 }
358 if let Value::WithMeta(inner, _) = other {
359 return self == inner.as_ref();
360 }
361 if let Value::Reduced(inner) = self {
363 return inner.as_ref() == other;
364 }
365 if let Value::Reduced(inner) = other {
366 return self == inner.as_ref();
367 }
368 if let (Value::LazySeq(a), Value::LazySeq(b)) = (self, other)
371 && GcPtr::ptr_eq(a, b)
372 {
373 return true;
374 }
375 if let Value::LazySeq(ls) = self {
379 let realized = ls.get().realize();
380 if realized == Value::Nil && other.is_sequential() {
381 return value_to_seq_vec(other).is_empty();
382 }
383 return realized == *other;
384 }
385 if let Value::LazySeq(ls) = other {
386 let realized = ls.get().realize();
387 if realized == Value::Nil && self.is_sequential() {
388 return value_to_seq_vec(self).is_empty();
389 }
390 return *self == realized;
391 }
392 match (self, other) {
393 (Value::Nil, Value::Nil) => true,
394 (Value::Bool(a), Value::Bool(b)) => a == b,
395 (Value::Long(a), Value::Long(b)) => a == b,
397 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a) == *b.get(),
398 (Value::BigInt(a), Value::Long(b)) => *a.get() == BigInt::from(*b),
399 (Value::BigInt(a), Value::BigInt(b)) => a.get() == b.get(),
400 (Value::Double(a), Value::Double(b)) => a == b, (Value::Long(a), Value::Double(b)) => b.fract() == 0.0 && b.to_i64() == Some(*a),
402 (Value::Double(a), Value::Long(b)) => a.fract() == 0.0 && a.to_i64() == Some(*b),
403 (Value::BigDecimal(a), Value::BigDecimal(b)) => a.get() == b.get(),
404 (Value::Ratio(a), Value::Ratio(b)) => a.get() == b.get(),
405 (Value::Char(a), Value::Char(b)) => a == b,
406 (Value::Str(a), Value::Str(b)) => a.get() == b.get(),
407 (Value::Symbol(a), Value::Symbol(b)) => a.get() == b.get(),
408 (Value::Keyword(a), Value::Keyword(b)) => a.get() == b.get(),
409 (Value::List(a), Value::List(b)) => a.get() == b.get(),
411 (Value::Vector(a), Value::Vector(b)) => a.get() == b.get(),
412 (Value::Set(a), Value::Set(b)) => sets_equal(a, b),
413 (Value::Queue(a), Value::Queue(b)) => a.get() == b.get(),
414 (Value::Map(a), Value::Map(b)) => maps_equal(a, b),
415 (Value::List(_), Value::Vector(_)) | (Value::Vector(_), Value::List(_)) => {
417 seq_equal(self, other)
418 }
419 (Value::Cons(_), _) | (_, Value::Cons(_)) => seq_equal(self, other),
421 (Value::Fn(a), Value::Fn(b)) => std::ptr::eq(a.get() as *const _, b.get() as *const _),
423 (Value::Macro(a), Value::Macro(b)) => {
424 std::ptr::eq(a.get() as *const _, b.get() as *const _)
425 }
426 (Value::NativeFunction(a), Value::NativeFunction(b)) => {
427 std::ptr::eq(a.get() as *const _, b.get() as *const _)
428 }
429 (Value::Protocol(a), Value::Protocol(b)) => {
431 std::ptr::eq(a.get() as *const _, b.get() as *const _)
432 }
433 (Value::ProtocolFn(a), Value::ProtocolFn(b)) => {
434 std::ptr::eq(a.get() as *const _, b.get() as *const _)
435 }
436 (Value::MultiFn(a), Value::MultiFn(b)) => {
437 std::ptr::eq(a.get() as *const _, b.get() as *const _)
438 }
439 (Value::Volatile(a), Value::Volatile(b)) => {
441 std::ptr::eq(a.get() as *const _, b.get() as *const _)
442 }
443 (Value::Delay(a), Value::Delay(b)) => {
444 std::ptr::eq(a.get() as *const _, b.get() as *const _)
445 }
446 (Value::Promise(a), Value::Promise(b)) => {
447 std::ptr::eq(a.get() as *const _, b.get() as *const _)
448 }
449 (Value::Future(a), Value::Future(b)) => {
450 std::ptr::eq(a.get() as *const _, b.get() as *const _)
451 }
452 (Value::Agent(a), Value::Agent(b)) => {
453 std::ptr::eq(a.get() as *const _, b.get() as *const _)
454 }
455 (Value::Atom(a), Value::Atom(b)) => {
456 std::ptr::eq(a.get() as *const _, b.get() as *const _)
457 }
458 (Value::Var(a), Value::Var(b)) => {
459 std::ptr::eq(a.get() as *const _, b.get() as *const _)
460 }
461 (Value::Namespace(a), Value::Namespace(b)) => {
462 std::ptr::eq(a.get() as *const _, b.get() as *const _)
463 }
464 (Value::Uuid(a), Value::Uuid(b)) => a == b,
466 (Value::Pattern(a), Value::Pattern(b)) => a.get().as_str() == b.get().as_str(),
469 (Value::NativeObject(a), Value::NativeObject(b)) => {
471 std::ptr::eq(a.get() as *const _, b.get() as *const _)
472 }
473 (Value::Resource(a), Value::Resource(b)) => Arc::ptr_eq(&a.0, &b.0),
475 (Value::TypeInstance(a), Value::TypeInstance(b)) => {
477 a.get().type_tag == b.get().type_tag && maps_equal(&a.get().fields, &b.get().fields)
478 }
479 (Value::Error(a), Value::Error(b)) => {
480 std::ptr::eq(a.get() as *const _, b.get() as *const _)
481 }
482 _ => false,
483 }
484 }
485}
486
487fn maps_equal(a: &MapValue, b: &MapValue) -> bool {
488 if a.count() != b.count() {
489 return false;
490 }
491 let mut equal = true;
492 a.for_each(|k, v| {
493 if equal {
494 match b.get(k) {
495 Some(bv) if &bv == v => {}
496 _ => equal = false,
497 }
498 }
499 });
500 equal
501}
502
503fn sets_equal(a: &SetValue, b: &SetValue) -> bool {
504 if a.count() != b.count() {
505 return false;
506 }
507 for k in a.iter() {
508 if !b.contains(k) {
509 return false;
510 }
511 }
512 true
513}
514
515fn seq_equal(a: &Value, b: &Value) -> bool {
516 let a_items = value_to_seq_vec(a);
517 let b_items = value_to_seq_vec(b);
518 a_items.len() == b_items.len() && a_items.iter().zip(b_items.iter()).all(|(x, y)| x == y)
519}
520
521fn value_to_seq_vec(v: &Value) -> Vec<Value> {
522 let mut v = v.clone();
524 while let Value::LazySeq(ls) = &v {
525 v = ls.get().realize();
526 }
527 match &v {
528 Value::List(l) => l.get().iter().cloned().collect(),
529 Value::Vector(v) => v.get().iter().cloned().collect(),
530 Value::LazySeq(_) => unreachable!("unwrapped above"),
531 Value::Cons(c) => {
532 let mut result = vec![c.get().head.clone()];
533 let mut tail = c.get().tail.clone();
534 loop {
535 match tail {
536 Value::Nil => break,
537 Value::List(l) => {
538 result.extend(l.get().iter().cloned());
539 break;
540 }
541 Value::Cons(next_c) => {
542 result.push(next_c.get().head.clone());
543 tail = next_c.get().tail.clone();
544 }
545 Value::LazySeq(ls) => {
546 tail = ls.get().realize();
547 }
548 _ => break,
549 }
550 }
551 result
552 }
553 _ => vec![],
554 }
555}
556
557impl ClojureHash for Value {
560 fn clojure_hash(&self) -> u32 {
561 match self {
562 Value::WithMeta(inner, _) => inner.clojure_hash(),
563 Value::Reduced(inner) => inner.clojure_hash(),
564 Value::Nil => 0,
565 Value::Bool(b) => {
566 if *b { 1231 } else { 1237 } }
568 Value::Long(n) => hash_i64(*n),
569 Value::Double(f) => {
570 if f.fract() == 0.0
572 && f.is_finite()
573 && let Some(n) = num_traits::ToPrimitive::to_i64(f)
574 {
575 return hash_i64(n);
576 }
577 hash_i64(f.to_bits() as i64)
578 }
579 Value::BigInt(n) => {
580 if let Some(l) = n.get().to_i64() {
582 return hash_i64(l);
583 }
584 hash_string(&n.get().to_string())
586 }
587 Value::Char(c) => *c as u32,
588 Value::Str(s) => hash_string(s.get()),
589 Value::Pattern(r) => hash_string(r.get().as_str()),
590 Value::Matcher(m) => hash_string(m.get().pattern.get().as_str()),
591 Value::Keyword(k) => hash_string(&k.get().to_string()),
592 Value::Symbol(s) => hash_string(&s.get().to_string()),
593 Value::Uuid(u) => hash_u128(*u),
594 Value::NativeObject(obj) => {
595 let ptr = obj.get() as *const _ as usize;
596 hash_i64(ptr as i64)
597 }
598 Value::Resource(r) => {
599 let ptr = Arc::as_ptr(&r.0) as *const () as usize;
600 hash_i64(ptr as i64)
601 }
602 Value::List(l) => {
603 let mut h: u32 = 1;
604 for v in l.get().iter() {
605 h = hash_combine_ordered(h, v.clojure_hash());
606 }
607 h
608 }
609 Value::Vector(v) => {
610 let mut h: u32 = 1;
611 for item in v.get().iter() {
612 h = hash_combine_ordered(h, item.clojure_hash());
613 }
614 h
615 }
616 Value::Map(m) => {
617 let mut h: u32 = 0;
618 m.for_each(|k, v| {
619 h = hash_combine_unordered(
620 h,
621 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
622 );
623 });
624 h
625 }
626 Value::Set(s) => {
627 let mut h: u32 = 0;
628 for k in s.iter() {
629 h = hash_combine_unordered(h, k.clojure_hash());
630 }
631 h
632 }
633 Value::TransientMap(m) => m.get().clojure_hash(),
634 Value::TransientSet(s) => s.get().clojure_hash(),
635 Value::TransientVector(v) => v.get().clojure_hash(),
636
637 Value::BooleanArray(a) => {
639 let mut h: u32 = 0;
640 for b in a.get().lock().unwrap().iter() {
641 h = hash_combine_ordered(h, if *b { 1231 } else { 1237 })
642 }
643 h
644 }
645 Value::ByteArray(a) => {
646 let mut h: u32 = 0;
647 for b in a.get().lock().unwrap().iter() {
648 h = hash_combine_ordered(h, *b as u32)
649 }
650 h
651 }
652 Value::ShortArray(a) => {
653 let mut h: u32 = 0;
654 for item in a.get().lock().unwrap().iter() {
655 h = hash_combine_ordered(h, *item as u32)
656 }
657 h
658 }
659 Value::IntArray(a) => {
660 let mut h: u32 = 0;
661 for item in a.get().lock().unwrap().iter() {
662 h = hash_combine_ordered(h, *item as u32)
663 }
664 h
665 }
666 Value::CharArray(a) => {
667 let mut h: u32 = 0;
668 for item in a.get().lock().unwrap().iter() {
669 h = hash_combine_ordered(h, *item as u32)
670 }
671 h
672 }
673 Value::LongArray(a) => {
674 let mut h: u32 = 0;
675 for item in a.get().lock().unwrap().iter() {
676 let v = *item;
677 h = hash_combine_ordered(h, hash_i64(v));
678 }
679 h
680 }
681 Value::FloatArray(a) => {
682 let mut h: u32 = 0;
683 for item in a.get().lock().unwrap().iter() {
684 let f = *item;
685 h = hash_combine_ordered(
686 h,
687 if f.fract() == 0.0
688 && f.is_finite()
689 && let Some(n) = ToPrimitive::to_i64(item)
690 {
691 hash_i64(n)
692 } else {
693 hash_i64(f.to_bits() as i64)
694 },
695 )
696 }
697 h
698 }
699 Value::DoubleArray(a) => {
700 let mut h: u32 = 0;
701 for item in a.get().lock().unwrap().iter() {
702 let f = *item;
703 h = hash_combine_ordered(
704 h,
705 if f.fract() == 0.0
706 && f.is_finite()
707 && let Some(n) = ToPrimitive::to_i64(item)
708 {
709 hash_i64(n)
710 } else {
711 hash_i64(f.to_bits() as i64)
712 },
713 )
714 }
715 h
716 }
717 Value::ObjectArray(a) => {
718 let mut h: u32 = 0;
719 for item in a.get().0.lock().unwrap().iter() {
720 h = hash_combine_ordered(h, item.clojure_hash())
721 }
722 h
723 }
724
725 Value::Fn(f) => f.get() as *const _ as u32,
727 Value::BoundFn(f) => f.get() as *const _ as u32,
728 Value::NativeFunction(f) => f.get() as *const _ as u32,
729 Value::Var(v) => v.get() as *const _ as u32,
730 Value::Atom(a) => a.get() as *const _ as u32,
731 Value::Namespace(n) => n.get() as *const _ as u32,
732 Value::Queue(q) => {
733 let mut h: u32 = 1;
734 for v in q.get().iter() {
735 h = hash_combine_ordered(h, v.clojure_hash());
736 }
737 h
738 }
739 Value::Macro(f) => f.get() as *const _ as u32,
740 Value::BigDecimal(d) => hash_string(&d.get().to_string()),
741 Value::Ratio(r) => hash_string(&r.get().to_string()),
742 Value::LazySeq(ls) => ls.get().realize().clojure_hash(),
743 Value::Protocol(p) => p.get() as *const _ as u32,
744 Value::ProtocolFn(pf) => pf.get() as *const _ as u32,
745 Value::MultiFn(mf) => mf.get() as *const _ as u32,
746 Value::Cons(_) => {
747 let mut h: u32 = 1;
749 for v in value_to_seq_vec(self) {
750 h = hash_combine_ordered(h, v.clojure_hash());
751 }
752 h
753 }
754 Value::Volatile(v) => v.get() as *const _ as u32,
756 Value::Delay(d) => d.get() as *const _ as u32,
757 Value::Promise(p) => p.get() as *const _ as u32,
758 Value::Future(fu) => fu.get() as *const _ as u32,
759 Value::Agent(a) => a.get() as *const _ as u32,
760 Value::TypeInstance(ti) => {
762 let tag_hash = hash_string(&ti.get().type_tag);
763 let mut fields_hash: u32 = 0;
764 ti.get().fields.for_each(|k, v| {
765 fields_hash = hash_combine_unordered(
766 fields_hash,
767 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
768 );
769 });
770 hash_combine_ordered(tag_hash, fields_hash)
771 }
772 Value::Error(e) => e.get().clojure_hash(),
773 }
774 }
775}
776
777impl std::hash::Hash for Value {
779 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
780 self.clojure_hash().hash(state);
781 }
782}
783
784impl fmt::Display for Value {
787 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789 pr_str(self, f, true)
790 }
791}
792
793pub struct PrintValue<'a>(pub &'a Value);
795
796impl fmt::Display for PrintValue<'_> {
797 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
798 pr_str(self.0, f, false)
799 }
800}
801
802pub fn pr_str(v: &Value, f: &mut fmt::Formatter<'_>, readably: bool) -> fmt::Result {
804 match v {
805 Value::WithMeta(inner, _) => pr_str(inner, f, readably),
806 Value::Reduced(inner) => {
807 write!(f, "#reduced ")?;
808 pr_str(inner, f, readably)
809 }
810 Value::Nil => write!(f, "nil"),
811 Value::Bool(b) => write!(f, "{b}"),
812 Value::Long(n) => write!(f, "{n}"),
813 Value::Double(d) => {
814 if d.is_infinite() {
815 if readably {
816 if *d > 0.0 {
817 write!(f, "##Inf")
818 } else {
819 write!(f, "##-Inf")
820 }
821 } else if *d > 0.0 {
822 write!(f, "Infinity")
823 } else {
824 write!(f, "-Infinity")
825 }
826 } else if d.is_nan() {
827 if readably {
828 write!(f, "##NaN")
829 } else {
830 write!(f, "NaN")
831 }
832 } else if d.fract() == 0.0 && d.abs() < 1e15 {
833 write!(f, "{d:.1}")
834 } else {
835 write!(f, "{d}")
836 }
837 }
838 Value::BigInt(n) => {
839 if readably {
840 write!(f, "{}N", n.get())
841 } else {
842 write!(f, "{}", n.get())
843 }
844 }
845 Value::BigDecimal(d) => {
846 let dec = d.get();
847 let s = format!("{}", dec);
848 if !s.contains('.') && dec.fractional_digit_count() > 0 {
851 let zeros = "0".repeat(dec.fractional_digit_count() as usize);
852 if readably {
853 write!(f, "{s}.{zeros}M")
854 } else {
855 write!(f, "{s}.{zeros}")
856 }
857 } else if readably {
858 write!(f, "{s}M")
859 } else {
860 write!(f, "{s}")
861 }
862 }
863 Value::Ratio(r) => write!(f, "{}", r.get()),
864 Value::Uuid(u) => {
865 let uuid = uuid::Uuid::from_u128(*u);
866 if readably {
867 write!(f, "#uuid \"{}\"", uuid)
868 } else {
869 write!(f, "{}", uuid)
870 }
871 }
872 Value::Char(c) => {
873 if readably {
874 match c {
875 '\n' => write!(f, "\\newline"),
876 '\t' => write!(f, "\\tab"),
877 ' ' => write!(f, "\\space"),
878 '\r' => write!(f, "\\return"),
879 c => write!(f, "\\{c}"),
880 }
881 } else {
882 write!(f, "{c}")
883 }
884 }
885 Value::Str(s) => {
886 if readably {
887 write!(f, "\"")?;
888 for c in s.get().chars() {
889 match c {
890 '"' => write!(f, "\\\"")?,
891 '\\' => write!(f, "\\\\")?,
892 '\n' => write!(f, "\\n")?,
893 '\t' => write!(f, "\\t")?,
894 '\r' => write!(f, "\\r")?,
895 c => write!(f, "{c}")?,
896 }
897 }
898 write!(f, "\"")
899 } else {
900 write!(f, "{}", s.get())
901 }
902 }
903 Value::Pattern(r) => {
904 if readably {
905 write!(f, "#\"")?;
906 write!(f, "{}", r.get().as_str())?;
907 write!(f, "\"")
908 } else {
909 write!(f, "#<{}>", r.get())
910 }
911 }
912 Value::Matcher(_) => write!(f, "#<Matcher>"),
913 Value::Symbol(s) => write!(f, "{}", s.get()),
914 Value::Keyword(k) => write!(f, "{}", k.get()),
915 Value::List(l) => {
916 write!(f, "(")?;
917 let mut first = true;
918 for item in l.get().iter() {
919 if !first {
920 write!(f, " ")?;
921 }
922 pr_str(item, f, readably)?;
923 first = false;
924 }
925 write!(f, ")")
926 }
927 Value::Vector(v) => {
928 write!(f, "[")?;
929 let mut first = true;
930 for item in v.get().iter() {
931 if !first {
932 write!(f, " ")?;
933 }
934 pr_str(item, f, readably)?;
935 first = false;
936 }
937 write!(f, "]")
938 }
939 Value::Map(m) => {
940 write!(f, "{{")?;
941 let mut first = true;
942 m.for_each(|k, v| {
943 if !first {
945 let _ = write!(f, ", ");
946 }
947 let _ = pr_str(k, f, readably);
948 let _ = write!(f, " ");
949 let _ = pr_str(v, f, readably);
950 first = false;
951 });
952 write!(f, "}}")
953 }
954 Value::Set(s) => {
955 write!(f, "#{{")?;
956 let mut first = true;
957 for item in s.iter() {
958 if !first {
959 write!(f, " ")?;
960 }
961 pr_str(item, f, readably)?;
962 first = false;
963 }
964 write!(f, "}}")
965 }
966 Value::BooleanArray(_)
967 | Value::ByteArray(_)
968 | Value::ShortArray(_)
969 | Value::IntArray(_)
970 | Value::LongArray(_)
971 | Value::CharArray(_)
972 | Value::FloatArray(_)
973 | Value::DoubleArray(_)
974 | Value::ObjectArray(_) => write!(f, "#[array]"),
975 Value::Queue(q) => {
976 write!(f, "#queue (")?;
978 let mut first = true;
979 for item in q.get().iter() {
980 if !first {
981 write!(f, " ")?;
982 }
983 pr_str(item, f, readably)?;
984 first = false;
985 }
986 write!(f, ")")
987 }
988 Value::LazySeq(ls) => pr_str(&ls.get().realize(), f, readably),
989 Value::Cons(c) => {
990 write!(f, "(")?;
991 pr_str(&c.get().head, f, readably)?;
992 let mut tail = c.get().tail.clone();
993 loop {
994 match tail {
995 Value::Nil => break,
996 Value::List(l) => {
997 for item in l.get().iter() {
998 write!(f, " ")?;
999 pr_str(item, f, readably)?;
1000 }
1001 break;
1002 }
1003 Value::Cons(next_c) => {
1004 write!(f, " ")?;
1005 pr_str(&next_c.get().head, f, readably)?;
1006 tail = next_c.get().tail.clone();
1007 }
1008 Value::LazySeq(ls) => {
1009 tail = ls.get().realize();
1010 }
1011 other => {
1012 write!(f, " . ")?;
1013 pr_str(&other, f, readably)?;
1014 break;
1015 }
1016 }
1017 }
1018 write!(f, ")")
1019 }
1020 Value::NativeFunction(nf) => write!(f, "#<NativeFn {}>", nf.get().name),
1021 Value::BoundFn(_) => write!(f, "#<BoundFn>"),
1022 Value::Fn(fun) => match &fun.get().name {
1023 Some(n) => write!(f, "#<Fn {n}>"),
1024 None => write!(f, "#<Fn>"),
1025 },
1026 Value::Macro(m) => match &m.get().name {
1027 Some(n) => write!(f, "#<Macro {n}>"),
1028 None => write!(f, "#<Macro>"),
1029 },
1030 Value::Var(v) => write!(f, "#'{}/{}", v.get().namespace, v.get().name),
1031 Value::Atom(a) => write!(f, "#<Atom {}>", a.get().deref()),
1032 Value::Namespace(n) => write!(f, "#<Namespace {}>", n.get().name),
1033 Value::Protocol(p) => write!(f, "#<Protocol {}>", p.get().name),
1034 Value::ProtocolFn(pf) => {
1035 write!(
1036 f,
1037 "#<fn {}/{}>",
1038 pf.get().protocol.get().name,
1039 pf.get().method_name
1040 )
1041 }
1042 Value::MultiFn(mf) => write!(f, "#<MultiFn {}>", mf.get().name),
1043 Value::Volatile(_) => write!(f, "#<Volatile>"),
1044 Value::Delay(_) => write!(f, "#<Delay>"),
1045 Value::Promise(_) => write!(f, "#<Promise>"),
1046 Value::Future(_) => write!(f, "#<Future>"),
1047 Value::Agent(_) => write!(f, "#<Agent>"),
1048 Value::TypeInstance(ti) => {
1049 let ti = ti.get();
1050 write!(f, "#{}{{", ti.type_tag)?;
1051 let mut first = true;
1052 ti.fields.for_each(|k, v| {
1053 if !first {
1054 let _ = write!(f, ", ");
1055 }
1056 let _ = pr_str(k, f, readably);
1057 let _ = write!(f, " ");
1058 let _ = pr_str(v, f, readably);
1059 first = false;
1060 });
1061 write!(f, "}}")
1062 }
1063 Value::NativeObject(obj) => {
1064 write!(f, "#<{} {:?}>", obj.get().type_tag(), obj.get().inner())
1065 }
1066 Value::Resource(r) => {
1067 if r.is_closed() {
1068 write!(f, "#<{} (closed)>", r.resource_type())
1069 } else {
1070 write!(f, "#<{}>", r.resource_type())
1071 }
1072 }
1073 Value::TransientMap(_) => write!(f, "#<TransientMap>"),
1074 Value::TransientSet(_) => write!(f, "#<TransientSet>"),
1075 Value::TransientVector(_) => write!(f, "#<TransientVector>"),
1076 Value::Error(e) => {
1077 write!(f, "#error ")?;
1078 let map = e.get().to_map().map_err(|_| fmt::Error {})?;
1079 pr_str(&map, f, readably)
1080 }
1081 }
1082}
1083
1084impl Value {
1087 pub fn unwrap_meta(&self) -> &Value {
1089 match self {
1090 Value::WithMeta(inner, _) => inner.unwrap_meta(),
1091 other => other,
1092 }
1093 }
1094
1095 pub fn get_meta(&self) -> Option<&Value> {
1097 match self {
1098 Value::WithMeta(_, meta) => Some(meta),
1099 _ => None,
1100 }
1101 }
1102
1103 pub fn with_meta(self, meta: Value) -> Value {
1105 match self {
1106 Value::WithMeta(inner, _) => Value::WithMeta(inner, Box::new(meta)),
1107 other => Value::WithMeta(Box::new(other), Box::new(meta)),
1108 }
1109 }
1110}
1111
1112impl Value {
1115 pub fn type_name(&self) -> &'static str {
1117 match self {
1118 Value::WithMeta(inner, _) => inner.type_name(),
1119 Value::Reduced(_) => "reduced",
1120 Value::Nil => "nil",
1121 Value::Bool(_) => "boolean",
1122 Value::Long(_) => "long",
1123 Value::Double(_) => "double",
1124 Value::BigInt(_) => "bigint",
1125 Value::BigDecimal(_) => "bigdecimal",
1126 Value::Ratio(_) => "ratio",
1127 Value::Char(_) => "char",
1128 Value::Str(_) => "string",
1129 Value::Pattern(_) => "pattern",
1130 Value::Matcher(_) => "matcher",
1131 Value::Symbol(_) => "symbol",
1132 Value::Keyword(_) => "keyword",
1133 Value::Uuid(_) => "uuid",
1134 Value::List(_) => "list",
1135 Value::Vector(_) => "vector",
1136 Value::Map(_) => "map",
1137 Value::Set(_) => "set",
1138 Value::Queue(_) => "queue",
1139 Value::NativeFunction(_)
1140 | Value::Fn(_)
1141 | Value::BoundFn(_)
1142 | Value::Macro(_)
1143 | Value::ProtocolFn(_)
1144 | Value::MultiFn(_) => "fn",
1145 Value::Var(_) => "var",
1146 Value::Atom(_) => "atom",
1147 Value::Namespace(_) => "namespace",
1148 Value::LazySeq(_) => "lazyseq",
1149 Value::Cons(_) => "cons",
1150 Value::Protocol(_) => "protocol",
1151 Value::Volatile(_) => "volatile",
1152 Value::Delay(_) => "delay",
1153 Value::Promise(_) => "promise",
1154 Value::Future(_) => "future",
1155 Value::Agent(_) => "agent",
1156 Value::TypeInstance(_) => "record",
1157 Value::NativeObject(_) => "native-object",
1158 Value::BooleanArray(_) => "boolean-array",
1159 Value::ByteArray(_) => "byte-array",
1160 Value::ShortArray(_) => "short-array",
1161 Value::IntArray(_) => "int-array",
1162 Value::LongArray(_) => "long-array",
1163 Value::FloatArray(_) => "float-array",
1164 Value::DoubleArray(_) => "double-array",
1165 Value::CharArray(_) => "char-array",
1166 Value::ObjectArray(_) => "object-array",
1167 Value::Resource(r) => r.resource_type(),
1168 Value::TransientMap(_) => "transient-map",
1169 Value::TransientSet(_) => "transient-set",
1170 Value::TransientVector(_) => "transient-vector",
1171 Value::Error(_) => "error",
1172 }
1173 }
1174
1175 pub fn string(s: impl Into<String>) -> Self {
1177 Value::Str(GcPtr::new(s.into()))
1178 }
1179
1180 pub fn symbol(s: Symbol) -> Self {
1182 Value::Symbol(GcPtr::new(s))
1183 }
1184
1185 pub fn keyword(k: Keyword) -> Self {
1187 Value::Keyword(GcPtr::new(k))
1188 }
1189
1190 pub fn is_sequential(&self) -> bool {
1192 matches!(
1193 self,
1194 Value::List(_) | Value::Vector(_) | Value::LazySeq(_) | Value::Cons(_)
1195 )
1196 }
1197
1198 pub fn is_coll(&self) -> bool {
1200 self.unwrap_meta().is_coll_inner()
1201 }
1202
1203 fn is_coll_inner(&self) -> bool {
1204 matches!(
1205 self,
1206 Value::List(_)
1207 | Value::Vector(_)
1208 | Value::Map(_)
1209 | Value::Set(_)
1210 | Value::Queue(_)
1211 | Value::LazySeq(_)
1212 | Value::Cons(_)
1213 )
1214 }
1215}
1216
1217impl cljrs_gc::Trace for Value {
1218 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1219 use cljrs_gc::GcVisitor as _;
1220 match self {
1221 Value::Reduced(inner) => inner.trace(visitor),
1222 Value::WithMeta(inner, meta) => {
1223 inner.trace(visitor);
1224 meta.trace(visitor);
1225 }
1226 Value::Nil
1227 | Value::Bool(_)
1228 | Value::Long(_)
1229 | Value::Double(_)
1230 | Value::Char(_)
1231 | Value::Uuid(_) => {}
1232 Value::BigInt(p) => visitor.visit(p),
1233 Value::BigDecimal(p) => visitor.visit(p),
1234 Value::Ratio(p) => visitor.visit(p),
1235 Value::Str(p) => visitor.visit(p),
1236 Value::Pattern(p) => visitor.visit(p),
1237 Value::Matcher(m) => visitor.visit(m),
1238 Value::Symbol(p) => visitor.visit(p),
1239 Value::Keyword(p) => visitor.visit(p),
1240 Value::List(p) => visitor.visit(p),
1241 Value::Vector(p) => visitor.visit(p),
1242 Value::Map(m) => m.trace(visitor),
1243 Value::Set(s) => s.trace(visitor),
1244 Value::Queue(p) => visitor.visit(p),
1245 Value::NativeFunction(p) => visitor.visit(p),
1246 Value::BoundFn(p) => visitor.visit(p),
1247 Value::Fn(p) | Value::Macro(p) => visitor.visit(p),
1248 Value::Var(p) => visitor.visit(p),
1249 Value::Atom(p) => visitor.visit(p),
1250 Value::Namespace(p) => visitor.visit(p),
1251 Value::LazySeq(p) => visitor.visit(p),
1252 Value::Cons(p) => visitor.visit(p),
1253 Value::Protocol(p) => visitor.visit(p),
1254 Value::ProtocolFn(p) => visitor.visit(p),
1255 Value::MultiFn(p) => visitor.visit(p),
1256 Value::Volatile(p) => visitor.visit(p),
1257 Value::Delay(p) => visitor.visit(p),
1258 Value::Promise(p) => visitor.visit(p),
1259 Value::Future(p) => visitor.visit(p),
1260 Value::Agent(p) => visitor.visit(p),
1261 Value::TypeInstance(p) => visitor.visit(p),
1262 Value::ObjectArray(p) => visitor.visit(p),
1263 Value::BooleanArray(_)
1264 | Value::ByteArray(_)
1265 | Value::ShortArray(_)
1266 | Value::IntArray(_)
1267 | Value::LongArray(_)
1268 | Value::FloatArray(_)
1269 | Value::DoubleArray(_)
1270 | Value::CharArray(_) => {}
1271 Value::NativeObject(p) => visitor.visit(p),
1272 Value::Resource(_) => {}
1274 Value::TransientMap(m) => visitor.visit(m),
1275 Value::TransientVector(p) => visitor.visit(p),
1276 Value::TransientSet(m) => visitor.visit(m),
1277 Value::Error(e) => visitor.visit(e),
1278 }
1279 }
1280}
1281
1282impl cljrs_gc::Trace for MapValue {
1283 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1284 use cljrs_gc::GcVisitor as _;
1285 match self {
1286 MapValue::Array(p) => visitor.visit(p),
1287 MapValue::Hash(p) => visitor.visit(p),
1288 MapValue::Sorted(p) => visitor.visit(p),
1289 }
1290 }
1291}
1292
1293#[derive(Clone, Debug)]
1298pub struct TypeInstance {
1299 pub type_tag: Arc<str>,
1300 pub fields: MapValue,
1301}
1302
1303impl cljrs_gc::Trace for TypeInstance {
1304 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1305 self.fields.trace(visitor);
1306 }
1307}
1308
1309#[cfg(test)]
1310mod tests {
1311 use super::*;
1312
1313 fn kw(s: &str) -> Value {
1314 Value::keyword(Keyword::simple(s))
1315 }
1316 fn sym(s: &str) -> Value {
1317 Value::symbol(Symbol::simple(s))
1318 }
1319 fn int(n: i64) -> Value {
1320 Value::Long(n)
1321 }
1322 fn s(v: &str) -> Value {
1323 Value::string(v)
1324 }
1325
1326 #[test]
1329 fn test_nil_eq() {
1330 assert_eq!(Value::Nil, Value::Nil);
1331 assert_ne!(Value::Nil, int(0));
1332 }
1333
1334 #[test]
1335 fn test_numeric_cross_type() {
1336 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1337 assert_eq!(int(1), big1.clone());
1338 assert_eq!(big1, int(1));
1339 assert_eq!(Value::Double(1.0), int(1));
1341 assert_eq!(int(1), Value::Double(1.0));
1342 assert_ne!(Value::Double(1.5), int(1));
1344 }
1345
1346 #[test]
1347 fn test_nan_not_equal_to_itself() {
1348 let nan = Value::Double(f64::NAN);
1349 assert_ne!(nan, nan.clone());
1350 }
1351
1352 #[test]
1353 fn test_string_equality() {
1354 assert_eq!(s("hello"), s("hello"));
1355 assert_ne!(s("hello"), s("world"));
1356 }
1357
1358 #[test]
1359 fn test_list_vector_seq_equality() {
1360 let list = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1361 let vec = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1362 assert_eq!(list, vec);
1364 }
1365
1366 #[test]
1367 fn test_map_equality_order_independent() {
1368 let mut a = MapValue::empty();
1369 a = a.assoc(kw("a"), int(1));
1370 a = a.assoc(kw("b"), int(2));
1371
1372 let mut b = MapValue::empty();
1373 b = b.assoc(kw("b"), int(2));
1374 b = b.assoc(kw("a"), int(1));
1375
1376 assert_eq!(Value::Map(a), Value::Map(b));
1377 }
1378
1379 #[test]
1382 fn test_hash_consistency() {
1383 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1384 assert_eq!(int(1).clojure_hash(), big1.clojure_hash());
1385 }
1386
1387 #[test]
1388 fn test_hash_whole_double() {
1389 assert_eq!(int(1).clojure_hash(), Value::Double(1.0).clojure_hash());
1391 }
1392
1393 #[test]
1396 fn test_pr_str_nil() {
1397 assert_eq!(Value::Nil.to_string(), "nil");
1398 }
1399
1400 #[test]
1401 fn test_pr_str_string() {
1402 assert_eq!(s("hello").to_string(), "\"hello\"");
1403 assert_eq!(s("a\"b").to_string(), "\"a\\\"b\"");
1404 }
1405
1406 #[test]
1407 fn test_pr_str_char() {
1408 assert_eq!(Value::Char('a').to_string(), "\\a");
1409 assert_eq!(Value::Char('\n').to_string(), "\\newline");
1410 }
1411
1412 #[test]
1413 fn test_pr_str_list() {
1414 let l = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1415 assert_eq!(l.to_string(), "(1 2)");
1416 }
1417
1418 #[test]
1419 fn test_pr_str_vector() {
1420 let v = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1421 assert_eq!(v.to_string(), "[1 2]");
1422 }
1423
1424 #[test]
1425 fn test_pr_str_double() {
1426 assert_eq!(Value::Double(1.0).to_string(), "1.0");
1427 assert_eq!(Value::Double(3.14).to_string(), "3.14");
1428 assert_eq!(Value::Double(f64::INFINITY).to_string(), "##Inf");
1429 assert_eq!(Value::Double(f64::NEG_INFINITY).to_string(), "##-Inf");
1430 assert_eq!(Value::Double(f64::NAN).to_string(), "##NaN");
1431 }
1432}
1433
1434impl PartialOrd for Value {
1437 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1438 Some(self.cmp(other))
1439 }
1440}
1441
1442impl Ord for Value {
1443 fn cmp(&self, other: &Self) -> Ordering {
1444 let a = self.unwrap_meta();
1446 let b = other.unwrap_meta();
1447 if !std::ptr::eq(a, self) || !std::ptr::eq(b, other) {
1448 return a.cmp(b);
1449 }
1450 match (self, other) {
1452 (Value::Nil, Value::Nil) => Ordering::Equal,
1454
1455 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
1457
1458 (Value::Long(a), Value::Long(b)) => a.cmp(b),
1460 (Value::Double(a), Value::Double(b)) => total_cmp_f64(*a, *b),
1461 (Value::BigInt(a), Value::BigInt(b)) => a.get().cmp(b.get()),
1462 (Value::BigDecimal(a), Value::BigDecimal(b)) => {
1463 a.get()
1465 .partial_cmp(b.get())
1466 .unwrap_or_else(|| a.get().to_string().cmp(&b.get().to_string()))
1467 }
1468 (Value::Ratio(a), Value::Ratio(b)) => a.get().cmp(b.get()),
1469
1470 (Value::Long(a), Value::Double(b)) => total_cmp_f64(*a as f64, *b),
1472 (Value::Double(a), Value::Long(b)) => total_cmp_f64(*a, *b as f64),
1473 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a).cmp(b.get()),
1474 (Value::BigInt(a), Value::Long(b)) => a.get().cmp(&BigInt::from(*b)),
1475 (Value::Long(a), Value::Ratio(b)) => {
1476 num_rational::Ratio::from(BigInt::from(*a)).cmp(b.get())
1477 }
1478 (Value::Ratio(a), Value::Long(b)) => {
1479 a.get().cmp(&num_rational::Ratio::from(BigInt::from(*b)))
1480 }
1481 (Value::BigInt(a), Value::Ratio(b)) => {
1482 num_rational::Ratio::from(a.get().clone()).cmp(b.get())
1483 }
1484 (Value::Ratio(a), Value::BigInt(b)) => {
1485 a.get().cmp(&num_rational::Ratio::from(b.get().clone()))
1486 }
1487 (Value::Double(a), Value::BigInt(b)) => {
1488 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1489 }
1490 (Value::BigInt(a), Value::Double(b)) => {
1491 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1492 }
1493 (Value::Double(a), Value::Ratio(b)) => {
1494 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1495 }
1496 (Value::Ratio(a), Value::Double(b)) => {
1497 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1498 }
1499 (Value::Long(a), Value::BigDecimal(b)) => {
1500 let ad = bigdecimal::BigDecimal::from(*a);
1501 ad.partial_cmp(b.get())
1502 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1503 }
1504 (Value::BigDecimal(a), Value::Long(b)) => {
1505 let bd = bigdecimal::BigDecimal::from(*b);
1506 a.get()
1507 .partial_cmp(&bd)
1508 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1509 }
1510 (Value::Double(a), Value::BigDecimal(b)) => {
1511 match bigdecimal::BigDecimal::try_from(*a) {
1512 Ok(ad) => ad
1513 .partial_cmp(b.get())
1514 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1515 Err(_) => {
1516 if a.is_nan() {
1518 Ordering::Greater
1519 } else if *a < 0.0 {
1520 Ordering::Less
1521 } else {
1522 Ordering::Greater
1523 }
1524 }
1525 }
1526 }
1527 (Value::BigDecimal(a), Value::Double(b)) => {
1528 match bigdecimal::BigDecimal::try_from(*b) {
1529 Ok(bd) => a
1530 .get()
1531 .partial_cmp(&bd)
1532 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1533 Err(_) => {
1534 if b.is_nan() {
1535 Ordering::Less
1536 } else if *b < 0.0 {
1537 Ordering::Greater
1538 } else {
1539 Ordering::Less
1540 }
1541 }
1542 }
1543 }
1544 (Value::BigInt(a), Value::BigDecimal(b)) => {
1545 let ad = bigdecimal::BigDecimal::from(a.get().clone());
1546 ad.partial_cmp(b.get())
1547 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1548 }
1549 (Value::BigDecimal(a), Value::BigInt(b)) => {
1550 let bd = bigdecimal::BigDecimal::from(b.get().clone());
1551 a.get()
1552 .partial_cmp(&bd)
1553 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1554 }
1555 (Value::Ratio(a), Value::BigDecimal(b)) => {
1556 let af = a.get().to_f64().unwrap_or(f64::MAX);
1557 match bigdecimal::BigDecimal::try_from(af) {
1558 Ok(ad) => ad
1559 .partial_cmp(b.get())
1560 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1561 Err(_) => Ordering::Greater,
1562 }
1563 }
1564 (Value::BigDecimal(a), Value::Ratio(b)) => {
1565 let bf = b.get().to_f64().unwrap_or(f64::MAX);
1566 match bigdecimal::BigDecimal::try_from(bf) {
1567 Ok(bd) => a
1568 .get()
1569 .partial_cmp(&bd)
1570 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1571 Err(_) => Ordering::Less,
1572 }
1573 }
1574
1575 (Value::Char(a), Value::Char(b)) => a.cmp(b),
1577
1578 (Value::Str(a), Value::Str(b)) => a.get().cmp(b.get()),
1580
1581 (Value::Symbol(a), Value::Symbol(b)) => cmp_ns_name(
1583 &a.get().namespace,
1584 &a.get().name,
1585 &b.get().namespace,
1586 &b.get().name,
1587 ),
1588
1589 (Value::Keyword(a), Value::Keyword(b)) => cmp_ns_name(
1591 &a.get().namespace,
1592 &a.get().name,
1593 &b.get().namespace,
1594 &b.get().name,
1595 ),
1596
1597 (Value::Vector(a), Value::Vector(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1599 (Value::List(a), Value::List(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1600
1601 (Value::Set(a), Value::Set(b)) => a.count().cmp(&b.count()),
1603
1604 (Value::Map(a), Value::Map(b)) => a.count().cmp(&b.count()),
1606
1607 _ => type_discriminant(self).cmp(&type_discriminant(other)),
1609 }
1610 }
1611}
1612
1613fn iter_cmp<'a>(
1615 mut a: impl Iterator<Item = &'a Value>,
1616 mut b: impl Iterator<Item = &'a Value>,
1617) -> Ordering {
1618 loop {
1619 match (a.next(), b.next()) {
1620 (None, None) => return Ordering::Equal,
1621 (None, Some(_)) => return Ordering::Less,
1622 (Some(_), None) => return Ordering::Greater,
1623 (Some(x), Some(y)) => {
1624 let c = x.cmp(y);
1625 if c != Ordering::Equal {
1626 return c;
1627 }
1628 }
1629 }
1630 }
1631}
1632
1633fn total_cmp_f64(a: f64, b: f64) -> Ordering {
1635 a.total_cmp(&b)
1636}
1637
1638fn cmp_ns_name(
1640 ns_a: &Option<Arc<str>>,
1641 name_a: &Arc<str>,
1642 ns_b: &Option<Arc<str>>,
1643 name_b: &Arc<str>,
1644) -> Ordering {
1645 match (ns_a, ns_b) {
1646 (None, None) => name_a.cmp(name_b),
1647 (None, Some(_)) => Ordering::Less,
1648 (Some(_), None) => Ordering::Greater,
1649 (Some(a), Some(b)) => a.cmp(b).then_with(|| name_a.cmp(name_b)),
1650 }
1651}
1652
1653fn type_discriminant(v: &Value) -> u8 {
1655 match v {
1656 Value::WithMeta(inner, _) => type_discriminant(inner),
1657 Value::Reduced(inner) => type_discriminant(inner),
1658 Value::Nil => 0,
1659 Value::Bool(_) => 1,
1660 Value::Long(_)
1661 | Value::Double(_)
1662 | Value::BigInt(_)
1663 | Value::BigDecimal(_)
1664 | Value::Ratio(_) => 2,
1665 Value::Char(_) => 3,
1666 Value::Str(_) => 4,
1667 Value::Symbol(_) => 5,
1668 Value::Keyword(_) => 6,
1669 Value::List(_) => 7,
1670 Value::Vector(_) => 8,
1671 Value::Map(_) => 9,
1672 Value::Set(_) => 10,
1673 Value::Queue(_) => 11,
1674 Value::LazySeq(_) => 12,
1675 Value::Cons(_) => 13,
1676 Value::NativeFunction(_) => 14,
1677 Value::BoundFn(_) => 14,
1678 Value::Fn(_) => 15,
1679 Value::Macro(_) => 16,
1680 Value::Var(_) => 17,
1681 Value::Atom(_) => 18,
1682 Value::Namespace(_) => 19,
1683 Value::Protocol(_) => 20,
1684 Value::ProtocolFn(_) => 21,
1685 Value::MultiFn(_) => 22,
1686 Value::Volatile(_) => 23,
1687 Value::Delay(_) => 24,
1688 Value::Promise(_) => 25,
1689 Value::Future(_) => 26,
1690 Value::Agent(_) => 27,
1691 Value::TypeInstance(_) => 28,
1692 Value::BooleanArray(_) => 29,
1693 Value::ByteArray(_) => 30,
1694 Value::ShortArray(_) => 31,
1695 Value::IntArray(_) => 32,
1696 Value::LongArray(_) => 33,
1697 Value::CharArray(_) => 34,
1698 Value::FloatArray(_) => 35,
1699 Value::DoubleArray(_) => 36,
1700 Value::ObjectArray(_) => 37,
1701 Value::Uuid(_) => 38,
1702 Value::NativeObject(_) => 43,
1703 Value::Resource(_) => 39,
1704 Value::TransientMap(_) => 40,
1705 Value::TransientSet(_) => 41,
1706 Value::TransientVector(_) => 42,
1707 Value::Pattern(_) => 43,
1708 Value::Matcher(_) => 44,
1709 Value::Error(_) => 45,
1710 }
1711}