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::{ByteBlob, 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<ByteBlob>),
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 = crate::realization::for_trait(ls.get());
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 = crate::realization::for_trait(ls.get());
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 = crate::realization::for_trait(ls.get());
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 = crate::realization::for_trait(ls.get());
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 values = a.get().0.lock().unwrap().clone();
747 crate::collections::hash_values(values)
748 }
749
750 Value::SharedAtom(a) => Arc::as_ptr(a) as u32,
751 Value::ByteBlob(b) => {
752 let mut h: u32 = 0;
753 for byte in b.iter() {
754 h = hash_combine_ordered(h, hash_i64(*byte as i64));
755 }
756 h
757 }
758
759 Value::Fn(f) => f.get() as *const _ as u32,
761 Value::BoundFn(f) => f.get() as *const _ as u32,
762 Value::NativeFunction(f) => f.get() as *const _ as u32,
763 Value::Var(v) => v.get() as *const _ as u32,
764 Value::Atom(a) => a.get() as *const _ as u32,
765 Value::Namespace(n) => n.get() as *const _ as u32,
766 Value::Queue(q) => {
767 let mut h: u32 = 1;
768 for v in q.get().iter() {
769 h = hash_combine_ordered(h, v.clojure_hash());
770 }
771 h
772 }
773 Value::Macro(f) => f.get() as *const _ as u32,
774 Value::BigDecimal(d) => hash_string(&d.get().to_string()),
775 Value::Ratio(r) => hash_string(&r.get().to_string()),
776 Value::LazySeq(ls) => crate::realization::for_trait(ls.get()).clojure_hash(),
777 Value::Protocol(p) => p.get() as *const _ as u32,
778 Value::ProtocolFn(pf) => pf.get() as *const _ as u32,
779 Value::MultiFn(mf) => mf.get() as *const _ as u32,
780 Value::Cons(_) => {
781 let mut h: u32 = 1;
783 for v in value_to_seq_vec(self) {
784 h = hash_combine_ordered(h, v.clojure_hash());
785 }
786 h
787 }
788 Value::Volatile(v) => v.get() as *const _ as u32,
790 Value::Delay(d) => d.get() as *const _ as u32,
791 Value::Promise(p) => p.get() as *const _ as u32,
792 Value::Future(fu) => fu.get() as *const _ as u32,
793 Value::Agent(a) => a.get() as *const _ as u32,
794 Value::TypeInstance(ti) => {
796 let tag_hash = hash_string(&ti.get().type_tag);
797 let mut fields_hash: u32 = 0;
798 ti.get().fields.for_each(|k, v| {
799 fields_hash = hash_combine_unordered(
800 fields_hash,
801 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
802 );
803 });
804 hash_combine_ordered(tag_hash, fields_hash)
805 }
806 Value::Error(e) => e.get().clojure_hash(),
807 }
808 }
809}
810
811impl std::hash::Hash for Value {
813 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
814 self.clojure_hash().hash(state);
815 }
816}
817
818impl fmt::Display for Value {
821 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823 pr_str(self, f, true)
824 }
825}
826
827pub struct PrintValue<'a>(pub &'a Value);
829
830impl fmt::Display for PrintValue<'_> {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 pr_str(self.0, f, false)
833 }
834}
835
836pub fn pr_str(v: &Value, f: &mut fmt::Formatter<'_>, readably: bool) -> fmt::Result {
838 match v {
839 Value::WithMeta(inner, _) => pr_str(inner, f, readably),
840 Value::Reduced(inner) => {
841 write!(f, "#reduced ")?;
842 pr_str(inner, f, readably)
843 }
844 Value::Nil => write!(f, "nil"),
845 Value::Bool(b) => write!(f, "{b}"),
846 Value::Long(n) => write!(f, "{n}"),
847 Value::Double(d) => {
848 if d.is_infinite() {
849 if readably {
850 if *d > 0.0 {
851 write!(f, "##Inf")
852 } else {
853 write!(f, "##-Inf")
854 }
855 } else if *d > 0.0 {
856 write!(f, "Infinity")
857 } else {
858 write!(f, "-Infinity")
859 }
860 } else if d.is_nan() {
861 if readably {
862 write!(f, "##NaN")
863 } else {
864 write!(f, "NaN")
865 }
866 } else if d.fract() == 0.0 && d.abs() < 1e15 {
867 write!(f, "{d:.1}")
868 } else {
869 write!(f, "{d}")
870 }
871 }
872 Value::BigInt(n) => {
873 if readably {
874 write!(f, "{}N", n.get())
875 } else {
876 write!(f, "{}", n.get())
877 }
878 }
879 Value::BigDecimal(d) => {
880 let dec = d.get();
881 let s = format!("{}", dec);
882 if !s.contains('.') && dec.fractional_digit_count() > 0 {
885 let zeros = "0".repeat(dec.fractional_digit_count() as usize);
886 if readably {
887 write!(f, "{s}.{zeros}M")
888 } else {
889 write!(f, "{s}.{zeros}")
890 }
891 } else if readably {
892 write!(f, "{s}M")
893 } else {
894 write!(f, "{s}")
895 }
896 }
897 Value::Ratio(r) => write!(f, "{}", r.get()),
898 Value::Uuid(u) => {
899 let uuid = uuid::Uuid::from_u128(u.get().0);
900 if readably {
901 write!(f, "#uuid \"{}\"", uuid)
902 } else {
903 write!(f, "{}", uuid)
904 }
905 }
906 Value::Char(c) => {
907 if readably {
908 match c {
909 '\n' => write!(f, "\\newline"),
910 '\t' => write!(f, "\\tab"),
911 ' ' => write!(f, "\\space"),
912 '\r' => write!(f, "\\return"),
913 c => write!(f, "\\{c}"),
914 }
915 } else {
916 write!(f, "{c}")
917 }
918 }
919 Value::Str(s) => {
920 if readably {
921 write!(f, "\"")?;
922 for c in s.get().chars() {
923 match c {
924 '"' => write!(f, "\\\"")?,
925 '\\' => write!(f, "\\\\")?,
926 '\n' => write!(f, "\\n")?,
927 '\t' => write!(f, "\\t")?,
928 '\r' => write!(f, "\\r")?,
929 c => write!(f, "{c}")?,
930 }
931 }
932 write!(f, "\"")
933 } else {
934 write!(f, "{}", s.get())
935 }
936 }
937 Value::Pattern(r) => {
938 if readably {
939 write!(f, "#\"")?;
940 write!(f, "{}", r.get().as_str())?;
941 write!(f, "\"")
942 } else {
943 write!(f, "#<{}>", r.get())
944 }
945 }
946 Value::Matcher(_) => write!(f, "#<Matcher>"),
947 Value::Symbol(s) => write!(f, "{}", s.get()),
948 Value::Keyword(k) => write!(f, "{}", k.get()),
949 Value::List(l) => {
950 write!(f, "(")?;
951 let mut first = true;
952 for item in l.get().iter() {
953 if !first {
954 write!(f, " ")?;
955 }
956 pr_str(item, f, readably)?;
957 first = false;
958 }
959 write!(f, ")")
960 }
961 Value::Vector(v) => {
962 write!(f, "[")?;
963 let mut first = true;
964 for item in v.get().iter() {
965 if !first {
966 write!(f, " ")?;
967 }
968 pr_str(item, f, readably)?;
969 first = false;
970 }
971 write!(f, "]")
972 }
973 Value::Map(m) => {
974 write!(f, "{{")?;
975 let mut first = true;
976 m.for_each(|k, v| {
977 if !first {
979 let _ = write!(f, ", ");
980 }
981 let _ = pr_str(k, f, readably);
982 let _ = write!(f, " ");
983 let _ = pr_str(v, f, readably);
984 first = false;
985 });
986 write!(f, "}}")
987 }
988 Value::Set(s) => {
989 write!(f, "#{{")?;
990 let mut first = true;
991 for item in s.iter() {
992 if !first {
993 write!(f, " ")?;
994 }
995 pr_str(item, f, readably)?;
996 first = false;
997 }
998 write!(f, "}}")
999 }
1000 Value::BooleanArray(_)
1001 | Value::ByteArray(_)
1002 | Value::ShortArray(_)
1003 | Value::IntArray(_)
1004 | Value::LongArray(_)
1005 | Value::CharArray(_)
1006 | Value::FloatArray(_)
1007 | Value::DoubleArray(_)
1008 | Value::ObjectArray(_) => write!(f, "#[array]"),
1009 Value::Queue(q) => {
1010 write!(f, "#queue (")?;
1012 let mut first = true;
1013 for item in q.get().iter() {
1014 if !first {
1015 write!(f, " ")?;
1016 }
1017 pr_str(item, f, readably)?;
1018 first = false;
1019 }
1020 write!(f, ")")
1021 }
1022 Value::LazySeq(ls) => pr_str(&crate::realization::for_trait(ls.get()), f, readably),
1023 Value::Cons(c) => {
1024 write!(f, "(")?;
1025 pr_str(&c.get().head, f, readably)?;
1026 let mut tail = c.get().tail.clone();
1027 loop {
1028 match tail {
1029 Value::Nil => break,
1030 Value::List(l) => {
1031 for item in l.get().iter() {
1032 write!(f, " ")?;
1033 pr_str(item, f, readably)?;
1034 }
1035 break;
1036 }
1037 Value::Cons(next_c) => {
1038 write!(f, " ")?;
1039 pr_str(&next_c.get().head, f, readably)?;
1040 tail = next_c.get().tail.clone();
1041 }
1042 Value::LazySeq(ls) => {
1043 tail = crate::realization::for_trait(ls.get());
1044 }
1045 other => {
1046 write!(f, " . ")?;
1047 pr_str(&other, f, readably)?;
1048 break;
1049 }
1050 }
1051 }
1052 write!(f, ")")
1053 }
1054 Value::NativeFunction(nf) => write!(f, "#<NativeFn {}>", nf.get().name),
1055 Value::BoundFn(_) => write!(f, "#<BoundFn>"),
1056 Value::Fn(fun) => match &fun.get().name {
1057 Some(n) => write!(f, "#<Fn {n}>"),
1058 None => write!(f, "#<Fn>"),
1059 },
1060 Value::Macro(m) => match &m.get().name {
1061 Some(n) => write!(f, "#<Macro {n}>"),
1062 None => write!(f, "#<Macro>"),
1063 },
1064 Value::Var(v) => write!(f, "#'{}/{}", v.get().namespace, v.get().name),
1065 Value::Atom(a) => write!(f, "#<Atom {}>", a.get().deref()),
1066 Value::SharedAtom(a) => {
1067 write!(f, "#<SharedAtom {}>", a.deref_val().type_name())
1068 }
1069 Value::ByteBlob(b) => write!(f, "#<ByteBlob {} bytes>", b.len()),
1070 Value::Namespace(n) => write!(f, "#<Namespace {}>", n.get().name),
1071 Value::Protocol(p) => write!(f, "#<Protocol {}>", p.get().name),
1072 Value::ProtocolFn(pf) => {
1073 write!(
1074 f,
1075 "#<fn {}/{}>",
1076 pf.get().protocol.get().name,
1077 pf.get().method_name
1078 )
1079 }
1080 Value::MultiFn(mf) => write!(f, "#<MultiFn {}>", mf.get().name),
1081 Value::Volatile(_) => write!(f, "#<Volatile>"),
1082 Value::Delay(_) => write!(f, "#<Delay>"),
1083 Value::Promise(_) => write!(f, "#<Promise>"),
1084 Value::Future(_) => write!(f, "#<Future>"),
1085 Value::Agent(_) => write!(f, "#<Agent>"),
1086 Value::TypeInstance(ti) => {
1087 let ti = ti.get();
1088 write!(f, "#{}{{", ti.type_tag)?;
1089 let mut first = true;
1090 ti.fields.for_each(|k, v| {
1091 if !first {
1092 let _ = write!(f, ", ");
1093 }
1094 let _ = pr_str(k, f, readably);
1095 let _ = write!(f, " ");
1096 let _ = pr_str(v, f, readably);
1097 first = false;
1098 });
1099 write!(f, "}}")
1100 }
1101 Value::NativeObject(obj) => {
1102 write!(f, "#<{} {:?}>", obj.get().type_tag(), obj.get().inner())
1103 }
1104 Value::Resource(r) => {
1105 if r.is_closed() {
1106 write!(f, "#<{} (closed)>", r.resource_type())
1107 } else {
1108 write!(f, "#<{}>", r.resource_type())
1109 }
1110 }
1111 Value::TransientMap(_) => write!(f, "#<TransientMap>"),
1112 Value::TransientSet(_) => write!(f, "#<TransientSet>"),
1113 Value::TransientVector(_) => write!(f, "#<TransientVector>"),
1114 Value::Error(e) => {
1115 write!(f, "#error ")?;
1116 let map = e.get().to_map().map_err(|_| fmt::Error {})?;
1117 pr_str(&map, f, readably)
1118 }
1119 }
1120}
1121
1122impl Value {
1125 pub fn from_kwargs_rest(mut entries: Vec<Value>) -> Result<Value, ValueError> {
1145 if entries.len() < 2 {
1146 return Ok(entries.pop().unwrap_or(Value::Nil));
1147 }
1148
1149 let trailing = match entries.last().map(Value::unwrap_meta) {
1153 Some(Value::Map(_)) if !entries.len().is_multiple_of(2) => entries.pop(),
1154 _ => None,
1155 };
1156
1157 if !entries.len().is_multiple_of(2) {
1158 let key = entries.last().expect("odd length implies a last entry");
1159 return Err(ValueError::Other(format!(
1160 "No value supplied for key: {}",
1161 PrintValue(key)
1162 )));
1163 }
1164
1165 let mut result = MapValue::from_flat_entries(entries);
1166 if let Some(Value::Map(map)) = trailing.as_ref().map(Value::unwrap_meta) {
1167 for (key, value) in map.iter() {
1168 result = result.assoc(key.clone(), value.clone());
1169 }
1170 }
1171 Ok(Value::Map(result))
1172 }
1173}
1174
1175impl Value {
1178 pub fn unwrap_meta(&self) -> &Value {
1180 match self {
1181 Value::WithMeta(inner, _) => inner.unwrap_meta(),
1182 other => other,
1183 }
1184 }
1185
1186 pub fn get_meta(&self) -> Option<&Value> {
1188 match self {
1189 Value::WithMeta(_, meta) => Some(meta),
1190 _ => None,
1191 }
1192 }
1193
1194 pub fn with_meta(self, meta: Value) -> Value {
1196 match self {
1197 Value::WithMeta(inner, _) => Value::WithMeta(inner, Box::new(meta)),
1198 other => Value::WithMeta(Box::new(other), Box::new(meta)),
1199 }
1200 }
1201}
1202
1203impl Value {
1206 pub fn type_name(&self) -> &'static str {
1208 match self {
1209 Value::WithMeta(inner, _) => inner.type_name(),
1210 Value::Reduced(_) => "reduced",
1211 Value::Nil => "nil",
1212 Value::Bool(_) => "boolean",
1213 Value::Long(_) => "long",
1214 Value::Double(_) => "double",
1215 Value::BigInt(_) => "bigint",
1216 Value::BigDecimal(_) => "bigdecimal",
1217 Value::Ratio(_) => "ratio",
1218 Value::Char(_) => "char",
1219 Value::Str(_) => "string",
1220 Value::Pattern(_) => "pattern",
1221 Value::Matcher(_) => "matcher",
1222 Value::Symbol(_) => "symbol",
1223 Value::Keyword(_) => "keyword",
1224 Value::Uuid(_) => "uuid",
1225 Value::List(_) => "list",
1226 Value::Vector(_) => "vector",
1227 Value::Map(_) => "map",
1228 Value::Set(_) => "set",
1229 Value::Queue(_) => "queue",
1230 Value::NativeFunction(_)
1231 | Value::Fn(_)
1232 | Value::BoundFn(_)
1233 | Value::Macro(_)
1234 | Value::ProtocolFn(_)
1235 | Value::MultiFn(_) => "fn",
1236 Value::Var(_) => "var",
1237 Value::Atom(_) => "atom",
1238 Value::SharedAtom(_) => "shared-atom",
1239 Value::ByteBlob(_) => "byte-blob",
1240 Value::Namespace(_) => "namespace",
1241 Value::LazySeq(_) => "lazyseq",
1242 Value::Cons(_) => "cons",
1243 Value::Protocol(_) => "protocol",
1244 Value::Volatile(_) => "volatile",
1245 Value::Delay(_) => "delay",
1246 Value::Promise(_) => "promise",
1247 Value::Future(_) => "future",
1248 Value::Agent(_) => "agent",
1249 Value::TypeInstance(_) => "record",
1250 Value::NativeObject(_) => "native-object",
1251 Value::BooleanArray(_) => "boolean-array",
1252 Value::ByteArray(_) => "byte-array",
1253 Value::ShortArray(_) => "short-array",
1254 Value::IntArray(_) => "int-array",
1255 Value::LongArray(_) => "long-array",
1256 Value::FloatArray(_) => "float-array",
1257 Value::DoubleArray(_) => "double-array",
1258 Value::CharArray(_) => "char-array",
1259 Value::ObjectArray(_) => "object-array",
1260 Value::Resource(r) => r.resource_type(),
1261 Value::TransientMap(_) => "transient-map",
1262 Value::TransientSet(_) => "transient-set",
1263 Value::TransientVector(_) => "transient-vector",
1264 Value::Error(_) => "error",
1265 }
1266 }
1267
1268 pub fn string(s: impl Into<String>) -> Self {
1270 Value::Str(GcPtr::new(s.into()))
1271 }
1272
1273 pub fn uuid(value: u128) -> Self {
1275 Value::Uuid(GcPtr::new(UuidValue(value)))
1276 }
1277
1278 pub fn map_entry(key: Value, val: Value) -> Self {
1280 Value::Vector(GcPtr::new(PersistentVector::map_entry(key, val)))
1281 }
1282
1283 pub fn is_map_entry(&self) -> bool {
1286 matches!(self.unwrap_meta(), Value::Vector(v) if v.get().is_map_entry())
1287 }
1288
1289 pub fn symbol(s: Symbol) -> Self {
1291 Value::Symbol(GcPtr::new(s))
1292 }
1293
1294 pub fn keyword(k: Keyword) -> Self {
1296 Value::Keyword(GcPtr::new(k))
1297 }
1298
1299 pub fn is_sequential(&self) -> bool {
1301 matches!(
1302 self,
1303 Value::List(_) | Value::Vector(_) | Value::LazySeq(_) | Value::Cons(_)
1304 )
1305 }
1306
1307 pub fn is_coll(&self) -> bool {
1309 self.unwrap_meta().is_coll_inner()
1310 }
1311
1312 fn is_coll_inner(&self) -> bool {
1313 matches!(
1314 self,
1315 Value::List(_)
1316 | Value::Vector(_)
1317 | Value::Map(_)
1318 | Value::Set(_)
1319 | Value::Queue(_)
1320 | Value::LazySeq(_)
1321 | Value::Cons(_)
1322 )
1323 }
1324}
1325
1326impl cljrs_gc::Trace for Value {
1327 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1328 use cljrs_gc::GcVisitor as _;
1329 match self {
1330 Value::Reduced(inner) => inner.trace(visitor),
1331 Value::WithMeta(inner, meta) => {
1332 inner.trace(visitor);
1333 meta.trace(visitor);
1334 }
1335 Value::Nil | Value::Bool(_) | Value::Long(_) | Value::Double(_) | Value::Char(_) => {}
1336 Value::Uuid(p) => visitor.visit(p),
1337 Value::BigInt(p) => visitor.visit(p),
1338 Value::BigDecimal(p) => visitor.visit(p),
1339 Value::Ratio(p) => visitor.visit(p),
1340 Value::Str(p) => visitor.visit(p),
1341 Value::Pattern(p) => visitor.visit(p),
1342 Value::Matcher(m) => visitor.visit(m),
1343 Value::Symbol(p) => visitor.visit(p),
1344 Value::Keyword(p) => visitor.visit(p),
1345 Value::List(p) => visitor.visit(p),
1346 Value::Vector(p) => visitor.visit(p),
1347 Value::Map(m) => m.trace(visitor),
1348 Value::Set(s) => s.trace(visitor),
1349 Value::Queue(p) => visitor.visit(p),
1350 Value::NativeFunction(p) => visitor.visit(p),
1351 Value::BoundFn(p) => visitor.visit(p),
1352 Value::Fn(p) | Value::Macro(p) => visitor.visit(p),
1353 Value::Var(p) => visitor.visit(p),
1354 Value::Atom(p) => visitor.visit(p),
1355 Value::Namespace(p) => visitor.visit(p),
1356 Value::LazySeq(p) => visitor.visit(p),
1357 Value::Cons(p) => visitor.visit(p),
1358 Value::Protocol(p) => visitor.visit(p),
1359 Value::ProtocolFn(p) => visitor.visit(p),
1360 Value::MultiFn(p) => visitor.visit(p),
1361 Value::Volatile(p) => visitor.visit(p),
1362 Value::Delay(p) => visitor.visit(p),
1363 Value::Promise(p) => visitor.visit(p),
1364 Value::Future(p) => visitor.visit(p),
1365 Value::Agent(p) => visitor.visit(p),
1366 Value::TypeInstance(p) => visitor.visit(p),
1367 Value::ObjectArray(p) => visitor.visit(p),
1368 Value::BooleanArray(p) => visitor.visit(p),
1371 Value::ByteArray(p) => visitor.visit(p),
1372 Value::ShortArray(p) => visitor.visit(p),
1373 Value::IntArray(p) => visitor.visit(p),
1374 Value::LongArray(p) => visitor.visit(p),
1375 Value::FloatArray(p) => visitor.visit(p),
1376 Value::DoubleArray(p) => visitor.visit(p),
1377 Value::CharArray(p) => visitor.visit(p),
1378 Value::NativeObject(p) => visitor.visit(p),
1379 Value::Resource(_) | Value::SharedAtom(_) | Value::ByteBlob(_) => {}
1382 Value::TransientMap(m) => visitor.visit(m),
1383 Value::TransientVector(p) => visitor.visit(p),
1384 Value::TransientSet(m) => visitor.visit(m),
1385 Value::Error(e) => visitor.visit(e),
1386 }
1387 }
1388}
1389
1390impl cljrs_gc::Trace for MapValue {
1391 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1392 use cljrs_gc::GcVisitor as _;
1393 match self {
1394 MapValue::Array(p) => visitor.visit(p),
1395 MapValue::Hash(p) => visitor.visit(p),
1396 MapValue::Sorted(p) => visitor.visit(p),
1397 }
1398 }
1399}
1400
1401#[derive(Clone, Debug)]
1406pub struct TypeInstance {
1407 pub type_tag: Arc<str>,
1408 pub fields: MapValue,
1409 pub mutable: Option<GcPtr<crate::types::Atom>>,
1415}
1416
1417impl cljrs_gc::Trace for TypeInstance {
1418 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1419 use cljrs_gc::GcVisitor as _;
1420 self.fields.trace(visitor);
1421 if let Some(m) = &self.mutable {
1422 visitor.visit(m);
1423 }
1424 }
1425}
1426
1427#[allow(clippy::items_after_test_module)]
1428#[cfg(test)]
1429mod tests {
1430 use super::*;
1431
1432 fn kw(s: &str) -> Value {
1433 Value::keyword(Keyword::simple(s))
1434 }
1435 #[allow(dead_code)]
1436 fn sym(s: &str) -> Value {
1437 Value::symbol(Symbol::simple(s))
1438 }
1439 fn int(n: i64) -> Value {
1440 Value::Long(n)
1441 }
1442 fn s(v: &str) -> Value {
1443 Value::string(v)
1444 }
1445
1446 #[test]
1449 fn test_nil_eq() {
1450 assert_eq!(Value::Nil, Value::Nil);
1451 assert_ne!(Value::Nil, int(0));
1452 }
1453
1454 #[test]
1455 fn test_numeric_cross_type() {
1456 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1457 assert_eq!(int(1), big1.clone());
1458 assert_eq!(big1, int(1));
1459 assert_eq!(Value::Double(1.0), int(1));
1461 assert_eq!(int(1), Value::Double(1.0));
1462 assert_ne!(Value::Double(1.5), int(1));
1464 }
1465
1466 #[test]
1467 fn test_nan_not_equal_to_itself() {
1468 let nan = Value::Double(f64::NAN);
1469 assert_ne!(nan, nan.clone());
1470 }
1471
1472 #[test]
1473 fn test_string_equality() {
1474 assert_eq!(s("hello"), s("hello"));
1475 assert_ne!(s("hello"), s("world"));
1476 }
1477
1478 #[test]
1479 fn test_list_vector_seq_equality() {
1480 let list = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1481 let vec = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1482 assert_eq!(list, vec);
1484 }
1485
1486 #[test]
1487 fn test_map_equality_order_independent() {
1488 let mut a = MapValue::empty();
1489 a = a.assoc(kw("a"), int(1));
1490 a = a.assoc(kw("b"), int(2));
1491
1492 let mut b = MapValue::empty();
1493 b = b.assoc(kw("b"), int(2));
1494 b = b.assoc(kw("a"), int(1));
1495
1496 assert_eq!(Value::Map(a), Value::Map(b));
1497 }
1498
1499 #[test]
1502 fn test_hash_consistency() {
1503 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1504 assert_eq!(int(1).clojure_hash(), big1.clojure_hash());
1505 }
1506
1507 #[test]
1508 fn test_hash_whole_double() {
1509 assert_eq!(int(1).clojure_hash(), Value::Double(1.0).clojure_hash());
1511 }
1512
1513 #[test]
1516 fn test_pr_str_nil() {
1517 assert_eq!(Value::Nil.to_string(), "nil");
1518 }
1519
1520 #[test]
1521 fn test_pr_str_string() {
1522 assert_eq!(s("hello").to_string(), "\"hello\"");
1523 assert_eq!(s("a\"b").to_string(), "\"a\\\"b\"");
1524 }
1525
1526 #[test]
1527 fn test_pr_str_char() {
1528 assert_eq!(Value::Char('a').to_string(), "\\a");
1529 assert_eq!(Value::Char('\n').to_string(), "\\newline");
1530 }
1531
1532 #[test]
1533 fn test_pr_str_list() {
1534 let l = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1535 assert_eq!(l.to_string(), "(1 2)");
1536 }
1537
1538 #[test]
1539 fn test_pr_str_vector() {
1540 let v = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1541 assert_eq!(v.to_string(), "[1 2]");
1542 }
1543
1544 #[test]
1545 #[allow(clippy::approx_constant)]
1546 fn test_pr_str_double() {
1547 assert_eq!(Value::Double(1.0).to_string(), "1.0");
1548 assert_eq!(Value::Double(3.14).to_string(), "3.14");
1549 assert_eq!(Value::Double(f64::INFINITY).to_string(), "##Inf");
1550 assert_eq!(Value::Double(f64::NEG_INFINITY).to_string(), "##-Inf");
1551 assert_eq!(Value::Double(f64::NAN).to_string(), "##NaN");
1552 }
1553
1554 fn kwargs(entries: Vec<Value>) -> Value {
1557 Value::from_kwargs_rest(entries).expect("well-formed kwargs")
1558 }
1559
1560 fn map_of(entries: Vec<Value>) -> Value {
1561 Value::Map(MapValue::from_flat_entries(entries))
1562 }
1563
1564 #[test]
1565 fn kwargs_rest_empty_and_lone_values_pass_through() {
1566 assert_eq!(kwargs(vec![]), Value::Nil);
1569 assert_eq!(kwargs(vec![Value::Nil]), Value::Nil);
1570 assert_eq!(kwargs(vec![kw("a")]), kw("a"));
1574 let sorted = Value::Map(MapValue::Sorted(GcPtr::new(SortedMap::from_pairs(vec![
1575 (kw("b"), int(1)),
1576 (kw("a"), int(2)),
1577 ]))));
1578 assert!(matches!(
1579 kwargs(vec![sorted.clone()]),
1580 Value::Map(MapValue::Sorted(_))
1581 ));
1582 let with_meta = map_of(vec![kw("a"), int(1)]).with_meta(map_of(vec![kw("t"), int(1)]));
1583 assert_eq!(kwargs(vec![with_meta.clone()]), with_meta);
1584 }
1585
1586 #[test]
1587 fn kwargs_rest_pairs_build_a_map() {
1588 assert_eq!(
1589 kwargs(vec![kw("a"), int(1), kw("b"), int(2)]),
1590 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1591 );
1592 assert_eq!(
1594 kwargs(vec![kw("a"), int(1), kw("a"), int(2)]),
1595 map_of(vec![kw("a"), int(2)])
1596 );
1597 }
1598
1599 #[test]
1600 fn kwargs_rest_trailing_map_merges_and_wins() {
1601 assert_eq!(
1603 kwargs(vec![kw("a"), int(1), map_of(vec![kw("b"), int(2)])]),
1604 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1605 );
1606 assert_eq!(
1608 kwargs(vec![kw("a"), int(1), map_of(vec![kw("a"), int(9)])]),
1609 map_of(vec![kw("a"), int(9)])
1610 );
1611 let meta_map = map_of(vec![kw("b"), int(2)]).with_meta(map_of(vec![kw("t"), int(1)]));
1614 assert_eq!(
1615 kwargs(vec![kw("a"), int(1), meta_map]),
1616 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1617 );
1618 }
1619
1620 #[test]
1621 fn kwargs_rest_map_in_value_position_is_not_a_trailing_map() {
1622 let inner = map_of(vec![kw("x"), int(1)]);
1624 assert_eq!(
1625 kwargs(vec![kw("a"), inner.clone()]),
1626 map_of(vec![kw("a"), inner])
1627 );
1628 }
1629
1630 #[test]
1631 fn kwargs_rest_dangling_key_is_an_error() {
1632 let err = Value::from_kwargs_rest(vec![kw("a"), int(1), kw("b")])
1635 .expect_err("odd arity with no trailing map");
1636 assert_eq!(err.to_string(), "No value supplied for key: :b");
1637 }
1638}
1639
1640impl PartialOrd for Value {
1643 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1644 Some(self.cmp(other))
1645 }
1646}
1647
1648impl Ord for Value {
1649 fn cmp(&self, other: &Self) -> Ordering {
1650 let a = self.unwrap_meta();
1652 let b = other.unwrap_meta();
1653 if !std::ptr::eq(a, self) || !std::ptr::eq(b, other) {
1654 return a.cmp(b);
1655 }
1656 match (self, other) {
1658 (Value::Nil, Value::Nil) => Ordering::Equal,
1660
1661 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
1663
1664 (Value::Long(a), Value::Long(b)) => a.cmp(b),
1666 (Value::Double(a), Value::Double(b)) => total_cmp_f64(*a, *b),
1667 (Value::BigInt(a), Value::BigInt(b)) => a.get().cmp(b.get()),
1668 (Value::BigDecimal(a), Value::BigDecimal(b)) => {
1669 a.get()
1671 .partial_cmp(b.get())
1672 .unwrap_or_else(|| a.get().to_string().cmp(&b.get().to_string()))
1673 }
1674 (Value::Ratio(a), Value::Ratio(b)) => a.get().cmp(b.get()),
1675
1676 (Value::Long(a), Value::Double(b)) => total_cmp_f64(*a as f64, *b),
1678 (Value::Double(a), Value::Long(b)) => total_cmp_f64(*a, *b as f64),
1679 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a).cmp(b.get()),
1680 (Value::BigInt(a), Value::Long(b)) => a.get().cmp(&BigInt::from(*b)),
1681 (Value::Long(a), Value::Ratio(b)) => {
1682 num_rational::Ratio::from(BigInt::from(*a)).cmp(b.get())
1683 }
1684 (Value::Ratio(a), Value::Long(b)) => {
1685 a.get().cmp(&num_rational::Ratio::from(BigInt::from(*b)))
1686 }
1687 (Value::BigInt(a), Value::Ratio(b)) => {
1688 num_rational::Ratio::from(a.get().clone()).cmp(b.get())
1689 }
1690 (Value::Ratio(a), Value::BigInt(b)) => {
1691 a.get().cmp(&num_rational::Ratio::from(b.get().clone()))
1692 }
1693 (Value::Double(a), Value::BigInt(b)) => {
1694 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1695 }
1696 (Value::BigInt(a), Value::Double(b)) => {
1697 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1698 }
1699 (Value::Double(a), Value::Ratio(b)) => {
1700 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1701 }
1702 (Value::Ratio(a), Value::Double(b)) => {
1703 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1704 }
1705 (Value::Long(a), Value::BigDecimal(b)) => {
1706 let ad = bigdecimal::BigDecimal::from(*a);
1707 ad.partial_cmp(b.get())
1708 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1709 }
1710 (Value::BigDecimal(a), Value::Long(b)) => {
1711 let bd = bigdecimal::BigDecimal::from(*b);
1712 a.get()
1713 .partial_cmp(&bd)
1714 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1715 }
1716 (Value::Double(a), Value::BigDecimal(b)) => {
1717 match bigdecimal::BigDecimal::try_from(*a) {
1718 Ok(ad) => ad
1719 .partial_cmp(b.get())
1720 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1721 Err(_) => {
1722 if a.is_nan() {
1724 Ordering::Greater
1725 } else if *a < 0.0 {
1726 Ordering::Less
1727 } else {
1728 Ordering::Greater
1729 }
1730 }
1731 }
1732 }
1733 (Value::BigDecimal(a), Value::Double(b)) => {
1734 match bigdecimal::BigDecimal::try_from(*b) {
1735 Ok(bd) => a
1736 .get()
1737 .partial_cmp(&bd)
1738 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1739 Err(_) => {
1740 if b.is_nan() {
1741 Ordering::Less
1742 } else if *b < 0.0 {
1743 Ordering::Greater
1744 } else {
1745 Ordering::Less
1746 }
1747 }
1748 }
1749 }
1750 (Value::BigInt(a), Value::BigDecimal(b)) => {
1751 let ad = bigdecimal::BigDecimal::from(a.get().clone());
1752 ad.partial_cmp(b.get())
1753 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1754 }
1755 (Value::BigDecimal(a), Value::BigInt(b)) => {
1756 let bd = bigdecimal::BigDecimal::from(b.get().clone());
1757 a.get()
1758 .partial_cmp(&bd)
1759 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1760 }
1761 (Value::Ratio(a), Value::BigDecimal(b)) => {
1762 let af = a.get().to_f64().unwrap_or(f64::MAX);
1763 match bigdecimal::BigDecimal::try_from(af) {
1764 Ok(ad) => ad
1765 .partial_cmp(b.get())
1766 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1767 Err(_) => Ordering::Greater,
1768 }
1769 }
1770 (Value::BigDecimal(a), Value::Ratio(b)) => {
1771 let bf = b.get().to_f64().unwrap_or(f64::MAX);
1772 match bigdecimal::BigDecimal::try_from(bf) {
1773 Ok(bd) => a
1774 .get()
1775 .partial_cmp(&bd)
1776 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1777 Err(_) => Ordering::Less,
1778 }
1779 }
1780
1781 (Value::Char(a), Value::Char(b)) => a.cmp(b),
1783
1784 (Value::Str(a), Value::Str(b)) => a.get().cmp(b.get()),
1786
1787 (Value::Symbol(a), Value::Symbol(b)) => cmp_ns_name(
1789 &a.get().namespace,
1790 &a.get().name,
1791 &b.get().namespace,
1792 &b.get().name,
1793 ),
1794
1795 (Value::Keyword(a), Value::Keyword(b)) => cmp_ns_name(
1797 &a.get().namespace,
1798 &a.get().name,
1799 &b.get().namespace,
1800 &b.get().name,
1801 ),
1802
1803 (Value::Vector(a), Value::Vector(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1805 (Value::List(a), Value::List(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1806
1807 (Value::Set(a), Value::Set(b)) => a.count().cmp(&b.count()),
1809
1810 (Value::Map(a), Value::Map(b)) => a.count().cmp(&b.count()),
1812
1813 _ => type_discriminant(self).cmp(&type_discriminant(other)),
1815 }
1816 }
1817}
1818
1819fn iter_cmp<'a>(
1821 mut a: impl Iterator<Item = &'a Value>,
1822 mut b: impl Iterator<Item = &'a Value>,
1823) -> Ordering {
1824 loop {
1825 match (a.next(), b.next()) {
1826 (None, None) => return Ordering::Equal,
1827 (None, Some(_)) => return Ordering::Less,
1828 (Some(_), None) => return Ordering::Greater,
1829 (Some(x), Some(y)) => {
1830 let c = x.cmp(y);
1831 if c != Ordering::Equal {
1832 return c;
1833 }
1834 }
1835 }
1836 }
1837}
1838
1839fn total_cmp_f64(a: f64, b: f64) -> Ordering {
1841 a.total_cmp(&b)
1842}
1843
1844fn cmp_ns_name(
1846 ns_a: &Option<Arc<str>>,
1847 name_a: &Arc<str>,
1848 ns_b: &Option<Arc<str>>,
1849 name_b: &Arc<str>,
1850) -> Ordering {
1851 match (ns_a, ns_b) {
1852 (None, None) => name_a.cmp(name_b),
1853 (None, Some(_)) => Ordering::Less,
1854 (Some(_), None) => Ordering::Greater,
1855 (Some(a), Some(b)) => a.cmp(b).then_with(|| name_a.cmp(name_b)),
1856 }
1857}
1858
1859fn type_discriminant(v: &Value) -> u8 {
1861 match v {
1862 Value::WithMeta(inner, _) => type_discriminant(inner),
1863 Value::Reduced(inner) => type_discriminant(inner),
1864 Value::Nil => 0,
1865 Value::Bool(_) => 1,
1866 Value::Long(_)
1867 | Value::Double(_)
1868 | Value::BigInt(_)
1869 | Value::BigDecimal(_)
1870 | Value::Ratio(_) => 2,
1871 Value::Char(_) => 3,
1872 Value::Str(_) => 4,
1873 Value::Symbol(_) => 5,
1874 Value::Keyword(_) => 6,
1875 Value::List(_) => 7,
1876 Value::Vector(_) => 8,
1877 Value::Map(_) => 9,
1878 Value::Set(_) => 10,
1879 Value::Queue(_) => 11,
1880 Value::LazySeq(_) => 12,
1881 Value::Cons(_) => 13,
1882 Value::NativeFunction(_) => 14,
1883 Value::BoundFn(_) => 14,
1884 Value::Fn(_) => 15,
1885 Value::Macro(_) => 16,
1886 Value::Var(_) => 17,
1887 Value::Atom(_) => 18,
1888 Value::SharedAtom(_) => 46,
1889 Value::ByteBlob(_) => 47,
1890 Value::Namespace(_) => 19,
1891 Value::Protocol(_) => 20,
1892 Value::ProtocolFn(_) => 21,
1893 Value::MultiFn(_) => 22,
1894 Value::Volatile(_) => 23,
1895 Value::Delay(_) => 24,
1896 Value::Promise(_) => 25,
1897 Value::Future(_) => 26,
1898 Value::Agent(_) => 27,
1899 Value::TypeInstance(_) => 28,
1900 Value::BooleanArray(_) => 29,
1901 Value::ByteArray(_) => 30,
1902 Value::ShortArray(_) => 31,
1903 Value::IntArray(_) => 32,
1904 Value::LongArray(_) => 33,
1905 Value::CharArray(_) => 34,
1906 Value::FloatArray(_) => 35,
1907 Value::DoubleArray(_) => 36,
1908 Value::ObjectArray(_) => 37,
1909 Value::Uuid(_) => 38,
1910 Value::NativeObject(_) => 43,
1911 Value::Resource(_) => 39,
1912 Value::TransientMap(_) => 40,
1913 Value::TransientSet(_) => 41,
1914 Value::TransientVector(_) => 42,
1915 Value::Pattern(_) => 43,
1916 Value::Matcher(_) => 44,
1917 Value::Error(_) => 45,
1918 }
1919}