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, ValueError};
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, Pattern};
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;
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(Debug)]
57pub struct UuidValue(pub u128);
58
59impl Trace for UuidValue {
60 fn trace(&self, _: &mut MarkVisitor) {}
61}
62
63#[derive(Clone, Debug)]
68pub enum Value {
69 Nil,
71 Bool(bool),
72 Long(i64),
73 Double(f64),
74 BigInt(GcPtr<BigInt>),
75 BigDecimal(GcPtr<bigdecimal::BigDecimal>),
76 Ratio(GcPtr<num_rational::Ratio<BigInt>>),
77 Char(char),
78 Str(GcPtr<String>),
79 Uuid(GcPtr<UuidValue>),
80 Pattern(GcPtr<Pattern>),
81 Matcher(GcPtr<Matcher>),
82
83 Symbol(GcPtr<Symbol>),
85 Keyword(GcPtr<Keyword>),
86
87 List(GcPtr<PersistentList>),
89 Vector(GcPtr<PersistentVector>),
90 Map(MapValue),
93 Set(SetValue),
94 Queue(GcPtr<PersistentQueue>),
95
96 TransientMap(GcPtr<TransientMap>),
98 TransientSet(GcPtr<TransientSet>),
99 TransientVector(GcPtr<TransientVector>),
100
101 IntArray(GcPtr<Mutex<Vec<i32>>>),
103 LongArray(GcPtr<Mutex<Vec<i64>>>),
104 ShortArray(GcPtr<Mutex<Vec<i16>>>),
105 ByteArray(GcPtr<Mutex<Vec<i8>>>),
106 FloatArray(GcPtr<Mutex<Vec<f32>>>),
107 DoubleArray(GcPtr<Mutex<Vec<f64>>>),
108 BooleanArray(GcPtr<Mutex<Vec<bool>>>),
109 CharArray(GcPtr<Mutex<Vec<char>>>),
110 ObjectArray(GcPtr<ObjectArray>),
111
112 NativeFunction(GcPtr<NativeFn>),
114 Fn(GcPtr<CljxFn>),
115 Macro(GcPtr<CljxFn>),
116 BoundFn(GcPtr<BoundFn>),
117
118 Var(GcPtr<Var>),
120 Atom(GcPtr<Atom>),
121 SharedAtom(std::sync::Arc<SharedAtom>),
125 ByteBlob(std::sync::Arc<[u8]>),
129
130 Reduced(Box<Value>),
132
133 Namespace(GcPtr<Namespace>),
135
136 LazySeq(GcPtr<LazySeq>),
139 Cons(GcPtr<CljxCons>),
141
142 Protocol(GcPtr<Protocol>),
144 ProtocolFn(GcPtr<ProtocolFn>),
145 MultiFn(GcPtr<MultiFn>),
146
147 Volatile(GcPtr<Volatile>),
149 Delay(GcPtr<Delay>),
150 Promise(GcPtr<CljxPromise>),
151 Future(GcPtr<CljxFuture>),
152 Agent(GcPtr<Agent>),
153
154 TypeInstance(GcPtr<TypeInstance>),
156
157 NativeObject(GcPtr<crate::native_object::NativeObjectBox>),
159
160 Resource(ResourceHandle),
162
163 WithMeta(Box<Value>, Box<Value>),
166
167 Error(GcPtr<ExceptionInfo>),
169}
170
171#[derive(Clone, Debug)]
173pub enum MapValue {
174 Array(GcPtr<PersistentArrayMap>),
175 Hash(GcPtr<PersistentHashMap>),
176 Sorted(GcPtr<SortedMap>),
177}
178
179impl MapValue {
180 pub fn empty() -> Self {
181 MapValue::Array(GcPtr::new(PersistentArrayMap::empty()))
182 }
183
184 pub fn from_pairs(pairs: Vec<(Value, Value)>) -> Self {
191 use crate::collections::array_map::AssocResult;
192
193 match PersistentArrayMap::from_pairs(pairs) {
195 AssocResult::Array(m) => MapValue::Array(GcPtr::new(m)),
196 AssocResult::Promote(pairs) => {
197 MapValue::Hash(GcPtr::new(PersistentHashMap::from_pairs(pairs)))
198 }
199 }
200 }
201
202 pub fn from_flat_entries(entries: Vec<Value>) -> Self {
207 debug_assert!(entries.len().is_multiple_of(2));
208 let pairs: Vec<(Value, Value)> = entries
210 .chunks(2)
211 .map(|chunk| (chunk[0].clone(), chunk[1].clone()))
212 .collect();
213 Self::from_pairs(pairs)
214 }
215
216 pub fn get(&self, key: &Value) -> Option<Value> {
217 match self {
218 MapValue::Array(m) => m.get().get(key).cloned(),
219 MapValue::Hash(m) => m.get().get(key).cloned(),
220 MapValue::Sorted(m) => m.get().get(key).cloned(),
221 }
222 }
223
224 pub fn count(&self) -> usize {
225 match self {
226 MapValue::Array(m) => m.get().count(),
227 MapValue::Hash(m) => m.get().count(),
228 MapValue::Sorted(m) => m.get().count(),
229 }
230 }
231
232 pub fn assoc(&self, k: Value, v: Value) -> Self {
233 match self {
234 MapValue::Array(m) => match m.get().assoc(k, v) {
235 crate::collections::array_map::AssocResult::Array(new_m) => {
236 MapValue::Array(GcPtr::new(new_m))
237 }
238 crate::collections::array_map::AssocResult::Promote(pairs) => {
239 let hm = PersistentHashMap::from_pairs(pairs);
240 MapValue::Hash(GcPtr::new(hm))
241 }
242 },
243 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().assoc(k, v))),
244 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().assoc(k, v))),
245 }
246 }
247
248 pub fn dissoc(&self, key: &Value) -> Self {
249 match self {
250 MapValue::Array(m) => MapValue::Array(GcPtr::new(m.get().dissoc(key))),
251 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().dissoc(key))),
252 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().dissoc(key))),
253 }
254 }
255
256 pub fn contains_key(&self, key: &Value) -> bool {
257 match self {
258 MapValue::Array(m) => m.get().contains_key(key),
259 MapValue::Hash(m) => m.get().contains_key(key),
260 MapValue::Sorted(m) => m.get().contains_key(key),
261 }
262 }
263
264 pub fn for_each<F: FnMut(&Value, &Value)>(&self, mut f: F) {
266 match self {
267 MapValue::Array(m) => {
268 for (k, v) in m.get().iter() {
269 f(k, v);
270 }
271 }
272 MapValue::Hash(m) => {
273 for (k, v) in m.get().iter() {
274 f(k, v);
275 }
276 }
277 MapValue::Sorted(m) => {
278 for (k, v) in m.get().iter() {
279 f(k, v);
280 }
281 }
282 }
283 }
284
285 pub fn iter(&self) -> Box<dyn Iterator<Item = (&Value, &Value)> + '_> {
287 match self {
288 MapValue::Array(m) => Box::new(m.get().iter()),
289 MapValue::Hash(m) => Box::new(m.get().iter()),
290 MapValue::Sorted(m) => Box::new(m.get().iter()),
291 }
292 }
293}
294
295#[derive(Clone, Debug)]
297pub enum SetValue {
298 Hash(GcPtr<PersistentHashSet>),
299 Sorted(GcPtr<SortedSet>),
300}
301
302impl SetValue {
303 pub fn empty() -> Self {
304 Self::Hash(GcPtr::new(PersistentHashSet::empty()))
305 }
306
307 pub fn count(&self) -> usize {
308 match self {
309 SetValue::Hash(m) => m.get().count(),
310 SetValue::Sorted(m) => m.get().count(),
311 }
312 }
313
314 pub fn is_empty(&self) -> bool {
315 match self {
316 SetValue::Hash(m) => m.get().is_empty(),
317 SetValue::Sorted(m) => m.get().is_empty(),
318 }
319 }
320
321 pub fn contains(&self, key: &Value) -> bool {
322 match self {
323 SetValue::Hash(m) => m.get().contains(key),
324 SetValue::Sorted(m) => m.get().contains(key),
325 }
326 }
327
328 pub fn conj(&self, value: Value) -> Self {
329 match self {
330 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().conj(value))),
331 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().conj(value))),
332 }
333 }
334
335 pub fn conj_mut(&mut self, value: Value) -> &mut Self {
336 match self {
337 SetValue::Hash(m) => {
338 m.get_mut().conj_mut(value);
339 }
340 SetValue::Sorted(s) => {
341 s.get_mut().conj_mut(value);
342 }
343 }
344 self
345 }
346
347 pub fn disj(&self, value: &Value) -> Self {
348 match self {
349 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().disj(value))),
350 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().disj(value))),
351 }
352 }
353
354 pub fn iter(&self) -> Box<dyn Iterator<Item = &Value> + '_> {
355 match self {
356 SetValue::Hash(s) => Box::new(s.get().iter()),
357 SetValue::Sorted(s) => Box::new(s.get().iter()),
358 }
359 }
360}
361
362impl cljrs_gc::Trace for SetValue {
363 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
364 use cljrs_gc::GcVisitor as _;
365 match self {
366 SetValue::Hash(s) => visitor.visit(s),
367 SetValue::Sorted(s) => visitor.visit(s),
368 }
369 }
370}
371
372impl Eq for Value {}
375
376impl PartialEq for Value {
377 fn eq(&self, other: &Self) -> bool {
378 if let Value::WithMeta(inner, _) = self {
380 return inner.as_ref() == other;
381 }
382 if let Value::WithMeta(inner, _) = other {
383 return self == inner.as_ref();
384 }
385 if let Value::Reduced(inner) = self {
387 return inner.as_ref() == other;
388 }
389 if let Value::Reduced(inner) = other {
390 return self == inner.as_ref();
391 }
392 if let (Value::LazySeq(a), Value::LazySeq(b)) = (self, other)
395 && GcPtr::ptr_eq(a, b)
396 {
397 return true;
398 }
399 if let Value::LazySeq(ls) = self {
403 let realized = ls.get().realize();
404 if realized == Value::Nil && other.is_sequential() {
405 return value_to_seq_vec(other).is_empty();
406 }
407 return realized == *other;
408 }
409 if let Value::LazySeq(ls) = other {
410 let realized = ls.get().realize();
411 if realized == Value::Nil && self.is_sequential() {
412 return value_to_seq_vec(self).is_empty();
413 }
414 return *self == realized;
415 }
416 match (self, other) {
417 (Value::Nil, Value::Nil) => true,
418 (Value::Bool(a), Value::Bool(b)) => a == b,
419 (Value::Long(a), Value::Long(b)) => a == b,
421 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a) == *b.get(),
422 (Value::BigInt(a), Value::Long(b)) => *a.get() == BigInt::from(*b),
423 (Value::BigInt(a), Value::BigInt(b)) => a.get() == b.get(),
424 (Value::Double(a), Value::Double(b)) => a == b, (Value::Long(a), Value::Double(b)) => b.fract() == 0.0 && b.to_i64() == Some(*a),
426 (Value::Double(a), Value::Long(b)) => a.fract() == 0.0 && a.to_i64() == Some(*b),
427 (Value::BigDecimal(a), Value::BigDecimal(b)) => a.get() == b.get(),
428 (Value::Ratio(a), Value::Ratio(b)) => a.get() == b.get(),
429 (Value::Char(a), Value::Char(b)) => a == b,
430 (Value::Str(a), Value::Str(b)) => a.get() == b.get(),
431 (Value::Symbol(a), Value::Symbol(b)) => a.get() == b.get(),
432 (Value::Keyword(a), Value::Keyword(b)) => a.get() == b.get(),
433 (Value::List(a), Value::List(b)) => a.get() == b.get(),
435 (Value::Vector(a), Value::Vector(b)) => a.get() == b.get(),
436 (Value::Set(a), Value::Set(b)) => sets_equal(a, b),
437 (Value::Queue(a), Value::Queue(b)) => a.get() == b.get(),
438 (Value::Map(a), Value::Map(b)) => maps_equal(a, b),
439 (Value::List(_), Value::Vector(_)) | (Value::Vector(_), Value::List(_)) => {
441 seq_equal(self, other)
442 }
443 (Value::Cons(_), _) | (_, Value::Cons(_)) => seq_equal(self, other),
445 (Value::Fn(a), Value::Fn(b)) => std::ptr::eq(a.get() as *const _, b.get() as *const _),
447 (Value::Macro(a), Value::Macro(b)) => {
448 std::ptr::eq(a.get() as *const _, b.get() as *const _)
449 }
450 (Value::NativeFunction(a), Value::NativeFunction(b)) => {
451 std::ptr::eq(a.get() as *const _, b.get() as *const _)
452 }
453 (Value::Protocol(a), Value::Protocol(b)) => {
455 std::ptr::eq(a.get() as *const _, b.get() as *const _)
456 }
457 (Value::ProtocolFn(a), Value::ProtocolFn(b)) => {
458 std::ptr::eq(a.get() as *const _, b.get() as *const _)
459 }
460 (Value::MultiFn(a), Value::MultiFn(b)) => {
461 std::ptr::eq(a.get() as *const _, b.get() as *const _)
462 }
463 (Value::Volatile(a), Value::Volatile(b)) => {
465 std::ptr::eq(a.get() as *const _, b.get() as *const _)
466 }
467 (Value::Delay(a), Value::Delay(b)) => {
468 std::ptr::eq(a.get() as *const _, b.get() as *const _)
469 }
470 (Value::Promise(a), Value::Promise(b)) => {
471 std::ptr::eq(a.get() as *const _, b.get() as *const _)
472 }
473 (Value::Future(a), Value::Future(b)) => {
474 std::ptr::eq(a.get() as *const _, b.get() as *const _)
475 }
476 (Value::Agent(a), Value::Agent(b)) => {
477 std::ptr::eq(a.get() as *const _, b.get() as *const _)
478 }
479 (Value::Atom(a), Value::Atom(b)) => {
480 std::ptr::eq(a.get() as *const _, b.get() as *const _)
481 }
482 (Value::Var(a), Value::Var(b)) => {
483 std::ptr::eq(a.get() as *const _, b.get() as *const _)
484 }
485 (Value::Namespace(a), Value::Namespace(b)) => {
486 std::ptr::eq(a.get() as *const _, b.get() as *const _)
487 }
488 (Value::Uuid(a), Value::Uuid(b)) => a.get().0 == b.get().0,
490 (Value::Pattern(a), Value::Pattern(b)) => a.get().as_str() == b.get().as_str(),
493 (Value::NativeObject(a), Value::NativeObject(b)) => {
495 std::ptr::eq(a.get() as *const _, b.get() as *const _)
496 }
497 (Value::Resource(a), Value::Resource(b)) => Arc::ptr_eq(&a.0, &b.0),
499 (Value::TypeInstance(a), Value::TypeInstance(b)) => {
501 a.get().type_tag == b.get().type_tag && maps_equal(&a.get().fields, &b.get().fields)
502 }
503 (Value::Error(a), Value::Error(b)) => {
504 std::ptr::eq(a.get() as *const _, b.get() as *const _)
505 }
506 (Value::SharedAtom(a), Value::SharedAtom(b)) => Arc::ptr_eq(a, b),
508 (Value::ByteBlob(a), Value::ByteBlob(b)) => Arc::ptr_eq(a, b),
510 _ => false,
511 }
512 }
513}
514
515fn maps_equal(a: &MapValue, b: &MapValue) -> bool {
516 if a.count() != b.count() {
517 return false;
518 }
519 let mut equal = true;
520 a.for_each(|k, v| {
521 if equal {
522 match b.get(k) {
523 Some(bv) if &bv == v => {}
524 _ => equal = false,
525 }
526 }
527 });
528 equal
529}
530
531fn sets_equal(a: &SetValue, b: &SetValue) -> bool {
532 if a.count() != b.count() {
533 return false;
534 }
535 for k in a.iter() {
536 if !b.contains(k) {
537 return false;
538 }
539 }
540 true
541}
542
543fn seq_equal(a: &Value, b: &Value) -> bool {
544 let a_items = value_to_seq_vec(a);
545 let b_items = value_to_seq_vec(b);
546 a_items.len() == b_items.len() && a_items.iter().zip(b_items.iter()).all(|(x, y)| x == y)
547}
548
549fn value_to_seq_vec(v: &Value) -> Vec<Value> {
550 let mut v = v.clone();
552 while let Value::LazySeq(ls) = &v {
553 v = ls.get().realize();
554 }
555 match &v {
556 Value::List(l) => l.get().iter().cloned().collect(),
557 Value::Vector(v) => v.get().iter().cloned().collect(),
558 Value::LazySeq(_) => unreachable!("unwrapped above"),
559 Value::Cons(c) => {
560 let mut result = vec![c.get().head.clone()];
561 let mut tail = c.get().tail.clone();
562 loop {
563 match tail {
564 Value::Nil => break,
565 Value::List(l) => {
566 result.extend(l.get().iter().cloned());
567 break;
568 }
569 Value::Cons(next_c) => {
570 result.push(next_c.get().head.clone());
571 tail = next_c.get().tail.clone();
572 }
573 Value::LazySeq(ls) => {
574 tail = ls.get().realize();
575 }
576 _ => break,
577 }
578 }
579 result
580 }
581 _ => vec![],
582 }
583}
584
585impl ClojureHash for Value {
588 fn clojure_hash(&self) -> u32 {
589 match self {
590 Value::WithMeta(inner, _) => inner.clojure_hash(),
591 Value::Reduced(inner) => inner.clojure_hash(),
592 Value::Nil => 0,
593 Value::Bool(b) => {
594 if *b { 1231 } else { 1237 } }
596 Value::Long(n) => hash_i64(*n),
597 Value::Double(f) => {
598 if f.fract() == 0.0
600 && f.is_finite()
601 && let Some(n) = num_traits::ToPrimitive::to_i64(f)
602 {
603 return hash_i64(n);
604 }
605 hash_i64(f.to_bits() as i64)
606 }
607 Value::BigInt(n) => {
608 if let Some(l) = n.get().to_i64() {
610 return hash_i64(l);
611 }
612 hash_string(&n.get().to_string())
614 }
615 Value::Char(c) => *c as u32,
616 Value::Str(s) => hash_string(s.get()),
617 Value::Pattern(r) => hash_string(r.get().as_str()),
618 Value::Matcher(m) => hash_string(m.get().pattern.get().as_str()),
619 Value::Keyword(k) => hash_string(&k.get().to_string()),
620 Value::Symbol(s) => hash_string(&s.get().to_string()),
621 Value::Uuid(u) => hash_u128(u.get().0),
622 Value::NativeObject(obj) => {
623 let ptr = obj.get() as *const _ as usize;
624 hash_i64(ptr as i64)
625 }
626 Value::Resource(r) => {
627 let ptr = Arc::as_ptr(&r.0) as *const () as usize;
628 hash_i64(ptr as i64)
629 }
630 Value::List(l) => {
631 let mut h: u32 = 1;
632 for v in l.get().iter() {
633 h = hash_combine_ordered(h, v.clojure_hash());
634 }
635 h
636 }
637 Value::Vector(v) => {
638 let mut h: u32 = 1;
639 for item in v.get().iter() {
640 h = hash_combine_ordered(h, item.clojure_hash());
641 }
642 h
643 }
644 Value::Map(m) => {
645 let mut h: u32 = 0;
646 m.for_each(|k, v| {
647 h = hash_combine_unordered(
648 h,
649 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
650 );
651 });
652 h
653 }
654 Value::Set(s) => {
655 let mut h: u32 = 0;
656 for k in s.iter() {
657 h = hash_combine_unordered(h, k.clojure_hash());
658 }
659 h
660 }
661 Value::TransientMap(m) => m.get().clojure_hash(),
662 Value::TransientSet(s) => s.get().clojure_hash(),
663 Value::TransientVector(v) => v.get().clojure_hash(),
664
665 Value::BooleanArray(a) => {
667 let mut h: u32 = 0;
668 for b in a.get().lock().unwrap().iter() {
669 h = hash_combine_ordered(h, if *b { 1231 } else { 1237 })
670 }
671 h
672 }
673 Value::ByteArray(a) => {
674 let mut h: u32 = 0;
675 for b in a.get().lock().unwrap().iter() {
676 h = hash_combine_ordered(h, *b as u32)
677 }
678 h
679 }
680 Value::ShortArray(a) => {
681 let mut h: u32 = 0;
682 for item in a.get().lock().unwrap().iter() {
683 h = hash_combine_ordered(h, *item as u32)
684 }
685 h
686 }
687 Value::IntArray(a) => {
688 let mut h: u32 = 0;
689 for item in a.get().lock().unwrap().iter() {
690 h = hash_combine_ordered(h, *item as u32)
691 }
692 h
693 }
694 Value::CharArray(a) => {
695 let mut h: u32 = 0;
696 for item in a.get().lock().unwrap().iter() {
697 h = hash_combine_ordered(h, *item as u32)
698 }
699 h
700 }
701 Value::LongArray(a) => {
702 let mut h: u32 = 0;
703 for item in a.get().lock().unwrap().iter() {
704 let v = *item;
705 h = hash_combine_ordered(h, hash_i64(v));
706 }
707 h
708 }
709 Value::FloatArray(a) => {
710 let mut h: u32 = 0;
711 for item in a.get().lock().unwrap().iter() {
712 let f = *item;
713 h = hash_combine_ordered(
714 h,
715 if f.fract() == 0.0
716 && f.is_finite()
717 && let Some(n) = ToPrimitive::to_i64(item)
718 {
719 hash_i64(n)
720 } else {
721 hash_i64(f.to_bits() as i64)
722 },
723 )
724 }
725 h
726 }
727 Value::DoubleArray(a) => {
728 let mut h: u32 = 0;
729 for item in a.get().lock().unwrap().iter() {
730 let f = *item;
731 h = hash_combine_ordered(
732 h,
733 if f.fract() == 0.0
734 && f.is_finite()
735 && let Some(n) = ToPrimitive::to_i64(item)
736 {
737 hash_i64(n)
738 } else {
739 hash_i64(f.to_bits() as i64)
740 },
741 )
742 }
743 h
744 }
745 Value::ObjectArray(a) => {
746 let mut h: u32 = 0;
747 for item in a.get().0.lock().unwrap().iter() {
748 h = hash_combine_ordered(h, item.clojure_hash())
749 }
750 h
751 }
752
753 Value::SharedAtom(a) => Arc::as_ptr(a) as u32,
754 Value::ByteBlob(b) => {
755 let mut h: u32 = 0;
756 for byte in b.iter() {
757 h = hash_combine_ordered(h, hash_i64(*byte as i64));
758 }
759 h
760 }
761
762 Value::Fn(f) => f.get() as *const _ as u32,
764 Value::BoundFn(f) => f.get() as *const _ as u32,
765 Value::NativeFunction(f) => f.get() as *const _ as u32,
766 Value::Var(v) => v.get() as *const _ as u32,
767 Value::Atom(a) => a.get() as *const _ as u32,
768 Value::Namespace(n) => n.get() as *const _ as u32,
769 Value::Queue(q) => {
770 let mut h: u32 = 1;
771 for v in q.get().iter() {
772 h = hash_combine_ordered(h, v.clojure_hash());
773 }
774 h
775 }
776 Value::Macro(f) => f.get() as *const _ as u32,
777 Value::BigDecimal(d) => hash_string(&d.get().to_string()),
778 Value::Ratio(r) => hash_string(&r.get().to_string()),
779 Value::LazySeq(ls) => ls.get().realize().clojure_hash(),
780 Value::Protocol(p) => p.get() as *const _ as u32,
781 Value::ProtocolFn(pf) => pf.get() as *const _ as u32,
782 Value::MultiFn(mf) => mf.get() as *const _ as u32,
783 Value::Cons(_) => {
784 let mut h: u32 = 1;
786 for v in value_to_seq_vec(self) {
787 h = hash_combine_ordered(h, v.clojure_hash());
788 }
789 h
790 }
791 Value::Volatile(v) => v.get() as *const _ as u32,
793 Value::Delay(d) => d.get() as *const _ as u32,
794 Value::Promise(p) => p.get() as *const _ as u32,
795 Value::Future(fu) => fu.get() as *const _ as u32,
796 Value::Agent(a) => a.get() as *const _ as u32,
797 Value::TypeInstance(ti) => {
799 let tag_hash = hash_string(&ti.get().type_tag);
800 let mut fields_hash: u32 = 0;
801 ti.get().fields.for_each(|k, v| {
802 fields_hash = hash_combine_unordered(
803 fields_hash,
804 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
805 );
806 });
807 hash_combine_ordered(tag_hash, fields_hash)
808 }
809 Value::Error(e) => e.get().clojure_hash(),
810 }
811 }
812}
813
814impl std::hash::Hash for Value {
816 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
817 self.clojure_hash().hash(state);
818 }
819}
820
821impl fmt::Display for Value {
824 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826 pr_str(self, f, true)
827 }
828}
829
830pub struct PrintValue<'a>(pub &'a Value);
832
833impl fmt::Display for PrintValue<'_> {
834 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
835 pr_str(self.0, f, false)
836 }
837}
838
839pub fn pr_str(v: &Value, f: &mut fmt::Formatter<'_>, readably: bool) -> fmt::Result {
841 match v {
842 Value::WithMeta(inner, _) => pr_str(inner, f, readably),
843 Value::Reduced(inner) => {
844 write!(f, "#reduced ")?;
845 pr_str(inner, f, readably)
846 }
847 Value::Nil => write!(f, "nil"),
848 Value::Bool(b) => write!(f, "{b}"),
849 Value::Long(n) => write!(f, "{n}"),
850 Value::Double(d) => {
851 if d.is_infinite() {
852 if readably {
853 if *d > 0.0 {
854 write!(f, "##Inf")
855 } else {
856 write!(f, "##-Inf")
857 }
858 } else if *d > 0.0 {
859 write!(f, "Infinity")
860 } else {
861 write!(f, "-Infinity")
862 }
863 } else if d.is_nan() {
864 if readably {
865 write!(f, "##NaN")
866 } else {
867 write!(f, "NaN")
868 }
869 } else if d.fract() == 0.0 && d.abs() < 1e15 {
870 write!(f, "{d:.1}")
871 } else {
872 write!(f, "{d}")
873 }
874 }
875 Value::BigInt(n) => {
876 if readably {
877 write!(f, "{}N", n.get())
878 } else {
879 write!(f, "{}", n.get())
880 }
881 }
882 Value::BigDecimal(d) => {
883 let dec = d.get();
884 let s = format!("{}", dec);
885 if !s.contains('.') && dec.fractional_digit_count() > 0 {
888 let zeros = "0".repeat(dec.fractional_digit_count() as usize);
889 if readably {
890 write!(f, "{s}.{zeros}M")
891 } else {
892 write!(f, "{s}.{zeros}")
893 }
894 } else if readably {
895 write!(f, "{s}M")
896 } else {
897 write!(f, "{s}")
898 }
899 }
900 Value::Ratio(r) => write!(f, "{}", r.get()),
901 Value::Uuid(u) => {
902 let uuid = uuid::Uuid::from_u128(u.get().0);
903 if readably {
904 write!(f, "#uuid \"{}\"", uuid)
905 } else {
906 write!(f, "{}", uuid)
907 }
908 }
909 Value::Char(c) => {
910 if readably {
911 match c {
912 '\n' => write!(f, "\\newline"),
913 '\t' => write!(f, "\\tab"),
914 ' ' => write!(f, "\\space"),
915 '\r' => write!(f, "\\return"),
916 c => write!(f, "\\{c}"),
917 }
918 } else {
919 write!(f, "{c}")
920 }
921 }
922 Value::Str(s) => {
923 if readably {
924 write!(f, "\"")?;
925 for c in s.get().chars() {
926 match c {
927 '"' => write!(f, "\\\"")?,
928 '\\' => write!(f, "\\\\")?,
929 '\n' => write!(f, "\\n")?,
930 '\t' => write!(f, "\\t")?,
931 '\r' => write!(f, "\\r")?,
932 c => write!(f, "{c}")?,
933 }
934 }
935 write!(f, "\"")
936 } else {
937 write!(f, "{}", s.get())
938 }
939 }
940 Value::Pattern(r) => {
941 if readably {
942 write!(f, "#\"")?;
943 write!(f, "{}", r.get().as_str())?;
944 write!(f, "\"")
945 } else {
946 write!(f, "#<{}>", r.get())
947 }
948 }
949 Value::Matcher(_) => write!(f, "#<Matcher>"),
950 Value::Symbol(s) => write!(f, "{}", s.get()),
951 Value::Keyword(k) => write!(f, "{}", k.get()),
952 Value::List(l) => {
953 write!(f, "(")?;
954 let mut first = true;
955 for item in l.get().iter() {
956 if !first {
957 write!(f, " ")?;
958 }
959 pr_str(item, f, readably)?;
960 first = false;
961 }
962 write!(f, ")")
963 }
964 Value::Vector(v) => {
965 write!(f, "[")?;
966 let mut first = true;
967 for item in v.get().iter() {
968 if !first {
969 write!(f, " ")?;
970 }
971 pr_str(item, f, readably)?;
972 first = false;
973 }
974 write!(f, "]")
975 }
976 Value::Map(m) => {
977 write!(f, "{{")?;
978 let mut first = true;
979 m.for_each(|k, v| {
980 if !first {
982 let _ = write!(f, ", ");
983 }
984 let _ = pr_str(k, f, readably);
985 let _ = write!(f, " ");
986 let _ = pr_str(v, f, readably);
987 first = false;
988 });
989 write!(f, "}}")
990 }
991 Value::Set(s) => {
992 write!(f, "#{{")?;
993 let mut first = true;
994 for item in s.iter() {
995 if !first {
996 write!(f, " ")?;
997 }
998 pr_str(item, f, readably)?;
999 first = false;
1000 }
1001 write!(f, "}}")
1002 }
1003 Value::BooleanArray(_)
1004 | Value::ByteArray(_)
1005 | Value::ShortArray(_)
1006 | Value::IntArray(_)
1007 | Value::LongArray(_)
1008 | Value::CharArray(_)
1009 | Value::FloatArray(_)
1010 | Value::DoubleArray(_)
1011 | Value::ObjectArray(_) => write!(f, "#[array]"),
1012 Value::Queue(q) => {
1013 write!(f, "#queue (")?;
1015 let mut first = true;
1016 for item in q.get().iter() {
1017 if !first {
1018 write!(f, " ")?;
1019 }
1020 pr_str(item, f, readably)?;
1021 first = false;
1022 }
1023 write!(f, ")")
1024 }
1025 Value::LazySeq(ls) => pr_str(&ls.get().realize(), f, readably),
1026 Value::Cons(c) => {
1027 write!(f, "(")?;
1028 pr_str(&c.get().head, f, readably)?;
1029 let mut tail = c.get().tail.clone();
1030 loop {
1031 match tail {
1032 Value::Nil => break,
1033 Value::List(l) => {
1034 for item in l.get().iter() {
1035 write!(f, " ")?;
1036 pr_str(item, f, readably)?;
1037 }
1038 break;
1039 }
1040 Value::Cons(next_c) => {
1041 write!(f, " ")?;
1042 pr_str(&next_c.get().head, f, readably)?;
1043 tail = next_c.get().tail.clone();
1044 }
1045 Value::LazySeq(ls) => {
1046 tail = ls.get().realize();
1047 }
1048 other => {
1049 write!(f, " . ")?;
1050 pr_str(&other, f, readably)?;
1051 break;
1052 }
1053 }
1054 }
1055 write!(f, ")")
1056 }
1057 Value::NativeFunction(nf) => write!(f, "#<NativeFn {}>", nf.get().name),
1058 Value::BoundFn(_) => write!(f, "#<BoundFn>"),
1059 Value::Fn(fun) => match &fun.get().name {
1060 Some(n) => write!(f, "#<Fn {n}>"),
1061 None => write!(f, "#<Fn>"),
1062 },
1063 Value::Macro(m) => match &m.get().name {
1064 Some(n) => write!(f, "#<Macro {n}>"),
1065 None => write!(f, "#<Macro>"),
1066 },
1067 Value::Var(v) => write!(f, "#'{}/{}", v.get().namespace, v.get().name),
1068 Value::Atom(a) => write!(f, "#<Atom {}>", a.get().deref()),
1069 Value::SharedAtom(a) => {
1070 write!(f, "#<SharedAtom {}>", a.deref_val().type_name())
1071 }
1072 Value::ByteBlob(b) => write!(f, "#<ByteBlob {} bytes>", b.len()),
1073 Value::Namespace(n) => write!(f, "#<Namespace {}>", n.get().name),
1074 Value::Protocol(p) => write!(f, "#<Protocol {}>", p.get().name),
1075 Value::ProtocolFn(pf) => {
1076 write!(
1077 f,
1078 "#<fn {}/{}>",
1079 pf.get().protocol.get().name,
1080 pf.get().method_name
1081 )
1082 }
1083 Value::MultiFn(mf) => write!(f, "#<MultiFn {}>", mf.get().name),
1084 Value::Volatile(_) => write!(f, "#<Volatile>"),
1085 Value::Delay(_) => write!(f, "#<Delay>"),
1086 Value::Promise(_) => write!(f, "#<Promise>"),
1087 Value::Future(_) => write!(f, "#<Future>"),
1088 Value::Agent(_) => write!(f, "#<Agent>"),
1089 Value::TypeInstance(ti) => {
1090 let ti = ti.get();
1091 write!(f, "#{}{{", ti.type_tag)?;
1092 let mut first = true;
1093 ti.fields.for_each(|k, v| {
1094 if !first {
1095 let _ = write!(f, ", ");
1096 }
1097 let _ = pr_str(k, f, readably);
1098 let _ = write!(f, " ");
1099 let _ = pr_str(v, f, readably);
1100 first = false;
1101 });
1102 write!(f, "}}")
1103 }
1104 Value::NativeObject(obj) => {
1105 write!(f, "#<{} {:?}>", obj.get().type_tag(), obj.get().inner())
1106 }
1107 Value::Resource(r) => {
1108 if r.is_closed() {
1109 write!(f, "#<{} (closed)>", r.resource_type())
1110 } else {
1111 write!(f, "#<{}>", r.resource_type())
1112 }
1113 }
1114 Value::TransientMap(_) => write!(f, "#<TransientMap>"),
1115 Value::TransientSet(_) => write!(f, "#<TransientSet>"),
1116 Value::TransientVector(_) => write!(f, "#<TransientVector>"),
1117 Value::Error(e) => {
1118 write!(f, "#error ")?;
1119 let map = e.get().to_map().map_err(|_| fmt::Error {})?;
1120 pr_str(&map, f, readably)
1121 }
1122 }
1123}
1124
1125impl Value {
1128 pub fn from_kwargs_rest(mut entries: Vec<Value>) -> Result<Value, ValueError> {
1148 if entries.len() < 2 {
1149 return Ok(entries.pop().unwrap_or(Value::Nil));
1150 }
1151
1152 let trailing = match entries.last().map(Value::unwrap_meta) {
1156 Some(Value::Map(_)) if !entries.len().is_multiple_of(2) => entries.pop(),
1157 _ => None,
1158 };
1159
1160 if !entries.len().is_multiple_of(2) {
1161 let key = entries.last().expect("odd length implies a last entry");
1162 return Err(ValueError::Other(format!(
1163 "No value supplied for key: {}",
1164 PrintValue(key)
1165 )));
1166 }
1167
1168 let mut result = MapValue::from_flat_entries(entries);
1169 if let Some(Value::Map(map)) = trailing.as_ref().map(Value::unwrap_meta) {
1170 for (key, value) in map.iter() {
1171 result = result.assoc(key.clone(), value.clone());
1172 }
1173 }
1174 Ok(Value::Map(result))
1175 }
1176}
1177
1178impl Value {
1181 pub fn unwrap_meta(&self) -> &Value {
1183 match self {
1184 Value::WithMeta(inner, _) => inner.unwrap_meta(),
1185 other => other,
1186 }
1187 }
1188
1189 pub fn get_meta(&self) -> Option<&Value> {
1191 match self {
1192 Value::WithMeta(_, meta) => Some(meta),
1193 _ => None,
1194 }
1195 }
1196
1197 pub fn with_meta(self, meta: Value) -> Value {
1199 match self {
1200 Value::WithMeta(inner, _) => Value::WithMeta(inner, Box::new(meta)),
1201 other => Value::WithMeta(Box::new(other), Box::new(meta)),
1202 }
1203 }
1204}
1205
1206impl Value {
1209 pub fn type_name(&self) -> &'static str {
1211 match self {
1212 Value::WithMeta(inner, _) => inner.type_name(),
1213 Value::Reduced(_) => "reduced",
1214 Value::Nil => "nil",
1215 Value::Bool(_) => "boolean",
1216 Value::Long(_) => "long",
1217 Value::Double(_) => "double",
1218 Value::BigInt(_) => "bigint",
1219 Value::BigDecimal(_) => "bigdecimal",
1220 Value::Ratio(_) => "ratio",
1221 Value::Char(_) => "char",
1222 Value::Str(_) => "string",
1223 Value::Pattern(_) => "pattern",
1224 Value::Matcher(_) => "matcher",
1225 Value::Symbol(_) => "symbol",
1226 Value::Keyword(_) => "keyword",
1227 Value::Uuid(_) => "uuid",
1228 Value::List(_) => "list",
1229 Value::Vector(_) => "vector",
1230 Value::Map(_) => "map",
1231 Value::Set(_) => "set",
1232 Value::Queue(_) => "queue",
1233 Value::NativeFunction(_)
1234 | Value::Fn(_)
1235 | Value::BoundFn(_)
1236 | Value::Macro(_)
1237 | Value::ProtocolFn(_)
1238 | Value::MultiFn(_) => "fn",
1239 Value::Var(_) => "var",
1240 Value::Atom(_) => "atom",
1241 Value::SharedAtom(_) => "shared-atom",
1242 Value::ByteBlob(_) => "byte-blob",
1243 Value::Namespace(_) => "namespace",
1244 Value::LazySeq(_) => "lazyseq",
1245 Value::Cons(_) => "cons",
1246 Value::Protocol(_) => "protocol",
1247 Value::Volatile(_) => "volatile",
1248 Value::Delay(_) => "delay",
1249 Value::Promise(_) => "promise",
1250 Value::Future(_) => "future",
1251 Value::Agent(_) => "agent",
1252 Value::TypeInstance(_) => "record",
1253 Value::NativeObject(_) => "native-object",
1254 Value::BooleanArray(_) => "boolean-array",
1255 Value::ByteArray(_) => "byte-array",
1256 Value::ShortArray(_) => "short-array",
1257 Value::IntArray(_) => "int-array",
1258 Value::LongArray(_) => "long-array",
1259 Value::FloatArray(_) => "float-array",
1260 Value::DoubleArray(_) => "double-array",
1261 Value::CharArray(_) => "char-array",
1262 Value::ObjectArray(_) => "object-array",
1263 Value::Resource(r) => r.resource_type(),
1264 Value::TransientMap(_) => "transient-map",
1265 Value::TransientSet(_) => "transient-set",
1266 Value::TransientVector(_) => "transient-vector",
1267 Value::Error(_) => "error",
1268 }
1269 }
1270
1271 pub fn string(s: impl Into<String>) -> Self {
1273 Value::Str(GcPtr::new(s.into()))
1274 }
1275
1276 pub fn uuid(value: u128) -> Self {
1278 Value::Uuid(GcPtr::new(UuidValue(value)))
1279 }
1280
1281 pub fn map_entry(key: Value, val: Value) -> Self {
1283 Value::Vector(GcPtr::new(PersistentVector::map_entry(key, val)))
1284 }
1285
1286 pub fn is_map_entry(&self) -> bool {
1289 matches!(self.unwrap_meta(), Value::Vector(v) if v.get().is_map_entry())
1290 }
1291
1292 pub fn symbol(s: Symbol) -> Self {
1294 Value::Symbol(GcPtr::new(s))
1295 }
1296
1297 pub fn keyword(k: Keyword) -> Self {
1299 Value::Keyword(GcPtr::new(k))
1300 }
1301
1302 pub fn is_sequential(&self) -> bool {
1304 matches!(
1305 self,
1306 Value::List(_) | Value::Vector(_) | Value::LazySeq(_) | Value::Cons(_)
1307 )
1308 }
1309
1310 pub fn is_coll(&self) -> bool {
1312 self.unwrap_meta().is_coll_inner()
1313 }
1314
1315 fn is_coll_inner(&self) -> bool {
1316 matches!(
1317 self,
1318 Value::List(_)
1319 | Value::Vector(_)
1320 | Value::Map(_)
1321 | Value::Set(_)
1322 | Value::Queue(_)
1323 | Value::LazySeq(_)
1324 | Value::Cons(_)
1325 )
1326 }
1327}
1328
1329impl cljrs_gc::Trace for Value {
1330 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1331 use cljrs_gc::GcVisitor as _;
1332 match self {
1333 Value::Reduced(inner) => inner.trace(visitor),
1334 Value::WithMeta(inner, meta) => {
1335 inner.trace(visitor);
1336 meta.trace(visitor);
1337 }
1338 Value::Nil | Value::Bool(_) | Value::Long(_) | Value::Double(_) | Value::Char(_) => {}
1339 Value::Uuid(p) => visitor.visit(p),
1340 Value::BigInt(p) => visitor.visit(p),
1341 Value::BigDecimal(p) => visitor.visit(p),
1342 Value::Ratio(p) => visitor.visit(p),
1343 Value::Str(p) => visitor.visit(p),
1344 Value::Pattern(p) => visitor.visit(p),
1345 Value::Matcher(m) => visitor.visit(m),
1346 Value::Symbol(p) => visitor.visit(p),
1347 Value::Keyword(p) => visitor.visit(p),
1348 Value::List(p) => visitor.visit(p),
1349 Value::Vector(p) => visitor.visit(p),
1350 Value::Map(m) => m.trace(visitor),
1351 Value::Set(s) => s.trace(visitor),
1352 Value::Queue(p) => visitor.visit(p),
1353 Value::NativeFunction(p) => visitor.visit(p),
1354 Value::BoundFn(p) => visitor.visit(p),
1355 Value::Fn(p) | Value::Macro(p) => visitor.visit(p),
1356 Value::Var(p) => visitor.visit(p),
1357 Value::Atom(p) => visitor.visit(p),
1358 Value::Namespace(p) => visitor.visit(p),
1359 Value::LazySeq(p) => visitor.visit(p),
1360 Value::Cons(p) => visitor.visit(p),
1361 Value::Protocol(p) => visitor.visit(p),
1362 Value::ProtocolFn(p) => visitor.visit(p),
1363 Value::MultiFn(p) => visitor.visit(p),
1364 Value::Volatile(p) => visitor.visit(p),
1365 Value::Delay(p) => visitor.visit(p),
1366 Value::Promise(p) => visitor.visit(p),
1367 Value::Future(p) => visitor.visit(p),
1368 Value::Agent(p) => visitor.visit(p),
1369 Value::TypeInstance(p) => visitor.visit(p),
1370 Value::ObjectArray(p) => visitor.visit(p),
1371 Value::BooleanArray(p) => visitor.visit(p),
1374 Value::ByteArray(p) => visitor.visit(p),
1375 Value::ShortArray(p) => visitor.visit(p),
1376 Value::IntArray(p) => visitor.visit(p),
1377 Value::LongArray(p) => visitor.visit(p),
1378 Value::FloatArray(p) => visitor.visit(p),
1379 Value::DoubleArray(p) => visitor.visit(p),
1380 Value::CharArray(p) => visitor.visit(p),
1381 Value::NativeObject(p) => visitor.visit(p),
1382 Value::Resource(_) | Value::SharedAtom(_) | Value::ByteBlob(_) => {}
1385 Value::TransientMap(m) => visitor.visit(m),
1386 Value::TransientVector(p) => visitor.visit(p),
1387 Value::TransientSet(m) => visitor.visit(m),
1388 Value::Error(e) => visitor.visit(e),
1389 }
1390 }
1391}
1392
1393impl cljrs_gc::Trace for MapValue {
1394 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1395 use cljrs_gc::GcVisitor as _;
1396 match self {
1397 MapValue::Array(p) => visitor.visit(p),
1398 MapValue::Hash(p) => visitor.visit(p),
1399 MapValue::Sorted(p) => visitor.visit(p),
1400 }
1401 }
1402}
1403
1404#[derive(Clone, Debug)]
1409pub struct TypeInstance {
1410 pub type_tag: Arc<str>,
1411 pub fields: MapValue,
1412 pub mutable: Option<GcPtr<crate::types::Atom>>,
1418}
1419
1420impl cljrs_gc::Trace for TypeInstance {
1421 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1422 use cljrs_gc::GcVisitor as _;
1423 self.fields.trace(visitor);
1424 if let Some(m) = &self.mutable {
1425 visitor.visit(m);
1426 }
1427 }
1428}
1429
1430#[allow(clippy::items_after_test_module)]
1431#[cfg(test)]
1432mod tests {
1433 use super::*;
1434
1435 fn kw(s: &str) -> Value {
1436 Value::keyword(Keyword::simple(s))
1437 }
1438 #[allow(dead_code)]
1439 fn sym(s: &str) -> Value {
1440 Value::symbol(Symbol::simple(s))
1441 }
1442 fn int(n: i64) -> Value {
1443 Value::Long(n)
1444 }
1445 fn s(v: &str) -> Value {
1446 Value::string(v)
1447 }
1448
1449 #[test]
1452 fn test_nil_eq() {
1453 assert_eq!(Value::Nil, Value::Nil);
1454 assert_ne!(Value::Nil, int(0));
1455 }
1456
1457 #[test]
1458 fn test_numeric_cross_type() {
1459 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1460 assert_eq!(int(1), big1.clone());
1461 assert_eq!(big1, int(1));
1462 assert_eq!(Value::Double(1.0), int(1));
1464 assert_eq!(int(1), Value::Double(1.0));
1465 assert_ne!(Value::Double(1.5), int(1));
1467 }
1468
1469 #[test]
1470 fn test_nan_not_equal_to_itself() {
1471 let nan = Value::Double(f64::NAN);
1472 assert_ne!(nan, nan.clone());
1473 }
1474
1475 #[test]
1476 fn test_string_equality() {
1477 assert_eq!(s("hello"), s("hello"));
1478 assert_ne!(s("hello"), s("world"));
1479 }
1480
1481 #[test]
1482 fn test_list_vector_seq_equality() {
1483 let list = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1484 let vec = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1485 assert_eq!(list, vec);
1487 }
1488
1489 #[test]
1490 fn test_map_equality_order_independent() {
1491 let mut a = MapValue::empty();
1492 a = a.assoc(kw("a"), int(1));
1493 a = a.assoc(kw("b"), int(2));
1494
1495 let mut b = MapValue::empty();
1496 b = b.assoc(kw("b"), int(2));
1497 b = b.assoc(kw("a"), int(1));
1498
1499 assert_eq!(Value::Map(a), Value::Map(b));
1500 }
1501
1502 #[test]
1505 fn test_hash_consistency() {
1506 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1507 assert_eq!(int(1).clojure_hash(), big1.clojure_hash());
1508 }
1509
1510 #[test]
1511 fn test_hash_whole_double() {
1512 assert_eq!(int(1).clojure_hash(), Value::Double(1.0).clojure_hash());
1514 }
1515
1516 #[test]
1519 fn test_pr_str_nil() {
1520 assert_eq!(Value::Nil.to_string(), "nil");
1521 }
1522
1523 #[test]
1524 fn test_pr_str_string() {
1525 assert_eq!(s("hello").to_string(), "\"hello\"");
1526 assert_eq!(s("a\"b").to_string(), "\"a\\\"b\"");
1527 }
1528
1529 #[test]
1530 fn test_pr_str_char() {
1531 assert_eq!(Value::Char('a').to_string(), "\\a");
1532 assert_eq!(Value::Char('\n').to_string(), "\\newline");
1533 }
1534
1535 #[test]
1536 fn test_pr_str_list() {
1537 let l = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1538 assert_eq!(l.to_string(), "(1 2)");
1539 }
1540
1541 #[test]
1542 fn test_pr_str_vector() {
1543 let v = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1544 assert_eq!(v.to_string(), "[1 2]");
1545 }
1546
1547 #[test]
1548 #[allow(clippy::approx_constant)]
1549 fn test_pr_str_double() {
1550 assert_eq!(Value::Double(1.0).to_string(), "1.0");
1551 assert_eq!(Value::Double(3.14).to_string(), "3.14");
1552 assert_eq!(Value::Double(f64::INFINITY).to_string(), "##Inf");
1553 assert_eq!(Value::Double(f64::NEG_INFINITY).to_string(), "##-Inf");
1554 assert_eq!(Value::Double(f64::NAN).to_string(), "##NaN");
1555 }
1556
1557 fn kwargs(entries: Vec<Value>) -> Value {
1560 Value::from_kwargs_rest(entries).expect("well-formed kwargs")
1561 }
1562
1563 fn map_of(entries: Vec<Value>) -> Value {
1564 Value::Map(MapValue::from_flat_entries(entries))
1565 }
1566
1567 #[test]
1568 fn kwargs_rest_empty_and_lone_values_pass_through() {
1569 assert_eq!(kwargs(vec![]), Value::Nil);
1572 assert_eq!(kwargs(vec![Value::Nil]), Value::Nil);
1573 assert_eq!(kwargs(vec![kw("a")]), kw("a"));
1577 let sorted = Value::Map(MapValue::Sorted(GcPtr::new(SortedMap::from_pairs(vec![
1578 (kw("b"), int(1)),
1579 (kw("a"), int(2)),
1580 ]))));
1581 assert!(matches!(
1582 kwargs(vec![sorted.clone()]),
1583 Value::Map(MapValue::Sorted(_))
1584 ));
1585 let with_meta = map_of(vec![kw("a"), int(1)]).with_meta(map_of(vec![kw("t"), int(1)]));
1586 assert_eq!(kwargs(vec![with_meta.clone()]), with_meta);
1587 }
1588
1589 #[test]
1590 fn kwargs_rest_pairs_build_a_map() {
1591 assert_eq!(
1592 kwargs(vec![kw("a"), int(1), kw("b"), int(2)]),
1593 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1594 );
1595 assert_eq!(
1597 kwargs(vec![kw("a"), int(1), kw("a"), int(2)]),
1598 map_of(vec![kw("a"), int(2)])
1599 );
1600 }
1601
1602 #[test]
1603 fn kwargs_rest_trailing_map_merges_and_wins() {
1604 assert_eq!(
1606 kwargs(vec![kw("a"), int(1), map_of(vec![kw("b"), int(2)])]),
1607 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1608 );
1609 assert_eq!(
1611 kwargs(vec![kw("a"), int(1), map_of(vec![kw("a"), int(9)])]),
1612 map_of(vec![kw("a"), int(9)])
1613 );
1614 let meta_map = map_of(vec![kw("b"), int(2)]).with_meta(map_of(vec![kw("t"), int(1)]));
1617 assert_eq!(
1618 kwargs(vec![kw("a"), int(1), meta_map]),
1619 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1620 );
1621 }
1622
1623 #[test]
1624 fn kwargs_rest_map_in_value_position_is_not_a_trailing_map() {
1625 let inner = map_of(vec![kw("x"), int(1)]);
1627 assert_eq!(
1628 kwargs(vec![kw("a"), inner.clone()]),
1629 map_of(vec![kw("a"), inner])
1630 );
1631 }
1632
1633 #[test]
1634 fn kwargs_rest_dangling_key_is_an_error() {
1635 let err = Value::from_kwargs_rest(vec![kw("a"), int(1), kw("b")])
1638 .expect_err("odd arity with no trailing map");
1639 assert_eq!(err.to_string(), "No value supplied for key: :b");
1640 }
1641}
1642
1643impl PartialOrd for Value {
1646 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1647 Some(self.cmp(other))
1648 }
1649}
1650
1651impl Ord for Value {
1652 fn cmp(&self, other: &Self) -> Ordering {
1653 let a = self.unwrap_meta();
1655 let b = other.unwrap_meta();
1656 if !std::ptr::eq(a, self) || !std::ptr::eq(b, other) {
1657 return a.cmp(b);
1658 }
1659 match (self, other) {
1661 (Value::Nil, Value::Nil) => Ordering::Equal,
1663
1664 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
1666
1667 (Value::Long(a), Value::Long(b)) => a.cmp(b),
1669 (Value::Double(a), Value::Double(b)) => total_cmp_f64(*a, *b),
1670 (Value::BigInt(a), Value::BigInt(b)) => a.get().cmp(b.get()),
1671 (Value::BigDecimal(a), Value::BigDecimal(b)) => {
1672 a.get()
1674 .partial_cmp(b.get())
1675 .unwrap_or_else(|| a.get().to_string().cmp(&b.get().to_string()))
1676 }
1677 (Value::Ratio(a), Value::Ratio(b)) => a.get().cmp(b.get()),
1678
1679 (Value::Long(a), Value::Double(b)) => total_cmp_f64(*a as f64, *b),
1681 (Value::Double(a), Value::Long(b)) => total_cmp_f64(*a, *b as f64),
1682 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a).cmp(b.get()),
1683 (Value::BigInt(a), Value::Long(b)) => a.get().cmp(&BigInt::from(*b)),
1684 (Value::Long(a), Value::Ratio(b)) => {
1685 num_rational::Ratio::from(BigInt::from(*a)).cmp(b.get())
1686 }
1687 (Value::Ratio(a), Value::Long(b)) => {
1688 a.get().cmp(&num_rational::Ratio::from(BigInt::from(*b)))
1689 }
1690 (Value::BigInt(a), Value::Ratio(b)) => {
1691 num_rational::Ratio::from(a.get().clone()).cmp(b.get())
1692 }
1693 (Value::Ratio(a), Value::BigInt(b)) => {
1694 a.get().cmp(&num_rational::Ratio::from(b.get().clone()))
1695 }
1696 (Value::Double(a), Value::BigInt(b)) => {
1697 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1698 }
1699 (Value::BigInt(a), Value::Double(b)) => {
1700 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1701 }
1702 (Value::Double(a), Value::Ratio(b)) => {
1703 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1704 }
1705 (Value::Ratio(a), Value::Double(b)) => {
1706 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1707 }
1708 (Value::Long(a), Value::BigDecimal(b)) => {
1709 let ad = bigdecimal::BigDecimal::from(*a);
1710 ad.partial_cmp(b.get())
1711 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1712 }
1713 (Value::BigDecimal(a), Value::Long(b)) => {
1714 let bd = bigdecimal::BigDecimal::from(*b);
1715 a.get()
1716 .partial_cmp(&bd)
1717 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1718 }
1719 (Value::Double(a), Value::BigDecimal(b)) => {
1720 match bigdecimal::BigDecimal::try_from(*a) {
1721 Ok(ad) => ad
1722 .partial_cmp(b.get())
1723 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1724 Err(_) => {
1725 if a.is_nan() {
1727 Ordering::Greater
1728 } else if *a < 0.0 {
1729 Ordering::Less
1730 } else {
1731 Ordering::Greater
1732 }
1733 }
1734 }
1735 }
1736 (Value::BigDecimal(a), Value::Double(b)) => {
1737 match bigdecimal::BigDecimal::try_from(*b) {
1738 Ok(bd) => a
1739 .get()
1740 .partial_cmp(&bd)
1741 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1742 Err(_) => {
1743 if b.is_nan() {
1744 Ordering::Less
1745 } else if *b < 0.0 {
1746 Ordering::Greater
1747 } else {
1748 Ordering::Less
1749 }
1750 }
1751 }
1752 }
1753 (Value::BigInt(a), Value::BigDecimal(b)) => {
1754 let ad = bigdecimal::BigDecimal::from(a.get().clone());
1755 ad.partial_cmp(b.get())
1756 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1757 }
1758 (Value::BigDecimal(a), Value::BigInt(b)) => {
1759 let bd = bigdecimal::BigDecimal::from(b.get().clone());
1760 a.get()
1761 .partial_cmp(&bd)
1762 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1763 }
1764 (Value::Ratio(a), Value::BigDecimal(b)) => {
1765 let af = a.get().to_f64().unwrap_or(f64::MAX);
1766 match bigdecimal::BigDecimal::try_from(af) {
1767 Ok(ad) => ad
1768 .partial_cmp(b.get())
1769 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1770 Err(_) => Ordering::Greater,
1771 }
1772 }
1773 (Value::BigDecimal(a), Value::Ratio(b)) => {
1774 let bf = b.get().to_f64().unwrap_or(f64::MAX);
1775 match bigdecimal::BigDecimal::try_from(bf) {
1776 Ok(bd) => a
1777 .get()
1778 .partial_cmp(&bd)
1779 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1780 Err(_) => Ordering::Less,
1781 }
1782 }
1783
1784 (Value::Char(a), Value::Char(b)) => a.cmp(b),
1786
1787 (Value::Str(a), Value::Str(b)) => a.get().cmp(b.get()),
1789
1790 (Value::Symbol(a), Value::Symbol(b)) => cmp_ns_name(
1792 &a.get().namespace,
1793 &a.get().name,
1794 &b.get().namespace,
1795 &b.get().name,
1796 ),
1797
1798 (Value::Keyword(a), Value::Keyword(b)) => cmp_ns_name(
1800 &a.get().namespace,
1801 &a.get().name,
1802 &b.get().namespace,
1803 &b.get().name,
1804 ),
1805
1806 (Value::Vector(a), Value::Vector(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1808 (Value::List(a), Value::List(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1809
1810 (Value::Set(a), Value::Set(b)) => a.count().cmp(&b.count()),
1812
1813 (Value::Map(a), Value::Map(b)) => a.count().cmp(&b.count()),
1815
1816 _ => type_discriminant(self).cmp(&type_discriminant(other)),
1818 }
1819 }
1820}
1821
1822fn iter_cmp<'a>(
1824 mut a: impl Iterator<Item = &'a Value>,
1825 mut b: impl Iterator<Item = &'a Value>,
1826) -> Ordering {
1827 loop {
1828 match (a.next(), b.next()) {
1829 (None, None) => return Ordering::Equal,
1830 (None, Some(_)) => return Ordering::Less,
1831 (Some(_), None) => return Ordering::Greater,
1832 (Some(x), Some(y)) => {
1833 let c = x.cmp(y);
1834 if c != Ordering::Equal {
1835 return c;
1836 }
1837 }
1838 }
1839 }
1840}
1841
1842fn total_cmp_f64(a: f64, b: f64) -> Ordering {
1844 a.total_cmp(&b)
1845}
1846
1847fn cmp_ns_name(
1849 ns_a: &Option<Arc<str>>,
1850 name_a: &Arc<str>,
1851 ns_b: &Option<Arc<str>>,
1852 name_b: &Arc<str>,
1853) -> Ordering {
1854 match (ns_a, ns_b) {
1855 (None, None) => name_a.cmp(name_b),
1856 (None, Some(_)) => Ordering::Less,
1857 (Some(_), None) => Ordering::Greater,
1858 (Some(a), Some(b)) => a.cmp(b).then_with(|| name_a.cmp(name_b)),
1859 }
1860}
1861
1862fn type_discriminant(v: &Value) -> u8 {
1864 match v {
1865 Value::WithMeta(inner, _) => type_discriminant(inner),
1866 Value::Reduced(inner) => type_discriminant(inner),
1867 Value::Nil => 0,
1868 Value::Bool(_) => 1,
1869 Value::Long(_)
1870 | Value::Double(_)
1871 | Value::BigInt(_)
1872 | Value::BigDecimal(_)
1873 | Value::Ratio(_) => 2,
1874 Value::Char(_) => 3,
1875 Value::Str(_) => 4,
1876 Value::Symbol(_) => 5,
1877 Value::Keyword(_) => 6,
1878 Value::List(_) => 7,
1879 Value::Vector(_) => 8,
1880 Value::Map(_) => 9,
1881 Value::Set(_) => 10,
1882 Value::Queue(_) => 11,
1883 Value::LazySeq(_) => 12,
1884 Value::Cons(_) => 13,
1885 Value::NativeFunction(_) => 14,
1886 Value::BoundFn(_) => 14,
1887 Value::Fn(_) => 15,
1888 Value::Macro(_) => 16,
1889 Value::Var(_) => 17,
1890 Value::Atom(_) => 18,
1891 Value::SharedAtom(_) => 46,
1892 Value::ByteBlob(_) => 47,
1893 Value::Namespace(_) => 19,
1894 Value::Protocol(_) => 20,
1895 Value::ProtocolFn(_) => 21,
1896 Value::MultiFn(_) => 22,
1897 Value::Volatile(_) => 23,
1898 Value::Delay(_) => 24,
1899 Value::Promise(_) => 25,
1900 Value::Future(_) => 26,
1901 Value::Agent(_) => 27,
1902 Value::TypeInstance(_) => 28,
1903 Value::BooleanArray(_) => 29,
1904 Value::ByteArray(_) => 30,
1905 Value::ShortArray(_) => 31,
1906 Value::IntArray(_) => 32,
1907 Value::LongArray(_) => 33,
1908 Value::CharArray(_) => 34,
1909 Value::FloatArray(_) => 35,
1910 Value::DoubleArray(_) => 36,
1911 Value::ObjectArray(_) => 37,
1912 Value::Uuid(_) => 38,
1913 Value::NativeObject(_) => 43,
1914 Value::Resource(_) => 39,
1915 Value::TransientMap(_) => 40,
1916 Value::TransientSet(_) => 41,
1917 Value::TransientVector(_) => 42,
1918 Value::Pattern(_) => 43,
1919 Value::Matcher(_) => 44,
1920 Value::Error(_) => 45,
1921 }
1922}