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