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