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