1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct ExceptionSite {
3 pub namespace: Option<String>,
4 pub resource: Option<String>,
5 pub line: usize,
6 pub column: usize,
7}
8
9#[derive(Debug, Clone, Default)]
10pub struct ExceptionProvenance {
11 pub created_at: Option<ExceptionSite>,
12 pub throws: Vec<ExceptionSite>,
13}
14
15#[derive(Debug, Clone)]
16pub struct ExceptionInfo {
17 pub message: String,
18 pub data: Box<Value>,
19 pub cause: Option<Box<Value>>,
20 pub provenance: Rc<RefCell<ExceptionProvenance>>,
21}
22
23fn default_exception_class(code: &Keyword) -> Option<Keyword> {
24 if code.get_namespace() != Some("hara") {
25 return None;
26 }
27 let class = match code.get_name() {
28 "security" | "timeout" | "not-found" | "conflict" | "limit" | "syntax" | "io"
29 | "database" | "dependency" | "serialization" | "argument" | "state" | "host" => {
30 code.get_name()
31 }
32 "generic" => "internal",
33 _ => return None,
34 };
35 Keyword::parse(&format!("ex.class/{class}")).ok()
36}
37
38fn normalize_exception_code(code: &Keyword) -> Result<Keyword, String> {
39 if code.get_namespace().is_some() {
40 return Ok(code.clone());
41 }
42 let canonical = Keyword::parse(&format!("hara/{}", code.get_name()))?;
43 if default_exception_class(&canonical).is_some() {
44 Ok(canonical)
45 } else {
46 Err("ex expects a registered standard keyword or namespaced keyword code".into())
47 }
48}
49
50pub(crate) fn record_exception_throw(value: &Value, site: Option<ExceptionSite>) {
51 let (Value::ExceptionInfo(exception), Some(site)) = (value, site) else {
52 return;
53 };
54 let mut provenance = exception.provenance.borrow_mut();
55 provenance.throws.push(site);
56}
57
58pub(crate) fn record_exception_creation(value: &Value, site: Option<ExceptionSite>) {
59 let (Value::ExceptionInfo(exception), Some(site)) = (value, site) else {
60 return;
61 };
62 let mut provenance = exception.provenance.borrow_mut();
63 if provenance.created_at.is_none() {
64 provenance.created_at = Some(site);
65 }
66}
67
68pub(crate) fn exception_site_value(site: &ExceptionSite) -> Value {
69 Value::Map(
70 [
71 (
72 "namespace",
73 site.namespace
74 .clone()
75 .map(Value::String)
76 .unwrap_or(Value::Nil),
77 ),
78 (
79 "resource",
80 site.resource
81 .clone()
82 .map(Value::String)
83 .unwrap_or(Value::Nil),
84 ),
85 ("line", Value::Number(site.line as i64)),
86 ("column", Value::Number(site.column as i64)),
87 ]
88 .into_iter()
89 .map(|(key, value)| (Value::Keyword(key.into()), value))
90 .collect(),
91 )
92}
93
94pub(crate) fn exception_provenance_value(exception: &ExceptionInfo) -> Value {
95 let provenance = exception.provenance.borrow();
96 Value::Map(
97 [
98 (
99 Value::Keyword("ex/created-at".into()),
100 provenance
101 .created_at
102 .as_ref()
103 .map(exception_site_value)
104 .unwrap_or(Value::Nil),
105 ),
106 (
107 Value::Keyword("ex/throws".into()),
108 Value::Vector(provenance.throws.iter().map(exception_site_value).collect()),
109 ),
110 ]
111 .into_iter()
112 .collect(),
113 )
114}
115
116#[derive(Debug, Clone)]
117pub enum Value {
118 Number(i64),
119 Float(f64),
120 BigInteger(BigInt),
121 Character(char),
122 Regex(String),
123 Tagged(Box<PTaggedLiteral<Value>>),
124 Bool(bool),
125 String(String),
126 Keyword(Keyword),
127 Bytes(Vec<u8>),
128 ByteBuffer(Rc<RefCell<Vec<u8>>>),
129 Array(Rc<RefCell<Vec<Value>>>),
130 Object(Rc<RefCell<Vec<(String, Value)>>>),
131 Promise(Promise),
132 Atom(Box<RuntimeAtom>),
133 Recur(Vec<Value>),
134 Map(PMap<Value, Value>),
135 OrderedMap(Box<POrderedMap<Value, Value>>),
136 SortedMap(Box<PSortedMap<Value, Value>>),
137 Trie(Box<PTrie<Value>>),
138 Set(PSet<Value>),
139 OrderedSet(Box<POrderedSet<Value>>),
140 SortedSet(Box<PSortedSet<Value>>),
141 List(PList<Value>),
142 Cons(Box<PCons<Value>>),
143 Deque(Box<PDeque<Value>>),
144 Queue(Box<PQueue<Value>>),
145 PriorityMap(Box<PPriorityMap<Value, Value>>),
146 Symbol(Symbol),
147 Pointer(PPointer),
148 Function(Rc<Function>),
149 Tuple(Box<PTuple<Value>>),
150 Vector(PVector<Value>),
151 MapEntry(Box<PMapEntry>),
152 MutableCollection(Rc<RefCell<Option<MutableCollection>>>),
153 Seq(Box<PSeq<Result<Value, String>>>),
154 Iterator(Rc<RefCell<IteratorState>>),
155 Var(KernelVar<Value>),
156 Namespace(Rc<crate::kernel::Namespace<Value>>),
157 Extension(ExtensionValue),
158 StructType(Rc<StructType>),
159 Struct(Rc<StructValue>),
160 MutableType(Rc<MutableType>),
161 Mutable(Rc<MutableValue>),
162 Protocol(Rc<GuestProtocol>),
163 NativeType(Rc<NativeType>),
164 Schema(Rc<RuntimeSchema>),
165 Coroutine(Rc<Coroutine>),
166 Stream(Rc<RuntimeStream>),
167 Result(Rc<ResultValue>),
168 ExceptionInfo(Rc<ExceptionInfo>),
169 Nil,
170}
171
172const UUID_TAG: &str = "uuid";
173
174fn uuid_value_from_uuid(value: uuid::Uuid) -> Value {
175 Value::Tagged(Box::new(PTaggedLiteral::new(
176 Symbol::parse(UUID_TAG),
177 Value::String(value.hyphenated().to_string()),
178 )))
179}
180
181fn uuid_from_bytes(bytes: &[u8]) -> uuid::Uuid {
182 let digest = md5::compute(bytes);
183 let mut value = digest.0;
184 value[6] = (value[6] & 0x0f) | 0x30;
185 value[8] = (value[8] & 0x3f) | 0x80;
186 uuid::Uuid::from_bytes(value)
187}
188
189fn uuid_from_parts(most: i64, least: i64) -> uuid::Uuid {
190 let value = ((most as u64 as u128) << 64) | least as u64 as u128;
191 uuid::Uuid::from_u128(value)
192}
193
194fn uuid_from_value(value: &Value) -> Result<uuid::Uuid, String> {
195 match value {
196 Value::String(value) => uuid::Uuid::parse_str(value)
197 .map_err(|_| "Base/uuid expects a valid UUID string".into()),
198 Value::Bytes(value) => Ok(uuid_from_bytes(value)),
199 Value::ByteBuffer(value) => Ok(uuid_from_bytes(&value.borrow())),
200 Value::Keyword(value) => Ok(uuid_from_parts(
201 crate::lang::hash::java_string_hash(value.as_str()) as i64,
202 crate::lang::hash::java_string_hash(value.get_name()) as i64,
203 )),
204 _ => Err("Base/uuid expects a string, bytes, or keyword".into()),
205 }
206}
207
208fn random_uuid() -> uuid::Uuid {
209 let mut bytes = [0u8; 16];
210 getrandom::getrandom(&mut bytes)
211 .unwrap_or_else(|_| panic!("could not retrieve random bytes for uuid"));
212 bytes[6] = (bytes[6] & 0x0f) | 0x40;
213 bytes[8] = (bytes[8] & 0x3f) | 0x80;
214 uuid::Uuid::from_bytes(bytes)
215}
216
217pub(crate) fn uuid_value(values: &[Value]) -> Result<Value, String> {
218 let value = match values {
219 [] => random_uuid(),
220 [value] => uuid_from_value(value)?,
221 [Value::Number(most), Value::Number(least)] => uuid_from_parts(*most, *least),
222 _ if values.len() == 2 => {
223 return Err("Base/uuid expects two integer arguments".into())
224 }
225 _ => return Err("Base/uuid expects zero, one, or two arguments".into()),
226 };
227 Ok(uuid_value_from_uuid(value))
228}
229
230pub(crate) fn uuid_text_from_tagged(value: &PTaggedLiteral<Value>) -> Option<&str> {
231 if value.tag().as_str() != UUID_TAG {
232 return None;
233 }
234 let Value::String(text) = value.form() else {
235 return None;
236 };
237 uuid::Uuid::parse_str(text)
238 .ok()
239 .filter(|uuid| uuid.hyphenated().to_string() == *text)
240 .map(|_| text.as_str())
241}
242
243pub(crate) fn is_uuid_tagged(value: &PTaggedLiteral<Value>) -> bool {
244 uuid_text_from_tagged(value).is_some()
245}
246
247#[derive(Debug, Clone)]
248pub enum MutableCollection {
249 Map(MutableMap<Value, Value>),
250 OrderedMap(MutableOrderedMap<Value, Value>),
251 SortedMap(MutableSortedMap<Value, Value>),
252 Trie(MutableTrie<Value>),
253 Set(MutableSet<Value>),
254 OrderedSet(MutableOrderedSet<Value>),
255 SortedSet(MutableSortedSet<Value>),
256 List(MutableList<Value>),
257 Queue(MutableQueue<Value>),
258 Vector(MutableVector<Value>),
259}
260
261fn named_field_key(field: &str) -> Value {
262 Value::Keyword(Keyword::from(field))
263}
264
265fn named_field_name(value: &Value) -> Option<&str> {
266 match value {
267 Value::String(name) => Some(name.as_str()),
268 Value::Keyword(name) if name.get_namespace().is_none() => Some(name.get_name()),
269 Value::Symbol(name) if name.get_namespace().is_none() => Some(name.get_name()),
270 _ => None,
271 }
272}
273
274impl StructValue {
275 pub(crate) fn from_values(
276 ty: Rc<StructType>,
277 values: Vec<Value>,
278 metadata: Option<Rc<Metadata>>,
279 ) -> Result<Self, String> {
280 if values.len() != ty.fields.len() {
281 return Err(format!("{} expects {} arguments", ty.name, ty.fields.len()));
282 }
283 let values = ty
284 .fields
285 .iter()
286 .zip(values)
287 .fold(POrderedMap::new(), |values, (field, value)| {
288 values.assoc_value(named_field_key(field), value)
289 });
290 Ok(Self {
291 ty,
292 values,
293 metadata,
294 })
295 }
296
297 pub(crate) fn get(&self, field: &str) -> Option<&Value> {
298 self.values.get(&named_field_key(field))
299 }
300
301 pub(crate) fn ordered_values(&self) -> Vec<&Value> {
302 self.ty
303 .fields
304 .iter()
305 .filter_map(|field| self.get(field))
306 .collect()
307 }
308
309 pub(crate) fn ordered_entries(&self) -> Vec<(Value, Value)> {
310 self.ty
311 .fields
312 .iter()
313 .filter_map(|field| {
314 self.get(field)
315 .cloned()
316 .map(|value| (named_field_key(field), value))
317 })
318 .collect()
319 }
320}
321
322impl MutableValue {
323 pub(crate) fn from_values(
324 ty: Rc<MutableType>,
325 values: Vec<Value>,
326 metadata: Option<Rc<Metadata>>,
327 ) -> Result<Self, String> {
328 if values.len() != ty.fields.len() {
329 return Err(format!("{} expects {} arguments", ty.name, ty.fields.len()));
330 }
331 Ok(Self {
332 ty,
333 values: Rc::new(RefCell::new(values)),
334 metadata,
335 })
336 }
337
338 fn field_index(&self, field: &str) -> Option<usize> {
339 self.ty
340 .fields
341 .iter()
342 .position(|candidate| candidate == field)
343 }
344
345 pub(crate) fn get(&self, field: &str) -> Option<Value> {
346 let index = self.field_index(field)?;
347 self.values.borrow().get(index).cloned()
348 }
349
350 pub(crate) fn set(&self, field: &str, replacement: Value) -> Result<Value, String> {
351 let index = self
352 .field_index(field)
353 .ok_or_else(|| format!("unknown mutable field: {field}"))?;
354 self.values.borrow_mut()[index] = replacement.clone();
355 Ok(replacement)
356 }
357
358 pub(crate) fn ordered_values(&self) -> Vec<Value> {
359 self.values.borrow().clone()
360 }
361
362 pub(crate) fn ordered_entries(&self) -> Vec<(Value, Value)> {
363 self.ty
364 .fields
365 .iter()
366 .cloned()
367 .zip(self.ordered_values())
368 .map(|(field, value)| (named_field_key(&field), value))
369 .collect()
370 }
371
372 fn same_identity(&self, other: &Self) -> bool {
373 Rc::ptr_eq(&self.values, &other.values)
374 }
375
376 fn identity_address(&self) -> usize {
377 Rc::as_ptr(&self.values) as usize
378 }
379}
380
381#[derive(Clone)]
382pub struct Function {
383 params: Vec<String>,
384 variadic: Option<String>,
385 patterns: Vec<Form>,
386 variadic_pattern: Option<Form>,
387 body: Vec<Form>,
388 captured: Rc<RefCell<HashMap<String, Value>>>,
389 pub name: Option<String>,
390 namespace: Option<String>,
393 native: Option<Rc<dyn Fn(Vec<Value>) -> Result<Value, String>>>,
394 fiber_native: Option<Rc<dyn Fn(Vec<Value>, Cont) -> Step>>,
395 clauses: Vec<Rc<Function>>,
397 metadata: Option<Rc<Metadata>>,
399 is_macro: bool,
401}
402
403impl Function {
404 pub(crate) fn accepts_arity(&self, argument_count: usize) -> bool {
405 if !self.clauses.is_empty() {
406 return self
407 .clauses
408 .iter()
409 .any(|clause| clause.accepts_arity(argument_count));
410 }
411 self.variadic.is_some() && argument_count >= self.params.len()
412 || self.variadic.is_none() && argument_count == self.params.len()
413 }
414
415 pub(crate) fn origin_symbol(&self) -> Option<Symbol> {
419 let name = self.name.as_deref()?;
420 if name.contains('/') {
421 Some(Symbol::parse(name))
422 } else {
423 Some(Symbol::create(self.namespace.as_deref(), name))
424 }
425 }
426}
427
428#[derive(Clone)]
429pub(crate) struct MultiMethod {
430 dispatch: Rc<Function>,
431 methods: Vec<(Value, Rc<Function>)>,
432 default: Option<Rc<Function>>,
433}
434
435impl std::fmt::Debug for Function {
436 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 formatter
438 .debug_struct("Function")
439 .field("params", &self.params)
440 .field("variadic", &self.variadic)
441 .field("name", &self.name)
442 .field("native", &self.native.is_some())
443 .finish()
444 }
445}
446
447pub enum CoroutineState {
449 New(Value),
451 Suspended(Box<dyn FnOnce(Value) -> Step>),
453 Running,
455 Dead,
457}
458
459impl std::fmt::Debug for CoroutineState {
460 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
461 match self {
462 Self::New(_) => formatter.debug_tuple("New").finish(),
463 Self::Suspended(_) => formatter.debug_tuple("Suspended").finish(),
464 Self::Running => formatter.write_str("Running"),
465 Self::Dead => formatter.write_str("Dead"),
466 }
467 }
468}
469
470pub struct Coroutine {
472 pub state: RefCell<CoroutineState>,
473}
474
475impl std::fmt::Debug for Coroutine {
476 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
477 formatter
478 .debug_struct("Coroutine")
479 .field("state", &self.state.borrow())
480 .finish()
481 }
482}
483
484impl Coroutine {
485 pub fn new(body: Value) -> Self {
486 Self {
487 state: RefCell::new(CoroutineState::New(body)),
488 }
489 }
490}
491
492pub struct RuntimeStream {
493 source: RuntimeStreamSource,
494 pending: Rc<Cell<bool>>,
495 closed: Rc<Cell<bool>>,
496}
497
498enum RuntimeStreamSource {
499 Coroutine {
500 coroutine: Rc<Coroutine>,
501 initial_arguments: RefCell<Option<Vec<Value>>>,
502 },
503 Guest {
504 next: Rc<Function>,
505 close: Option<Rc<Function>>,
506 },
507 Host {
508 next: Rc<dyn Fn() -> Result<Promise, String>>,
509 close: Rc<dyn Fn() -> Result<(), String>>,
510 },
511}
512
513impl std::fmt::Debug for RuntimeStream {
514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515 f.debug_struct("RuntimeStream")
516 .field("closed", &self.closed.get())
517 .finish()
518 }
519}
520
521impl RuntimeStream {
522 fn new(body: Value, initial_arguments: Vec<Value>) -> Self {
523 Self {
524 source: RuntimeStreamSource::Coroutine {
525 coroutine: Rc::new(Coroutine::new(body)),
526 initial_arguments: RefCell::new(Some(initial_arguments)),
527 },
528 pending: Rc::new(Cell::new(false)),
529 closed: Rc::new(Cell::new(false)),
530 }
531 }
532 fn host(
533 next: Rc<dyn Fn() -> Result<Promise, String>>,
534 close: Rc<dyn Fn() -> Result<(), String>>,
535 ) -> Self {
536 Self {
537 source: RuntimeStreamSource::Host { next, close },
538 pending: Rc::new(Cell::new(false)),
539 closed: Rc::new(Cell::new(false)),
540 }
541 }
542 fn guest(next: Rc<Function>, close: Option<Rc<Function>>) -> Self {
543 Self {
544 source: RuntimeStreamSource::Guest { next, close },
545 pending: Rc::new(Cell::new(false)),
546 closed: Rc::new(Cell::new(false)),
547 }
548 }
549}
550
551#[derive(Clone)]
552pub struct RuntimeAtom {
553 value: PAtom<Value>,
554 watches: Rc<RefCell<Vec<(Value, Rc<Function>)>>>,
555 watchable: bool,
556}
557
558impl RuntimeAtom {
559 pub(crate) fn new(value: Value, watchable: bool) -> Self {
560 Self {
561 value: PAtom::new(value),
562 watches: Rc::new(RefCell::new(Vec::new())),
563 watchable,
564 }
565 }
566 fn same_identity(&self, other: &Self) -> bool {
567 self.value.same_identity(&other.value)
568 }
569 fn identity_address(&self) -> usize {
570 self.value.identity_address()
571 }
572 pub(crate) fn deref_value(&self) -> Value {
573 self.value.deref_value()
574 }
575 fn reset(&self, new_value: Value) -> Result<Value, String> {
576 let old_value = self.value.deref_value();
577 let result = self.value.reset(new_value.clone())?;
578 self.notify(old_value, new_value)?;
579 Ok(result)
580 }
581 fn compare_and_set(&self, old: &Value, new_value: Value) -> Result<bool, String> {
582 let prior = self.value.deref_value();
583 let changed = self.value.compare_and_set(old, new_value.clone())?;
584 if changed {
585 self.notify(prior, new_value)?;
586 }
587 Ok(changed)
588 }
589 fn add_watch(&self, key: Value, function: Rc<Function>) -> Result<(), String> {
590 if !self.watchable {
591 return Err("watch-add expects a standard atom".into());
592 }
593 let mut watches = self.watches.borrow_mut();
594 watches.retain(|(candidate, _)| candidate != &key);
595 watches.push((key, function));
596 Ok(())
597 }
598 fn remove_watch(&self, key: &Value) -> Result<(), String> {
599 if !self.watchable {
600 return Err("watch-remove expects a standard atom".into());
601 }
602 self.watches
603 .borrow_mut()
604 .retain(|(candidate, _)| candidate != key);
605 Ok(())
606 }
607 fn watch_entries(&self) -> Result<Vec<Value>, String> {
608 if !self.watchable {
609 return Err("watch-list expects a standard atom".into());
610 }
611 self.watches
612 .borrow()
613 .iter()
614 .map(|(key, function)| {
615 vector_literal(vec![key.clone(), Value::Function(function.clone())])
616 })
617 .collect()
618 }
619 fn notify(&self, old_value: Value, new_value: Value) -> Result<(), String> {
620 let watches = self.watches.borrow().clone();
621 for (key, function) in watches {
622 call_function(
623 &function,
624 vec![
625 key,
626 Value::Atom(Box::new(self.clone())),
627 old_value.clone(),
628 new_value.clone(),
629 ],
630 )?;
631 }
632 Ok(())
633 }
634}
635
636impl std::fmt::Debug for RuntimeAtom {
637 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
638 formatter
639 .debug_struct("RuntimeAtom")
640 .finish_non_exhaustive()
641 }
642}
643
644fn function_definition_namespace() -> Option<String> {
645 namespace_registry()
646 .ok()
647 .map(|registry| registry.current().name().as_str().to_owned())
648}
649
650pub fn native_function(
652 name: &str,
653 arity: usize,
654 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
655) -> Value {
656 let function = Rc::new(Function {
657 params: (0..arity).map(|index| format!("arg{index}")).collect(),
658 variadic: None,
659 patterns: Vec::new(),
660 variadic_pattern: None,
661 body: Vec::new(),
662 captured: Rc::new(RefCell::new(HashMap::new())),
663 name: Some(name.into()),
664 namespace: function_definition_namespace(),
665 native: Some(Rc::new(callback)),
666 fiber_native: None,
667 clauses: Vec::new(),
668 metadata: None,
669 is_macro: false,
670 });
671 debug_assert!(function.origin_symbol().is_some());
672 Value::Function(function)
673}
674
675pub(crate) fn native_fixed_variadic_function(
681 name: &str,
682 fixed_arity: usize,
683 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
684) -> Value {
685 let function = Rc::new(Function {
686 params: (0..fixed_arity)
687 .map(|index| format!("arg{index}"))
688 .collect(),
689 variadic: Some("rest".into()),
690 patterns: Vec::new(),
691 variadic_pattern: None,
692 body: Vec::new(),
693 captured: Rc::new(RefCell::new(HashMap::new())),
694 name: Some(name.into()),
695 namespace: function_definition_namespace(),
696 native: Some(Rc::new(callback)),
697 fiber_native: None,
698 clauses: Vec::new(),
699 metadata: None,
700 is_macro: false,
701 });
702 debug_assert!(function.origin_symbol().is_some());
703 Value::Function(function)
704}
705
706pub(crate) fn native_variadic_function(
707 name: &str,
708 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
709) -> Value {
710 let function = Rc::new(Function {
711 params: Vec::new(),
712 variadic: Some("arguments".into()),
713 patterns: Vec::new(),
714 variadic_pattern: None,
715 body: Vec::new(),
716 captured: Rc::new(RefCell::new(HashMap::new())),
717 name: Some(name.into()),
718 namespace: function_definition_namespace(),
719 native: Some(Rc::new(callback)),
720 fiber_native: None,
721 clauses: Vec::new(),
722 metadata: None,
723 is_macro: false,
724 });
725 debug_assert!(function.origin_symbol().is_some());
726 Value::Function(function)
727}
728
729pub(crate) fn native_fiber_function(
730 name: &str,
731 fixed_arity: usize,
732 variadic: bool,
733 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
734 fiber_callback: impl Fn(Vec<Value>, Cont) -> Step + 'static,
735) -> Value {
736 native_fiber_function_with_arity_error(
737 name,
738 fixed_arity,
739 variadic,
740 callback,
741 fiber_callback,
742 |expectation, _received| format!("function expects {expectation} arguments"),
743 )
744}
745
746pub(crate) fn native_protocol_fiber_function(
747 name: &str,
748 protocol: &str,
749 method: &str,
750 fixed_arity: usize,
751 variadic: bool,
752 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
753 fiber_callback: impl Fn(Vec<Value>, Cont) -> Step + 'static,
754) -> Value {
755 let display_name = format!("{protocol}/{method}");
756 native_fiber_function_with_arity_error(
757 name,
758 fixed_arity,
759 variadic,
760 callback,
761 fiber_callback,
762 move |expectation, received| {
763 format!(
764 "protocol/arity: {display_name} expects {expectation} arguments, received {received}"
765 )
766 },
767 )
768}
769
770fn native_fiber_function_with_arity_error(
771 name: &str,
772 fixed_arity: usize,
773 variadic: bool,
774 callback: impl Fn(Vec<Value>) -> Result<Value, String> + 'static,
775 fiber_callback: impl Fn(Vec<Value>, Cont) -> Step + 'static,
776 arity_error: impl Fn(String, usize) -> String + 'static,
777) -> Value {
778 let fiber_callback = move |arguments: Vec<Value>, continuation: Cont| {
779 let valid = if variadic {
780 arguments.len() >= fixed_arity
781 } else {
782 arguments.len() == fixed_arity
783 };
784 if !valid {
785 let expectation = if variadic {
786 format!("at least {fixed_arity}")
787 } else {
788 fixed_arity.to_string()
789 };
790 return continuation(Err(arity_error(expectation, arguments.len())));
791 }
792 fiber_callback(arguments, continuation)
793 };
794 let function = Rc::new(Function {
795 params: (0..fixed_arity)
796 .map(|index| format!("arg{index}"))
797 .collect(),
798 variadic: variadic.then(|| "rest".into()),
799 patterns: Vec::new(),
800 variadic_pattern: None,
801 body: Vec::new(),
802 captured: Rc::new(RefCell::new(HashMap::new())),
803 name: Some(name.into()),
804 namespace: function_definition_namespace(),
805 native: Some(Rc::new(callback)),
806 fiber_native: Some(Rc::new(fiber_callback)),
807 clauses: Vec::new(),
808 metadata: None,
809 is_macro: false,
810 });
811 debug_assert!(function.origin_symbol().is_some());
812 Value::Function(function)
813}
814
815pub(crate) fn exception_function_values() -> Vec<(&'static str, Value)> {
816 vec![
817 (
818 "ex",
819 native_variadic_function("ex", |arguments| {
820 if arguments.len() < 2 || arguments.len() % 2 != 0 {
821 return Err("ex expects a code, attributes map, and key/value pairs".into());
822 }
823 let Value::Keyword(input_code) = &arguments[0] else {
824 return Err(
825 "ex expects a registered standard keyword or namespaced keyword code"
826 .into(),
827 );
828 };
829 let code = normalize_exception_code(input_code)?;
830 let mut attributes = arguments[1].clone();
831 for pair in arguments[2..].chunks_exact(2) {
832 attributes = map_assoc_value(&attributes, pair[0].clone(), pair[1].clone())?;
833 }
834 let Some(entries) = map_entries(&attributes) else {
835 return Err("ex expects an attributes map".into());
836 };
837 let lookup = |name: &str| {
838 entries.iter().find_map(|(key, value)| {
839 matches!(key, Value::Keyword(key_name) if key_name.as_str() == name)
840 .then_some(value)
841 })
842 };
843 let message = match lookup("ex/message") {
844 Some(Value::String(message)) => message.clone(),
845 Some(_) => return Err(":ex/message must be a string".into()),
846 None => format!(":{code}"),
847 };
848 if lookup("ex/code").is_some() {
849 return Err("ex attributes must not contain :ex/code; pass the code as the first argument".into());
850 }
851 if let Some(class) = lookup("ex/class") {
852 match class {
853 Value::Keyword(class) if class.get_namespace().is_some() => {
854 if let Some(expected) = default_exception_class(&code) {
855 if class != &expected {
856 return Err(":ex/class conflicts with the registered class for :ex/code".into());
857 }
858 }
859 }
860 _ => return Err(":ex/class must be a namespaced keyword".into()),
861 }
862 }
863 let cause = match lookup("ex/cause") {
864 Some(cause @ Value::ExceptionInfo(_)) => Some(cause.clone()),
865 Some(_) => return Err(":ex/cause must be an Exception".into()),
866 None => None,
867 };
868 if let Some(context) = lookup("ex/context") {
869 if map_entries(context).is_none() {
870 return Err(":ex/context must be a map".into());
871 }
872 }
873 let mut data = map_assoc_value(
874 &attributes,
875 Value::Keyword("ex/code".into()),
876 Value::Keyword(code.clone()),
877 )?;
878 if lookup("ex/class").is_none() {
879 if let Some(class) = default_exception_class(&code) {
880 data = map_assoc_value(
881 &data,
882 Value::Keyword("ex/class".into()),
883 Value::Keyword(class),
884 )?;
885 }
886 }
887 if let Some(cause) = &cause {
888 data =
889 map_assoc_value(&data, Value::Keyword("ex/cause".into()), cause.clone())?;
890 }
891 let value = Value::ExceptionInfo(Rc::new(ExceptionInfo {
892 message,
893 cause: cause.map(Box::new),
894 data: Box::new(data),
895 provenance: Rc::new(RefCell::new(ExceptionProvenance {
896 created_at: None,
897 throws: Vec::new(),
898 })),
899 }));
900 record_exception_creation(&value, current_exception_site());
901 Ok(value)
902 }),
903 ),
904 (
905 "ex-info",
906 native_variadic_function("ex-info", |arguments| {
907 if !(2..=3).contains(&arguments.len()) {
908 return Err("ex-info expects a message, data map, and optional cause".into());
909 }
910 let Value::String(message) = &arguments[0] else {
911 return Err("ex-info expects a string message".into());
912 };
913 if map_entries(&arguments[1]).is_none() {
914 return Err("ex-info expects a data map".into());
915 }
916 let cause = match arguments.get(2) {
917 Some(cause @ Value::ExceptionInfo(_)) => Some(Box::new(cause.clone())),
918 Some(_) => return Err("ex-info expects an Exception cause".into()),
919 None => None,
920 };
921 let value = Value::ExceptionInfo(Rc::new(ExceptionInfo {
922 message: message.clone(),
923 data: Box::new(arguments[1].clone()),
924 cause,
925 provenance: Rc::new(RefCell::new(ExceptionProvenance {
926 created_at: None,
927 throws: Vec::new(),
928 })),
929 }));
930 record_exception_creation(&value, current_exception_site());
931 Ok(value)
932 }),
933 ),
934 (
935 "ex-data",
936 native_function("ex-data", 1, |arguments| match &arguments[0] {
937 Value::ExceptionInfo(value) => Ok((*value.data).clone()),
938 _ => Ok(Value::Nil),
939 }),
940 ),
941 (
942 "ex-message",
943 native_function("ex-message", 1, |arguments| match &arguments[0] {
944 Value::ExceptionInfo(value) => Ok(Value::String(value.message.clone())),
945 Value::String(value) => Ok(Value::String(value.clone())),
946 value => Ok(Value::String(value.display())),
947 }),
948 ),
949 (
950 "ex-cause",
951 native_function("ex-cause", 1, |arguments| match &arguments[0] {
952 Value::ExceptionInfo(value) => {
953 Ok(value.cause.as_deref().cloned().unwrap_or(Value::Nil))
954 }
955 _ => Err("ex-cause expects an Exception".into()),
956 }),
957 ),
958 (
959 "ex-provenance",
960 native_function("ex-provenance", 1, |arguments| match &arguments[0] {
961 Value::ExceptionInfo(value) => Ok(exception_provenance_value(value)),
962 _ => Err("ex-provenance expects an Exception".into()),
963 }),
964 ),
965 (
966 "ex-class",
967 native_function("ex-class", 1, |arguments| match &arguments[0] {
968 Value::ExceptionInfo(value) => {
969 let Some(entries) = map_entries(&value.data) else {
970 return Err("Exception data must be a map".into());
971 };
972 match entries.iter().find_map(|(key, value)| {
973 matches!(key, Value::Keyword(name) if name.as_str() == "ex/class")
974 .then_some(value)
975 }) {
976 None => Ok(Value::Nil),
977 Some(Value::Keyword(class)) if class.get_namespace().is_some() => {
978 Ok(Value::Keyword(class.clone()))
979 }
980 Some(_) => Err(":ex/class must be a namespaced keyword".into()),
981 }
982 }
983 _ => Err("ex-class expects an Exception".into()),
984 }),
985 ),
986 (
987 "ex-native-type",
988 native_function("ex-native-type", 1, |arguments| match &arguments[0] {
989 Value::ExceptionInfo(_) => Ok(Value::Nil),
990 _ => Err("ex-native-type expects an Exception".into()),
991 }),
992 ),
993 ]
994}
995
996pub(crate) fn direct_function_value(name: &str) -> Option<Value> {
997 match name {
998 "pair" => Some(native_function("pair", 2, |arguments| {
999 Ok(Value::MapEntry(Box::new(PMapEntry::new(
1000 arguments[0].clone(),
1001 arguments[1].clone(),
1002 ))))
1003 })),
1004 "disj" => Some(native_variadic_function("disj", |arguments| {
1005 let (collection, values) = arguments
1006 .split_first()
1007 .ok_or_else(|| "disj expects a collection".to_string())?;
1008 let mut output = collection.clone();
1009 for value in values {
1010 if matches!(output, Value::Nil) {
1011 break;
1012 }
1013 output = crate::core::protocol_intrinsic_call(
1014 "std.protocol.idissoc.IDissoc/dissoc",
1015 &[output, value.clone()],
1016 )?;
1017 }
1018 Ok(output)
1019 })),
1020 "quot" => Some(native_function("quot", 2, |arguments| {
1021 numeric::numeric_quotient(&arguments[0], &arguments[1])
1022 })),
1023 "rem" => Some(native_function("rem", 2, |arguments| {
1024 apply_binary_intrinsic(IntrinsicOp::Remainder, &arguments[0], &arguments[1])
1025 })),
1026 "mod" => Some(native_variadic_function("mod", |arguments| {
1027 if arguments.len() != 2 {
1028 return Err("mod expects arguments".into());
1029 }
1030 numeric::numeric_binary(ArithmeticOp::Modulo, &arguments[0], &arguments[1])
1031 })),
1032 _ => IntrinsicOp::from_symbol(name).map(|primitive| {
1033 native_variadic_function(name, move |arguments| {
1034 apply_intrinsic(primitive, &arguments)
1035 })
1036 }),
1037 }
1038}
1039
1040pub fn native_type_function_value(native_type: &str, method: &str) -> Result<Value, String> {
1047 let declaration = NATIVE_DECLARATIONS
1048 .iter()
1049 .find(|declaration| declaration.name == native_type)
1050 .ok_or_else(|| {
1051 format!(
1052 "missing annotated native declaration: std.native.{native_type}/{method}"
1053 )
1054 })?;
1055 if !declaration.method(method) {
1056 return Err(format!(
1057 "unknown annotated native method: std.native.{native_type}/{method}"
1058 ));
1059 }
1060 (declaration.provider)(native_type, method)
1061}
1062
1063fn native_display_name(native_type: &str, method: &str) -> String {
1064 format!("std.native.{native_type}/{method}")
1065}
1066
1067fn native_base_provider(native_type: &str, method: &str) -> Result<Value, String> {
1068 let display_name = native_display_name(native_type, method);
1069 let method = method.to_owned();
1070 Ok(native_variadic_function(&display_name, move |arguments| {
1071 native_base_values(&method, &arguments)
1072 }))
1073}
1074
1075fn native_schema_provider(native_type: &str, method: &str) -> Result<Value, String> {
1076 let display_name = native_display_name(native_type, method);
1077 let method = method.to_owned();
1078 Ok(native_variadic_function(&display_name, move |arguments| {
1079 native_schema_values(&method, &arguments)
1080 }))
1081}
1082
1083fn native_string_provider(native_type: &str, method: &str) -> Result<Value, String> {
1084 let display_name = native_display_name(native_type, method);
1085 let operation = format!("str/{method}");
1086 Ok(native_variadic_function(&display_name, move |arguments| {
1087 string_operation(&operation, arguments)
1088 }))
1089}
1090
1091fn native_bytes_provider(native_type: &str, method: &str) -> Result<Value, String> {
1092 let display_name = native_display_name(native_type, method);
1093 let method = method.to_owned();
1094 Ok(native_variadic_function(&display_name, move |arguments| {
1095 native_bytes_operation(&method, arguments)
1096 }))
1097}
1098
1099fn native_iter_provider(native_type: &str, method: &str) -> Result<Value, String> {
1100 let display_name = native_display_name(native_type, method);
1101 let method = method.to_owned();
1102 Ok(native_variadic_function(&display_name, move |arguments| {
1103 native_iter_operation(&method, arguments)
1104 }))
1105}
1106
1107fn native_maths_provider(native_type: &str, method: &str) -> Result<Value, String> {
1108 let display_name = native_display_name(native_type, method);
1109 let method = method.to_owned();
1110 Ok(native_variadic_function(&display_name, move |arguments| {
1111 math_values(&method, arguments)
1112 }))
1113}
1114
1115fn native_num_provider(native_type: &str, method: &str) -> Result<Value, String> {
1116 let display_name = native_display_name(native_type, method);
1117 let method = method.to_owned();
1118 Ok(native_variadic_function(&display_name, move |arguments| {
1119 if arguments.len() != 1 {
1120 return Err(format!("{method} expects one value"));
1121 }
1122 number_conversion_value(&method, arguments.into_iter().next().unwrap())
1123 }))
1124}
1125
1126fn native_bits_provider(native_type: &str, method: &str) -> Result<Value, String> {
1127 let display_name = native_display_name(native_type, method);
1128 let method = method.to_owned();
1129 Ok(native_variadic_function(&display_name, move |arguments| {
1130 bit_values(&method, &arguments)
1131 }))
1132}
1133
1134fn native_kernel_provider(native_type: &str, method: &str) -> Result<Value, String> {
1135 let display_name = native_display_name(native_type, method);
1136 let method = method.to_owned();
1137 Ok(native_variadic_function(&display_name, move |arguments| {
1138 require_native_capability("Kernel", &method, "kernel")?;
1139 kernel_provider(&method)?(method.clone(), arguments)
1140 }))
1141}
1142
1143fn native_sandbox_provider(native_type: &str, method: &str) -> Result<Value, String> {
1144 let display_name = native_display_name(native_type, method);
1145 let operation = format!("sandbox-{method}");
1146 let method = method.to_owned();
1147 Ok(native_variadic_function(&display_name, move |arguments| {
1148 require_native_capability("Sandbox", &method, "sandbox")?;
1149 kernel_provider(&operation)?(operation.clone(), arguments)
1150 }))
1151}
1152
1153fn native_crypto_provider(native_type: &str, method: &str) -> Result<Value, String> {
1154 let display_name = native_display_name(native_type, method);
1155 let method = method.to_owned();
1156 Ok(native_variadic_function(&display_name, move |arguments| {
1157 native_crypto::operation(&method, arguments)
1158 }))
1159}
1160
1161fn native_document_provider(native_type: &str, method: &str) -> Result<Value, String> {
1162 let display_name = native_display_name(native_type, method);
1163 let method = method.to_owned();
1164 Ok(native_variadic_function(&display_name, move |arguments| {
1165 document_operation(&method, arguments)
1166 }))
1167}
1168
1169fn native_package_provider(native_type: &str, method: &str) -> Result<Value, String> {
1170 let display_name = native_display_name(native_type, method);
1171 let method = method.to_owned();
1172 Ok(native_variadic_function(&display_name, move |arguments| {
1173 require_native_capability("Package", &method, "kernel")?;
1174 native_package_values(&method, arguments, &mut HashMap::new())
1175 }))
1176}
1177
1178fn native_instrument_provider(native_type: &str, method: &str) -> Result<Value, String> {
1179 let display_name = native_display_name(native_type, method);
1180 let method = method.to_owned();
1181 Ok(native_variadic_function(&display_name, move |arguments| {
1182 native_instrument_values(&method, arguments)
1183 }))
1184}
1185
1186fn native_os_provider(native_type: &str, method: &str) -> Result<Value, String> {
1187 let display_name = native_display_name(native_type, method);
1188 let native_type = native_type.to_owned();
1189 let method = method.to_owned();
1190 let operation = native_display_name(&native_type, &method);
1191 Ok(native_variadic_function(&display_name, move |arguments| {
1192 if native_type == "Process" {
1193 require_native_capability("Process", &method, "native-runtime")?;
1194 }
1195 os_values(&operation, arguments)
1196 }))
1197}
1198
1199fn native_file_provider(native_type: &str, method: &str) -> Result<Value, String> {
1200 let display_name = native_display_name(native_type, method);
1201 let method = method.to_owned();
1202 let operation = native_display_name(native_type, &method);
1203 Ok(native_variadic_function(&display_name, move |arguments| {
1204 require_native_capability("File", &method, "file")?;
1205 file_values(&operation, arguments)
1206 }))
1207}
1208
1209fn native_socket_provider(native_type: &str, method: &str) -> Result<Value, String> {
1210 let display_name = native_display_name(native_type, method);
1211 let method = method.to_owned();
1212 let operation = native_display_name(native_type, &method);
1213 Ok(native_variadic_function(&display_name, move |arguments| {
1214 require_native_capability("Socket", &method, "network")?;
1215 socket_values(&operation, arguments)
1216 }))
1217}
1218
1219fn native_promise_provider(native_type: &str, method: &str) -> Result<Value, String> {
1220 let display_name = native_display_name(native_type, method);
1221 let method = method.to_owned();
1222 Ok(native_variadic_function(&display_name, move |arguments| {
1223 native_promise_values(&method, arguments)
1224 }))
1225}
1226
1227fn native_coroutine_provider(native_type: &str, method: &str) -> Result<Value, String> {
1228 let display_name = native_display_name(native_type, method);
1229 match method {
1230 "create" => Ok(native_fiber_function(
1231 &display_name,
1232 1,
1233 false,
1234 native_coroutine_create,
1235 native_coroutine_create_fiber,
1236 )),
1237 "yield" => Ok(native_fiber_function(
1238 &display_name,
1239 1,
1240 false,
1241 native_coroutine_yield,
1242 native_coroutine_yield_fiber,
1243 )),
1244 "await" => Ok(native_fiber_function(
1245 &display_name,
1246 1,
1247 false,
1248 native_coroutine_await,
1249 native_coroutine_await_fiber,
1250 )),
1251 _ => Err(format!("unknown std.native.Coroutine operation: {method}")),
1252 }
1253}
1254
1255fn native_stream_provider(native_type: &str, method: &str) -> Result<Value, String> {
1256 let display_name = native_display_name(native_type, method);
1257 let method = method.to_owned();
1258 Ok(native_variadic_function(&display_name, move |arguments| {
1259 native_stream_values(&method, arguments)
1260 }))
1261}
1262
1263fn native_mutable_provider(native_type: &str, method: &str) -> Result<Value, String> {
1264 let display_name = native_display_name(native_type, method);
1265 let operation = native_display_name(native_type, method);
1266 Ok(native_variadic_function(&display_name, move |arguments| {
1267 native_mutable_values(&operation, arguments)
1268 }))
1269}
1270
1271fn native_runtime_provider(native_type: &str, method: &str) -> Result<Value, String> {
1272 let display_name = native_display_name(native_type, method);
1273 let method = method.to_owned();
1274 Ok(native_variadic_function(&display_name, move |arguments| {
1275 native_runtime_values(&method, arguments, &mut HashMap::new())
1276 }))
1277}
1278
1279fn native_printer_provider(native_type: &str, method: &str) -> Result<Value, String> {
1280 let display_name = native_display_name(native_type, method);
1281 let method = method.to_owned();
1282 Ok(native_variadic_function(&display_name, move |arguments| {
1283 native_printer_values(&method, arguments)
1284 }))
1285}
1286
1287fn native_edn_provider(native_type: &str, method: &str) -> Result<Value, String> {
1288 let display_name = native_display_name(native_type, method);
1289 let method = method.to_owned();
1290 Ok(native_variadic_function(&display_name, move |arguments| {
1291 native_edn_values(&method, arguments)
1292 }))
1293}
1294
1295fn native_json_provider(native_type: &str, method: &str) -> Result<Value, String> {
1296 let display_name = native_display_name(native_type, method);
1297 let method = method.to_owned();
1298 Ok(native_variadic_function(&display_name, move |arguments| {
1299 match (method.as_str(), arguments.as_slice()) {
1300 ("read", [Value::String(source)]) => crate::json::read(source),
1301 ("write", [value]) => crate::json::write(value).map(Value::String),
1302 ("pretty", [value, options]) if map_entries(options).is_some() => {
1303 crate::json::write_pretty(value).map(Value::String)
1304 }
1305 ("pretty", [_, _]) => Err("json/pretty expects an options map".into()),
1306 ("read", _) => Err("json/read expects a string".into()),
1307 ("write", _) => Err("json/write expects one value".into()),
1308 ("pretty", _) => Err("json/pretty expects a value and options map".into()),
1309 _ => Err(format!("unknown std.native.Json operation: {method}")),
1310 }
1311 }))
1312}
1313
1314fn native_host_provider(native_type: &str, method: &str) -> Result<Value, String> {
1315 let display_name = native_display_name(native_type, method);
1316 let method = method.to_owned();
1317 Ok(native_variadic_function(&display_name, move |arguments| {
1318 if !native_capability_granted("host-call") {
1319 return Ok(native_capability_denied_promise(
1320 "Host",
1321 &method,
1322 "host-call",
1323 ));
1324 }
1325 native_host_values(&method, arguments)
1326 }))
1327}
1328
1329fn native_test_provider(native_type: &str, method: &str) -> Result<Value, String> {
1330 let display_name = native_display_name(native_type, method);
1331 let method = method.to_owned();
1332 Ok(native_variadic_function(&display_name, move |arguments| {
1333 native_test_values(&method, arguments)
1334 }))
1335}
1336
1337fn native_command_provider(native_type: &str, method: &str) -> Result<Value, String> {
1338 let display_name = native_display_name(native_type, method);
1339 let method = method.to_owned();
1340 Ok(native_variadic_function(&display_name, move |arguments| {
1341 native_command_values(&method, arguments)
1342 }))
1343}
1344
1345fn native_regexp_provider(native_type: &str, method: &str) -> Result<Value, String> {
1346 let display_name = native_display_name(native_type, method);
1347 let method = method.to_owned();
1348 Ok(native_variadic_function(&display_name, move |arguments| {
1349 native_regex_values(&method, arguments)
1350 }))
1351}
1352
1353fn native_result_provider(native_type: &str, method: &str) -> Result<Value, String> {
1354 let display_name = native_display_name(native_type, method);
1355 let method = method.to_owned();
1356 Ok(native_variadic_function(&display_name, move |arguments| {
1357 native_result_values(&method, arguments)
1358 }))
1359}
1360
1361fn native_exception_provider(native_type: &str, method: &str) -> Result<Value, String> {
1362 let display_name = native_display_name(native_type, method);
1363 let method = method.to_owned();
1364 Ok(native_variadic_function(&display_name, move |arguments| {
1365 native_exception_values(&method, arguments)
1366 }))
1367}
1368
1369fn native_algo_provider(native_type: &str, method: &str) -> Result<Value, String> {
1370 let display_name = native_display_name(native_type, method);
1371 let operation = native_display_name(native_type, method);
1372 Ok(native_variadic_function(&display_name, move |arguments| {
1373 native_algo_values(&operation, arguments)
1374 }))
1375}
1376
1377fn native_work_provider(_native_type: &str, method: &str) -> Result<Value, String> {
1378 crate::work::guest::values()
1379 .into_iter()
1380 .find(|(name, _)| *name == method)
1381 .map(|(_, value)| value)
1382 .ok_or_else(|| format!("unknown std.native.Work operation: {method}"))
1383}
1384
1385fn native_coroutine_create(arguments: Vec<Value>) -> Result<Value, String> {
1386 match arguments.as_slice() {
1387 [Value::Function(function)] => Ok(Value::Coroutine(Rc::new(Coroutine::new(
1388 Value::Function(function.clone()),
1389 )))),
1390 _ => Err("Coroutine/create expects one function".into()),
1391 }
1392}
1393
1394fn native_coroutine_create_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1395 match arguments.as_slice() {
1396 [Value::Function(function)] => k(Ok(Value::Coroutine(Rc::new(Coroutine::new(
1397 Value::Function(function.clone()),
1398 ))))),
1399 _ => k(Err("Coroutine/create expects one function".into())),
1400 }
1401}
1402
1403fn native_coroutine_yield(_arguments: Vec<Value>) -> Result<Value, String> {
1404 Err("Coroutine/yield requires the fiber evaluator".into())
1405}
1406
1407fn native_coroutine_yield_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1408 match arguments.as_slice() {
1409 [value] => Step::Yield(value.clone(), Box::new(move |resumed| k(Ok(resumed)))),
1410 _ => k(Err("Coroutine/yield expects one value".into())),
1411 }
1412}
1413
1414fn native_coroutine_await(_arguments: Vec<Value>) -> Result<Value, String> {
1415 Err("Coroutine/await requires the fiber evaluator".into())
1416}
1417
1418fn native_coroutine_await_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1419 match arguments.as_slice() {
1420 [Value::Var(reference)] => k(Ok(reference.deref_value())),
1421 [Value::Promise(promise)] => match promise.state() {
1422 PromiseState::Fulfilled(value) => k(Ok(value)),
1423 PromiseState::Rejected(error) => k(Err(crate::core::promise_rejection_error(error))),
1424 PromiseState::Pending => Step::Wait(
1425 promise.clone(),
1426 Box::new(move |state| match state {
1427 PromiseState::Fulfilled(value) => k(Ok(value)),
1428 PromiseState::Rejected(error) => {
1429 k(Err(crate::core::promise_rejection_error(error)))
1430 }
1431 PromiseState::Pending => k(Err("Coroutine/await resumed pending".into())),
1432 }),
1433 ),
1434 },
1435 _ => k(Err("Coroutine/await expects a derefable (e.g. a promise)".into())),
1436 }
1437}
1438
1439fn native_edn_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1440 match (method, arguments.as_slice()) {
1441 ("read", [Value::String(source)]) => read_edn(source),
1442 ("read-forms", [Value::String(path)]) => {
1443 if !(path.ends_with(".hal") || path.ends_with(".hrl")) {
1444 return Err("read-forms expects a .hal or .hrl path".into());
1445 }
1446 let promise = file_provider("read-forms")?
1447 .read(path)
1448 .map_err(|error| file_error("read-forms", error))?;
1449 let bytes = match promise.wait_state() {
1450 PromiseState::Fulfilled(Value::Bytes(bytes)) => bytes,
1451 PromiseState::Fulfilled(Value::ByteBuffer(bytes)) => bytes.borrow().clone(),
1452 PromiseState::Fulfilled(value) => {
1453 return Err(format!(
1454 "read-forms expected file bytes, got {}",
1455 value.display()
1456 ));
1457 }
1458 PromiseState::Rejected(error) => return Err(error.message()),
1459 PromiseState::Pending => return Err("read-forms file read is still pending".into()),
1460 };
1461 let source = String::from_utf8(bytes)
1462 .map_err(|_| format!("read-forms source is not UTF-8: {path}"))?;
1463 let forms = crate::kernel::parse_forms(&source)
1464 .map_err(|error| format!("read-forms failed: {error}"))?;
1465 Ok(Value::Vector(PVector::from_iter(
1466 forms
1467 .iter()
1468 .map(form_to_value)
1469 .collect::<Result<Vec<_>, _>>()?,
1470 )))
1471 }
1472 ("write", [value]) => Ok(Value::String(value.display())),
1473 ("pretty", [value, options]) if map_entries(options).is_some() => {
1474 Ok(Value::String(value.display()))
1475 }
1476 ("pretty", [_, _]) => Err("edn/pretty expects an options map".into()),
1477 ("read", _) => Err("edn/read expects one string".into()),
1478 ("read-forms", _) => Err("read-forms expects a path string".into()),
1479 ("write", _) => Err("std.native.Edn/write expects one value".into()),
1480 ("pretty", _) => Err("std.native.Edn/pretty expects a value and options map".into()),
1481 _ => Err(format!("unknown std.native.Edn operation: {method}")),
1482 }
1483}
1484
1485fn native_printer_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1486 match method {
1487 "capture" => {
1488 let [callable] = arguments.as_slice() else {
1489 return Err("Printer/capture expects one callable".into());
1490 };
1491 PRINTER_CAPTURES.with(|captures| captures.borrow_mut().push(String::new()));
1492 let result = call_value(callable.clone(), Vec::new());
1493 let output = PRINTER_CAPTURES.with(|captures| {
1494 captures
1495 .borrow_mut()
1496 .pop()
1497 .expect("Printer/capture stack must contain the active capture")
1498 });
1499 result.map(|_| Value::String(output))
1500 }
1501 "p" | "println" => {
1502 let text = arguments
1503 .iter()
1504 .map(|value| match (method, value) {
1505 ("p", Value::Nil) => String::new(),
1506 ("p", Value::String(text)) => text.clone(),
1507 ("p", Value::Character(character)) => character.to_string(),
1508 (_, Value::String(text)) => text.clone(),
1509 _ => value.display(),
1510 })
1511 .collect::<Vec<_>>()
1512 .join(if method == "println" { " " } else { "" });
1513 let output = if method == "println" {
1514 format!("{text}\n")
1515 } else {
1516 text
1517 };
1518 printer_write(&output)?;
1519 Ok(Value::Nil)
1520 }
1521 _ => Err(format!("unknown std.native.Printer operation: {method}")),
1522 }
1523}
1524
1525fn native_promise_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1526 match (method, arguments.as_slice()) {
1527 ("from", [value]) => Ok(Value::Promise(promise_from(value.clone()))),
1528 ("all", [values]) => Ok(Value::Promise(promise_all(iterator_values(
1529 values.clone(),
1530 )?))),
1531 ("run", [Value::Function(function)]) => {
1532 let function = function.clone();
1533 let context = crate::core::NativeCallbackContext::capture();
1534 let task = Rc::new(move || context.with(|| call_function(&function, Vec::new())));
1535 Ok(Value::Promise(promise_provider().run(task)))
1536 }
1537 ("new", [Value::Function(function)]) => {
1538 let promise = Promise::new();
1539 let resolving = promise.clone();
1540 let resolve = native_function("promise-resolve", 1, move |mut values| {
1541 let value = values.remove(0);
1542 settle_promise_result(&resolving, Ok(value.clone()));
1543 Ok(value)
1544 });
1545 let rejecting = promise.clone();
1546 let reject = native_function("promise-reject", 1, move |mut values| {
1547 let value = values.remove(0);
1548 rejecting.reject_value(value.clone());
1549 Ok(value)
1550 });
1551 if let Err(error) = call_function(function, vec![resolve, reject]) {
1552 promise.reject(error);
1553 }
1554 Ok(Value::Promise(promise))
1555 }
1556 ("delay", [millis, Value::Function(function)]) => {
1557 let millis = value_u64_integer(millis, "promise/delay")
1558 .map_err(|_| "promise/delay expects non-negative milliseconds".to_string())?;
1559 let function = function.clone();
1560 let context = crate::core::NativeCallbackContext::capture();
1561 let task = Rc::new(move || context.with(|| call_function(&function, Vec::new())));
1562 Ok(Value::Promise(
1563 promise_provider().delay(std::time::Duration::from_millis(millis), task),
1564 ))
1565 }
1566 ("run", _) => Err("promise/run expects one function".into()),
1567 ("new", [_]) => Err("promise/new expects a function".into()),
1568 ("new", _) => Err("promise/new expects one function".into()),
1569 ("from", _) => Err("promise/from expects one value".into()),
1570 ("all", _) => Err("promise/all expects one collection".into()),
1571 ("delay", _) => Err("promise/delay expects milliseconds and a function".into()),
1572 _ => Err(format!("unknown std.native.Promise operation: {method}")),
1573 }
1574}
1575
1576fn native_iter_operation(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1577 let unary = |label: &str| {
1578 arguments
1579 .first()
1580 .cloned()
1581 .filter(|_| arguments.len() == 1)
1582 .ok_or_else(|| format!("Iter/{label} expects one argument"))
1583 };
1584 let binary = |label: &str| {
1585 if arguments.len() == 2 {
1586 Ok((arguments[0].clone(), arguments[1].clone()))
1587 } else {
1588 Err(format!("Iter/{label} expects two arguments"))
1589 }
1590 };
1591 match method {
1592 "seq" => iterator_seq(unary(method)?),
1593 "iter" => make_iterator(unary(method)?),
1594 "iter-finite?" => Ok(Value::Bool(iterator_is_finite(&unary(method)?))),
1595 "iter-materialize" => Ok(Value::Vector(iterator_to_vec(unary(method)?)?.into())),
1596 "iter-next?" => iterator_has_next(&unary(method)?),
1597 "iter-next" => iterator_next(&unary(method)?),
1598 "iter-close" => iterator_close(&unary(method)?),
1599 "iter-concat" => iterator_concat(arguments),
1600 "iter-interleave" => iterator_interleave(arguments),
1601 "iter-zip" => iterator_zip(arguments),
1602 "iter-map" => {
1603 let (function, source) = binary(method)?;
1604 iterator_map(function, source)
1605 }
1606 "iter-filter" => {
1607 let (function, source) = binary(method)?;
1608 iterator_filter(function, source)
1609 }
1610 "iter-take-while" => {
1611 let (function, source) = binary(method)?;
1612 iterator_take_while(function, source)
1613 }
1614 "iter-drop-while" => {
1615 let (function, source) = binary(method)?;
1616 iterator_drop_while(function, source)
1617 }
1618 "iter-mapcat" => {
1619 let (function, source) = binary(method)?;
1620 iterator_mapcat(function, source)
1621 }
1622 "iter-keep" => {
1623 let (function, source) = binary(method)?;
1624 iterator_keep(function, source)
1625 }
1626 "iter-interpose" => {
1627 let (separator, source) = binary(method)?;
1628 iterator_interpose(separator, source)
1629 }
1630 "iter-every?" | "iter-any?" => {
1631 let (predicate, source) = binary(method)?;
1632 let iterator = make_iterator(source)?;
1633 let expect_every = method == "iter-every?";
1634 let result = (|| {
1635 while let Some(value) = iterator_try_next(&iterator)? {
1636 let matched = call_value(predicate.clone(), vec![value])?.truthy();
1637 if matched != expect_every {
1638 return Ok(Value::Bool(!expect_every));
1639 }
1640 }
1641 Ok(Value::Bool(expect_every))
1642 })();
1643 let close = iterator_close(&iterator);
1644 close?;
1645 result
1646 }
1647 "iter-take" | "iter-drop" => {
1648 let (amount, source) = binary(method)?;
1649 let amount = value_index(&amount)?;
1650 if method == "iter-take" {
1651 iterator_take(source, amount)
1652 } else {
1653 iterator_drop(source, amount)
1654 }
1655 }
1656 "iter-cycle" => iterator_cycle(unary(method)?),
1657 "iter-partition-pair" => iterator_partition(unary(method)?, 2, false),
1658 "iter-partition" | "iter-partition-all" => {
1659 let (amount, source) = binary(method)?;
1660 iterator_partition(source, value_index(&amount)?, method.ends_with("-all"))
1661 }
1662 "iter-range" => {
1663 let bounds = arguments
1664 .iter()
1665 .map(|value| {
1666 numeric::to_i64_exact(value).map_err(|_| {
1667 "iter-range bounds must fit signed 64-bit integers".to_string()
1668 })
1669 })
1670 .collect::<Result<Vec<_>, _>>()?;
1671 let (start, end) = match bounds.as_slice() {
1672 [end] => (0, *end),
1673 [start, end] => (*start, *end),
1674 _ => return Err("iter-range expects an end or start and end".into()),
1675 };
1676 Ok(iterator_from_values(
1677 (start..end).map(Value::Number).collect(),
1678 ))
1679 }
1680 "iter-constantly" => Ok(iterator_constant(unary(method)?)),
1681 "iter-repeatedly" => Ok(iterator_repeated(unary(method)?)),
1682 "iter-iterate" => {
1683 let (function, seed) = binary(method)?;
1684 Ok(iterator_iterate(function, seed))
1685 }
1686 _ => Err(format!("unknown std.native.Iter operation: {method}")),
1687 }
1688}
1689
1690fn native_bytes_operation(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1691 match (method, arguments.as_slice()) {
1692 ("new", values) => native_bytes_new(values),
1693 ("count", [value]) => byte_count(value),
1694 ("get", [value, index]) => byte_get(value, index, None),
1695 ("get", [value, index, default]) => byte_get(value, index, Some(default.clone())),
1696 ("set", [value, index, item]) => byte_set(value, index, item),
1697 ("copy", [value]) => byte_copy(value),
1698 ("slice", [value, start]) => {
1699 let end = byte_count(value)?;
1700 byte_slice(value, start, &end)
1701 }
1702 ("slice", [value, start, end]) => byte_slice(value, start, end),
1703 ("u8" | "s8", [Value::Number(number)]) if (-128..=255).contains(number) => {
1704 let raw = (*number as i8) as u8;
1705 Ok(Value::Number(if method == "u8" {
1706 raw as i64
1707 } else {
1708 raw as i8 as i64
1709 }))
1710 }
1711 ("u8" | "s8", [_]) => Err(format!(
1712 "bytes/{method} expects a value in the range -128..255"
1713 )),
1714 _ => Err(format!(
1715 "std.native.Bytes/{method} received unsupported arguments"
1716 )),
1717 }
1718}
1719
1720fn native_bytes_new(values: &[Value]) -> Result<Value, String> {
1721 let values = values
1722 .iter()
1723 .map(|value| byte_input(value, "bytes"))
1724 .collect::<Result<Vec<_>, _>>()?;
1725 Ok(Value::ByteBuffer(Rc::new(RefCell::new(values))))
1726}
1727
1728pub(crate) fn syntax_symbol(name: &str) -> bool {
1733 const SYNTAX_FORMS: &[&str] = &[
1734 ".",
1735 "binding",
1736 "comment",
1737 "declare",
1738 "def",
1739 "defmacro",
1740 "defn",
1741 "do",
1742 "field",
1743 "fn",
1744 "if",
1745 "let",
1746 "letfn",
1747 "loop",
1748 "ns",
1749 "ns+",
1750 "quote",
1751 "read-forms",
1752 "recur",
1753 "require",
1754 "set!",
1755 "syntax-quote",
1756 "throw",
1757 "try",
1758 "var",
1759 ];
1760 SYNTAX_FORMS.contains(&name)
1761}
1762
1763pub fn with_macros<R>(
1764 macros: Rc<RefCell<HashMap<(String, String), Rc<Function>>>>,
1765 operation: impl FnOnce() -> R,
1766) -> R {
1767 ACTIVE_MACROS.with(|active| {
1768 let previous = active.replace(Some(macros));
1769 let result = operation();
1770 active.replace(previous);
1771 result
1772 })
1773}
1774
1775fn register_macro(namespace: &str, name: &str, function: Rc<Function>) -> Result<(), String> {
1776 ACTIVE_MACROS.with(|active| {
1777 active
1778 .try_borrow_mut()
1779 .map_err(|_| "macro registry is busy".into())
1780 .and_then(|opt| {
1781 if let Some(macros) = opt.as_ref() {
1782 macros
1783 .try_borrow_mut()
1784 .map_err(|_| "macro registry is busy".into())
1785 .map(|mut macros| {
1786 macros.insert((namespace.into(), name.into()), function);
1787 })
1788 } else {
1789 Err("macro registry is unavailable".into())
1790 }
1791 })
1792 })
1793}
1794
1795fn resolve_macro_in(namespace: &str, name: &str) -> Option<Rc<Function>> {
1796 ACTIVE_MACROS.with(|active| {
1797 active.borrow().as_ref().and_then(|macros| {
1798 macros
1799 .borrow()
1800 .get(&(namespace.into(), name.into()))
1801 .cloned()
1802 })
1803 })
1804}
1805
1806pub(crate) fn resolve_macro(name: &str) -> Option<Rc<Function>> {
1807 if let Some((namespace, local)) = name.split_once('/') {
1808 let resolved = namespace_registry().ok().and_then(|registry| {
1809 let current = registry.current();
1810 if namespace == "-" {
1811 return Some(current.name().as_str().to_owned());
1812 }
1813 current
1814 .aliases()
1815 .into_iter()
1816 .find(|(alias, _)| alias.as_str() == namespace)
1817 .map(|(_, target)| target.name().as_str().to_owned())
1818 });
1819 return resolve_macro_in(resolved.as_deref().unwrap_or(namespace), local);
1820 }
1821 let current = namespace_registry()
1822 .map(|registry| registry.current().name().as_str().to_owned())
1823 .ok()?;
1824 resolve_macro_in(¤t, name).or_else(|| resolve_macro_in("std.foundation", name))
1825}
1826
1827fn gensym(prefix: &str) -> String {
1828 let index = GENSYM_COUNTER.with(|counter| {
1829 let value = counter.get();
1830 counter.set(value + 1);
1831 value
1832 });
1833 format!("{prefix}{index}")
1834}
1835
1836pub(crate) fn form_to_value(form: &Form) -> Result<Value, String> {
1837 literal_value(form)
1838}
1839
1840fn metadata_value_to_form(value: &MetadataValue) -> Form {
1841 match value {
1842 MetadataValue::Nil => Form::Nil,
1843 MetadataValue::Boolean(value) => Form::Bool(*value),
1844 MetadataValue::Number(value) => Form::Number(*value),
1845 MetadataValue::Float(value) => Form::Float(*value),
1846 MetadataValue::BigInteger(value) => Form::BigInteger(value.clone()),
1847 MetadataValue::Character(value) => Form::Character(*value),
1848 MetadataValue::Regex(value) => Form::Regex(value.clone()),
1849 MetadataValue::Tagged(tag, value) => {
1850 Form::Tagged(tag.clone(), Box::new(metadata_value_to_form(value)))
1851 }
1852 MetadataValue::String(value) => Form::String(value.clone()),
1853 MetadataValue::Keyword(value) => Form::Keyword(value.as_str().into()),
1854 MetadataValue::Symbol(value) => Form::Symbol(value.as_str().into()),
1855 MetadataValue::Vector(values) => {
1856 Form::Vector(values.iter().map(metadata_value_to_form).collect())
1857 }
1858 MetadataValue::List(values) => {
1859 Form::List(values.iter().map(metadata_value_to_form).collect())
1860 }
1861 MetadataValue::Set(values) => {
1862 Form::Set(values.iter().map(metadata_value_to_form).collect())
1863 }
1864 MetadataValue::Map(values) => Form::Map(
1865 values
1866 .iter()
1867 .map(|(key, value)| (metadata_value_to_form(key), metadata_value_to_form(value)))
1868 .collect(),
1869 ),
1870 }
1871}
1872
1873pub(crate) fn value_to_form(value: &Value) -> Result<Form, String> {
1874 let form = match value {
1875 Value::Nil => Ok(Form::Nil),
1876 Value::Bool(value) => Ok(Form::Bool(*value)),
1877 Value::Number(value) => Ok(Form::Number(*value)),
1878 Value::Float(value) => Ok(Form::Float(*value)),
1879 Value::BigInteger(value) => Ok(Form::BigInteger(value.clone())),
1880 Value::Character(value) => Ok(Form::Character(*value)),
1881 Value::Regex(value) => Ok(Form::Regex(value.clone())),
1882 Value::String(value) => Ok(Form::String(value.clone())),
1883 Value::Keyword(value) => Ok(Form::Keyword(value.as_str().into())),
1884 Value::Symbol(value) => Ok(Form::Symbol(value.as_str().into())),
1885 Value::Tagged(value) => Ok(Form::Tagged(
1886 value.tag().get_name().into(),
1887 Box::new(value_to_form(value.form())?),
1888 )),
1889 Value::Pointer(value) => Ok(Form::Tagged(
1890 "ptr".into(),
1891 Box::new(value_to_form(&Value::Map(value.descriptor()))?),
1892 )),
1893 Value::List(values) => Ok(Form::List(
1894 values
1895 .iter()
1896 .map(|v| value_to_form(v))
1897 .collect::<Result<_, _>>()?,
1898 )),
1899 Value::Queue(values) => Ok(Form::List(
1900 values
1901 .iter()
1902 .map(|v| value_to_form(v))
1903 .collect::<Result<_, _>>()?,
1904 )),
1905 Value::Deque(values) => Ok(Form::List(
1906 values
1907 .iter()
1908 .map(|v| value_to_form(v))
1909 .collect::<Result<_, _>>()?,
1910 )),
1911 Value::Cons(values) => Ok(Form::List(
1912 values
1913 .iter()
1914 .map(|v| value_to_form(&v))
1915 .collect::<Result<_, _>>()?,
1916 )),
1917 Value::Vector(values) => Ok(Form::Vector(
1918 values
1919 .iter()
1920 .map(|v| value_to_form(v))
1921 .collect::<Result<_, _>>()?,
1922 )),
1923 Value::Tuple(values) => Ok(Form::Vector(
1924 values
1925 .iter()
1926 .map(|v| value_to_form(v))
1927 .collect::<Result<_, _>>()?,
1928 )),
1929 Value::MapEntry(entry) => Ok(Form::Vector(
1930 entry
1931 .iter()
1932 .map(value_to_form)
1933 .collect::<Result<_, _>>()?,
1934 )),
1935 Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_) => Ok(Form::Set(
1936 set_items(value)
1937 .unwrap()
1938 .iter()
1939 .copied()
1940 .map(value_to_form)
1941 .collect::<Result<_, _>>()?,
1942 )),
1943 Value::Map(_)
1944 | Value::OrderedMap(_)
1945 | Value::SortedMap(_)
1946 | Value::Trie(_)
1947 | Value::PriorityMap(_) => Ok(Form::Map(
1948 map_entries(value)
1949 .unwrap()
1950 .into_iter()
1951 .map(|(key, value)| -> Result<(Form, Form), String> {
1952 Ok((value_to_form(&key)?, value_to_form(&value)?))
1953 })
1954 .collect::<Result<_, _>>()?,
1955 )),
1956 value => Err(format!("cannot use {} as code", portable_type_name(value))),
1957 }?;
1958 Ok(match value_metadata(value) {
1959 Some(metadata) => Form::Metadata(
1960 Box::new(metadata_value_to_form(&MetadataValue::Map(
1961 metadata.entries().to_vec(),
1962 ))),
1963 Box::new(form),
1964 ),
1965 None => form,
1966 })
1967}
1968
1969pub(crate) fn bytecode_dynamic_bind(name: &str, value: Value) -> Result<(), String> {
1970 let registry = namespace_registry()?;
1971 let var = registry
1972 .resolve(&crate::lang::data::Symbol::parse(name))
1973 .ok_or_else(|| format!("binding expects a Var: {name}"))?;
1974 if !var.is_dynamic() {
1975 return Err(format!("binding expects a dynamic Var: {name}"));
1976 }
1977 var.bind(value);
1978 Ok(())
1979}
1980
1981pub(crate) fn bytecode_dynamic_unbind(name: &str) -> Result<(), String> {
1982 let registry = namespace_registry()?;
1983 let var = registry
1984 .resolve(&crate::lang::data::Symbol::parse(name))
1985 .ok_or_else(|| format!("binding expects a Var: {name}"))?;
1986 var.unbind().map(|_| ())
1987}
1988
1989fn macro_environment() -> Result<Value, String> {
1990 let namespace = namespace_registry()?.current().name().as_str().to_owned();
1991 let entries = vec![
1992 (
1993 Value::Keyword(Keyword::from("ns")),
1994 Value::Symbol(Symbol::from(namespace)),
1995 ),
1996 (
1997 Value::Keyword(Keyword::from("locals")),
1998 Value::OrderedMap(Box::new(POrderedMap::new())),
1999 ),
2000 (
2001 Value::Keyword(Keyword::from("aliases")),
2002 Value::OrderedMap(Box::new(POrderedMap::new())),
2003 ),
2004 ];
2005 Ok(Value::OrderedMap(Box::new(POrderedMap::from_iter(entries))))
2006}
2007
2008fn macroexpand_call(
2009 name: &str,
2010 invocation: &[Form],
2011 _env: &mut HashMap<String, Value>,
2012) -> Result<Option<Form>, String> {
2013 let function = match resolve_macro(name) {
2014 Some(function) => function,
2015 None => return Ok(None),
2016 };
2017 let mut arguments = Vec::with_capacity(invocation.len() + 1);
2018 arguments.push(form_to_value(&Form::List(invocation.to_vec()))?);
2019 arguments.push(macro_environment()?);
2020 for form in &invocation[1..] {
2021 arguments.push(form_to_value(form)?);
2022 }
2023 let expansion = call_function(&function, arguments)?;
2024 let expansion = value_to_form(&expansion)?;
2025 #[cfg(feature = "evaluation-journal")]
2026 evaluation_journal_macro(name, &Form::List(invocation.to_vec()), &expansion);
2027 Ok(Some(expansion))
2028}
2029
2030pub(crate) fn form_without_metadata(mut form: &Form) -> &Form {
2031 while let Form::Metadata(_, value) = form {
2032 form = value.as_ref();
2033 }
2034 form
2035}
2036
2037fn macro_clause_with_implicit_params(clause: &Form) -> Result<Form, String> {
2038 match form_without_metadata(clause) {
2039 Form::List(parts) if !parts.is_empty() => {
2040 let params = match form_without_metadata(&parts[0]) {
2041 Form::Vector(params) => params,
2042 _ => return Err("macro arity must start with a parameter vector".into()),
2043 };
2044 let mut implicit = vec![Form::Symbol("&form".into()), Form::Symbol("&env".into())];
2045 implicit.extend_from_slice(params);
2046 let mut new_parts = vec![Form::Vector(implicit)];
2047 new_parts.extend_from_slice(&parts[1..]);
2048 Ok(Form::List(new_parts))
2049 }
2050 _ => Err("macro arity must be a list".into()),
2051 }
2052}
2053
2054fn macroexpand_once(form: &Form, env: &mut HashMap<String, Value>) -> Result<Form, String> {
2055 match form {
2056 Form::List(values) if !values.is_empty() => {
2057 if let Form::Symbol(name) = &values[0] {
2058 if let Some(expanded) = macroexpand_call(name, values, env)? {
2059 return Ok(expanded);
2060 }
2061 }
2062 Ok(form.clone())
2063 }
2064 _ => Ok(form.clone()),
2065 }
2066}
2067
2068pub(crate) fn vm_macroexpand(form: &Form) -> Result<Form, String> {
2069 let mut current = form.clone();
2070 let mut env = HashMap::new();
2071 for _ in 0..1000 {
2072 let expanded = macroexpand_once(¤t, &mut env)?;
2073 if expanded == current {
2074 return Ok(current);
2075 }
2076 current = expanded;
2077 }
2078 Err("macro expansion exceeded 1000 steps".into())
2079}
2080
2081thread_local! {
2082 static TRACE_ENABLED: Cell<bool> = const { Cell::new(false) };
2083 static TRACE_STACK: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
2084 #[cfg(feature = "evaluation-journal")]
2085 static EVALUATION_JOURNAL: RefCell<Option<crate::journal::JournalCollector>> = const { RefCell::new(None) };
2086 #[cfg(feature = "evaluation-journal")]
2087 static EVALUATION_JOURNAL_STACK: RefCell<Vec<crate::journal::OperationId>> = const { RefCell::new(Vec::new()) };
2088 static ACTIVE_MACROS: RefCell<Option<Rc<RefCell<HashMap<(String, String), Rc<Function>>>>>> =
2089 const { RefCell::new(None) };
2090 static GENSYM_COUNTER: Cell<u64> = const { Cell::new(0) };
2091}
2092
2093pub(crate) fn trace_stack_snapshot() -> Vec<String> {
2094 TRACE_STACK.with(|stack| stack.borrow().clone())
2095}
2096
2097pub(crate) fn with_trace_stack<R>(trace: &[String], operation: impl FnOnce() -> R) -> R {
2098 let previous = TRACE_STACK.with(|stack| {
2099 std::mem::replace(&mut *stack.borrow_mut(), trace.to_vec())
2100 });
2101 let result = operation();
2102 TRACE_STACK.with(|stack| {
2103 *stack.borrow_mut() = previous;
2104 });
2105 result
2106}
2107
2108pub(crate) fn trace_frame_label(
2109 name: String,
2110 namespace: Option<String>,
2111 site: Option<ExceptionSite>,
2112) -> String {
2113 let label = namespace
2114 .map(|namespace| format!("{namespace}/{name}"))
2115 .unwrap_or(name);
2116 match site {
2117 Some(site) if site.line > 0 => format!("{label} @ {}:{}", site.line, site.column),
2118 _ => label,
2119 }
2120}
2121
2122#[cfg(feature = "evaluation-journal")]
2123fn journal_preview(value: &Value) -> crate::journal::ValuePreview {
2124 EVALUATION_JOURNAL.with(|active| {
2125 active
2126 .borrow()
2127 .as_ref()
2128 .expect("evaluation journal must be active")
2129 .preview_value(portable_type_name(value), value.display())
2130 })
2131}
2132
2133#[cfg(feature = "evaluation-journal")]
2134fn evaluation_journal_enter(
2135 function: &Function,
2136 arguments: &[Value],
2137) -> Option<crate::journal::OperationId> {
2138 if EVALUATION_JOURNAL.with(|active| active.borrow().is_none()) {
2139 return None;
2140 }
2141 let values = arguments.iter().map(journal_preview).collect();
2142 let parent_operation = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().last().copied());
2143 let depth = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().len());
2144 EVALUATION_JOURNAL.with(|active| {
2145 let mut active = active.borrow_mut();
2146 let collector = active.as_mut()?;
2147 let operation = collector.next_operation_id();
2148 let mut event =
2149 crate::journal::JournalEvent::new(crate::journal::JournalEventKind::OperationEnter);
2150 event.operation = Some(operation);
2151 event.parent_operation = parent_operation;
2152 event.depth = depth;
2153 event.function = Some(
2154 function
2155 .name
2156 .clone()
2157 .unwrap_or_else(|| "<anonymous>".into()),
2158 );
2159 event.values = values;
2160 collector.record(event);
2161 EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow_mut().push(operation));
2162 Some(operation)
2163 })
2164}
2165
2166#[cfg(feature = "evaluation-journal")]
2167fn evaluation_journal_exit(
2168 operation: Option<crate::journal::OperationId>,
2169 function: &Function,
2170 result: Option<&Value>,
2171) {
2172 let Some(operation) = operation else { return };
2173 let value = result.map(journal_preview);
2174 EVALUATION_JOURNAL.with(|active| {
2175 if let Some(collector) = active.borrow_mut().as_mut() {
2176 let mut event = crate::journal::JournalEvent::new(
2177 crate::journal::JournalEventKind::OperationReturn,
2178 );
2179 event.operation = Some(operation);
2180 event.function = Some(
2181 function
2182 .name
2183 .clone()
2184 .unwrap_or_else(|| "<anonymous>".into()),
2185 );
2186 event.values = value.into_iter().collect();
2187 collector.record(event);
2188 }
2189 });
2190 EVALUATION_JOURNAL_STACK.with(|stack| {
2191 let popped = stack.borrow_mut().pop();
2192 debug_assert_eq!(popped, Some(operation));
2193 });
2194}
2195
2196#[cfg(feature = "evaluation-journal")]
2197fn evaluation_journal_macro(name: &str, source: &Form, expansion: &Form) {
2198 let parent_operation = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().last().copied());
2199 let depth = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().len());
2200 EVALUATION_JOURNAL.with(|active| {
2201 if let Some(collector) = active.borrow_mut().as_mut() {
2202 let mut event =
2203 crate::journal::JournalEvent::new(crate::journal::JournalEventKind::MacroExpand);
2204 event.parent_operation = parent_operation;
2205 event.depth = depth;
2206 event.function = Some(name.into());
2207 event.values = vec![
2208 collector.preview_value("form", source.to_string()),
2209 collector.preview_value("form", expansion.to_string()),
2210 ];
2211 collector.record(event);
2212 }
2213 });
2214}
2215
2216struct StackTraceGuard {
2217 previous: bool,
2218}
2219
2220impl StackTraceGuard {
2221 fn enable() -> Self {
2222 let previous = TRACE_ENABLED.with(|enabled| {
2223 let previous = enabled.get();
2224 enabled.set(true);
2225 previous
2226 });
2227 TRACE_STACK.with(|stack| stack.borrow_mut().clear());
2228 Self { previous }
2229 }
2230}
2231
2232pub(crate) fn with_stack_trace<R>(operation: impl FnOnce() -> R) -> R {
2238 let _guard = StackTraceGuard::enable();
2239 operation()
2240}
2241
2242impl Drop for StackTraceGuard {
2243 fn drop(&mut self) {
2244 TRACE_STACK.with(|stack| stack.borrow_mut().clear());
2245 TRACE_ENABLED.with(|enabled| enabled.set(self.previous));
2246 }
2247}
2248
2249fn tracing_enabled() -> bool {
2250 TRACE_ENABLED.with(Cell::get)
2251}
2252
2253pub(crate) fn append_trace(error: String) -> String {
2254 if !tracing_enabled() {
2255 return error;
2256 }
2257 let frames = TRACE_STACK.with(|stack| stack.borrow().iter().rev().cloned().collect::<Vec<_>>());
2258 if frames.is_empty() {
2259 return error;
2260 }
2261 if error.contains("\n[hara stack]") {
2262 return error;
2263 }
2264 format!(
2265 "{error}\n[hara stack]\n{}",
2266 frames
2267 .iter()
2268 .map(|frame| format!(" at {frame}"))
2269 .collect::<Vec<_>>()
2270 .join("\n")
2271 )
2272}
2273
2274#[derive(Debug, Clone)]
2275enum IteratorGenerator {
2276 Seq(PSeq<Result<Value, String>>),
2277 Constant(Value),
2278 Repeated(Value),
2279 Iterate(Value, Value),
2280 Take(Value, usize),
2281 Drop(Value, usize),
2282 Cycle(Value, Vec<Value>, usize, bool),
2283 TakeWhile(Value, Value),
2284 DropWhile(Value, Value, bool),
2285 Map(Value, Value, bool),
2286 Filter(Value, Value),
2287 Mapcat(Value, Value, Option<Value>),
2288 Keep(Value, Value),
2289 Prepend(Option<Value>, Value),
2290 Concat(Vec<Value>, usize),
2291 Zip(Vec<Value>),
2292 Interleave(Vec<Value>, usize),
2293 Interpose(Value, Value, bool, Option<Value>),
2294 Partition(Value, usize, bool),
2295}
2296
2297#[derive(Debug, Clone)]
2298pub struct IteratorState {
2299 values: Vec<Value>,
2300 index: usize,
2301 closed: bool,
2302 cycle: bool,
2303 lookahead: Option<Value>,
2304 generator: Option<IteratorGenerator>,
2305}
2306
2307fn close_iterator_source(value: &Value) {
2308 if let Value::Iterator(iterator) = value {
2309 if let Ok(mut state) = iterator.try_borrow_mut() {
2310 state.close();
2311 }
2312 }
2313}
2314
2315impl IteratorState {
2316 fn new(values: Vec<Value>) -> Self {
2317 Self {
2318 values,
2319 index: 0,
2320 closed: false,
2321 cycle: false,
2322 lookahead: None,
2323 generator: None,
2324 }
2325 }
2326 fn generated(generator: IteratorGenerator) -> Self {
2327 Self {
2328 values: Vec::new(),
2329 index: 0,
2330 closed: false,
2331 cycle: false,
2332 lookahead: None,
2333 generator: Some(generator),
2334 }
2335 }
2336 pub(crate) fn is_finite(&self) -> bool {
2337 if self.closed || self.generator.is_none() {
2338 return true;
2339 }
2340 match self.generator.as_ref().unwrap() {
2341 IteratorGenerator::Seq(_) => false,
2342 IteratorGenerator::Constant(_)
2343 | IteratorGenerator::Repeated(_)
2344 | IteratorGenerator::Iterate(_, _)
2345 | IteratorGenerator::Cycle(_, _, _, _) => false,
2346 IteratorGenerator::Take(_, _) => true,
2347 IteratorGenerator::Drop(source, _)
2348 | IteratorGenerator::TakeWhile(_, source)
2349 | IteratorGenerator::DropWhile(_, source, _)
2350 | IteratorGenerator::Map(_, source, _)
2351 | IteratorGenerator::Filter(_, source)
2352 | IteratorGenerator::Keep(_, source)
2353 | IteratorGenerator::Prepend(_, source)
2354 | IteratorGenerator::Interpose(source, _, _, _)
2355 | IteratorGenerator::Partition(source, _, _) => value_iterator_is_finite(source),
2356 IteratorGenerator::Mapcat(_, _, _) => false,
2357 IteratorGenerator::Concat(sources, _) | IteratorGenerator::Interleave(sources, _) => {
2358 sources.iter().all(value_iterator_is_finite)
2359 }
2360 IteratorGenerator::Zip(sources) => sources.iter().any(value_iterator_is_finite),
2361 }
2362 }
2363 fn has_next(&mut self) -> Result<bool, String> {
2364 if self.lookahead.is_some() {
2365 return Ok(true);
2366 }
2367 match self.pull_next()? {
2368 Some(value) => {
2369 self.lookahead = Some(value);
2370 Ok(true)
2371 }
2372 None => Ok(false),
2373 }
2374 }
2375 fn try_next(&mut self) -> Result<Option<Value>, String> {
2376 if let Some(value) = self.lookahead.take() {
2377 return Ok(Some(value));
2378 }
2379 self.pull_next()
2380 }
2381 fn pull_next(&mut self) -> Result<Option<Value>, String> {
2382 if self.closed {
2383 return Ok(None);
2384 }
2385 if let Some(generator) = &mut self.generator {
2386 return match generator {
2387 IteratorGenerator::Seq(sequence) => match sequence.peek_first() {
2388 None => {
2389 self.closed = true;
2390 Ok(None)
2391 }
2392 Some(result) => {
2393 *sequence = sequence.pop_first();
2394 result.map(Some)
2395 }
2396 },
2397 IteratorGenerator::Constant(value) => Ok(Some(value.clone())),
2398 IteratorGenerator::Repeated(function) => {
2399 call_value(function.clone(), Vec::new()).map(Some)
2400 }
2401 IteratorGenerator::Iterate(function, current) => {
2402 let output = current.clone();
2403 *current = call_value(function.clone(), vec![current.clone()])?;
2404 Ok(Some(output))
2405 }
2406 IteratorGenerator::Take(source, remaining) => {
2407 if *remaining == 0 {
2408 close_iterator_source(source);
2409 self.closed = true;
2410 Ok(None)
2411 } else {
2412 *remaining -= 1;
2413 let value = iterator_try_next(source)?;
2414 if value.is_none() {
2415 close_iterator_source(source);
2416 self.closed = true;
2417 }
2418 Ok(value)
2419 }
2420 }
2421 IteratorGenerator::Drop(source, remaining) => {
2422 while *remaining > 0 {
2423 if iterator_try_next(source)?.is_none() {
2424 close_iterator_source(source);
2425 self.closed = true;
2426 return Ok(None);
2427 }
2428 *remaining -= 1;
2429 }
2430 let value = iterator_try_next(source)?;
2431 if value.is_none() {
2432 close_iterator_source(source);
2433 self.closed = true;
2434 }
2435 Ok(value)
2436 }
2437 IteratorGenerator::Cycle(source, cache, index, exhausted) => {
2438 if *index < cache.len() {
2439 let value = cache[*index].clone();
2440 *index += 1;
2441 Ok(Some(value))
2442 } else if *exhausted {
2443 if cache.is_empty() {
2444 self.closed = true;
2445 Ok(None)
2446 } else {
2447 *index = 1;
2448 Ok(Some(cache[0].clone()))
2449 }
2450 } else {
2451 match iterator_try_next(source)? {
2452 Some(value) => {
2453 cache.push(value.clone());
2454 *index += 1;
2455 Ok(Some(value))
2456 }
2457 None => {
2458 close_iterator_source(source);
2459 *exhausted = true;
2460 if cache.is_empty() {
2461 self.closed = true;
2462 Ok(None)
2463 } else {
2464 *index = 1;
2465 Ok(Some(cache[0].clone()))
2466 }
2467 }
2468 }
2469 }
2470 }
2471 IteratorGenerator::TakeWhile(function, source) => {
2472 let Some(value) = iterator_try_next(source)? else {
2473 close_iterator_source(source);
2474 self.closed = true;
2475 return Ok(None);
2476 };
2477 if call_value(function.clone(), vec![value.clone()])?.truthy() {
2478 Ok(Some(value))
2479 } else {
2480 close_iterator_source(source);
2481 self.closed = true;
2482 Ok(None)
2483 }
2484 }
2485 IteratorGenerator::DropWhile(function, source, started) => loop {
2486 let Some(value) = iterator_try_next(source)? else {
2487 close_iterator_source(source);
2488 self.closed = true;
2489 break Ok(None);
2490 };
2491 if *started || !call_value(function.clone(), vec![value.clone()])?.truthy() {
2492 *started = true;
2493 break Ok(Some(value));
2494 }
2495 },
2496 IteratorGenerator::Map(function, source, spread) => {
2497 let Some(value) = iterator_try_next(source)? else {
2498 close_iterator_source(source);
2499 self.closed = true;
2500 return Ok(None);
2501 };
2502 match value {
2503 value if !*spread => call_value(function.clone(), vec![value]),
2504 Value::Tuple(values) => {
2505 call_value(function.clone(), values.iter().cloned().collect())
2506 }
2507 Value::Vector(values) => {
2508 call_value(function.clone(), values.iter().cloned().collect())
2509 }
2510 value => call_value(function.clone(), vec![value]),
2511 }
2512 .map(Some)
2513 }
2514 IteratorGenerator::Filter(function, source) => loop {
2515 let Some(value) = iterator_try_next(source)? else {
2516 close_iterator_source(source);
2517 self.closed = true;
2518 break Ok(None);
2519 };
2520 if call_value(function.clone(), vec![value.clone()])?.truthy() {
2521 break Ok(Some(value));
2522 }
2523 },
2524 IteratorGenerator::Mapcat(function, source, pending) => loop {
2525 if let Some(iterator) = pending {
2526 match iterator_try_next(iterator)? {
2527 Some(value) => break Ok(Some(value)),
2528 None => {
2529 close_iterator_source(iterator);
2530 *pending = None;
2531 }
2532 }
2533 }
2534 let Some(value) = iterator_try_next(source)? else {
2535 close_iterator_source(source);
2536 self.closed = true;
2537 break Ok(None);
2538 };
2539 *pending = Some(make_iterator(call_value(function.clone(), vec![value])?)?);
2540 },
2541 IteratorGenerator::Keep(function, source) => loop {
2542 let Some(value) = iterator_try_next(source)? else {
2543 close_iterator_source(source);
2544 self.closed = true;
2545 break Ok(None);
2546 };
2547 let mapped = call_value(function.clone(), vec![value])?;
2548 if !matches!(mapped, Value::Nil) {
2549 break Ok(Some(mapped));
2550 }
2551 },
2552 IteratorGenerator::Prepend(head, source) => {
2553 if let Some(value) = head.take() {
2554 Ok(Some(value))
2555 } else {
2556 let value = iterator_try_next(source)?;
2557 if value.is_none() {
2558 close_iterator_source(source);
2559 self.closed = true;
2560 }
2561 Ok(value)
2562 }
2563 }
2564 IteratorGenerator::Concat(sources, index) => {
2565 while *index < sources.len() {
2566 match iterator_try_next(&sources[*index])? {
2567 Some(value) => return Ok(Some(value)),
2568 None => {
2569 close_iterator_source(&sources[*index]);
2570 *index += 1;
2571 }
2572 }
2573 }
2574 self.closed = true;
2575 Ok(None)
2576 }
2577 IteratorGenerator::Zip(sources) => {
2578 for source in sources.iter() {
2579 if !matches!(iterator_has_next(source)?, Value::Bool(true)) {
2580 for source in sources.iter() {
2581 close_iterator_source(source);
2582 }
2583 self.closed = true;
2584 return Ok(None);
2585 }
2586 }
2587 let mut values = Vec::new();
2588 for source in sources.iter() {
2589 let Some(value) = iterator_try_next(source)? else {
2590 for source in sources.iter() {
2591 close_iterator_source(source);
2592 }
2593 self.closed = true;
2594 return Ok(None);
2595 };
2596 values.push(value);
2597 }
2598 Ok(Some(Value::Vector(values.into())))
2599 }
2600 IteratorGenerator::Interleave(sources, index) => {
2601 if sources.is_empty() {
2602 self.closed = true;
2603 return Ok(None);
2604 }
2605 if *index == 0 {
2606 for source in sources.iter() {
2607 if !matches!(iterator_has_next(source)?, Value::Bool(true)) {
2608 for source in sources.iter() {
2609 close_iterator_source(source);
2610 }
2611 self.closed = true;
2612 return Ok(None);
2613 }
2614 }
2615 }
2616 let source = &sources[*index];
2617 let Some(value) = iterator_try_next(source)? else {
2618 for source in sources.iter() {
2619 close_iterator_source(source);
2620 }
2621 self.closed = true;
2622 return Ok(None);
2623 };
2624 *index = (*index + 1) % sources.len();
2625 Ok(Some(value))
2626 }
2627 IteratorGenerator::Interpose(source, separator, first, pending) => {
2628 if let Some(value) = pending.take() {
2629 return Ok(Some(value));
2630 }
2631 match iterator_try_next(source)? {
2632 None => {
2633 close_iterator_source(source);
2634 self.closed = true;
2635 Ok(None)
2636 }
2637 Some(value) if *first => {
2638 *first = false;
2639 Ok(Some(value))
2640 }
2641 Some(value) => {
2642 *pending = Some(value);
2643 Ok(Some(separator.clone()))
2644 }
2645 }
2646 }
2647 IteratorGenerator::Partition(source, amount, all) => {
2648 let mut values = Vec::new();
2649 for _ in 0..*amount {
2650 match iterator_try_next(source)? {
2651 Some(value) => values.push(value),
2652 None => {
2653 close_iterator_source(source);
2654 self.closed = true;
2655 if values.is_empty() || !*all {
2656 return Ok(None);
2657 }
2658 break;
2659 }
2660 }
2661 }
2662 if values.is_empty() {
2663 self.closed = true;
2664 Ok(None)
2665 } else {
2666 Ok(Some(Value::Vector(values.into())))
2667 }
2668 }
2669 };
2670 }
2671 if self.values.is_empty() {
2672 self.closed = true;
2673 return Ok(None);
2674 }
2675 if self.cycle && self.index >= self.values.len() {
2676 self.index = 0;
2677 }
2678 if self.index >= self.values.len() {
2679 self.closed = true;
2680 return Ok(None);
2681 }
2682 let value = self.values[self.index].clone();
2683 self.index += 1;
2684 Ok(Some(value))
2685 }
2686 fn close(&mut self) {
2687 if self.closed {
2688 self.lookahead = None;
2689 return;
2690 }
2691 self.closed = true;
2692 self.lookahead = None;
2693 if let Some(generator) = &self.generator {
2694 match generator {
2695 IteratorGenerator::Constant(_)
2696 | IteratorGenerator::Repeated(_)
2697 | IteratorGenerator::Iterate(_, _)
2698 | IteratorGenerator::Seq(_) => {}
2699 IteratorGenerator::Take(source, _)
2700 | IteratorGenerator::Drop(source, _)
2701 | IteratorGenerator::Cycle(source, _, _, _)
2702 | IteratorGenerator::TakeWhile(_, source)
2703 | IteratorGenerator::DropWhile(_, source, _)
2704 | IteratorGenerator::Map(_, source, _)
2705 | IteratorGenerator::Filter(_, source)
2706 | IteratorGenerator::Keep(_, source)
2707 | IteratorGenerator::Prepend(_, source)
2708 | IteratorGenerator::Interpose(source, _, _, _)
2709 | IteratorGenerator::Partition(source, _, _) => close_iterator_source(source),
2710 IteratorGenerator::Mapcat(_, source, pending) => {
2711 close_iterator_source(source);
2712 if let Some(pending) = pending {
2713 close_iterator_source(pending);
2714 }
2715 }
2716 IteratorGenerator::Concat(sources, _)
2717 | IteratorGenerator::Zip(sources)
2718 | IteratorGenerator::Interleave(sources, _) => {
2719 for source in sources {
2720 close_iterator_source(source);
2721 }
2722 }
2723 }
2724 }
2725 }
2726}
2727
2728fn value_iterator_is_finite(value: &Value) -> bool {
2729 match value {
2730 Value::Iterator(iterator) => iterator.borrow().is_finite(),
2731 Value::Seq(_) => false,
2732 _ => true,
2733 }
2734}
2735
2736#[inline(never)]
2737fn sequential_equality(left: &Value, right: &Value) -> Option<bool> {
2738 fn items(value: &Value) -> Option<Vec<Value>> {
2739 match value {
2740 Value::Seq(values) => values.iter().collect::<Result<Vec<_>, _>>().ok(),
2741 Value::List(values) => Some(values.iter().cloned().collect()),
2742 Value::Cons(values) => Some(values.iter().collect()),
2743 Value::Queue(values) => Some(values.iter().cloned().collect()),
2744 Value::Deque(values) => Some(values.iter().cloned().collect()),
2745 Value::Tuple(values) => Some(values.iter().cloned().collect()),
2746 Value::Vector(values) => Some(values.iter().cloned().collect()),
2747 _ => None,
2748 }
2749 }
2750 Some(items(left)? == items(right)?)
2751}
2752
2753pub fn map_entries(value: &Value) -> Option<Vec<(Value, Value)>> {
2757 match value {
2758 Value::Map(values) => Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect()),
2759 Value::OrderedMap(values) => {
2760 Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
2761 }
2762 Value::SortedMap(values) => {
2763 Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
2764 }
2765 Value::PriorityMap(values) => Some(values.iter().collect()),
2766 Value::Trie(values) => Some(
2767 values
2768 .entries()
2769 .into_iter()
2770 .map(|(k, v)| (Value::String(k), v.clone()))
2771 .collect(),
2772 ),
2773 _ => None,
2774 }
2775}
2776
2777fn pointer_from_descriptor(descriptor: Value) -> Result<Value, String> {
2778 let entries =
2779 map_entries(&descriptor).ok_or_else(|| "pointer expects one descriptor map".to_string())?;
2780 let context_key = Value::Keyword(Keyword::from("context"));
2781 let mut context = None;
2782 let mut fields = Vec::new();
2783 for (key, value) in entries {
2784 if key == context_key {
2785 if context.is_some() {
2786 return Err("pointer descriptor contains duplicate :context".into());
2787 }
2788 context = match value {
2789 Value::Keyword(context) => Some(context),
2790 _ => return Err("pointer :context must be a keyword".into()),
2791 };
2792 } else {
2793 if !matches!(key, Value::Keyword(_)) {
2794 return Err("pointer descriptor fields must use keyword keys".into());
2795 }
2796 fields.push((key, value));
2797 }
2798 }
2799 let context = context.ok_or_else(|| "pointer descriptor requires :context".to_string())?;
2800 Ok(Value::Pointer(PPointer::new(
2801 context,
2802 fields.into_iter().collect(),
2803 )))
2804}
2805
2806pub(crate) fn session_transferable(value: &Value) -> bool {
2813 match value {
2814 Value::Number(_)
2815 | Value::Float(_)
2816 | Value::BigInteger(_)
2817 | Value::Character(_)
2818 | Value::Regex(_)
2819 | Value::Tagged(_)
2820 | Value::Bool(_)
2821 | Value::String(_)
2822 | Value::Keyword(_)
2823 | Value::Bytes(_)
2824 | Value::Symbol(_)
2825 | Value::Nil => true,
2826 value @ (Value::Map(_)
2827 | Value::OrderedMap(_)
2828 | Value::SortedMap(_)
2829 | Value::Trie(_)
2830 | Value::PriorityMap(_)) => map_entries(value).is_some_and(|entries| {
2831 entries
2832 .iter()
2833 .all(|(key, value)| session_transferable(key) && session_transferable(value))
2834 }),
2835 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => set_items(value)
2836 .is_some_and(|values| values.iter().all(|value| session_transferable(value))),
2837 Value::List(values) => values.iter().all(session_transferable),
2838 Value::Cons(values) => values.iter().all(|value| session_transferable(&value)),
2839 Value::Queue(values) => values.iter().all(session_transferable),
2840 Value::Deque(values) => values.iter().all(session_transferable),
2841 Value::Tuple(values) => values.iter().all(session_transferable),
2842 Value::Vector(values) => values.iter().all(session_transferable),
2843 Value::MapEntry(entry) => {
2844 session_transferable(entry.key()) && session_transferable(entry.value())
2845 }
2846 Value::Struct(value) => value.ordered_values().into_iter().all(session_transferable),
2847 Value::Pointer(value) => value
2848 .fields()
2849 .iter()
2850 .all(|(key, value)| session_transferable(key) && session_transferable(value)),
2851 Value::ExceptionInfo(value) => {
2852 session_transferable(&value.data)
2853 && value.cause.as_deref().map_or(true, session_transferable)
2854 }
2855 Value::ByteBuffer(_)
2856 | Value::Array(_)
2857 | Value::Object(_)
2858 | Value::Promise(_)
2859 | Value::Atom(_)
2860 | Value::Recur(_)
2861 | Value::Function(_)
2862 | Value::Seq(_)
2863 | Value::Iterator(_)
2864 | Value::Var(_)
2865 | Value::Namespace(_)
2866 | Value::Extension(_)
2867 | Value::StructType(_)
2868 | Value::MutableType(_)
2869 | Value::Mutable(_)
2870 | Value::Protocol(_)
2871 | Value::NativeType(_)
2872 | Value::Schema(_)
2873 | Value::Coroutine(_)
2874 | Value::Stream(_)
2875 | Value::Result(_)
2876 | Value::MutableCollection(_) => false,
2877 }
2878}
2879
2880fn map_value<'a>(value: &'a Value, key: &Value) -> Option<&'a Value> {
2881 match value {
2882 Value::Map(values) => values.get(key),
2883 Value::OrderedMap(values) => values.get(key),
2884 Value::SortedMap(values) => values.get(key),
2885 Value::PriorityMap(values) => values.get(key),
2886 Value::Trie(values) => match key {
2887 Value::String(key) => values.get(key),
2888 _ => None,
2889 },
2890 _ => None,
2891 }
2892}
2893
2894fn map_equality(left: &Value, right: &Value) -> Option<bool> {
2895 let left_entries = map_entries(left)?;
2896 let right_entries = map_entries(right)?;
2897 Some(
2898 left_entries.len() == right_entries.len()
2899 && left_entries
2900 .iter()
2901 .all(|(key, value)| map_value(right, key) == Some(value)),
2902 )
2903}
2904
2905fn set_items(value: &Value) -> Option<Vec<&Value>> {
2906 match value {
2907 Value::Set(values) => Some(values.iter().collect()),
2908 Value::OrderedSet(values) => Some(values.iter().collect()),
2909 Value::SortedSet(values) => Some(values.iter().collect()),
2910 _ => None,
2911 }
2912}
2913
2914fn set_equality(left: &Value, right: &Value) -> Option<bool> {
2915 let left_items = set_items(left)?;
2916 let right_items = set_items(right)?;
2917 Some(
2918 left_items.len() == right_items.len()
2919 && left_items.iter().all(|item| right_items.contains(item)),
2920 )
2921}
2922
2923fn map_assoc_value(collection: &Value, key: Value, value: Value) -> Result<Value, String> {
2924 Ok(match collection {
2925 Value::Map(values) => Value::Map(values.assoc_value(key, value)),
2926 Value::OrderedMap(values) => Value::OrderedMap(Box::new(values.assoc_value(key, value))),
2927 Value::SortedMap(values) => Value::SortedMap(Box::new(values.assoc_value(key, value))),
2928 Value::PriorityMap(values) => Value::PriorityMap(Box::new(values.assoc_value(key, value))),
2929 Value::Trie(values) => match key {
2930 Value::String(key) => Value::Trie(Box::new(values.assoc_value(key, value))),
2931 _ => return Err("trie expects string keys".into()),
2932 },
2933 _ => return Err("assoc expects a map".into()),
2934 })
2935}
2936
2937fn map_dissoc_value(collection: &Value, key: &Value) -> Result<Value, String> {
2938 Ok(match collection {
2939 Value::Map(values) => Value::Map(values.dissoc_value(key)),
2940 Value::OrderedMap(values) => Value::OrderedMap(Box::new(values.dissoc_value(key))),
2941 Value::SortedMap(values) => Value::SortedMap(Box::new(values.dissoc_value(key))),
2942 Value::PriorityMap(values) => Value::PriorityMap(Box::new(values.dissoc_value(key))),
2943 Value::Trie(values) => match key {
2944 Value::String(key) => Value::Trie(Box::new(values.dissoc_value(key))),
2945 _ => return Err("trie expects string keys".into()),
2946 },
2947 _ => return Err("dissoc expects a map".into()),
2948 })
2949}
2950
2951fn set_find(collection: &Value, key: &Value) -> Option<Value> {
2952 set_items(collection)?
2953 .into_iter()
2954 .find(|value| *value == key)
2955 .cloned()
2956}
2957
2958fn set_conj_value(collection: &Value, value: Value) -> Result<Value, String> {
2959 Ok(match collection {
2960 Value::Set(values) => Value::Set(values.conj_value(value)),
2961 Value::OrderedSet(values) => Value::OrderedSet(Box::new(values.conj_value(value))),
2962 Value::SortedSet(values) => Value::SortedSet(Box::new(values.conj_value(value))),
2963 _ => return Err("conj expects a set".into()),
2964 })
2965}
2966
2967fn set_dissoc_value(collection: &Value, value: &Value) -> Result<Value, String> {
2968 Ok(match collection {
2969 Value::Set(values) => Value::Set(values.dissoc_value(value)),
2970 Value::OrderedSet(values) => Value::OrderedSet(Box::new(values.dissoc_value(value))),
2971 Value::SortedSet(values) => Value::SortedSet(Box::new(values.dissoc_value(value))),
2972 _ => return Err("dissoc expects a set".into()),
2973 })
2974}
2975
2976fn collection_to_mutable(value: &Value) -> Result<Value, String> {
2977 let mutable = match value {
2978 Value::Map(values) => MutableCollection::Map(values.to_mutable()),
2979 Value::OrderedMap(values) => MutableCollection::OrderedMap(values.to_mutable()),
2980 Value::SortedMap(values) => MutableCollection::SortedMap(values.to_mutable()),
2981 Value::Trie(values) => MutableCollection::Trie(values.to_mutable()),
2982 Value::Set(values) => MutableCollection::Set(values.to_mutable()),
2983 Value::OrderedSet(values) => MutableCollection::OrderedSet(values.to_mutable()),
2984 Value::SortedSet(values) => MutableCollection::SortedSet(values.to_mutable()),
2985 Value::List(values) => MutableCollection::List(values.to_mutable()),
2986 Value::Queue(values) => MutableCollection::Queue(values.to_mutable()),
2987 Value::Vector(values) => MutableCollection::Vector(values.to_mutable()),
2988 Value::MutableCollection(_) => return Err("value is already mutable".into()),
2989 _ => return Err("to-mutable expects a persistent collection".into()),
2990 };
2991 Ok(Value::MutableCollection(Rc::new(RefCell::new(Some(
2992 mutable,
2993 )))))
2994}
2995
2996fn collection_to_persistent(value: &Value) -> Result<Value, String> {
2997 let Value::MutableCollection(collection) = value else {
2998 return Err("to-persistent expects a mutable collection".into());
2999 };
3000 let mut mutable = collection
3001 .borrow_mut()
3002 .take()
3003 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
3004 Ok(match &mut mutable {
3005 MutableCollection::Map(values) => Value::Map(values.to_persistent()),
3006 MutableCollection::OrderedMap(values) => {
3007 Value::OrderedMap(Box::new(values.to_persistent()))
3008 }
3009 MutableCollection::SortedMap(values) => Value::SortedMap(Box::new(values.to_persistent())),
3010 MutableCollection::Trie(values) => Value::Trie(Box::new(values.to_persistent())),
3011 MutableCollection::Set(values) => Value::Set(values.to_persistent()),
3012 MutableCollection::OrderedSet(values) => {
3013 Value::OrderedSet(Box::new(values.to_persistent()))
3014 }
3015 MutableCollection::SortedSet(values) => Value::SortedSet(Box::new(values.to_persistent())),
3016 MutableCollection::List(values) => Value::List(values.to_persistent()),
3017 MutableCollection::Queue(values) => Value::Queue(Box::new(values.to_persistent())),
3018 MutableCollection::Vector(values) => Value::Vector(values.to_persistent()),
3019 })
3020}
3021
3022fn protocol_to_mutable(arguments: &[Value]) -> Result<Value, String> {
3023 match arguments {
3024 [Value::Extension(receiver)] => extension_protocol_call(
3025 receiver,
3026 "std.protocol.itomutable.IToMutable",
3027 "to-mutable",
3028 arguments,
3029 ),
3030 [value] => collection_to_mutable(value),
3031 _ => Err("IToMutable/to-mutable expects one value".into()),
3032 }
3033}
3034
3035fn protocol_to_persistent(arguments: &[Value]) -> Result<Value, String> {
3036 match arguments {
3037 [Value::Extension(receiver)] => extension_protocol_call(
3038 receiver,
3039 "std.protocol.itopersistent.IToPersistent",
3040 "to-persistent",
3041 arguments,
3042 ),
3043 [value] => collection_to_persistent(value),
3044 _ => Err("IToPersistent/to-persistent expects one value".into()),
3045 }
3046}
3047
3048impl PartialEq for Value {
3049 fn eq(&self, other: &Self) -> bool {
3050 if let Some(equal) = sequential_equality(self, other) {
3051 return equal;
3052 }
3053 if let Some(equal) = map_equality(self, other) {
3054 return equal;
3055 }
3056 if let Some(equal) = set_equality(self, other) {
3057 return equal;
3058 }
3059 if let Some(equal) = numeric::numeric_equal(self, other) {
3060 return equal;
3061 }
3062 match (self, other) {
3063 (Value::Number(a), Value::Number(b)) => a == b,
3064 (Value::Float(a), Value::Float(b)) => a.to_bits() == b.to_bits(),
3065 (Value::BigInteger(a), Value::BigInteger(b)) => a == b,
3066 (Value::Character(a), Value::Character(b)) => a == b,
3067 (Value::Regex(a), Value::Regex(b)) => a == b,
3068 (Value::Tagged(a), Value::Tagged(b)) => a == b,
3069 (Value::Bool(a), Value::Bool(b)) => a == b,
3070 (Value::String(a), Value::String(b)) => a == b,
3071 (Value::Keyword(a), Value::Keyword(b)) => a == b,
3072 (Value::Bytes(a), Value::Bytes(b)) => a == b,
3073 (Value::ByteBuffer(a), Value::ByteBuffer(b)) => *a.borrow() == *b.borrow(),
3074 (Value::Array(a), Value::Array(b)) => Rc::ptr_eq(a, b),
3075 (Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b),
3076 (Value::Promise(a), Value::Promise(b)) => a.same_identity(b),
3077 (Value::Atom(a), Value::Atom(b)) => a.same_identity(b),
3078 (Value::Recur(a), Value::Recur(b)) => a == b,
3079 (Value::Map(a), Value::Map(b)) => a == b,
3080 (Value::Set(a), Value::Set(b)) => a == b,
3081 (Value::List(a), Value::List(b)) => a == b,
3082 (Value::Cons(a), Value::Cons(b)) => a == b,
3083 (Value::Symbol(a), Value::Symbol(b)) => a == b,
3084 (Value::Pointer(a), Value::Pointer(b)) => a == b,
3085 (Value::Function(a), Value::Function(b)) => Rc::ptr_eq(a, b),
3086 (Value::Tuple(a), Value::Tuple(b)) => a == b,
3087 (Value::Vector(a), Value::Vector(b)) => a == b,
3088 (Value::MapEntry(a), Value::MapEntry(b)) => a == b,
3089 (Value::MutableCollection(a), Value::MutableCollection(b)) => Rc::ptr_eq(a, b),
3090 (Value::Iterator(a), Value::Iterator(b)) => Rc::ptr_eq(a, b),
3091 (Value::Var(a), Value::Var(b)) => a.same_identity(b),
3092 (Value::Namespace(a), Value::Namespace(b)) => a.same_identity(b),
3093 (Value::Extension(a), Value::Extension(b)) => a == b,
3094 (Value::StructType(a), Value::StructType(b)) => Rc::ptr_eq(a, b),
3095 (Value::Struct(a), Value::Struct(b)) => {
3096 Rc::ptr_eq(&a.ty, &b.ty) && a.values == b.values
3097 }
3098 (Value::MutableType(a), Value::MutableType(b)) => Rc::ptr_eq(a, b),
3099 (Value::Mutable(a), Value::Mutable(b)) => a.same_identity(b),
3100 (Value::Protocol(a), Value::Protocol(b)) => Rc::ptr_eq(a, b),
3101 (Value::NativeType(a), Value::NativeType(b)) => a.name == b.name,
3102 (Value::Schema(a), Value::Schema(b)) => a.ast == b.ast,
3103 (Value::Coroutine(a), Value::Coroutine(b)) => Rc::ptr_eq(a, b),
3104 (Value::Stream(a), Value::Stream(b)) => Rc::ptr_eq(a, b),
3105 (Value::Result(a), Value::Result(b)) => a == b,
3106 (Value::ExceptionInfo(a), Value::ExceptionInfo(b)) => Rc::ptr_eq(a, b),
3107 (Value::Nil, Value::Nil) => true,
3108 _ => false,
3109 }
3110 }
3111}
3112
3113impl Eq for Value {}
3114impl PartialOrd for Value {
3115 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3116 Some(self.cmp(other))
3117 }
3118}
3119impl Ord for Value {
3120 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3121 if let Some(ordering) = numeric::numeric_total_compare(self, other) {
3122 return ordering;
3123 }
3124 if self == other {
3125 return std::cmp::Ordering::Equal;
3126 }
3127 match (self, other) {
3128 (Value::Number(left), Value::Number(right)) => return left.cmp(right),
3129 (Value::Float(left), Value::Float(right)) => return left.total_cmp(right),
3130 (Value::Character(left), Value::Character(right)) => return left.cmp(right),
3131 (Value::Bool(left), Value::Bool(right)) => return left.cmp(right),
3132 (Value::String(left), Value::String(right)) => return left.cmp(right),
3133 (Value::Keyword(left), Value::Keyword(right)) => return left.cmp(right),
3134 (Value::BigInteger(left), Value::BigInteger(right)) => return left.cmp(right),
3135 _ => {}
3136 }
3137 fn rank(value: &Value) -> u8 {
3138 match value {
3139 Value::Nil => 0,
3140 Value::Bool(_) => 1,
3141 Value::Number(_) => 2,
3142 Value::Float(_) => 3,
3143 Value::BigInteger(_) => 4,
3144 Value::Character(_) => 5,
3145 Value::String(_) => 7,
3146 Value::Keyword(_) => 8,
3147 Value::Symbol(_) => 9,
3148 Value::Pointer(_) => 9,
3149 Value::List(_)
3150 | Value::Cons(_)
3151 | Value::Queue(_)
3152 | Value::Deque(_)
3153 | Value::Tuple(_)
3154 | Value::Vector(_)
3155 | Value::MapEntry(_)
3156 | Value::Seq(_) => 10,
3157 Value::Map(_)
3158 | Value::OrderedMap(_)
3159 | Value::SortedMap(_)
3160 | Value::Trie(_)
3161 | Value::PriorityMap(_) => 11,
3162 Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_) => 12,
3163 Value::Bytes(_) => 13,
3164 Value::ByteBuffer(_) => 14,
3165 Value::Regex(_) => 15,
3166 Value::Tagged(_) => 16,
3167 Value::Array(_) => 17,
3168 Value::Object(_) => 18,
3169 Value::Promise(_) => 19,
3170 Value::Atom(_) => 26,
3171 Value::Recur(_) => 20,
3172 Value::Function(_) => 21,
3173 Value::Iterator(_) => 22,
3174 Value::Var(_) => 23,
3175 Value::Namespace(_) => 24,
3176 Value::Extension(_) => 25,
3177 Value::StructType(_) => 27,
3178 Value::Struct(_) => 28,
3179 Value::MutableType(_) => 29,
3180 Value::Mutable(_) => 30,
3181 Value::Protocol(_) => 31,
3182 Value::NativeType(_) => 32,
3183 Value::Schema(_) => 33,
3184 Value::Coroutine(_) => 33,
3185 Value::Stream(_) => 34,
3186 Value::Result(_) => 36,
3187 Value::ExceptionInfo(_) => 37,
3188 Value::MutableCollection(_) => 38,
3189 }
3190 }
3191 rank(self)
3192 .cmp(&rank(other))
3193 .then_with(|| self.display().cmp(&other.display()))
3194 .then_with(|| self.stable_hash().cmp(&other.stable_hash()))
3195 }
3196}
3197impl Hash for Value {
3198 fn hash<H: Hasher>(&self, state: &mut H) {
3199 if crate::lang::data::map::champ_placement_hashing() {
3202 if let Self::Number(value) = self {
3203 state.write_u64(crate::lang::hash::hash_long_placement(*value) as i64 as u64);
3204 return;
3205 }
3206 if let Self::Float(value) = self {
3207 if value.is_finite() && value.fract() == 0.0 {
3208 if let Ok(integer) = (*value).to_string().parse::<i64>() {
3209 state.write_u64(
3210 crate::lang::hash::hash_long_placement(integer) as i64 as u64,
3211 );
3212 return;
3213 }
3214 }
3215 }
3216 }
3217 if let Some(hash) = numeric::numeric_hash(self) {
3218 state.write_u64(hash as i64 as u64);
3219 return;
3220 }
3221 match self {
3222 Value::Bool(value) => state.write_u64(crate::lang::hash::hash_bool(*value) as u64),
3223 Value::Nil => state.write_u64(0),
3224 _ => state.write_u64(self.stable_hash()),
3225 }
3226 }
3227}
3228
3229impl crate::lang::hash::JavaHash for Value {
3230 fn java_hash(&self, hash_type: crate::lang::protocol::HashType) -> i64 {
3235 use crate::lang::hash as jh;
3236 use crate::lang::protocol::IHash;
3237
3238 fn opaque(
3242 tag: u64,
3243 write: impl FnOnce(&mut std::collections::hash_map::DefaultHasher),
3244 ) -> i64 {
3245 let mut state = std::collections::hash_map::DefaultHasher::new();
3246 tag.hash(&mut state);
3247 write(&mut state);
3248 state.finish() as i64
3249 }
3250
3251 match self {
3252 Self::Nil => 0,
3253 Self::Bool(v) => jh::hash_bool(*v) as i64,
3254 Self::Character(v) => jh::hash_char(*v) as i64,
3255 Self::String(v) => jh::java_string_hash(v) as i64,
3256 Self::Number(value) => jh::hash_long(*value) as i64,
3257 Self::Float(value) => jh::hash_double(*value) as i64,
3258 Self::BigInteger(value) => jh::canonical_decimal_str_hash(&value.to_string()) as i64,
3259 Self::Regex(v) => jh::java_string_hash(v) as i64,
3262 Self::Keyword(v) => v.java_hash(hash_type),
3263 Self::Symbol(v) => v.java_hash(hash_type),
3264 Self::Pointer(v) => v.java_hash(hash_type),
3265 Self::Bytes(v) => jh::hash_bytes(v) as i64,
3266 Self::ByteBuffer(v) => jh::hash_bytes(v.borrow().as_slice()) as i64,
3267 Self::Array(v) => jh::compose_ordered(
3269 "SEQUENTIAL",
3270 v.borrow().iter().map(|item| item.java_hash(hash_type)),
3271 ),
3272 Self::Object(v) => jh::compose_unordered(
3273 "MAP",
3274 v.borrow().iter().map(|(key, item)| {
3275 jh::compose_entry(jh::java_string_hash(key) as i64, item.java_hash(hash_type))
3276 }),
3277 ),
3278 Self::Recur(v) => {
3279 jh::compose_ordered("SEQUENTIAL", v.iter().map(|item| item.java_hash(hash_type)))
3280 }
3281 Self::Tagged(v) => jh::compose_ordered(
3282 "SEQUENTIAL",
3283 [v.tag().java_hash(hash_type), v.form().java_hash(hash_type)],
3284 ),
3285 Self::Map(v) => v.hash_calc(hash_type) as i64,
3286 Self::OrderedMap(v) => v.hash_calc(hash_type) as i64,
3287 Self::SortedMap(v) => v.hash_calc(hash_type) as i64,
3288 Self::PriorityMap(v) => v.hash_calc(hash_type) as i64,
3289 Self::Trie(v) => v.hash_calc(hash_type) as i64,
3290 Self::Set(v) => v.hash_calc(hash_type) as i64,
3291 Self::OrderedSet(v) => v.hash_calc(hash_type) as i64,
3292 Self::SortedSet(v) => v.hash_calc(hash_type) as i64,
3293 Self::List(v) => v.hash_calc(hash_type) as i64,
3294 Self::Cons(v) => v.hash_calc(hash_type) as i64,
3295 Self::Deque(v) => v.hash_calc(hash_type) as i64,
3296 Self::Queue(v) => v.hash_calc(hash_type) as i64,
3297 Self::Tuple(v) => v.hash_calc(hash_type) as i64,
3298 Self::Vector(v) => v.hash_calc(hash_type) as i64,
3299 Self::MapEntry(v) => v.hash_calc(hash_type) as i64,
3300 Self::Seq(v) => jh::compose_ordered(
3301 "SEQUENTIAL",
3302 v.iter().map(|item| match item {
3303 Ok(value) => value.java_hash(hash_type),
3304 Err(error) => jh::java_string_hash(&error) as i64,
3305 }),
3306 ),
3307 Self::MutableCollection(v) => opaque(32, |s| Rc::as_ptr(v).hash(s)),
3308 Self::Promise(v) => opaque(8, |s| v.identity_address().hash(s)),
3309 Self::Atom(v) => opaque(28, |s| v.identity_address().hash(s)),
3310 Self::Function(v) => opaque(14, |s| Rc::as_ptr(v).hash(s)),
3311 Self::Iterator(v) => opaque(16, |s| Rc::as_ptr(v).hash(s)),
3312 Self::Var(v) => opaque(17, |s| v.identity_address().hash(s)),
3313 Self::Namespace(v) => opaque(27, |s| v.identity_address().hash(s)),
3314 Self::Extension(v) => opaque(18, |s| {
3315 v.provider.hash(s);
3316 v.type_name.hash(s);
3317 v.handle.hash(s);
3318 }),
3319 Self::StructType(v) => opaque(26, |s| Rc::as_ptr(v).hash(s)),
3320 Self::Struct(v) => opaque(27, |s| {
3321 Rc::as_ptr(&v.ty).hash(s);
3322 for value in v.ordered_values() {
3323 value.hash(s);
3324 }
3325 }),
3326 Self::MutableType(v) => opaque(28, |s| Rc::as_ptr(v).hash(s)),
3327 Self::Mutable(v) => opaque(29, |s| v.identity_address().hash(s)),
3328 Self::Protocol(v) => opaque(30, |s| v.name.hash(s)),
3329 Self::NativeType(v) => opaque(31, |s| v.name.hash(s)),
3330 Self::Schema(v) => opaque(34, |s| v.form.to_string().hash(s)),
3331 Self::Coroutine(v) => opaque(32, |s| Rc::as_ptr(v).hash(s)),
3332 Self::Stream(v) => opaque(35, |s| Rc::as_ptr(v).hash(s)),
3333 Self::Result(v) => v.java_hash(hash_type),
3334 Self::ExceptionInfo(v) => opaque(33, |s| Rc::as_ptr(v).hash(s)),
3335 }
3336 }
3337}
3338
3339impl Value {
3340 pub fn display(&self) -> String {
3341 match self {
3342 Self::Number(v) => v.to_string(),
3343 Self::Float(v) => {
3344 assert!(v.is_finite(), "non-finite number");
3345 format!("(double {v})")
3346 }
3347 Self::BigInteger(v) => v.to_string(),
3348 Self::Character('\n') => "\\newline".into(),
3349 Self::Character(' ') => "\\space".into(),
3350 Self::Character('\t') => "\\tab".into(),
3351 Self::Character('\u{0008}') => "\\backspace".into(),
3352 Self::Character('\u{000c}') => "\\formfeed".into(),
3353 Self::Character('\r') => "\\return".into(),
3354 Self::Character(v) if v.is_control() => format!("\\u{:04X}", *v as u32),
3355 Self::Character(v) => format!("\\{v}"),
3356 Self::Regex(v) => crate::kernel::form::display_regex(v),
3357 Self::Tagged(value) => uuid_text_from_tagged(value).map_or_else(
3358 || format!("#{}{}", value.tag().as_str(), value.form().display()),
3359 str::to_owned,
3360 ),
3361 Self::Bool(v) => v.to_string(),
3362 Self::String(v) => crate::kernel::form::display_string(v),
3363 Self::Keyword(v) => format!(":{}", v.as_str()),
3364 Self::Bytes(values) => format!(
3365 "#bytes[{}]",
3366 values
3367 .iter()
3368 .map(|v| (*v as i8).to_string())
3369 .collect::<Vec<_>>()
3370 .join(" ")
3371 ),
3372 Self::ByteBuffer(values) => {
3373 let body = values
3374 .borrow()
3375 .iter()
3376 .map(|v| (*v as i8).to_string())
3377 .collect::<Vec<_>>()
3378 .join(" ");
3379 if body.is_empty() {
3380 "(bytes)".into()
3381 } else {
3382 format!("(bytes {body})")
3383 }
3384 }
3385 Self::Array(values) => format!(
3386 "(array {})",
3387 values
3388 .borrow()
3389 .iter()
3390 .map(Value::display)
3391 .collect::<Vec<_>>()
3392 .join(" ")
3393 ),
3394 Self::Object(values) => format!(
3395 "(object {})",
3396 values
3397 .borrow()
3398 .iter()
3399 .map(|(key, value)| format!("\"{}\" {}", key, value.display()))
3400 .collect::<Vec<_>>()
3401 .join(" ")
3402 ),
3403 Self::Promise(_) => "<promise>".into(),
3404 Self::Atom(value) => format!("#atom <{}>", value.deref_value().display()),
3405 Self::Recur(values) => format!(
3406 "<recur {}>",
3407 values
3408 .iter()
3409 .map(Value::display)
3410 .collect::<Vec<_>>()
3411 .join(" ")
3412 ),
3413 value @ (Self::Map(_)
3414 | Self::OrderedMap(_)
3415 | Self::SortedMap(_)
3416 | Self::PriorityMap(_)
3417 | Self::Trie(_)) => {
3418 format!(
3419 "{{{}}}",
3420 map_entries(value)
3421 .unwrap()
3422 .iter()
3423 .map(|(k, v)| format!("{} {}", k.display(), v.display()))
3424 .collect::<Vec<_>>()
3425 .join(" ")
3426 )
3427 }
3428 value @ (Self::Set(_) | Self::OrderedSet(_) | Self::SortedSet(_)) => format!(
3429 "#{{{}}}",
3430 set_items(value)
3431 .unwrap()
3432 .iter()
3433 .map(|item| item.display())
3434 .collect::<Vec<_>>()
3435 .join(" ")
3436 ),
3437 Self::Queue(values) => format!(
3438 "#queue[{}]",
3439 values
3440 .iter()
3441 .map(Value::display)
3442 .collect::<Vec<_>>()
3443 .join(" ")
3444 ),
3445 Self::Deque(values) => format!(
3446 "#deque[{}]",
3447 values
3448 .iter()
3449 .map(Value::display)
3450 .collect::<Vec<_>>()
3451 .join(" ")
3452 ),
3453 Self::Cons(values) => format!(
3454 "({})",
3455 values
3456 .iter()
3457 .map(|value| value.display())
3458 .collect::<Vec<_>>()
3459 .join(" ")
3460 ),
3461 Self::List(values) => format!(
3462 "({})",
3463 values
3464 .iter()
3465 .map(Value::display)
3466 .collect::<Vec<_>>()
3467 .join(" ")
3468 ),
3469 Self::Symbol(v) => v.as_str().to_owned(),
3470 Self::Pointer(v) => v.display(),
3471 Self::Function(_) => "<fn>".into(),
3472 Self::Tuple(values) => format!(
3473 "[{}]",
3474 values
3475 .iter()
3476 .map(Value::display)
3477 .collect::<Vec<_>>()
3478 .join(" ")
3479 ),
3480 Self::MapEntry(entry) => entry.display(),
3481 Self::Vector(values) => format!(
3482 "[{}]",
3483 values
3484 .iter()
3485 .map(Value::display)
3486 .collect::<Vec<_>>()
3487 .join(" ")
3488 ),
3489 Self::MutableCollection(values) => {
3490 let borrowed = values.borrow();
3491 let Some(values) = borrowed.as_ref() else {
3492 return "#<mutable-frozen>".into();
3493 };
3494 let kind = match values {
3495 MutableCollection::Map(_) => "map",
3496 MutableCollection::OrderedMap(_) => "ordered-map",
3497 MutableCollection::SortedMap(_) => "sorted-map",
3498 MutableCollection::Trie(_) => "trie",
3499 MutableCollection::Set(_) => "set",
3500 MutableCollection::OrderedSet(_) => "ordered-set",
3501 MutableCollection::SortedSet(_) => "sorted-set",
3502 MutableCollection::List(_) => "list",
3503 MutableCollection::Queue(_) => "queue",
3504 MutableCollection::Vector(_) => "vector",
3505 };
3506 format!("#<mutable-{kind}>")
3507 }
3508 Self::Seq(sequence) => {
3509 let mut values = sequence.iter();
3510 let mut displayed = Vec::new();
3511 for _ in 0..10 {
3512 match values.next() {
3513 Some(Ok(value)) => displayed.push(value.display()),
3514 Some(Err(error)) => {
3515 displayed.push(format!("#error[{}]", Value::String(error).display()));
3516 break;
3517 }
3518 None => break,
3519 }
3520 }
3521 if values.next().is_some() {
3522 displayed.push("...".into());
3523 }
3524 format!("({})", displayed.join(" "))
3525 }
3526 Self::Iterator(_) => "<iterator>".into(),
3527 Self::Var(value) => value.display(),
3528 Self::Namespace(value) => format!("#namespace[{}]", value.name().as_str()),
3529 Self::Extension(value) => format!("#ht[:handle {}]", value.handle),
3530 Self::StructType(value) => value.name.clone(),
3531 Self::Struct(value) => format!(
3532 "#{}{{{}}}",
3533 value.ty.name,
3534 value
3535 .ty
3536 .fields
3537 .iter()
3538 .filter_map(|field| value.get(field).map(|value| (field, value)))
3539 .map(|(field, value)| format!(":{field} {}", value.display()))
3540 .collect::<Vec<_>>()
3541 .join(" ")
3542 ),
3543 Self::MutableType(value) => value.name.clone(),
3544 Self::Mutable(value) => format!(
3545 "#{}{{{}}}",
3546 value.ty.name,
3547 value
3548 .ty
3549 .fields
3550 .iter()
3551 .zip(value.ordered_values())
3552 .map(|(field, value)| format!(":{field} {}", value.display()))
3553 .collect::<Vec<_>>()
3554 .join(" ")
3555 ),
3556 Self::Protocol(value) => format!("#protocol[{}]", value.name),
3557 Self::NativeType(value) => format!("#<native-type {}>", value.name),
3558 Self::Schema(value) => format!("(schema {})", value.form),
3559 Self::Coroutine(value) => {
3560 let status = match &*value.state.borrow() {
3561 CoroutineState::New(_) | CoroutineState::Suspended(_) => "suspended",
3562 CoroutineState::Running => "running",
3563 CoroutineState::Dead => "dead",
3564 };
3565 format!("#<coroutine {status}>")
3566 }
3567 Self::Stream(value) => format!(
3568 "#<stream {}>",
3569 if value.closed.get() {
3570 "closed"
3571 } else {
3572 "ready"
3573 }
3574 ),
3575 Self::Result(value) => value.display(),
3576 Self::ExceptionInfo(value) => {
3577 format!(
3578 "#error[{} {}]",
3579 Self::String(value.message.clone()).display(),
3580 value.data.display()
3581 )
3582 }
3583 Self::Nil => "nil".into(),
3584 }
3585 }
3586 pub(crate) fn truthy(&self) -> bool {
3587 !matches!(self, Self::Nil | Self::Bool(false))
3588 }
3589
3590 pub fn stable_hash(&self) -> u64 {
3600 self.java_hash(crate::lang::hash::DEFAULT_HASH) as u64
3601 }
3602}