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