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 Drop for ObjectArray {
37 fn drop(&mut self) {
38 crate::publish::clear_slots(self as *const _ as usize);
39 }
40}
41impl Trace for ObjectArray {
42 #[cfg(feature = "no-gc")]
43 fn init_ownership(&self) {
44 for (index, value) in self.0.lock().unwrap().iter().enumerate() {
45 let lease = cljrs_gc::region::RegionLease::for_value(value);
46 cljrs_gc::region::AllocationOwner::for_address(self as *const _ as usize).set_slot(
47 self as *const _ as usize,
48 index,
49 &lease,
50 );
51 }
52 }
53 #[cfg(feature = "no-gc")]
54 fn trace(&self, _: &mut MarkVisitor) {}
55 #[cfg(not(feature = "no-gc"))]
56 fn trace(&self, visitor: &mut MarkVisitor) {
57 for value in self.0.lock().unwrap().iter() {
58 value.trace(visitor);
59 }
60 }
61
62 fn gc_size_extra(&self) -> usize {
63 let guard = self.0.lock().unwrap();
64 guard.capacity() * std::mem::size_of::<Value>()
65 }
66}
67
68#[derive(Clone, Debug)]
73pub struct UuidValue(pub u128);
74
75impl Trace for UuidValue {
76 fn trace(&self, _: &mut MarkVisitor) {}
77}
78
79#[derive(Clone, Debug)]
84pub enum Value {
85 Nil,
87 Bool(bool),
88 Long(i64),
89 Double(f64),
90 BigInt(GcPtr<BigInt>),
91 BigDecimal(GcPtr<bigdecimal::BigDecimal>),
92 Ratio(GcPtr<num_rational::Ratio<BigInt>>),
93 Char(char),
94 Str(GcPtr<String>),
95 Uuid(GcPtr<UuidValue>),
96 Pattern(GcPtr<Pattern>),
97 Matcher(GcPtr<Matcher>),
98
99 Symbol(GcPtr<Symbol>),
101 Keyword(GcPtr<Keyword>),
102
103 List(GcPtr<PersistentList>),
105 Vector(GcPtr<PersistentVector>),
106 Map(MapValue),
109 Set(SetValue),
110 Queue(GcPtr<PersistentQueue>),
111
112 TransientMap(GcPtr<TransientMap>),
114 TransientSet(GcPtr<TransientSet>),
115 TransientVector(GcPtr<TransientVector>),
116
117 IntArray(GcPtr<Mutex<Vec<i32>>>),
119 LongArray(GcPtr<Mutex<Vec<i64>>>),
120 ShortArray(GcPtr<Mutex<Vec<i16>>>),
121 ByteArray(GcPtr<Mutex<Vec<i8>>>),
122 FloatArray(GcPtr<Mutex<Vec<f32>>>),
123 DoubleArray(GcPtr<Mutex<Vec<f64>>>),
124 BooleanArray(GcPtr<Mutex<Vec<bool>>>),
125 CharArray(GcPtr<Mutex<Vec<char>>>),
126 ObjectArray(GcPtr<ObjectArray>),
127
128 NativeFunction(GcPtr<NativeFn>),
130 Fn(GcPtr<CljxFn>),
131 Macro(GcPtr<CljxFn>),
132 BoundFn(GcPtr<BoundFn>),
133
134 Var(GcPtr<Var>),
136 Atom(GcPtr<Atom>),
137 SharedAtom(std::sync::Arc<SharedAtom>),
141 ByteBlob(std::sync::Arc<ByteBlob>),
145
146 Reduced(Arc<Value>),
148
149 Namespace(GcPtr<Namespace>),
151
152 LazySeq(GcPtr<LazySeq>),
155 Cons(GcPtr<CljxCons>),
157
158 Protocol(GcPtr<Protocol>),
160 ProtocolFn(GcPtr<ProtocolFn>),
161 MultiFn(GcPtr<MultiFn>),
162
163 Volatile(GcPtr<Volatile>),
165 Delay(GcPtr<Delay>),
166 Promise(GcPtr<CljxPromise>),
167 Future(GcPtr<CljxFuture>),
168 Agent(GcPtr<Agent>),
169
170 TypeInstance(GcPtr<TypeInstance>),
172
173 NativeObject(GcPtr<crate::native_object::NativeObjectBox>),
175
176 Resource(ResourceHandle),
178
179 WithMeta(Arc<Value>, Arc<Value>),
182
183 Error(GcPtr<ExceptionInfo>),
185}
186
187#[derive(Clone, Debug)]
189pub enum MapValue {
190 Array(GcPtr<PersistentArrayMap>),
191 Hash(GcPtr<PersistentHashMap>),
192 Sorted(GcPtr<SortedMap>),
193}
194
195impl MapValue {
196 pub fn empty() -> Self {
197 MapValue::Array(GcPtr::new(PersistentArrayMap::empty()))
198 }
199
200 pub fn from_pairs(pairs: Vec<(Value, Value)>) -> Self {
207 use crate::collections::array_map::AssocResult;
208
209 match PersistentArrayMap::from_pairs(pairs) {
211 AssocResult::Array(m) => MapValue::Array(GcPtr::new(m)),
212 AssocResult::Promote(pairs) => {
213 MapValue::Hash(GcPtr::new(PersistentHashMap::from_pairs(pairs)))
214 }
215 }
216 }
217
218 pub fn from_flat_entries(entries: Vec<Value>) -> Self {
223 debug_assert!(entries.len().is_multiple_of(2));
224 let pairs: Vec<(Value, Value)> = entries
226 .chunks(2)
227 .map(|chunk| (chunk[0].clone(), chunk[1].clone()))
228 .collect();
229 Self::from_pairs(pairs)
230 }
231
232 pub fn get(&self, key: &Value) -> Option<Value> {
233 match self {
234 MapValue::Array(m) => m.get().get(key).cloned(),
235 MapValue::Hash(m) => m.get().get(key).cloned(),
236 MapValue::Sorted(m) => m.get().get(key).cloned(),
237 }
238 }
239
240 pub fn count(&self) -> usize {
241 match self {
242 MapValue::Array(m) => m.get().count(),
243 MapValue::Hash(m) => m.get().count(),
244 MapValue::Sorted(m) => m.get().count(),
245 }
246 }
247
248 pub fn assoc(&self, k: Value, v: Value) -> Self {
249 match self {
250 MapValue::Array(m) => match m.get().assoc(k, v) {
251 crate::collections::array_map::AssocResult::Array(new_m) => {
252 MapValue::Array(GcPtr::new(new_m))
253 }
254 crate::collections::array_map::AssocResult::Promote(pairs) => {
255 let hm = PersistentHashMap::from_pairs(pairs);
256 MapValue::Hash(GcPtr::new(hm))
257 }
258 },
259 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().assoc(k, v))),
260 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().assoc(k, v))),
261 }
262 }
263
264 pub fn dissoc(&self, key: &Value) -> Self {
265 match self {
266 MapValue::Array(m) => MapValue::Array(GcPtr::new(m.get().dissoc(key))),
267 MapValue::Hash(m) => MapValue::Hash(GcPtr::new(m.get().dissoc(key))),
268 MapValue::Sorted(m) => MapValue::Sorted(GcPtr::new(m.get().dissoc(key))),
269 }
270 }
271
272 pub fn contains_key(&self, key: &Value) -> bool {
273 match self {
274 MapValue::Array(m) => m.get().contains_key(key),
275 MapValue::Hash(m) => m.get().contains_key(key),
276 MapValue::Sorted(m) => m.get().contains_key(key),
277 }
278 }
279
280 pub fn for_each<F: FnMut(&Value, &Value)>(&self, mut f: F) {
282 match self {
283 MapValue::Array(m) => {
284 for (k, v) in m.get().iter() {
285 f(k, v);
286 }
287 }
288 MapValue::Hash(m) => {
289 for (k, v) in m.get().iter() {
290 f(k, v);
291 }
292 }
293 MapValue::Sorted(m) => {
294 for (k, v) in m.get().iter() {
295 f(k, v);
296 }
297 }
298 }
299 }
300
301 pub fn iter(&self) -> Box<dyn Iterator<Item = (&Value, &Value)> + '_> {
303 match self {
304 MapValue::Array(m) => Box::new(m.get().iter()),
305 MapValue::Hash(m) => Box::new(m.get().iter()),
306 MapValue::Sorted(m) => Box::new(m.get().iter()),
307 }
308 }
309}
310
311#[derive(Clone, Debug)]
313pub enum SetValue {
314 Hash(GcPtr<PersistentHashSet>),
315 Sorted(GcPtr<SortedSet>),
316}
317
318impl SetValue {
319 pub fn empty() -> Self {
320 Self::Hash(GcPtr::new(PersistentHashSet::empty()))
321 }
322
323 pub fn count(&self) -> usize {
324 match self {
325 SetValue::Hash(m) => m.get().count(),
326 SetValue::Sorted(m) => m.get().count(),
327 }
328 }
329
330 pub fn is_empty(&self) -> bool {
331 match self {
332 SetValue::Hash(m) => m.get().is_empty(),
333 SetValue::Sorted(m) => m.get().is_empty(),
334 }
335 }
336
337 pub fn contains(&self, key: &Value) -> bool {
338 match self {
339 SetValue::Hash(m) => m.get().contains(key),
340 SetValue::Sorted(m) => m.get().contains(key),
341 }
342 }
343
344 pub fn conj(&self, value: Value) -> Self {
345 match self {
346 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().conj(value))),
347 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().conj(value))),
348 }
349 }
350
351 pub fn conj_mut(&mut self, value: Value) -> &mut Self {
352 match self {
353 SetValue::Hash(m) => {
354 m.get_mut().conj_mut(value);
355 }
356 SetValue::Sorted(s) => {
357 s.get_mut().conj_mut(value);
358 }
359 }
360 self
361 }
362
363 pub fn disj(&self, value: &Value) -> Self {
364 match self {
365 SetValue::Hash(m) => SetValue::Hash(GcPtr::new(m.get().disj(value))),
366 SetValue::Sorted(m) => SetValue::Sorted(GcPtr::new(m.get().disj(value))),
367 }
368 }
369
370 pub fn iter(&self) -> Box<dyn Iterator<Item = &Value> + '_> {
371 match self {
372 SetValue::Hash(s) => Box::new(s.get().iter()),
373 SetValue::Sorted(s) => Box::new(s.get().iter()),
374 }
375 }
376}
377
378impl cljrs_gc::Trace for SetValue {
379 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
380 use cljrs_gc::GcVisitor as _;
381 match self {
382 SetValue::Hash(s) => visitor.visit(s),
383 SetValue::Sorted(s) => visitor.visit(s),
384 }
385 }
386}
387
388impl Eq for Value {}
391
392impl PartialEq for Value {
393 fn eq(&self, other: &Self) -> bool {
394 crate::realization::check_stack();
395 if let Value::WithMeta(inner, _) = self {
397 return inner.as_ref() == other;
398 }
399 if let Value::WithMeta(inner, _) = other {
400 return self == inner.as_ref();
401 }
402 if let Value::Reduced(inner) = self {
404 return inner.as_ref() == other;
405 }
406 if let Value::Reduced(inner) = other {
407 return self == inner.as_ref();
408 }
409 if let (Value::LazySeq(a), Value::LazySeq(b)) = (self, other)
412 && GcPtr::ptr_eq(a, b)
413 {
414 return true;
415 }
416 if let Value::LazySeq(ls) = self {
420 let realized = crate::realization::for_trait(ls.get());
421 if realized == Value::Nil && other.is_sequential() {
422 return value_to_seq_vec(other).is_empty();
423 }
424 return realized == *other;
425 }
426 if let Value::LazySeq(ls) = other {
427 let realized = crate::realization::for_trait(ls.get());
428 if realized == Value::Nil && self.is_sequential() {
429 return value_to_seq_vec(self).is_empty();
430 }
431 return *self == realized;
432 }
433 match (self, other) {
434 (Value::Nil, Value::Nil) => true,
435 (Value::Bool(a), Value::Bool(b)) => a == b,
436 (Value::Long(a), Value::Long(b)) => a == b,
438 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a) == *b.get(),
439 (Value::BigInt(a), Value::Long(b)) => *a.get() == BigInt::from(*b),
440 (Value::BigInt(a), Value::BigInt(b)) => a.get() == b.get(),
441 (Value::Double(a), Value::Double(b)) => a == b, (Value::Long(a), Value::Double(b)) => b.fract() == 0.0 && b.to_i64() == Some(*a),
443 (Value::Double(a), Value::Long(b)) => a.fract() == 0.0 && a.to_i64() == Some(*b),
444 (Value::BigDecimal(a), Value::BigDecimal(b)) => a.get() == b.get(),
445 (Value::Ratio(a), Value::Ratio(b)) => a.get() == b.get(),
446 (Value::Char(a), Value::Char(b)) => a == b,
447 (Value::Str(a), Value::Str(b)) => a.get() == b.get(),
448 (Value::Symbol(a), Value::Symbol(b)) => a.get() == b.get(),
449 (Value::Keyword(a), Value::Keyword(b)) => a.get() == b.get(),
450 (Value::List(a), Value::List(b)) => a.get() == b.get(),
452 (Value::Vector(a), Value::Vector(b)) => a.get() == b.get(),
453 (Value::Set(a), Value::Set(b)) => sets_equal(a, b),
454 (Value::Queue(a), Value::Queue(b)) => a.get() == b.get(),
455 (Value::Map(a), Value::Map(b)) => maps_equal(a, b),
456 (Value::List(_), Value::Vector(_)) | (Value::Vector(_), Value::List(_)) => {
458 seq_equal(self, other)
459 }
460 (Value::Cons(_), _) | (_, Value::Cons(_)) => seq_equal(self, other),
462 (Value::Fn(a), Value::Fn(b)) => std::ptr::eq(a.get() as *const _, b.get() as *const _),
464 (Value::Macro(a), Value::Macro(b)) => {
465 std::ptr::eq(a.get() as *const _, b.get() as *const _)
466 }
467 (Value::NativeFunction(a), Value::NativeFunction(b)) => {
468 std::ptr::eq(a.get() as *const _, b.get() as *const _)
469 }
470 (Value::Protocol(a), Value::Protocol(b)) => {
472 std::ptr::eq(a.get() as *const _, b.get() as *const _)
473 }
474 (Value::ProtocolFn(a), Value::ProtocolFn(b)) => {
475 std::ptr::eq(a.get() as *const _, b.get() as *const _)
476 }
477 (Value::MultiFn(a), Value::MultiFn(b)) => {
478 std::ptr::eq(a.get() as *const _, b.get() as *const _)
479 }
480 (Value::Volatile(a), Value::Volatile(b)) => {
482 std::ptr::eq(a.get() as *const _, b.get() as *const _)
483 }
484 (Value::Delay(a), Value::Delay(b)) => {
485 std::ptr::eq(a.get() as *const _, b.get() as *const _)
486 }
487 (Value::Promise(a), Value::Promise(b)) => {
488 std::ptr::eq(a.get() as *const _, b.get() as *const _)
489 }
490 (Value::Future(a), Value::Future(b)) => {
491 std::ptr::eq(a.get() as *const _, b.get() as *const _)
492 }
493 (Value::Agent(a), Value::Agent(b)) => {
494 std::ptr::eq(a.get() as *const _, b.get() as *const _)
495 }
496 (Value::Atom(a), Value::Atom(b)) => {
497 std::ptr::eq(a.get() as *const _, b.get() as *const _)
498 }
499 (Value::Var(a), Value::Var(b)) => {
500 std::ptr::eq(a.get() as *const _, b.get() as *const _)
501 }
502 (Value::Namespace(a), Value::Namespace(b)) => {
503 std::ptr::eq(a.get() as *const _, b.get() as *const _)
504 }
505 (Value::Uuid(a), Value::Uuid(b)) => a.get().0 == b.get().0,
507 (Value::Pattern(a), Value::Pattern(b)) => a.get().as_str() == b.get().as_str(),
510 (Value::NativeObject(a), Value::NativeObject(b)) => {
512 std::ptr::eq(a.get() as *const _, b.get() as *const _)
513 }
514 (Value::Resource(a), Value::Resource(b)) => Arc::ptr_eq(&a.0, &b.0),
516 (Value::TypeInstance(a), Value::TypeInstance(b)) => {
518 a.get().type_tag == b.get().type_tag && maps_equal(&a.get().fields, &b.get().fields)
519 }
520 (Value::Error(a), Value::Error(b)) => {
521 std::ptr::eq(a.get() as *const _, b.get() as *const _)
522 }
523 (Value::SharedAtom(a), Value::SharedAtom(b)) => Arc::ptr_eq(a, b),
525 (Value::ByteBlob(a), Value::ByteBlob(b)) => Arc::ptr_eq(a, b),
527 _ => false,
528 }
529 }
530}
531
532fn maps_equal(a: &MapValue, b: &MapValue) -> bool {
533 if a.count() != b.count() {
534 return false;
535 }
536 let mut equal = true;
537 a.for_each(|k, v| {
538 if equal {
539 match b.get(k) {
540 Some(bv) if &bv == v => {}
541 _ => equal = false,
542 }
543 }
544 });
545 equal
546}
547
548fn sets_equal(a: &SetValue, b: &SetValue) -> bool {
549 if a.count() != b.count() {
550 return false;
551 }
552 for k in a.iter() {
553 if !b.contains(k) {
554 return false;
555 }
556 }
557 true
558}
559
560fn seq_equal(a: &Value, b: &Value) -> bool {
561 let a_items = value_to_seq_vec(a);
562 let b_items = value_to_seq_vec(b);
563 a_items.len() == b_items.len() && a_items.iter().zip(b_items.iter()).all(|(x, y)| x == y)
564}
565
566fn value_to_seq_vec(v: &Value) -> Vec<Value> {
567 let mut v = v.clone();
569 while let Value::LazySeq(ls) = &v {
570 v = crate::realization::for_trait(ls.get());
571 }
572 match &v {
573 Value::List(l) => l.get().iter().cloned().collect(),
574 Value::Vector(v) => v.get().iter().cloned().collect(),
575 Value::LazySeq(_) => unreachable!("unwrapped above"),
576 Value::Cons(c) => {
577 let mut result = vec![c.get().head.clone()];
578 let mut tail = c.get().tail.clone();
579 loop {
580 match tail {
581 Value::Nil => break,
582 Value::List(l) => {
583 result.extend(l.get().iter().cloned());
584 break;
585 }
586 Value::Cons(next_c) => {
587 result.push(next_c.get().head.clone());
588 tail = next_c.get().tail.clone();
589 }
590 Value::LazySeq(ls) => {
591 tail = crate::realization::for_trait(ls.get());
592 }
593 _ => break,
594 }
595 }
596 result
597 }
598 _ => vec![],
599 }
600}
601
602impl ClojureHash for Value {
605 fn clojure_hash(&self) -> u32 {
606 crate::realization::check_stack();
607 match self {
608 Value::WithMeta(inner, _) => inner.clojure_hash(),
609 Value::Reduced(inner) => inner.clojure_hash(),
610 Value::Nil => 0,
611 Value::Bool(b) => {
612 if *b { 1231 } else { 1237 } }
614 Value::Long(n) => hash_i64(*n),
615 Value::Double(f) => {
616 if f.fract() == 0.0
618 && f.is_finite()
619 && let Some(n) = num_traits::ToPrimitive::to_i64(f)
620 {
621 return hash_i64(n);
622 }
623 hash_i64(f.to_bits() as i64)
624 }
625 Value::BigInt(n) => {
626 if let Some(l) = n.get().to_i64() {
628 return hash_i64(l);
629 }
630 hash_string(&n.get().to_string())
632 }
633 Value::Char(c) => *c as u32,
634 Value::Str(s) => hash_string(s.get()),
635 Value::Pattern(r) => hash_string(r.get().as_str()),
636 Value::Matcher(m) => hash_string(m.get().pattern.get().as_str()),
637 Value::Keyword(k) => hash_string(&k.get().to_string()),
638 Value::Symbol(s) => hash_string(&s.get().to_string()),
639 Value::Uuid(u) => hash_u128(u.get().0),
640 Value::NativeObject(obj) => {
641 let ptr = obj.get() as *const _ as usize;
642 hash_i64(ptr as i64)
643 }
644 Value::Resource(r) => {
645 let ptr = Arc::as_ptr(&r.0) as *const () as usize;
646 hash_i64(ptr as i64)
647 }
648 Value::List(l) => {
649 let mut h: u32 = 1;
650 for v in l.get().iter() {
651 h = hash_combine_ordered(h, v.clojure_hash());
652 }
653 h
654 }
655 Value::Vector(v) => {
656 let mut h: u32 = 1;
657 for item in v.get().iter() {
658 h = hash_combine_ordered(h, item.clojure_hash());
659 }
660 h
661 }
662 Value::Map(m) => {
663 let mut h: u32 = 0;
664 m.for_each(|k, v| {
665 h = hash_combine_unordered(
666 h,
667 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
668 );
669 });
670 h
671 }
672 Value::Set(s) => {
673 let mut h: u32 = 0;
674 for k in s.iter() {
675 h = hash_combine_unordered(h, k.clojure_hash());
676 }
677 h
678 }
679 Value::TransientMap(m) => m.get().clojure_hash(),
680 Value::TransientSet(s) => s.get().clojure_hash(),
681 Value::TransientVector(v) => v.get().clojure_hash(),
682
683 Value::BooleanArray(a) => {
685 let mut h: u32 = 0;
686 for b in a.get().lock().unwrap().iter() {
687 h = hash_combine_ordered(h, if *b { 1231 } else { 1237 })
688 }
689 h
690 }
691 Value::ByteArray(a) => {
692 let mut h: u32 = 0;
693 for b in a.get().lock().unwrap().iter() {
694 h = hash_combine_ordered(h, *b as u32)
695 }
696 h
697 }
698 Value::ShortArray(a) => {
699 let mut h: u32 = 0;
700 for item in a.get().lock().unwrap().iter() {
701 h = hash_combine_ordered(h, *item as u32)
702 }
703 h
704 }
705 Value::IntArray(a) => {
706 let mut h: u32 = 0;
707 for item in a.get().lock().unwrap().iter() {
708 h = hash_combine_ordered(h, *item as u32)
709 }
710 h
711 }
712 Value::CharArray(a) => {
713 let mut h: u32 = 0;
714 for item in a.get().lock().unwrap().iter() {
715 h = hash_combine_ordered(h, *item as u32)
716 }
717 h
718 }
719 Value::LongArray(a) => {
720 let mut h: u32 = 0;
721 for item in a.get().lock().unwrap().iter() {
722 let v = *item;
723 h = hash_combine_ordered(h, hash_i64(v));
724 }
725 h
726 }
727 Value::FloatArray(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::DoubleArray(a) => {
746 let mut h: u32 = 0;
747 for item in a.get().lock().unwrap().iter() {
748 let f = *item;
749 h = hash_combine_ordered(
750 h,
751 if f.fract() == 0.0
752 && f.is_finite()
753 && let Some(n) = ToPrimitive::to_i64(item)
754 {
755 hash_i64(n)
756 } else {
757 hash_i64(f.to_bits() as i64)
758 },
759 )
760 }
761 h
762 }
763 Value::ObjectArray(a) => {
764 let values = a.get().0.lock().unwrap().clone();
765 crate::collections::hash_values(values)
766 }
767
768 Value::SharedAtom(a) => Arc::as_ptr(a) as u32,
769 Value::ByteBlob(b) => {
770 let mut h: u32 = 0;
771 for byte in b.iter() {
772 h = hash_combine_ordered(h, hash_i64(*byte as i64));
773 }
774 h
775 }
776
777 Value::Fn(f) => f.get() as *const _ as u32,
779 Value::BoundFn(f) => f.get() as *const _ as u32,
780 Value::NativeFunction(f) => f.get() as *const _ as u32,
781 Value::Var(v) => v.get() as *const _ as u32,
782 Value::Atom(a) => a.get() as *const _ as u32,
783 Value::Namespace(n) => n.get() as *const _ as u32,
784 Value::Queue(q) => {
785 let mut h: u32 = 1;
786 for v in q.get().iter() {
787 h = hash_combine_ordered(h, v.clojure_hash());
788 }
789 h
790 }
791 Value::Macro(f) => f.get() as *const _ as u32,
792 Value::BigDecimal(d) => hash_string(&d.get().to_string()),
793 Value::Ratio(r) => hash_string(&r.get().to_string()),
794 Value::LazySeq(ls) => crate::realization::for_trait(ls.get()).clojure_hash(),
795 Value::Protocol(p) => p.get() as *const _ as u32,
796 Value::ProtocolFn(pf) => pf.get() as *const _ as u32,
797 Value::MultiFn(mf) => mf.get() as *const _ as u32,
798 Value::Cons(_) => {
799 let mut h: u32 = 1;
801 for v in value_to_seq_vec(self) {
802 h = hash_combine_ordered(h, v.clojure_hash());
803 }
804 h
805 }
806 Value::Volatile(v) => v.get() as *const _ as u32,
808 Value::Delay(d) => d.get() as *const _ as u32,
809 Value::Promise(p) => p.get() as *const _ as u32,
810 Value::Future(fu) => fu.get() as *const _ as u32,
811 Value::Agent(a) => a.get() as *const _ as u32,
812 Value::TypeInstance(ti) => {
814 let tag_hash = hash_string(&ti.get().type_tag);
815 let mut fields_hash: u32 = 0;
816 ti.get().fields.for_each(|k, v| {
817 fields_hash = hash_combine_unordered(
818 fields_hash,
819 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
820 );
821 });
822 hash_combine_ordered(tag_hash, fields_hash)
823 }
824 Value::Error(e) => e.get().clojure_hash(),
825 }
826 }
827}
828
829impl std::hash::Hash for Value {
831 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
832 self.clojure_hash().hash(state);
833 }
834}
835
836impl fmt::Display for Value {
839 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
841 #[cfg(feature = "no-gc")]
842 let _reads = cljrs_gc::region::ReadScope::enter();
843 pr_str(self, f, true)
844 }
845}
846
847pub struct PrintValue<'a>(pub &'a Value);
849
850impl fmt::Display for PrintValue<'_> {
851 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
852 #[cfg(feature = "no-gc")]
853 let _reads = cljrs_gc::region::ReadScope::enter();
854 pr_str(self.0, f, false)
855 }
856}
857
858pub fn pr_str(v: &Value, f: &mut fmt::Formatter<'_>, readably: bool) -> fmt::Result {
860 crate::realization::check_stack();
861 match v {
862 Value::WithMeta(inner, _) => pr_str(inner, f, readably),
863 Value::Reduced(inner) => {
864 write!(f, "#reduced ")?;
865 pr_str(inner, f, readably)
866 }
867 Value::Nil => write!(f, "nil"),
868 Value::Bool(b) => write!(f, "{b}"),
869 Value::Long(n) => write!(f, "{n}"),
870 Value::Double(d) => {
871 if d.is_infinite() {
872 if readably {
873 if *d > 0.0 {
874 write!(f, "##Inf")
875 } else {
876 write!(f, "##-Inf")
877 }
878 } else if *d > 0.0 {
879 write!(f, "Infinity")
880 } else {
881 write!(f, "-Infinity")
882 }
883 } else if d.is_nan() {
884 if readably {
885 write!(f, "##NaN")
886 } else {
887 write!(f, "NaN")
888 }
889 } else if d.fract() == 0.0 && d.abs() < 1e15 {
890 write!(f, "{d:.1}")
891 } else {
892 write!(f, "{d}")
893 }
894 }
895 Value::BigInt(n) => {
896 if readably {
897 write!(f, "{}N", n.get())
898 } else {
899 write!(f, "{}", n.get())
900 }
901 }
902 Value::BigDecimal(d) => {
903 let dec = d.get();
904 let s = format!("{}", dec);
905 if !s.contains('.') && dec.fractional_digit_count() > 0 {
908 let zeros = "0".repeat(dec.fractional_digit_count() as usize);
909 if readably {
910 write!(f, "{s}.{zeros}M")
911 } else {
912 write!(f, "{s}.{zeros}")
913 }
914 } else if readably {
915 write!(f, "{s}M")
916 } else {
917 write!(f, "{s}")
918 }
919 }
920 Value::Ratio(r) => write!(f, "{}", r.get()),
921 Value::Uuid(u) => {
922 let uuid = uuid::Uuid::from_u128(u.get().0);
923 if readably {
924 write!(f, "#uuid \"{}\"", uuid)
925 } else {
926 write!(f, "{}", uuid)
927 }
928 }
929 Value::Char(c) => {
930 if readably {
931 match c {
932 '\n' => write!(f, "\\newline"),
933 '\t' => write!(f, "\\tab"),
934 ' ' => write!(f, "\\space"),
935 '\r' => write!(f, "\\return"),
936 c => write!(f, "\\{c}"),
937 }
938 } else {
939 write!(f, "{c}")
940 }
941 }
942 Value::Str(s) => {
943 if readably {
944 write!(f, "\"")?;
945 for c in s.get().chars() {
946 match c {
947 '"' => write!(f, "\\\"")?,
948 '\\' => write!(f, "\\\\")?,
949 '\n' => write!(f, "\\n")?,
950 '\t' => write!(f, "\\t")?,
951 '\r' => write!(f, "\\r")?,
952 c => write!(f, "{c}")?,
953 }
954 }
955 write!(f, "\"")
956 } else {
957 write!(f, "{}", s.get())
958 }
959 }
960 Value::Pattern(r) => {
961 if readably {
962 write!(f, "#\"")?;
963 write!(f, "{}", r.get().as_str())?;
964 write!(f, "\"")
965 } else {
966 write!(f, "#<{}>", r.get())
967 }
968 }
969 Value::Matcher(_) => write!(f, "#<Matcher>"),
970 Value::Symbol(s) => write!(f, "{}", s.get()),
971 Value::Keyword(k) => write!(f, "{}", k.get()),
972 Value::List(l) => {
973 write!(f, "(")?;
974 let mut first = true;
975 for item in l.get().iter() {
976 if !first {
977 write!(f, " ")?;
978 }
979 pr_str(item, f, readably)?;
980 first = false;
981 }
982 write!(f, ")")
983 }
984 Value::Vector(v) => {
985 write!(f, "[")?;
986 let mut first = true;
987 for item in v.get().iter() {
988 if !first {
989 write!(f, " ")?;
990 }
991 pr_str(item, f, readably)?;
992 first = false;
993 }
994 write!(f, "]")
995 }
996 Value::Map(m) => {
997 write!(f, "{{")?;
998 let mut first = true;
999 m.for_each(|k, v| {
1000 if !first {
1002 let _ = write!(f, ", ");
1003 }
1004 let _ = pr_str(k, f, readably);
1005 let _ = write!(f, " ");
1006 let _ = pr_str(v, f, readably);
1007 first = false;
1008 });
1009 write!(f, "}}")
1010 }
1011 Value::Set(s) => {
1012 write!(f, "#{{")?;
1013 let mut first = true;
1014 for item in s.iter() {
1015 if !first {
1016 write!(f, " ")?;
1017 }
1018 pr_str(item, f, readably)?;
1019 first = false;
1020 }
1021 write!(f, "}}")
1022 }
1023 Value::BooleanArray(_)
1024 | Value::ByteArray(_)
1025 | Value::ShortArray(_)
1026 | Value::IntArray(_)
1027 | Value::LongArray(_)
1028 | Value::CharArray(_)
1029 | Value::FloatArray(_)
1030 | Value::DoubleArray(_)
1031 | Value::ObjectArray(_) => write!(f, "#[array]"),
1032 Value::Queue(q) => {
1033 write!(f, "#queue (")?;
1035 let mut first = true;
1036 for item in q.get().iter() {
1037 if !first {
1038 write!(f, " ")?;
1039 }
1040 pr_str(item, f, readably)?;
1041 first = false;
1042 }
1043 write!(f, ")")
1044 }
1045 Value::LazySeq(ls) => pr_str(&crate::realization::for_trait(ls.get()), f, readably),
1046 Value::Cons(c) => {
1047 write!(f, "(")?;
1048 pr_str(&c.get().head, f, readably)?;
1049 let mut tail = c.get().tail.clone();
1050 loop {
1051 match tail {
1052 Value::Nil => break,
1053 Value::List(l) => {
1054 for item in l.get().iter() {
1055 write!(f, " ")?;
1056 pr_str(item, f, readably)?;
1057 }
1058 break;
1059 }
1060 Value::Cons(next_c) => {
1061 write!(f, " ")?;
1062 pr_str(&next_c.get().head, f, readably)?;
1063 tail = next_c.get().tail.clone();
1064 }
1065 Value::LazySeq(ls) => {
1066 tail = crate::realization::for_trait(ls.get());
1067 }
1068 other => {
1069 write!(f, " . ")?;
1070 pr_str(&other, f, readably)?;
1071 break;
1072 }
1073 }
1074 }
1075 write!(f, ")")
1076 }
1077 Value::NativeFunction(nf) => write!(f, "#<NativeFn {}>", nf.get().name),
1078 Value::BoundFn(_) => write!(f, "#<BoundFn>"),
1079 Value::Fn(fun) => match &fun.get().name {
1080 Some(n) => write!(f, "#<Fn {n}>"),
1081 None => write!(f, "#<Fn>"),
1082 },
1083 Value::Macro(m) => match &m.get().name {
1084 Some(n) => write!(f, "#<Macro {n}>"),
1085 None => write!(f, "#<Macro>"),
1086 },
1087 Value::Var(v) => write!(f, "#'{}/{}", v.get().namespace, v.get().name),
1088 Value::Atom(a) => write!(f, "#<Atom {}>", a.get().deref()),
1089 Value::SharedAtom(a) => {
1090 write!(f, "#<SharedAtom {}>", a.deref_val().type_name())
1091 }
1092 Value::ByteBlob(b) => write!(f, "#<ByteBlob {} bytes>", b.len()),
1093 Value::Namespace(n) => write!(f, "#<Namespace {}>", n.get().name),
1094 Value::Protocol(p) => write!(f, "#<Protocol {}>", p.get().name),
1095 Value::ProtocolFn(pf) => {
1096 write!(
1097 f,
1098 "#<fn {}/{}>",
1099 pf.get().protocol.get().name,
1100 pf.get().method_name
1101 )
1102 }
1103 Value::MultiFn(mf) => write!(f, "#<MultiFn {}>", mf.get().name),
1104 Value::Volatile(_) => write!(f, "#<Volatile>"),
1105 Value::Delay(_) => write!(f, "#<Delay>"),
1106 Value::Promise(_) => write!(f, "#<Promise>"),
1107 Value::Future(_) => write!(f, "#<Future>"),
1108 Value::Agent(_) => write!(f, "#<Agent>"),
1109 Value::TypeInstance(ti) => {
1110 let ti = ti.get();
1111 write!(f, "#{}{{", ti.type_tag)?;
1112 let mut first = true;
1113 ti.fields.for_each(|k, v| {
1114 if !first {
1115 let _ = write!(f, ", ");
1116 }
1117 let _ = pr_str(k, f, readably);
1118 let _ = write!(f, " ");
1119 let _ = pr_str(v, f, readably);
1120 first = false;
1121 });
1122 write!(f, "}}")
1123 }
1124 Value::NativeObject(obj) => {
1125 write!(f, "#<{} {:?}>", obj.get().type_tag(), obj.get().inner())
1126 }
1127 Value::Resource(r) => {
1128 if r.is_closed() {
1129 write!(f, "#<{} (closed)>", r.resource_type())
1130 } else {
1131 write!(f, "#<{}>", r.resource_type())
1132 }
1133 }
1134 Value::TransientMap(_) => write!(f, "#<TransientMap>"),
1135 Value::TransientSet(_) => write!(f, "#<TransientSet>"),
1136 Value::TransientVector(_) => write!(f, "#<TransientVector>"),
1137 Value::Error(e) => {
1138 write!(f, "#error ")?;
1139 let map = e.get().to_map().map_err(|_| fmt::Error {})?;
1140 pr_str(&map, f, readably)
1141 }
1142 }
1143}
1144
1145impl Value {
1148 pub fn identical(&self, other: &Value) -> bool {
1150 macro_rules! peq {
1151 ($a:expr, $b:expr) => {
1152 GcPtr::identity_eq($a, $b)
1153 };
1154 }
1155 match (self, other) {
1156 (Value::Nil, Value::Nil) => true,
1157 (Value::Bool(a), Value::Bool(b)) => a == b,
1158 (Value::Long(a), Value::Long(b)) => a == b,
1159 (Value::Double(a), Value::Double(b)) => a.to_bits() == b.to_bits(),
1160 (Value::Char(a), Value::Char(b)) => a == b,
1161 (Value::Uuid(a), Value::Uuid(b)) => GcPtr::identity_eq(a, b),
1162 (Value::BigInt(a), Value::BigInt(b)) => GcPtr::identity_eq(a, b),
1163 (Value::BigDecimal(a), Value::BigDecimal(b)) => GcPtr::identity_eq(a, b),
1164 (Value::Ratio(a), Value::Ratio(b)) => GcPtr::identity_eq(a, b),
1165 (Value::Str(a), Value::Str(b)) => GcPtr::identity_eq(a, b),
1166 (Value::Symbol(a), Value::Symbol(b)) => GcPtr::identity_eq(a, b),
1167 (Value::Keyword(a), Value::Keyword(b)) => a.get() == b.get(),
1168 (Value::List(a), Value::List(b)) => peq!(a, b),
1169 (Value::Vector(a), Value::Vector(b)) => peq!(a, b),
1170 (Value::Map(a), Value::Map(b)) => match (a, b) {
1171 (MapValue::Array(a), MapValue::Array(b)) => peq!(a, b),
1172 (MapValue::Hash(a), MapValue::Hash(b)) => peq!(a, b),
1173 (MapValue::Sorted(a), MapValue::Sorted(b)) => peq!(a, b),
1174 _ => false,
1175 },
1176 (Value::Set(a), Value::Set(b)) => match (a, b) {
1177 (SetValue::Hash(a), SetValue::Hash(b)) => peq!(a, b),
1178 (SetValue::Sorted(a), SetValue::Sorted(b)) => peq!(a, b),
1179 _ => false,
1180 },
1181 (Value::Queue(a), Value::Queue(b)) => peq!(a, b),
1182 (Value::NativeFunction(a), Value::NativeFunction(b)) => peq!(a, b),
1183 (Value::Fn(a), Value::Fn(b)) => peq!(a, b),
1184 (Value::Macro(a), Value::Macro(b)) => peq!(a, b),
1185 (Value::Var(a), Value::Var(b)) => peq!(a, b),
1186 (Value::Atom(a), Value::Atom(b)) => peq!(a, b),
1187 (Value::Namespace(a), Value::Namespace(b)) => peq!(a, b),
1188 (Value::LazySeq(a), Value::LazySeq(b)) => peq!(a, b),
1189 (Value::Cons(a), Value::Cons(b)) => peq!(a, b),
1190 (Value::Protocol(a), Value::Protocol(b)) => peq!(a, b),
1191 (Value::ProtocolFn(a), Value::ProtocolFn(b)) => peq!(a, b),
1192 (Value::MultiFn(a), Value::MultiFn(b)) => peq!(a, b),
1193 (Value::Volatile(a), Value::Volatile(b)) => peq!(a, b),
1194 (Value::Delay(a), Value::Delay(b)) => peq!(a, b),
1195 (Value::Promise(a), Value::Promise(b)) => peq!(a, b),
1196 (Value::Future(a), Value::Future(b)) => peq!(a, b),
1197 (Value::Agent(a), Value::Agent(b)) => peq!(a, b),
1198 (Value::TypeInstance(a), Value::TypeInstance(b)) => peq!(a, b),
1199 (Value::NativeObject(a), Value::NativeObject(b)) => peq!(a, b),
1200 (Value::BoundFn(a), Value::BoundFn(b)) => peq!(a, b),
1201 (Value::ObjectArray(a), Value::ObjectArray(b)) => peq!(a, b),
1202 (Value::IntArray(a), Value::IntArray(b)) => peq!(a, b),
1203 (Value::LongArray(a), Value::LongArray(b)) => peq!(a, b),
1204 (Value::ShortArray(a), Value::ShortArray(b)) => peq!(a, b),
1205 (Value::ByteArray(a), Value::ByteArray(b)) => peq!(a, b),
1206 (Value::FloatArray(a), Value::FloatArray(b)) => peq!(a, b),
1207 (Value::DoubleArray(a), Value::DoubleArray(b)) => peq!(a, b),
1208 (Value::BooleanArray(a), Value::BooleanArray(b)) => peq!(a, b),
1209 (Value::CharArray(a), Value::CharArray(b)) => peq!(a, b),
1210 (Value::TransientMap(a), Value::TransientMap(b)) => peq!(a, b),
1211 (Value::TransientSet(a), Value::TransientSet(b)) => peq!(a, b),
1212 (Value::TransientVector(a), Value::TransientVector(b)) => peq!(a, b),
1213 (Value::Error(a), Value::Error(b)) => peq!(a, b),
1214 (Value::Pattern(a), Value::Pattern(b)) => peq!(a, b),
1215 (Value::Matcher(a), Value::Matcher(b)) => peq!(a, b),
1216 (Value::SharedAtom(a), Value::SharedAtom(b)) => Arc::ptr_eq(a, b),
1217 (Value::ByteBlob(a), Value::ByteBlob(b)) => Arc::ptr_eq(a, b),
1218 (Value::Resource(a), Value::Resource(b)) => Arc::ptr_eq(&a.0, &b.0),
1219 (Value::Reduced(a), Value::Reduced(b)) => Arc::ptr_eq(a, b),
1220 (Value::WithMeta(a, am), Value::WithMeta(b, bm)) => {
1221 Arc::ptr_eq(a, b) && Arc::ptr_eq(am, bm)
1222 }
1223 _ => false,
1224 }
1225 }
1226
1227 pub fn from_kwargs_rest(mut entries: Vec<Value>) -> Result<Value, ValueError> {
1247 if entries.len() < 2 {
1248 return Ok(entries.pop().unwrap_or(Value::Nil));
1249 }
1250
1251 let trailing = match entries.last().map(Value::unwrap_meta) {
1255 Some(Value::Map(_)) if !entries.len().is_multiple_of(2) => entries.pop(),
1256 _ => None,
1257 };
1258
1259 if !entries.len().is_multiple_of(2) {
1260 let key = entries.last().expect("odd length implies a last entry");
1261 return Err(ValueError::Other(format!(
1262 "No value supplied for key: {}",
1263 PrintValue(key)
1264 )));
1265 }
1266
1267 let mut result = MapValue::from_flat_entries(entries);
1268 if let Some(Value::Map(map)) = trailing.as_ref().map(Value::unwrap_meta) {
1269 for (key, value) in map.iter() {
1270 result = result.assoc(key.clone(), value.clone());
1271 }
1272 }
1273 Ok(Value::Map(result))
1274 }
1275}
1276
1277impl Value {
1280 pub fn unwrap_meta(&self) -> &Value {
1282 match self {
1283 Value::WithMeta(inner, _) => inner.unwrap_meta(),
1284 other => other,
1285 }
1286 }
1287
1288 pub fn get_meta(&self) -> Option<&Value> {
1290 match self {
1291 Value::WithMeta(_, meta) => Some(meta),
1292 _ => None,
1293 }
1294 }
1295
1296 pub fn with_meta(self, meta: Value) -> Value {
1298 match self {
1299 Value::WithMeta(inner, _) => Value::WithMeta(inner, Arc::new(meta)),
1300 other => Value::WithMeta(Arc::new(other), Arc::new(meta)),
1301 }
1302 }
1303}
1304
1305impl Value {
1308 pub fn type_name(&self) -> &'static str {
1310 match self {
1311 Value::WithMeta(inner, _) => inner.type_name(),
1312 Value::Reduced(_) => "reduced",
1313 Value::Nil => "nil",
1314 Value::Bool(_) => "boolean",
1315 Value::Long(_) => "long",
1316 Value::Double(_) => "double",
1317 Value::BigInt(_) => "bigint",
1318 Value::BigDecimal(_) => "bigdecimal",
1319 Value::Ratio(_) => "ratio",
1320 Value::Char(_) => "char",
1321 Value::Str(_) => "string",
1322 Value::Pattern(_) => "pattern",
1323 Value::Matcher(_) => "matcher",
1324 Value::Symbol(_) => "symbol",
1325 Value::Keyword(_) => "keyword",
1326 Value::Uuid(_) => "uuid",
1327 Value::List(_) => "list",
1328 Value::Vector(_) => "vector",
1329 Value::Map(_) => "map",
1330 Value::Set(_) => "set",
1331 Value::Queue(_) => "queue",
1332 Value::NativeFunction(_)
1333 | Value::Fn(_)
1334 | Value::BoundFn(_)
1335 | Value::Macro(_)
1336 | Value::ProtocolFn(_)
1337 | Value::MultiFn(_) => "fn",
1338 Value::Var(_) => "var",
1339 Value::Atom(_) => "atom",
1340 Value::SharedAtom(_) => "shared-atom",
1341 Value::ByteBlob(_) => "byte-blob",
1342 Value::Namespace(_) => "namespace",
1343 Value::LazySeq(_) => "lazyseq",
1344 Value::Cons(_) => "cons",
1345 Value::Protocol(_) => "protocol",
1346 Value::Volatile(_) => "volatile",
1347 Value::Delay(_) => "delay",
1348 Value::Promise(_) => "promise",
1349 Value::Future(_) => "future",
1350 Value::Agent(_) => "agent",
1351 Value::TypeInstance(_) => "record",
1352 Value::NativeObject(_) => "native-object",
1353 Value::BooleanArray(_) => "boolean-array",
1354 Value::ByteArray(_) => "byte-array",
1355 Value::ShortArray(_) => "short-array",
1356 Value::IntArray(_) => "int-array",
1357 Value::LongArray(_) => "long-array",
1358 Value::FloatArray(_) => "float-array",
1359 Value::DoubleArray(_) => "double-array",
1360 Value::CharArray(_) => "char-array",
1361 Value::ObjectArray(_) => "object-array",
1362 Value::Resource(r) => r.resource_type(),
1363 Value::TransientMap(_) => "transient-map",
1364 Value::TransientSet(_) => "transient-set",
1365 Value::TransientVector(_) => "transient-vector",
1366 Value::Error(_) => "error",
1367 }
1368 }
1369
1370 pub fn string(s: impl Into<String>) -> Self {
1372 Value::Str(GcPtr::new(s.into()))
1373 }
1374
1375 pub fn uuid(value: u128) -> Self {
1377 Value::Uuid(GcPtr::new(UuidValue(value)))
1378 }
1379
1380 pub fn map_entry(key: Value, val: Value) -> Self {
1382 Value::Vector(GcPtr::new(PersistentVector::map_entry(key, val)))
1383 }
1384
1385 pub fn is_map_entry(&self) -> bool {
1388 matches!(self.unwrap_meta(), Value::Vector(v) if v.get().is_map_entry())
1389 }
1390
1391 pub fn symbol(s: Symbol) -> Self {
1393 Value::Symbol(GcPtr::new(s))
1394 }
1395
1396 pub fn keyword(k: Keyword) -> Self {
1398 Value::Keyword(GcPtr::new(k))
1399 }
1400
1401 pub fn is_sequential(&self) -> bool {
1403 matches!(
1404 self,
1405 Value::List(_) | Value::Vector(_) | Value::LazySeq(_) | Value::Cons(_)
1406 )
1407 }
1408
1409 pub fn is_coll(&self) -> bool {
1411 self.unwrap_meta().is_coll_inner()
1412 }
1413
1414 fn is_coll_inner(&self) -> bool {
1415 matches!(
1416 self,
1417 Value::List(_)
1418 | Value::Vector(_)
1419 | Value::Map(_)
1420 | Value::Set(_)
1421 | Value::Queue(_)
1422 | Value::LazySeq(_)
1423 | Value::Cons(_)
1424 )
1425 }
1426}
1427
1428impl cljrs_gc::Trace for Value {
1429 #[cfg(feature = "no-gc")]
1430 fn immutable_children(&self) -> bool {
1431 true
1432 }
1433 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1434 use cljrs_gc::GcVisitor as _;
1435 match self {
1436 Value::Reduced(inner) => inner.trace(visitor),
1437 Value::WithMeta(inner, meta) => {
1438 inner.trace(visitor);
1439 meta.trace(visitor);
1440 }
1441 Value::Nil | Value::Bool(_) | Value::Long(_) | Value::Double(_) | Value::Char(_) => {}
1442 Value::Uuid(p) => visitor.visit(p),
1443 Value::BigInt(p) => visitor.visit(p),
1444 Value::BigDecimal(p) => visitor.visit(p),
1445 Value::Ratio(p) => visitor.visit(p),
1446 Value::Str(p) => visitor.visit(p),
1447 Value::Pattern(p) => visitor.visit(p),
1448 Value::Matcher(m) => visitor.visit(m),
1449 Value::Symbol(p) => visitor.visit(p),
1450 Value::Keyword(p) => visitor.visit(p),
1451 Value::List(p) => visitor.visit(p),
1452 Value::Vector(p) => visitor.visit(p),
1453 Value::Map(m) => m.trace(visitor),
1454 Value::Set(s) => s.trace(visitor),
1455 Value::Queue(p) => visitor.visit(p),
1456 Value::NativeFunction(p) => visitor.visit(p),
1457 Value::BoundFn(p) => visitor.visit(p),
1458 Value::Fn(p) | Value::Macro(p) => visitor.visit(p),
1459 Value::Var(p) => visitor.visit(p),
1460 Value::Atom(p) => visitor.visit(p),
1461 Value::Namespace(p) => visitor.visit(p),
1462 Value::LazySeq(p) => visitor.visit(p),
1463 Value::Cons(p) => visitor.visit(p),
1464 Value::Protocol(p) => visitor.visit(p),
1465 Value::ProtocolFn(p) => visitor.visit(p),
1466 Value::MultiFn(p) => visitor.visit(p),
1467 Value::Volatile(p) => visitor.visit(p),
1468 Value::Delay(p) => visitor.visit(p),
1469 Value::Promise(p) => visitor.visit(p),
1470 Value::Future(p) => visitor.visit(p),
1471 Value::Agent(p) => visitor.visit(p),
1472 Value::TypeInstance(p) => visitor.visit(p),
1473 Value::ObjectArray(p) => visitor.visit(p),
1474 Value::BooleanArray(p) => visitor.visit(p),
1477 Value::ByteArray(p) => visitor.visit(p),
1478 Value::ShortArray(p) => visitor.visit(p),
1479 Value::IntArray(p) => visitor.visit(p),
1480 Value::LongArray(p) => visitor.visit(p),
1481 Value::FloatArray(p) => visitor.visit(p),
1482 Value::DoubleArray(p) => visitor.visit(p),
1483 Value::CharArray(p) => visitor.visit(p),
1484 Value::NativeObject(p) => visitor.visit(p),
1485 Value::Resource(_) | Value::SharedAtom(_) | Value::ByteBlob(_) => {}
1488 Value::TransientMap(m) => visitor.visit(m),
1489 Value::TransientVector(p) => visitor.visit(p),
1490 Value::TransientSet(m) => visitor.visit(m),
1491 Value::Error(e) => visitor.visit(e),
1492 }
1493 }
1494}
1495
1496impl cljrs_gc::Trace for MapValue {
1497 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1498 use cljrs_gc::GcVisitor as _;
1499 match self {
1500 MapValue::Array(p) => visitor.visit(p),
1501 MapValue::Hash(p) => visitor.visit(p),
1502 MapValue::Sorted(p) => visitor.visit(p),
1503 }
1504 }
1505}
1506
1507#[derive(Clone, Debug)]
1512pub struct TypeInstance {
1513 pub type_tag: Arc<str>,
1514 pub fields: MapValue,
1515 pub mutable: Option<GcPtr<crate::types::Atom>>,
1521}
1522
1523impl cljrs_gc::Trace for TypeInstance {
1524 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
1525 use cljrs_gc::GcVisitor as _;
1526 self.fields.trace(visitor);
1527 if let Some(m) = &self.mutable {
1528 visitor.visit(m);
1529 }
1530 }
1531}
1532
1533#[allow(clippy::items_after_test_module)]
1534#[cfg(test)]
1535mod tests {
1536 use super::*;
1537
1538 fn kw(s: &str) -> Value {
1539 Value::keyword(Keyword::simple(s))
1540 }
1541 #[allow(dead_code)]
1542 fn sym(s: &str) -> Value {
1543 Value::symbol(Symbol::simple(s))
1544 }
1545 fn int(n: i64) -> Value {
1546 Value::Long(n)
1547 }
1548 fn s(v: &str) -> Value {
1549 Value::string(v)
1550 }
1551
1552 #[test]
1555 fn test_nil_eq() {
1556 assert_eq!(Value::Nil, Value::Nil);
1557 assert_ne!(Value::Nil, int(0));
1558 }
1559
1560 #[test]
1561 fn test_numeric_cross_type() {
1562 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1563 assert_eq!(int(1), big1.clone());
1564 assert_eq!(big1, int(1));
1565 assert_eq!(Value::Double(1.0), int(1));
1567 assert_eq!(int(1), Value::Double(1.0));
1568 assert_ne!(Value::Double(1.5), int(1));
1570 }
1571
1572 #[test]
1573 fn test_nan_not_equal_to_itself() {
1574 let nan = Value::Double(f64::NAN);
1575 assert_ne!(nan, nan.clone());
1576 }
1577
1578 #[test]
1579 fn test_string_equality() {
1580 assert_eq!(s("hello"), s("hello"));
1581 assert_ne!(s("hello"), s("world"));
1582 }
1583
1584 #[test]
1585 fn test_list_vector_seq_equality() {
1586 let list = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1587 let vec = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1588 assert_eq!(list, vec);
1590 }
1591
1592 #[test]
1593 fn test_map_equality_order_independent() {
1594 let mut a = MapValue::empty();
1595 a = a.assoc(kw("a"), int(1));
1596 a = a.assoc(kw("b"), int(2));
1597
1598 let mut b = MapValue::empty();
1599 b = b.assoc(kw("b"), int(2));
1600 b = b.assoc(kw("a"), int(1));
1601
1602 assert_eq!(Value::Map(a), Value::Map(b));
1603 }
1604
1605 #[test]
1608 fn test_hash_consistency() {
1609 let big1 = Value::BigInt(GcPtr::new(BigInt::from(1i64)));
1610 assert_eq!(int(1).clojure_hash(), big1.clojure_hash());
1611 }
1612
1613 #[test]
1614 fn test_hash_whole_double() {
1615 assert_eq!(int(1).clojure_hash(), Value::Double(1.0).clojure_hash());
1617 }
1618
1619 #[test]
1622 fn test_pr_str_nil() {
1623 assert_eq!(Value::Nil.to_string(), "nil");
1624 }
1625
1626 #[test]
1627 fn test_pr_str_string() {
1628 assert_eq!(s("hello").to_string(), "\"hello\"");
1629 assert_eq!(s("a\"b").to_string(), "\"a\\\"b\"");
1630 }
1631
1632 #[test]
1633 fn test_pr_str_char() {
1634 assert_eq!(Value::Char('a').to_string(), "\\a");
1635 assert_eq!(Value::Char('\n').to_string(), "\\newline");
1636 }
1637
1638 #[test]
1639 fn test_pr_str_list() {
1640 let l = Value::List(GcPtr::new(PersistentList::from_iter([int(1), int(2)])));
1641 assert_eq!(l.to_string(), "(1 2)");
1642 }
1643
1644 #[test]
1645 fn test_pr_str_vector() {
1646 let v = Value::Vector(GcPtr::new(PersistentVector::from_iter([int(1), int(2)])));
1647 assert_eq!(v.to_string(), "[1 2]");
1648 }
1649
1650 #[test]
1651 #[allow(clippy::approx_constant)]
1652 fn test_pr_str_double() {
1653 assert_eq!(Value::Double(1.0).to_string(), "1.0");
1654 assert_eq!(Value::Double(3.14).to_string(), "3.14");
1655 assert_eq!(Value::Double(f64::INFINITY).to_string(), "##Inf");
1656 assert_eq!(Value::Double(f64::NEG_INFINITY).to_string(), "##-Inf");
1657 assert_eq!(Value::Double(f64::NAN).to_string(), "##NaN");
1658 }
1659
1660 fn kwargs(entries: Vec<Value>) -> Value {
1663 Value::from_kwargs_rest(entries).expect("well-formed kwargs")
1664 }
1665
1666 fn map_of(entries: Vec<Value>) -> Value {
1667 Value::Map(MapValue::from_flat_entries(entries))
1668 }
1669
1670 #[test]
1671 fn kwargs_rest_empty_and_lone_values_pass_through() {
1672 assert_eq!(kwargs(vec![]), Value::Nil);
1675 assert_eq!(kwargs(vec![Value::Nil]), Value::Nil);
1676 assert_eq!(kwargs(vec![kw("a")]), kw("a"));
1680 let sorted = Value::Map(MapValue::Sorted(GcPtr::new(SortedMap::from_pairs(vec![
1681 (kw("b"), int(1)),
1682 (kw("a"), int(2)),
1683 ]))));
1684 assert!(matches!(
1685 kwargs(vec![sorted.clone()]),
1686 Value::Map(MapValue::Sorted(_))
1687 ));
1688 let with_meta = map_of(vec![kw("a"), int(1)]).with_meta(map_of(vec![kw("t"), int(1)]));
1689 assert_eq!(kwargs(vec![with_meta.clone()]), with_meta);
1690 }
1691
1692 #[test]
1693 fn kwargs_rest_pairs_build_a_map() {
1694 assert_eq!(
1695 kwargs(vec![kw("a"), int(1), kw("b"), int(2)]),
1696 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1697 );
1698 assert_eq!(
1700 kwargs(vec![kw("a"), int(1), kw("a"), int(2)]),
1701 map_of(vec![kw("a"), int(2)])
1702 );
1703 }
1704
1705 #[test]
1706 fn kwargs_rest_trailing_map_merges_and_wins() {
1707 assert_eq!(
1709 kwargs(vec![kw("a"), int(1), map_of(vec![kw("b"), int(2)])]),
1710 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1711 );
1712 assert_eq!(
1714 kwargs(vec![kw("a"), int(1), map_of(vec![kw("a"), int(9)])]),
1715 map_of(vec![kw("a"), int(9)])
1716 );
1717 let meta_map = map_of(vec![kw("b"), int(2)]).with_meta(map_of(vec![kw("t"), int(1)]));
1720 assert_eq!(
1721 kwargs(vec![kw("a"), int(1), meta_map]),
1722 map_of(vec![kw("a"), int(1), kw("b"), int(2)])
1723 );
1724 }
1725
1726 #[test]
1727 fn kwargs_rest_map_in_value_position_is_not_a_trailing_map() {
1728 let inner = map_of(vec![kw("x"), int(1)]);
1730 assert_eq!(
1731 kwargs(vec![kw("a"), inner.clone()]),
1732 map_of(vec![kw("a"), inner])
1733 );
1734 }
1735
1736 #[test]
1737 fn kwargs_rest_dangling_key_is_an_error() {
1738 let err = Value::from_kwargs_rest(vec![kw("a"), int(1), kw("b")])
1741 .expect_err("odd arity with no trailing map");
1742 assert_eq!(err.to_string(), "No value supplied for key: :b");
1743 }
1744}
1745
1746impl PartialOrd for Value {
1749 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1750 Some(self.cmp(other))
1751 }
1752}
1753
1754impl Ord for Value {
1755 fn cmp(&self, other: &Self) -> Ordering {
1756 crate::realization::check_stack();
1757 let a = self.unwrap_meta();
1759 let b = other.unwrap_meta();
1760 if !std::ptr::eq(a, self) || !std::ptr::eq(b, other) {
1761 return a.cmp(b);
1762 }
1763 match (self, other) {
1765 (Value::Nil, Value::Nil) => Ordering::Equal,
1767
1768 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
1770
1771 (Value::Long(a), Value::Long(b)) => a.cmp(b),
1773 (Value::Double(a), Value::Double(b)) => total_cmp_f64(*a, *b),
1774 (Value::BigInt(a), Value::BigInt(b)) => a.get().cmp(b.get()),
1775 (Value::BigDecimal(a), Value::BigDecimal(b)) => {
1776 a.get()
1778 .partial_cmp(b.get())
1779 .unwrap_or_else(|| a.get().to_string().cmp(&b.get().to_string()))
1780 }
1781 (Value::Ratio(a), Value::Ratio(b)) => a.get().cmp(b.get()),
1782
1783 (Value::Long(a), Value::Double(b)) => total_cmp_f64(*a as f64, *b),
1785 (Value::Double(a), Value::Long(b)) => total_cmp_f64(*a, *b as f64),
1786 (Value::Long(a), Value::BigInt(b)) => BigInt::from(*a).cmp(b.get()),
1787 (Value::BigInt(a), Value::Long(b)) => a.get().cmp(&BigInt::from(*b)),
1788 (Value::Long(a), Value::Ratio(b)) => {
1789 num_rational::Ratio::from(BigInt::from(*a)).cmp(b.get())
1790 }
1791 (Value::Ratio(a), Value::Long(b)) => {
1792 a.get().cmp(&num_rational::Ratio::from(BigInt::from(*b)))
1793 }
1794 (Value::BigInt(a), Value::Ratio(b)) => {
1795 num_rational::Ratio::from(a.get().clone()).cmp(b.get())
1796 }
1797 (Value::Ratio(a), Value::BigInt(b)) => {
1798 a.get().cmp(&num_rational::Ratio::from(b.get().clone()))
1799 }
1800 (Value::Double(a), Value::BigInt(b)) => {
1801 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1802 }
1803 (Value::BigInt(a), Value::Double(b)) => {
1804 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1805 }
1806 (Value::Double(a), Value::Ratio(b)) => {
1807 total_cmp_f64(*a, b.get().to_f64().unwrap_or(f64::MAX))
1808 }
1809 (Value::Ratio(a), Value::Double(b)) => {
1810 total_cmp_f64(a.get().to_f64().unwrap_or(f64::MAX), *b)
1811 }
1812 (Value::Long(a), Value::BigDecimal(b)) => {
1813 let ad = bigdecimal::BigDecimal::from(*a);
1814 ad.partial_cmp(b.get())
1815 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1816 }
1817 (Value::BigDecimal(a), Value::Long(b)) => {
1818 let bd = bigdecimal::BigDecimal::from(*b);
1819 a.get()
1820 .partial_cmp(&bd)
1821 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1822 }
1823 (Value::Double(a), Value::BigDecimal(b)) => {
1824 match bigdecimal::BigDecimal::try_from(*a) {
1825 Ok(ad) => ad
1826 .partial_cmp(b.get())
1827 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1828 Err(_) => {
1829 if a.is_nan() {
1831 Ordering::Greater
1832 } else if *a < 0.0 {
1833 Ordering::Less
1834 } else {
1835 Ordering::Greater
1836 }
1837 }
1838 }
1839 }
1840 (Value::BigDecimal(a), Value::Double(b)) => {
1841 match bigdecimal::BigDecimal::try_from(*b) {
1842 Ok(bd) => a
1843 .get()
1844 .partial_cmp(&bd)
1845 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1846 Err(_) => {
1847 if b.is_nan() {
1848 Ordering::Less
1849 } else if *b < 0.0 {
1850 Ordering::Greater
1851 } else {
1852 Ordering::Less
1853 }
1854 }
1855 }
1856 }
1857 (Value::BigInt(a), Value::BigDecimal(b)) => {
1858 let ad = bigdecimal::BigDecimal::from(a.get().clone());
1859 ad.partial_cmp(b.get())
1860 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string()))
1861 }
1862 (Value::BigDecimal(a), Value::BigInt(b)) => {
1863 let bd = bigdecimal::BigDecimal::from(b.get().clone());
1864 a.get()
1865 .partial_cmp(&bd)
1866 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string()))
1867 }
1868 (Value::Ratio(a), Value::BigDecimal(b)) => {
1869 let af = a.get().to_f64().unwrap_or(f64::MAX);
1870 match bigdecimal::BigDecimal::try_from(af) {
1871 Ok(ad) => ad
1872 .partial_cmp(b.get())
1873 .unwrap_or_else(|| ad.to_string().cmp(&b.get().to_string())),
1874 Err(_) => Ordering::Greater,
1875 }
1876 }
1877 (Value::BigDecimal(a), Value::Ratio(b)) => {
1878 let bf = b.get().to_f64().unwrap_or(f64::MAX);
1879 match bigdecimal::BigDecimal::try_from(bf) {
1880 Ok(bd) => a
1881 .get()
1882 .partial_cmp(&bd)
1883 .unwrap_or_else(|| a.get().to_string().cmp(&bd.to_string())),
1884 Err(_) => Ordering::Less,
1885 }
1886 }
1887
1888 (Value::Char(a), Value::Char(b)) => a.cmp(b),
1890
1891 (Value::Str(a), Value::Str(b)) => a.get().cmp(b.get()),
1893
1894 (Value::Symbol(a), Value::Symbol(b)) => cmp_ns_name(
1896 &a.get().namespace,
1897 &a.get().name,
1898 &b.get().namespace,
1899 &b.get().name,
1900 ),
1901
1902 (Value::Keyword(a), Value::Keyword(b)) => cmp_ns_name(
1904 &a.get().namespace,
1905 &a.get().name,
1906 &b.get().namespace,
1907 &b.get().name,
1908 ),
1909
1910 (Value::Vector(a), Value::Vector(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1912 (Value::List(a), Value::List(b)) => iter_cmp(a.get().iter(), b.get().iter()),
1913
1914 (Value::Set(a), Value::Set(b)) => a.count().cmp(&b.count()),
1916
1917 (Value::Map(a), Value::Map(b)) => a.count().cmp(&b.count()),
1919
1920 _ => type_discriminant(self).cmp(&type_discriminant(other)),
1922 }
1923 }
1924}
1925
1926fn iter_cmp<'a>(
1928 mut a: impl Iterator<Item = &'a Value>,
1929 mut b: impl Iterator<Item = &'a Value>,
1930) -> Ordering {
1931 loop {
1932 match (a.next(), b.next()) {
1933 (None, None) => return Ordering::Equal,
1934 (None, Some(_)) => return Ordering::Less,
1935 (Some(_), None) => return Ordering::Greater,
1936 (Some(x), Some(y)) => {
1937 let c = x.cmp(y);
1938 if c != Ordering::Equal {
1939 return c;
1940 }
1941 }
1942 }
1943 }
1944}
1945
1946fn total_cmp_f64(a: f64, b: f64) -> Ordering {
1948 a.total_cmp(&b)
1949}
1950
1951fn cmp_ns_name(
1953 ns_a: &Option<Arc<str>>,
1954 name_a: &Arc<str>,
1955 ns_b: &Option<Arc<str>>,
1956 name_b: &Arc<str>,
1957) -> Ordering {
1958 match (ns_a, ns_b) {
1959 (None, None) => name_a.cmp(name_b),
1960 (None, Some(_)) => Ordering::Less,
1961 (Some(_), None) => Ordering::Greater,
1962 (Some(a), Some(b)) => a.cmp(b).then_with(|| name_a.cmp(name_b)),
1963 }
1964}
1965
1966fn type_discriminant(v: &Value) -> u8 {
1968 match v {
1969 Value::WithMeta(inner, _) => type_discriminant(inner),
1970 Value::Reduced(inner) => type_discriminant(inner),
1971 Value::Nil => 0,
1972 Value::Bool(_) => 1,
1973 Value::Long(_)
1974 | Value::Double(_)
1975 | Value::BigInt(_)
1976 | Value::BigDecimal(_)
1977 | Value::Ratio(_) => 2,
1978 Value::Char(_) => 3,
1979 Value::Str(_) => 4,
1980 Value::Symbol(_) => 5,
1981 Value::Keyword(_) => 6,
1982 Value::List(_) => 7,
1983 Value::Vector(_) => 8,
1984 Value::Map(_) => 9,
1985 Value::Set(_) => 10,
1986 Value::Queue(_) => 11,
1987 Value::LazySeq(_) => 12,
1988 Value::Cons(_) => 13,
1989 Value::NativeFunction(_) => 14,
1990 Value::BoundFn(_) => 14,
1991 Value::Fn(_) => 15,
1992 Value::Macro(_) => 16,
1993 Value::Var(_) => 17,
1994 Value::Atom(_) => 18,
1995 Value::SharedAtom(_) => 46,
1996 Value::ByteBlob(_) => 47,
1997 Value::Namespace(_) => 19,
1998 Value::Protocol(_) => 20,
1999 Value::ProtocolFn(_) => 21,
2000 Value::MultiFn(_) => 22,
2001 Value::Volatile(_) => 23,
2002 Value::Delay(_) => 24,
2003 Value::Promise(_) => 25,
2004 Value::Future(_) => 26,
2005 Value::Agent(_) => 27,
2006 Value::TypeInstance(_) => 28,
2007 Value::BooleanArray(_) => 29,
2008 Value::ByteArray(_) => 30,
2009 Value::ShortArray(_) => 31,
2010 Value::IntArray(_) => 32,
2011 Value::LongArray(_) => 33,
2012 Value::CharArray(_) => 34,
2013 Value::FloatArray(_) => 35,
2014 Value::DoubleArray(_) => 36,
2015 Value::ObjectArray(_) => 37,
2016 Value::Uuid(_) => 38,
2017 Value::NativeObject(_) => 43,
2018 Value::Resource(_) => 39,
2019 Value::TransientMap(_) => 40,
2020 Value::TransientSet(_) => 41,
2021 Value::TransientVector(_) => 42,
2022 Value::Pattern(_) => 43,
2023 Value::Matcher(_) => 44,
2024 Value::Error(_) => 45,
2025 }
2026}