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 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-data",
940 native_function("ex-data", 1, |arguments| match &arguments[0] {
941 Value::ExceptionInfo(value) => Ok((*value.data).clone()),
942 _ => Ok(Value::Nil),
943 }),
944 ),
945 (
946 "ex-message",
947 native_function("ex-message", 1, |arguments| match &arguments[0] {
948 Value::ExceptionInfo(value) => Ok(Value::String(value.message.clone())),
949 Value::String(value) => Ok(Value::String(value.clone())),
950 value => Ok(Value::String(value.display())),
951 }),
952 ),
953 (
954 "ex-cause",
955 native_function("ex-cause", 1, |arguments| match &arguments[0] {
956 Value::ExceptionInfo(value) => {
957 Ok(value.cause.as_deref().cloned().unwrap_or(Value::Nil))
958 }
959 _ => Err("ex-cause expects an Exception".into()),
960 }),
961 ),
962 (
963 "ex-provenance",
964 native_function("ex-provenance", 1, |arguments| match &arguments[0] {
965 Value::ExceptionInfo(value) => Ok(exception_provenance_value(value)),
966 _ => Err("ex-provenance expects an Exception".into()),
967 }),
968 ),
969 (
970 "ex-class",
971 native_function("ex-class", 1, |arguments| match &arguments[0] {
972 Value::ExceptionInfo(value) => {
973 let Some(entries) = map_entries(&value.data) else {
974 return Err("Exception data must be a map".into());
975 };
976 match entries.iter().find_map(|(key, value)| {
977 matches!(key, Value::Keyword(name) if name.as_str() == "ex/class")
978 .then_some(value)
979 }) {
980 None => Ok(Value::Nil),
981 Some(Value::Keyword(class)) if class.get_namespace().is_some() => {
982 Ok(Value::Keyword(class.clone()))
983 }
984 Some(_) => Err(":ex/class must be a namespaced keyword".into()),
985 }
986 }
987 _ => Err("ex-class expects an Exception".into()),
988 }),
989 ),
990 (
991 "ex-native-type",
992 native_function("ex-native-type", 1, |arguments| match &arguments[0] {
993 Value::ExceptionInfo(_) => Ok(Value::Nil),
994 _ => Err("ex-native-type expects an Exception".into()),
995 }),
996 ),
997 ]
998}
999
1000pub(crate) fn direct_function_value(name: &str) -> Option<Value> {
1001 match name {
1002 "pair" => Some(native_function("pair", 2, |arguments| {
1003 Ok(Value::MapEntry(Box::new(PMapEntry::new(
1004 arguments[0].clone(),
1005 arguments[1].clone(),
1006 ))))
1007 })),
1008 "disj" => Some(native_variadic_function("disj", |arguments| {
1009 let (collection, values) = arguments
1010 .split_first()
1011 .ok_or_else(|| "disj expects a collection".to_string())?;
1012 let mut output = collection.clone();
1013 for value in values {
1014 if matches!(output, Value::Nil) {
1015 break;
1016 }
1017 output = crate::core::protocol_intrinsic_call(
1018 "std.protocol.idissoc.IDissoc/dissoc",
1019 &[output, value.clone()],
1020 )?;
1021 }
1022 Ok(output)
1023 })),
1024 "quot" => Some(native_function("quot", 2, |arguments| {
1025 numeric::numeric_quotient(&arguments[0], &arguments[1])
1026 })),
1027 "rem" => Some(native_function("rem", 2, |arguments| {
1028 apply_binary_intrinsic(IntrinsicOp::Remainder, &arguments[0], &arguments[1])
1029 })),
1030 "mod" => Some(native_variadic_function("mod", |arguments| {
1031 if arguments.len() != 2 {
1032 return Err("mod expects arguments".into());
1033 }
1034 numeric::numeric_binary(ArithmeticOp::Modulo, &arguments[0], &arguments[1])
1035 })),
1036 _ => IntrinsicOp::from_symbol(name).map(|primitive| {
1037 native_variadic_function(name, move |arguments| {
1038 apply_intrinsic(primitive, &arguments)
1039 })
1040 }),
1041 }
1042}
1043
1044pub fn native_type_function_value(native_type: &str, method: &str) -> Result<Value, String> {
1051 native_qualified_type_function_value(&format!("std.native.{native_type}"), method)
1052}
1053
1054pub fn native_qualified_type_function_value(
1060 native_type: &str,
1061 method: &str,
1062) -> Result<Value, String> {
1063 let declaration = NATIVE_DECLARATIONS
1064 .iter()
1065 .find(|declaration| declaration.qualified_name() == native_type)
1066 .ok_or_else(|| {
1067 format!("missing annotated native declaration: {native_type}/{method}")
1068 })?;
1069 if !declaration.method(method) {
1070 return Err(format!("unknown annotated native method: {native_type}/{method}"));
1071 }
1072 (declaration.provider)(declaration.name, method)
1073}
1074
1075fn native_display_name(native_type: &str, method: &str) -> String {
1076 format!("std.native.{native_type}/{method}")
1077}
1078
1079fn native_base_provider(native_type: &str, method: &str) -> Result<Value, String> {
1080 let display_name = native_display_name(native_type, method);
1081 let method = method.to_owned();
1082 Ok(native_variadic_function(&display_name, move |arguments| {
1083 native_base_values(&method, &arguments)
1084 }))
1085}
1086
1087fn native_schema_provider(native_type: &str, method: &str) -> Result<Value, String> {
1088 let display_name = native_display_name(native_type, method);
1089 let method = method.to_owned();
1090 Ok(native_variadic_function(&display_name, move |arguments| {
1091 native_schema_values(&method, &arguments)
1092 }))
1093}
1094
1095fn native_string_provider(native_type: &str, method: &str) -> Result<Value, String> {
1096 let display_name = native_display_name(native_type, method);
1097 let operation = format!("str/{method}");
1098 Ok(native_variadic_function(&display_name, move |arguments| {
1099 string_operation(&operation, arguments)
1100 }))
1101}
1102
1103fn native_bytes_provider(native_type: &str, method: &str) -> Result<Value, String> {
1104 let display_name = native_display_name(native_type, method);
1105 let method = method.to_owned();
1106 Ok(native_variadic_function(&display_name, move |arguments| {
1107 native_bytes_operation(&method, arguments)
1108 }))
1109}
1110
1111fn native_iter_provider(native_type: &str, method: &str) -> Result<Value, String> {
1112 let display_name = native_display_name(native_type, method);
1113 let method = method.to_owned();
1114 Ok(native_variadic_function(&display_name, move |arguments| {
1115 native_iter_operation(&method, arguments)
1116 }))
1117}
1118
1119fn native_maths_provider(native_type: &str, method: &str) -> Result<Value, String> {
1120 let display_name = native_display_name(native_type, method);
1121 let method = method.to_owned();
1122 Ok(native_variadic_function(&display_name, move |arguments| {
1123 math_values(&method, arguments)
1124 }))
1125}
1126
1127fn native_num_provider(native_type: &str, method: &str) -> Result<Value, String> {
1128 let display_name = native_display_name(native_type, method);
1129 let method = method.to_owned();
1130 Ok(native_variadic_function(&display_name, move |arguments| {
1131 if arguments.len() != 1 {
1132 return Err(format!("{method} expects one value"));
1133 }
1134 number_conversion_value(&method, arguments.into_iter().next().unwrap())
1135 }))
1136}
1137
1138fn native_bits_provider(native_type: &str, method: &str) -> Result<Value, String> {
1139 let display_name = native_display_name(native_type, method);
1140 let method = method.to_owned();
1141 Ok(native_variadic_function(&display_name, move |arguments| {
1142 bit_values(&method, &arguments)
1143 }))
1144}
1145
1146fn native_kernel_provider(native_type: &str, method: &str) -> Result<Value, String> {
1147 let display_name = native_display_name(native_type, method);
1148 let method = method.to_owned();
1149 Ok(native_variadic_function(&display_name, move |arguments| {
1150 require_native_capability("Kernel", &method, "kernel")?;
1151 kernel_provider(&method)?(method.clone(), arguments)
1152 }))
1153}
1154
1155fn native_sandbox_provider(native_type: &str, method: &str) -> Result<Value, String> {
1156 let display_name = native_display_name(native_type, method);
1157 let operation = format!("sandbox-{method}");
1158 let method = method.to_owned();
1159 Ok(native_variadic_function(&display_name, move |arguments| {
1160 require_native_capability("Sandbox", &method, "sandbox")?;
1161 kernel_provider(&operation)?(operation.clone(), arguments)
1162 }))
1163}
1164
1165fn native_crypto_provider(native_type: &str, method: &str) -> Result<Value, String> {
1166 let display_name = native_display_name(native_type, method);
1167 let method = method.to_owned();
1168 Ok(native_variadic_function(&display_name, move |arguments| {
1169 native_crypto::operation(&method, arguments)
1170 }))
1171}
1172
1173fn native_document_provider(native_type: &str, method: &str) -> Result<Value, String> {
1174 let display_name = native_display_name(native_type, method);
1175 let method = method.to_owned();
1176 Ok(native_variadic_function(&display_name, move |arguments| {
1177 document_operation(&method, arguments)
1178 }))
1179}
1180
1181fn native_package_provider(native_type: &str, method: &str) -> Result<Value, String> {
1182 let display_name = native_display_name(native_type, method);
1183 let method = method.to_owned();
1184 Ok(native_variadic_function(&display_name, move |arguments| {
1185 require_native_capability("Package", &method, "kernel")?;
1186 native_package_values(&method, arguments, &mut HashMap::new())
1187 }))
1188}
1189
1190fn native_hbx_provider(native_type: &str, method: &str) -> Result<Value, String> {
1191 let display_name = native_display_name(native_type, method);
1192 let method = method.to_owned();
1193 Ok(native_variadic_function(&display_name, move |arguments| {
1194 hbx_operation(&method, arguments)
1195 }))
1196}
1197
1198fn native_instrument_provider(native_type: &str, method: &str) -> Result<Value, String> {
1199 let display_name = native_display_name(native_type, method);
1200 let method = method.to_owned();
1201 Ok(native_variadic_function(&display_name, move |arguments| {
1202 native_instrument_values(&method, arguments)
1203 }))
1204}
1205
1206fn native_os_provider(native_type: &str, method: &str) -> Result<Value, String> {
1207 let display_name = native_display_name(native_type, method);
1208 let native_type = native_type.to_owned();
1209 let method = method.to_owned();
1210 let operation = native_display_name(&native_type, &method);
1211 Ok(native_variadic_function(&display_name, move |arguments| {
1212 if native_type == "Process" {
1213 require_native_capability("Process", &method, "native-runtime")?;
1214 }
1215 os_values(&operation, arguments)
1216 }))
1217}
1218
1219fn native_file_provider(native_type: &str, method: &str) -> Result<Value, String> {
1220 let display_name = native_display_name(native_type, method);
1221 let method = method.to_owned();
1222 let operation = native_display_name(native_type, &method);
1223 Ok(native_variadic_function(&display_name, move |arguments| {
1224 require_native_capability("File", &method, "file")?;
1225 file_values(&operation, arguments)
1226 }))
1227}
1228
1229fn native_socket_provider(native_type: &str, method: &str) -> Result<Value, String> {
1230 let display_name = native_display_name(native_type, method);
1231 let method = method.to_owned();
1232 let operation = native_display_name(native_type, &method);
1233 Ok(native_variadic_function(&display_name, move |arguments| {
1234 require_native_capability("Socket", &method, "network")?;
1235 socket_values(&operation, arguments)
1236 }))
1237}
1238
1239fn native_promise_provider(native_type: &str, method: &str) -> Result<Value, String> {
1240 let display_name = native_display_name(native_type, method);
1241 let method = method.to_owned();
1242 Ok(native_variadic_function(&display_name, move |arguments| {
1243 native_promise_values(&method, arguments)
1244 }))
1245}
1246
1247fn native_coroutine_provider(native_type: &str, method: &str) -> Result<Value, String> {
1248 let display_name = native_display_name(native_type, method);
1249 match method {
1250 "create" => Ok(native_fiber_function(
1251 &display_name,
1252 1,
1253 false,
1254 native_coroutine_create,
1255 native_coroutine_create_fiber,
1256 )),
1257 "yield" => Ok(native_fiber_function(
1258 &display_name,
1259 1,
1260 false,
1261 native_coroutine_yield,
1262 native_coroutine_yield_fiber,
1263 )),
1264 "await" => Ok(native_fiber_function(
1265 &display_name,
1266 1,
1267 false,
1268 native_coroutine_await,
1269 native_coroutine_await_fiber,
1270 )),
1271 _ => Err(format!("unknown std.native.Coroutine operation: {method}")),
1272 }
1273}
1274
1275fn native_stream_provider(native_type: &str, method: &str) -> Result<Value, String> {
1276 let display_name = native_display_name(native_type, method);
1277 let method = method.to_owned();
1278 Ok(native_variadic_function(&display_name, move |arguments| {
1279 native_stream_values(&method, arguments)
1280 }))
1281}
1282
1283fn native_mutable_provider(native_type: &str, method: &str) -> Result<Value, String> {
1284 let display_name = native_display_name(native_type, method);
1285 let operation = native_display_name(native_type, method);
1286 Ok(native_variadic_function(&display_name, move |arguments| {
1287 native_mutable_values(&operation, arguments)
1288 }))
1289}
1290
1291fn native_runtime_provider(native_type: &str, method: &str) -> Result<Value, String> {
1292 let display_name = native_display_name(native_type, method);
1293 let method = method.to_owned();
1294 Ok(native_variadic_function(&display_name, move |arguments| {
1295 native_runtime_values(&method, arguments, &mut HashMap::new())
1296 }))
1297}
1298
1299fn native_printer_provider(native_type: &str, method: &str) -> Result<Value, String> {
1300 let display_name = native_display_name(native_type, method);
1301 let method = method.to_owned();
1302 Ok(native_variadic_function(&display_name, move |arguments| {
1303 native_printer_values(&method, arguments)
1304 }))
1305}
1306
1307fn native_edn_provider(native_type: &str, method: &str) -> Result<Value, String> {
1308 let display_name = native_display_name(native_type, method);
1309 let method = method.to_owned();
1310 Ok(native_variadic_function(&display_name, move |arguments| {
1311 native_edn_values(&method, arguments)
1312 }))
1313}
1314
1315fn native_json_provider(native_type: &str, method: &str) -> Result<Value, String> {
1316 let display_name = native_display_name(native_type, method);
1317 let method = method.to_owned();
1318 Ok(native_variadic_function(&display_name, move |arguments| {
1319 match (method.as_str(), arguments.as_slice()) {
1320 ("read", [Value::String(source)]) => crate::json::read(source),
1321 ("write", [value]) => crate::json::write(value).map(Value::String),
1322 ("pretty", [value, options]) if map_entries(options).is_some() => {
1323 crate::json::write_pretty(value).map(Value::String)
1324 }
1325 ("pretty", [_, _]) => Err("json/pretty expects an options map".into()),
1326 ("read", _) => Err("json/read expects a string".into()),
1327 ("write", _) => Err("json/write expects one value".into()),
1328 ("pretty", _) => Err("json/pretty expects a value and options map".into()),
1329 _ => Err(format!("unknown std.native.Json operation: {method}")),
1330 }
1331 }))
1332}
1333
1334fn native_host_provider(native_type: &str, method: &str) -> Result<Value, String> {
1335 let display_name = native_display_name(native_type, method);
1336 let method = method.to_owned();
1337 Ok(native_variadic_function(&display_name, move |arguments| {
1338 if !native_capability_granted("host-call") {
1339 return Ok(native_capability_denied_promise(
1340 "Host",
1341 &method,
1342 "host-call",
1343 ));
1344 }
1345 native_host_values(&method, arguments)
1346 }))
1347}
1348
1349fn native_test_provider(native_type: &str, method: &str) -> Result<Value, String> {
1350 let display_name = native_display_name(native_type, method);
1351 let method = method.to_owned();
1352 Ok(native_variadic_function(&display_name, move |arguments| {
1353 native_test_values(&method, arguments)
1354 }))
1355}
1356
1357fn native_command_provider(native_type: &str, method: &str) -> Result<Value, String> {
1358 let display_name = native_display_name(native_type, method);
1359 let method = method.to_owned();
1360 Ok(native_variadic_function(&display_name, move |arguments| {
1361 native_command_values(&method, arguments)
1362 }))
1363}
1364
1365fn native_regexp_provider(native_type: &str, method: &str) -> Result<Value, String> {
1366 let display_name = native_display_name(native_type, method);
1367 let method = method.to_owned();
1368 Ok(native_variadic_function(&display_name, move |arguments| {
1369 native_regex_values(&method, arguments)
1370 }))
1371}
1372
1373fn native_result_provider(native_type: &str, method: &str) -> Result<Value, String> {
1374 let display_name = native_display_name(native_type, method);
1375 let method = method.to_owned();
1376 Ok(native_variadic_function(&display_name, move |arguments| {
1377 native_result_values(&method, arguments)
1378 }))
1379}
1380
1381fn native_exception_provider(native_type: &str, method: &str) -> Result<Value, String> {
1382 let display_name = native_display_name(native_type, method);
1383 let method = method.to_owned();
1384 Ok(native_variadic_function(&display_name, move |arguments| {
1385 native_exception_values(&method, arguments)
1386 }))
1387}
1388
1389fn native_algo_provider(native_type: &str, method: &str) -> Result<Value, String> {
1390 let display_name = native_display_name(native_type, method);
1391 let operation = native_display_name(native_type, method);
1392 Ok(native_variadic_function(&display_name, move |arguments| {
1393 native_algo_values(&operation, arguments)
1394 }))
1395}
1396
1397fn native_work_provider(_native_type: &str, method: &str) -> Result<Value, String> {
1398 crate::work::guest::values()
1399 .into_iter()
1400 .find(|(name, _)| *name == method)
1401 .map(|(_, value)| value)
1402 .ok_or_else(|| format!("unknown std.native.Work operation: {method}"))
1403}
1404
1405fn native_lang_provider(native_type: &str, method: &str) -> Result<Value, String> {
1406 crate::lang_harness::function(native_type, method)
1407}
1408
1409fn native_coroutine_create(arguments: Vec<Value>) -> Result<Value, String> {
1410 match arguments.as_slice() {
1411 [Value::Function(function)] => Ok(Value::Coroutine(Rc::new(Coroutine::new(
1412 Value::Function(function.clone()),
1413 )))),
1414 _ => Err("Coroutine/create expects one function".into()),
1415 }
1416}
1417
1418fn native_coroutine_create_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1419 match arguments.as_slice() {
1420 [Value::Function(function)] => k(Ok(Value::Coroutine(Rc::new(Coroutine::new(
1421 Value::Function(function.clone()),
1422 ))))),
1423 _ => k(Err("Coroutine/create expects one function".into())),
1424 }
1425}
1426
1427fn native_coroutine_yield(_arguments: Vec<Value>) -> Result<Value, String> {
1428 Err("Coroutine/yield requires the fiber evaluator".into())
1429}
1430
1431fn native_coroutine_yield_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1432 match arguments.as_slice() {
1433 [value] => Step::Yield(value.clone(), Box::new(move |resumed| k(Ok(resumed)))),
1434 _ => k(Err("Coroutine/yield expects one value".into())),
1435 }
1436}
1437
1438fn native_coroutine_await(_arguments: Vec<Value>) -> Result<Value, String> {
1439 Err("Coroutine/await requires the fiber evaluator".into())
1440}
1441
1442fn native_coroutine_await_fiber(arguments: Vec<Value>, k: Cont) -> Step {
1443 match arguments.as_slice() {
1444 [Value::Var(reference)] => k(Ok(reference.deref_value())),
1445 [Value::Promise(promise)] => match promise.state() {
1446 PromiseState::Fulfilled(value) => k(Ok(value)),
1447 PromiseState::Rejected(error) => k(Err(crate::core::promise_rejection_error(error))),
1448 PromiseState::Pending => Step::Wait(
1449 promise.clone(),
1450 Box::new(move |state| match state {
1451 PromiseState::Fulfilled(value) => k(Ok(value)),
1452 PromiseState::Rejected(error) => {
1453 k(Err(crate::core::promise_rejection_error(error)))
1454 }
1455 PromiseState::Pending => k(Err("Coroutine/await resumed pending".into())),
1456 }),
1457 ),
1458 },
1459 _ => k(Err("Coroutine/await expects a derefable (e.g. a promise)".into())),
1460 }
1461}
1462
1463fn native_reader_position_value(position: crate::kernel::Position) -> Value {
1464 Value::Map(PMap::from_iter([
1465 (Value::Keyword("offset".into()), Value::Number(position.offset as i64)),
1466 (Value::Keyword("line".into()), Value::Number(position.line as i64)),
1467 (
1468 Value::Keyword("column".into()),
1469 Value::Number(position.column as i64),
1470 ),
1471 ]))
1472}
1473
1474fn native_spanned_form_value(form: &crate::kernel::SpannedForm) -> Result<Value, String> {
1475 let children = form
1476 .children
1477 .iter()
1478 .map(native_spanned_form_value)
1479 .collect::<Result<Vec<_>, _>>()?;
1480 Ok(Value::Map(PMap::from_iter([
1481 (Value::Keyword("form".into()), form_to_value(&form.form)?),
1482 (
1483 Value::Keyword("start".into()),
1484 native_reader_position_value(form.span.start),
1485 ),
1486 (
1487 Value::Keyword("end".into()),
1488 native_reader_position_value(form.span.end),
1489 ),
1490 (
1491 Value::Keyword("children".into()),
1492 Value::Vector(PVector::from_iter(children)),
1493 ),
1494 ])))
1495}
1496
1497fn native_edn_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1498 match (method, arguments.as_slice()) {
1499 ("read", [Value::String(source)]) => read_edn(source),
1500 ("read-forms-spanned", [Value::String(source)]) => {
1501 let forms = crate::kernel::read_forms(source)
1502 .map_err(|error| format!("read-forms-spanned failed: {error}"))?;
1503 Ok(Value::Vector(PVector::from_iter(
1504 forms
1505 .iter()
1506 .map(native_spanned_form_value)
1507 .collect::<Result<Vec<_>, _>>()?,
1508 )))
1509 }
1510 ("read-forms", [Value::String(path)]) => {
1511 if !(path.ends_with(".hal") || path.ends_with(".hrl")) {
1512 return Err("read-forms expects a .hal or .hrl path".into());
1513 }
1514 let promise = file_provider("read-forms")?
1515 .read(path)
1516 .map_err(|error| file_error("read-forms", error))?;
1517 let bytes = match promise.wait_state() {
1518 PromiseState::Fulfilled(Value::Bytes(bytes)) => bytes,
1519 PromiseState::Fulfilled(Value::ByteBuffer(bytes)) => bytes.borrow().clone(),
1520 PromiseState::Fulfilled(value) => {
1521 return Err(format!(
1522 "read-forms expected file bytes, got {}",
1523 value.display()
1524 ));
1525 }
1526 PromiseState::Rejected(error) => return Err(error.message()),
1527 PromiseState::Pending => return Err("read-forms file read is still pending".into()),
1528 };
1529 let source = String::from_utf8(bytes)
1530 .map_err(|_| format!("read-forms source is not UTF-8: {path}"))?;
1531 let forms = crate::kernel::parse_forms(&source)
1532 .map_err(|error| format!("read-forms failed: {error}"))?;
1533 Ok(Value::Vector(PVector::from_iter(
1534 forms
1535 .iter()
1536 .map(form_to_value)
1537 .collect::<Result<Vec<_>, _>>()?,
1538 )))
1539 }
1540 ("write", [value]) => Ok(Value::String(value.display())),
1541 ("pretty", [value, options]) if map_entries(options).is_some() => {
1542 Ok(Value::String(value.display()))
1543 }
1544 ("pretty", [_, _]) => Err("edn/pretty expects an options map".into()),
1545 ("read", _) => Err("edn/read expects one string".into()),
1546 ("read-forms", _) => Err("read-forms expects a path string".into()),
1547 ("read-forms-spanned", _) => {
1548 Err("read-forms-spanned expects one source string".into())
1549 }
1550 ("write", _) => Err("std.native.Edn/write expects one value".into()),
1551 ("pretty", _) => Err("std.native.Edn/pretty expects a value and options map".into()),
1552 _ => Err(format!("unknown std.native.Edn operation: {method}")),
1553 }
1554}
1555
1556fn native_printer_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1557 match method {
1558 "capture" => {
1559 let [callable] = arguments.as_slice() else {
1560 return Err("Printer/capture expects one callable".into());
1561 };
1562 PRINTER_CAPTURES.with(|captures| captures.borrow_mut().push(String::new()));
1563 let result = call_value(callable.clone(), Vec::new());
1564 let output = PRINTER_CAPTURES.with(|captures| {
1565 captures
1566 .borrow_mut()
1567 .pop()
1568 .expect("Printer/capture stack must contain the active capture")
1569 });
1570 result.map(|_| Value::String(output))
1571 }
1572 "p" | "println" => {
1573 let text = arguments
1574 .iter()
1575 .map(|value| match (method, value) {
1576 ("p", Value::Nil) => String::new(),
1577 ("p", Value::String(text)) => text.clone(),
1578 ("p", Value::Character(character)) => character.to_string(),
1579 (_, Value::String(text)) => text.clone(),
1580 _ => value.display(),
1581 })
1582 .collect::<Vec<_>>()
1583 .join(if method == "println" { " " } else { "" });
1584 let output = if method == "println" {
1585 format!("{text}\n")
1586 } else {
1587 text
1588 };
1589 printer_write(&output)?;
1590 Ok(Value::Nil)
1591 }
1592 _ => Err(format!("unknown std.native.Printer operation: {method}")),
1593 }
1594}
1595
1596fn native_promise_values(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1597 match (method, arguments.as_slice()) {
1598 ("from", [value]) => Ok(Value::Promise(promise_from(value.clone()))),
1599 ("all", [values]) => Ok(Value::Promise(promise_all(iterator_values(
1600 values.clone(),
1601 )?))),
1602 ("run", [Value::Function(function)]) => {
1603 let function = function.clone();
1604 let context = crate::core::NativeCallbackContext::capture();
1605 let task = Rc::new(move || context.with(|| call_function(&function, Vec::new())));
1606 Ok(Value::Promise(promise_provider().run(task)))
1607 }
1608 ("new", [Value::Function(function)]) => {
1609 let promise = Promise::new();
1610 let resolving = promise.clone();
1611 let resolve = native_function("promise-resolve", 1, move |mut values| {
1612 let value = values.remove(0);
1613 settle_promise_result(&resolving, Ok(value.clone()));
1614 Ok(value)
1615 });
1616 let rejecting = promise.clone();
1617 let reject = native_function("promise-reject", 1, move |mut values| {
1618 let value = values.remove(0);
1619 rejecting.reject_value(value.clone());
1620 Ok(value)
1621 });
1622 if let Err(error) = call_function(function, vec![resolve, reject]) {
1623 promise.reject(error);
1624 }
1625 Ok(Value::Promise(promise))
1626 }
1627 ("delay", [millis, Value::Function(function)]) => {
1628 let millis = value_u64_integer(millis, "promise/delay")
1629 .map_err(|_| "promise/delay expects non-negative milliseconds".to_string())?;
1630 let function = function.clone();
1631 let context = crate::core::NativeCallbackContext::capture();
1632 let task = Rc::new(move || context.with(|| call_function(&function, Vec::new())));
1633 Ok(Value::Promise(
1634 promise_provider().delay(std::time::Duration::from_millis(millis), task),
1635 ))
1636 }
1637 ("run", _) => Err("promise/run expects one function".into()),
1638 ("new", [_]) => Err("promise/new expects a function".into()),
1639 ("new", _) => Err("promise/new expects one function".into()),
1640 ("from", _) => Err("promise/from expects one value".into()),
1641 ("all", _) => Err("promise/all expects one collection".into()),
1642 ("delay", _) => Err("promise/delay expects milliseconds and a function".into()),
1643 _ => Err(format!("unknown std.native.Promise operation: {method}")),
1644 }
1645}
1646
1647fn native_iter_operation(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1648 let unary = |label: &str| {
1649 arguments
1650 .first()
1651 .cloned()
1652 .filter(|_| arguments.len() == 1)
1653 .ok_or_else(|| format!("Iter/{label} expects one argument"))
1654 };
1655 let binary = |label: &str| {
1656 if arguments.len() == 2 {
1657 Ok((arguments[0].clone(), arguments[1].clone()))
1658 } else {
1659 Err(format!("Iter/{label} expects two arguments"))
1660 }
1661 };
1662 match method {
1663 "seq" => iterator_seq(unary(method)?),
1664 "iter" => make_iterator(unary(method)?),
1665 "iter-finite?" => Ok(Value::Bool(iterator_is_finite(&unary(method)?))),
1666 "iter-materialize" => Ok(Value::Vector(iterator_to_vec(unary(method)?)?.into())),
1667 "iter-next?" => iterator_has_next(&unary(method)?),
1668 "iter-next" => iterator_next(&unary(method)?),
1669 "iter-close" => iterator_close(&unary(method)?),
1670 "iter-concat" => iterator_concat(arguments),
1671 "iter-interleave" => iterator_interleave(arguments),
1672 "iter-zip" => iterator_zip(arguments),
1673 "iter-map" => {
1674 let (function, source) = binary(method)?;
1675 iterator_map(function, source)
1676 }
1677 "iter-filter" => {
1678 let (function, source) = binary(method)?;
1679 iterator_filter(function, source)
1680 }
1681 "iter-take-while" => {
1682 let (function, source) = binary(method)?;
1683 iterator_take_while(function, source)
1684 }
1685 "iter-drop-while" => {
1686 let (function, source) = binary(method)?;
1687 iterator_drop_while(function, source)
1688 }
1689 "iter-mapcat" => {
1690 let (function, source) = binary(method)?;
1691 iterator_mapcat(function, source)
1692 }
1693 "iter-keep" => {
1694 let (function, source) = binary(method)?;
1695 iterator_keep(function, source)
1696 }
1697 "iter-interpose" => {
1698 let (separator, source) = binary(method)?;
1699 iterator_interpose(separator, source)
1700 }
1701 "iter-every?" | "iter-any?" => {
1702 let (predicate, source) = binary(method)?;
1703 let iterator = make_iterator(source)?;
1704 let expect_every = method == "iter-every?";
1705 let result = (|| {
1706 while let Some(value) = iterator_try_next(&iterator)? {
1707 let matched = call_value(predicate.clone(), vec![value])?.truthy();
1708 if matched != expect_every {
1709 return Ok(Value::Bool(!expect_every));
1710 }
1711 }
1712 Ok(Value::Bool(expect_every))
1713 })();
1714 let close = iterator_close(&iterator);
1715 close?;
1716 result
1717 }
1718 "iter-take" | "iter-drop" => {
1719 let (amount, source) = binary(method)?;
1720 let amount = value_index(&amount)?;
1721 if method == "iter-take" {
1722 iterator_take(source, amount)
1723 } else {
1724 iterator_drop(source, amount)
1725 }
1726 }
1727 "iter-cycle" => iterator_cycle(unary(method)?),
1728 "iter-partition-pair" => iterator_partition(unary(method)?, 2, false),
1729 "iter-partition" | "iter-partition-all" => {
1730 let (amount, source) = binary(method)?;
1731 iterator_partition(source, value_index(&amount)?, method.ends_with("-all"))
1732 }
1733 "iter-range" => {
1734 let bounds = arguments
1735 .iter()
1736 .map(|value| {
1737 numeric::to_i64_exact(value).map_err(|_| {
1738 "iter-range bounds must fit signed 64-bit integers".to_string()
1739 })
1740 })
1741 .collect::<Result<Vec<_>, _>>()?;
1742 let (start, end) = match bounds.as_slice() {
1743 [end] => (0, *end),
1744 [start, end] => (*start, *end),
1745 _ => return Err("iter-range expects an end or start and end".into()),
1746 };
1747 Ok(iterator_from_values(
1748 (start..end).map(Value::Number).collect(),
1749 ))
1750 }
1751 "iter-constantly" => Ok(iterator_constant(unary(method)?)),
1752 "iter-repeatedly" => Ok(iterator_repeated(unary(method)?)),
1753 "iter-iterate" => {
1754 let (function, seed) = binary(method)?;
1755 Ok(iterator_iterate(function, seed))
1756 }
1757 _ => Err(format!("unknown std.native.Iter operation: {method}")),
1758 }
1759}
1760
1761fn native_bytes_operation(method: &str, arguments: Vec<Value>) -> Result<Value, String> {
1762 match (method, arguments.as_slice()) {
1763 ("new", values) => native_bytes_new(values),
1764 ("count", [value]) => byte_count(value),
1765 ("get", [value, index]) => byte_get(value, index, None),
1766 ("get", [value, index, default]) => byte_get(value, index, Some(default.clone())),
1767 ("set", [value, index, item]) => byte_set(value, index, item),
1768 ("copy", [value]) => byte_copy(value),
1769 ("slice", [value, start]) => {
1770 let end = byte_count(value)?;
1771 byte_slice(value, start, &end)
1772 }
1773 ("slice", [value, start, end]) => byte_slice(value, start, end),
1774 ("u8" | "s8", [Value::Number(number)]) if (-128..=255).contains(number) => {
1775 let raw = (*number as i8) as u8;
1776 Ok(Value::Number(if method == "u8" {
1777 raw as i64
1778 } else {
1779 raw as i8 as i64
1780 }))
1781 }
1782 ("u8" | "s8", [_]) => Err(format!(
1783 "bytes/{method} expects a value in the range -128..255"
1784 )),
1785 _ => Err(format!(
1786 "std.native.Bytes/{method} received unsupported arguments"
1787 )),
1788 }
1789}
1790
1791fn native_bytes_new(values: &[Value]) -> Result<Value, String> {
1792 let values = values
1793 .iter()
1794 .map(|value| byte_input(value, "bytes"))
1795 .collect::<Result<Vec<_>, _>>()?;
1796 Ok(Value::ByteBuffer(Rc::new(RefCell::new(values))))
1797}
1798
1799pub(crate) fn syntax_symbol(name: &str) -> bool {
1804 const SYNTAX_FORMS: &[&str] = &[
1805 ".",
1806 "binding",
1807 "comment",
1808 "declare",
1809 "def",
1810 "defmacro",
1811 "defn",
1812 "do",
1813 "field",
1814 "fn",
1815 "if",
1816 "let",
1817 "letfn",
1818 "loop",
1819 "ns",
1820 "ns+",
1821 "quote",
1822 "read-forms",
1823 "recur",
1824 "require",
1825 "set!",
1826 "syntax-quote",
1827 "throw",
1828 "try",
1829 "var",
1830 ];
1831 SYNTAX_FORMS.contains(&name)
1832}
1833
1834pub fn with_macros<R>(
1835 macros: Rc<RefCell<HashMap<(String, String), Rc<Function>>>>,
1836 operation: impl FnOnce() -> R,
1837) -> R {
1838 ACTIVE_MACROS.with(|active| {
1839 let previous = active.replace(Some(macros));
1840 let result = operation();
1841 active.replace(previous);
1842 result
1843 })
1844}
1845
1846fn register_macro(namespace: &str, name: &str, function: Rc<Function>) -> Result<(), String> {
1847 ACTIVE_MACROS.with(|active| {
1848 active
1849 .try_borrow_mut()
1850 .map_err(|_| "macro registry is busy".into())
1851 .and_then(|opt| {
1852 if let Some(macros) = opt.as_ref() {
1853 macros
1854 .try_borrow_mut()
1855 .map_err(|_| "macro registry is busy".into())
1856 .map(|mut macros| {
1857 macros.insert((namespace.into(), name.into()), function);
1858 })
1859 } else {
1860 Err("macro registry is unavailable".into())
1861 }
1862 })
1863 })
1864}
1865
1866fn resolve_macro_in(namespace: &str, name: &str) -> Option<Rc<Function>> {
1867 ACTIVE_MACROS.with(|active| {
1868 active.borrow().as_ref().and_then(|macros| {
1869 macros
1870 .borrow()
1871 .get(&(namespace.into(), name.into()))
1872 .cloned()
1873 })
1874 })
1875}
1876
1877pub(crate) fn resolve_macro(name: &str) -> Option<Rc<Function>> {
1878 if let Some((namespace, local)) = name.split_once('/') {
1879 let resolved = namespace_registry().ok().and_then(|registry| {
1880 let current = registry.current();
1881 if namespace == "-" {
1882 return Some(current.name().as_str().to_owned());
1883 }
1884 current
1885 .aliases()
1886 .into_iter()
1887 .find(|(alias, _)| alias.as_str() == namespace)
1888 .map(|(_, target)| target.name().as_str().to_owned())
1889 });
1890 return resolve_macro_in(resolved.as_deref().unwrap_or(namespace), local);
1891 }
1892 let current = namespace_registry()
1893 .map(|registry| registry.current().name().as_str().to_owned())
1894 .ok()?;
1895 resolve_macro_in(¤t, name).or_else(|| resolve_macro_in("std.foundation", name))
1896}
1897
1898fn gensym(prefix: &str) -> String {
1899 let index = GENSYM_COUNTER.with(|counter| {
1900 let value = counter.get();
1901 counter.set(value + 1);
1902 value
1903 });
1904 format!("{prefix}{index}")
1905}
1906
1907pub(crate) fn form_to_value(form: &Form) -> Result<Value, String> {
1908 literal_value(form)
1909}
1910
1911fn metadata_value_to_form(value: &MetadataValue) -> Form {
1912 match value {
1913 MetadataValue::Nil => Form::Nil,
1914 MetadataValue::Boolean(value) => Form::Bool(*value),
1915 MetadataValue::Number(value) => Form::Number(*value),
1916 MetadataValue::Float(value) => Form::Float(*value),
1917 MetadataValue::BigInteger(value) => Form::BigInteger(value.clone()),
1918 MetadataValue::Character(value) => Form::Character(*value),
1919 MetadataValue::Regex(value) => Form::Regex(value.clone()),
1920 MetadataValue::Tagged(tag, value) => {
1921 Form::Tagged(tag.clone(), Box::new(metadata_value_to_form(value)))
1922 }
1923 MetadataValue::String(value) => Form::String(value.clone()),
1924 MetadataValue::Keyword(value) => Form::Keyword(value.as_str().into()),
1925 MetadataValue::Symbol(value) => Form::Symbol(value.as_str().into()),
1926 MetadataValue::Vector(values) => {
1927 Form::Vector(values.iter().map(metadata_value_to_form).collect())
1928 }
1929 MetadataValue::List(values) => {
1930 Form::List(values.iter().map(metadata_value_to_form).collect())
1931 }
1932 MetadataValue::Set(values) => {
1933 Form::Set(values.iter().map(metadata_value_to_form).collect())
1934 }
1935 MetadataValue::Map(values) => Form::Map(
1936 values
1937 .iter()
1938 .map(|(key, value)| (metadata_value_to_form(key), metadata_value_to_form(value)))
1939 .collect(),
1940 ),
1941 }
1942}
1943
1944pub(crate) fn value_to_form(value: &Value) -> Result<Form, String> {
1945 let form = match value {
1946 Value::Nil => Ok(Form::Nil),
1947 Value::Bool(value) => Ok(Form::Bool(*value)),
1948 Value::Number(value) => Ok(Form::Number(*value)),
1949 Value::Float(value) => Ok(Form::Float(*value)),
1950 Value::BigInteger(value) => Ok(Form::BigInteger(value.clone())),
1951 Value::Character(value) => Ok(Form::Character(*value)),
1952 Value::Regex(value) => Ok(Form::Regex(value.clone())),
1953 Value::String(value) => Ok(Form::String(value.clone())),
1954 Value::Keyword(value) => Ok(Form::Keyword(value.as_str().into())),
1955 Value::Symbol(value) => Ok(Form::Symbol(value.as_str().into())),
1956 Value::Tagged(value) => Ok(Form::Tagged(
1957 value.tag().get_name().into(),
1958 Box::new(value_to_form(value.form())?),
1959 )),
1960 Value::Pointer(value) => Ok(Form::Tagged(
1961 "ptr".into(),
1962 Box::new(value_to_form(&Value::Map(value.descriptor()))?),
1963 )),
1964 Value::List(values) => Ok(Form::List(
1965 values
1966 .iter()
1967 .map(|v| value_to_form(v))
1968 .collect::<Result<_, _>>()?,
1969 )),
1970 Value::Queue(values) => Ok(Form::List(
1971 values
1972 .iter()
1973 .map(|v| value_to_form(v))
1974 .collect::<Result<_, _>>()?,
1975 )),
1976 Value::Deque(values) => Ok(Form::List(
1977 values
1978 .iter()
1979 .map(|v| value_to_form(v))
1980 .collect::<Result<_, _>>()?,
1981 )),
1982 Value::Cons(values) => Ok(Form::List(
1983 values
1984 .iter()
1985 .map(|v| value_to_form(&v))
1986 .collect::<Result<_, _>>()?,
1987 )),
1988 Value::Vector(values) => Ok(Form::Vector(
1989 values
1990 .iter()
1991 .map(|v| value_to_form(v))
1992 .collect::<Result<_, _>>()?,
1993 )),
1994 Value::Tuple(values) => Ok(Form::Vector(
1995 values
1996 .iter()
1997 .map(|v| value_to_form(v))
1998 .collect::<Result<_, _>>()?,
1999 )),
2000 Value::MapEntry(entry) => Ok(Form::Vector(
2001 entry
2002 .iter()
2003 .map(value_to_form)
2004 .collect::<Result<_, _>>()?,
2005 )),
2006 Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_) => Ok(Form::Set(
2007 set_items(value)
2008 .unwrap()
2009 .iter()
2010 .copied()
2011 .map(value_to_form)
2012 .collect::<Result<_, _>>()?,
2013 )),
2014 Value::Map(_)
2015 | Value::OrderedMap(_)
2016 | Value::SortedMap(_)
2017 | Value::Trie(_)
2018 | Value::PriorityMap(_) => Ok(Form::Map(
2019 map_entries(value)
2020 .unwrap()
2021 .into_iter()
2022 .map(|(key, value)| -> Result<(Form, Form), String> {
2023 Ok((value_to_form(&key)?, value_to_form(&value)?))
2024 })
2025 .collect::<Result<_, _>>()?,
2026 )),
2027 value => Err(format!("cannot use {} as code", portable_type_name(value))),
2028 }?;
2029 Ok(match value_metadata(value) {
2030 Some(metadata) => Form::Metadata(
2031 Box::new(metadata_value_to_form(&MetadataValue::Map(
2032 metadata.entries().to_vec(),
2033 ))),
2034 Box::new(form),
2035 ),
2036 None => form,
2037 })
2038}
2039
2040pub(crate) fn bytecode_dynamic_bind(name: &str, value: Value) -> Result<(), String> {
2041 let registry = namespace_registry()?;
2042 let var = registry
2043 .resolve(&crate::lang::data::Symbol::parse(name))
2044 .ok_or_else(|| format!("binding expects a Var: {name}"))?;
2045 if !var.is_dynamic() {
2046 return Err(format!("binding expects a dynamic Var: {name}"));
2047 }
2048 var.bind(value);
2049 Ok(())
2050}
2051
2052pub(crate) fn bytecode_dynamic_unbind(name: &str) -> Result<(), String> {
2053 let registry = namespace_registry()?;
2054 let var = registry
2055 .resolve(&crate::lang::data::Symbol::parse(name))
2056 .ok_or_else(|| format!("binding expects a Var: {name}"))?;
2057 var.unbind().map(|_| ())
2058}
2059
2060fn macro_environment(env: &HashMap<String, Value>) -> Result<Value, String> {
2061 let namespace = namespace_registry()?.current().name().as_str().to_owned();
2062 let locals = env
2063 .iter()
2064 .filter(|(name, value)| !name.contains('/') && !matches!(value, Value::Var(_)))
2065 .map(|(name, _)| (Value::Symbol(Symbol::from(name.clone())), Value::Nil))
2066 .collect::<Vec<_>>();
2067 let entries = vec![
2068 (
2069 Value::Keyword(Keyword::from("ns")),
2070 Value::Symbol(Symbol::from(namespace)),
2071 ),
2072 (
2073 Value::Keyword(Keyword::from("locals")),
2074 Value::OrderedMap(Box::new(POrderedMap::from_iter(locals))),
2075 ),
2076 (
2077 Value::Keyword(Keyword::from("aliases")),
2078 Value::OrderedMap(Box::new(POrderedMap::new())),
2079 ),
2080 ];
2081 Ok(Value::OrderedMap(Box::new(POrderedMap::from_iter(entries))))
2082}
2083
2084fn macroexpand_call(
2085 name: &str,
2086 invocation: &[Form],
2087 env: &mut HashMap<String, Value>,
2088) -> Result<Option<Form>, String> {
2089 let function = match resolve_macro(name) {
2090 Some(function) => function,
2091 None => return Ok(None),
2092 };
2093 let mut arguments = Vec::with_capacity(invocation.len() + 1);
2094 arguments.push(form_to_value(&Form::List(invocation.to_vec()))?);
2095 arguments.push(macro_environment(env)?);
2096 for form in &invocation[1..] {
2097 arguments.push(form_to_value(form)?);
2098 }
2099 let expansion = call_function(&function, arguments)?;
2100 let expansion = value_to_form(&expansion)?;
2101 #[cfg(feature = "evaluation-journal")]
2102 evaluation_journal_macro(name, &Form::List(invocation.to_vec()), &expansion);
2103 Ok(Some(expansion))
2104}
2105
2106pub(crate) fn form_without_metadata(mut form: &Form) -> &Form {
2107 while let Form::Metadata(_, value) = form {
2108 form = value.as_ref();
2109 }
2110 form
2111}
2112
2113fn macro_clause_with_implicit_params(clause: &Form) -> Result<Form, String> {
2114 match form_without_metadata(clause) {
2115 Form::List(parts) if !parts.is_empty() => {
2116 let params = match form_without_metadata(&parts[0]) {
2117 Form::Vector(params) => params,
2118 _ => return Err("macro arity must start with a parameter vector".into()),
2119 };
2120 let mut implicit = vec![Form::Symbol("&form".into()), Form::Symbol("&env".into())];
2121 implicit.extend_from_slice(params);
2122 let mut new_parts = vec![Form::Vector(implicit)];
2123 new_parts.extend_from_slice(&parts[1..]);
2124 Ok(Form::List(new_parts))
2125 }
2126 _ => Err("macro arity must be a list".into()),
2127 }
2128}
2129
2130fn macroexpand_once(form: &Form, env: &mut HashMap<String, Value>) -> Result<Form, String> {
2131 match form {
2132 Form::List(values) if !values.is_empty() => {
2133 if let Form::Symbol(name) = &values[0] {
2134 if let Some(expanded) = macroexpand_call(name, values, env)? {
2135 return Ok(expanded);
2136 }
2137 }
2138 Ok(form.clone())
2139 }
2140 _ => Ok(form.clone()),
2141 }
2142}
2143
2144pub(crate) fn vm_macroexpand(form: &Form) -> Result<Form, String> {
2145 let mut current = form.clone();
2146 let mut env = HashMap::new();
2147 for _ in 0..1000 {
2148 let expanded = macroexpand_once(¤t, &mut env)?;
2149 if expanded == current {
2150 return Ok(current);
2151 }
2152 current = expanded;
2153 }
2154 Err("macro expansion exceeded 1000 steps".into())
2155}
2156
2157thread_local! {
2158 static TRACE_ENABLED: Cell<bool> = const { Cell::new(false) };
2159 static TRACE_STACK: RefCell<Vec<TraceFrame>> = const { RefCell::new(Vec::new()) };
2160 static TRACE_FAILURE_STACK: RefCell<Vec<TraceFrame>> = const { RefCell::new(Vec::new()) };
2161 #[cfg(feature = "evaluation-journal")]
2162 static EVALUATION_JOURNAL: RefCell<Option<crate::journal::JournalCollector>> = const { RefCell::new(None) };
2163 #[cfg(feature = "evaluation-journal")]
2164 static EVALUATION_JOURNAL_STACK: RefCell<Vec<crate::journal::OperationId>> = const { RefCell::new(Vec::new()) };
2165 static ACTIVE_MACROS: RefCell<Option<Rc<RefCell<HashMap<(String, String), Rc<Function>>>>>> =
2166 const { RefCell::new(None) };
2167 static GENSYM_COUNTER: Cell<u64> = const { Cell::new(0) };
2168}
2169
2170pub(crate) fn trace_stack_snapshot() -> Vec<TraceFrame> {
2171 TRACE_STACK.with(|stack| stack.borrow().clone())
2172}
2173
2174pub(crate) fn record_trace_failure() {
2175 if !tracing_enabled() {
2176 return;
2177 }
2178 let trace = trace_stack_snapshot();
2179 if !trace.is_empty() {
2180 TRACE_FAILURE_STACK.with(|failure| *failure.borrow_mut() = trace);
2181 }
2182}
2183
2184fn trace_failure_snapshot() -> Vec<TraceFrame> {
2185 TRACE_FAILURE_STACK.with(|stack| stack.borrow().clone())
2186}
2187
2188pub(crate) fn with_trace_stack<R>(trace: &[TraceFrame], operation: impl FnOnce() -> R) -> R {
2189 let previous = TRACE_STACK.with(|stack| {
2190 std::mem::replace(&mut *stack.borrow_mut(), trace.to_vec())
2191 });
2192 let result = operation();
2193 TRACE_STACK.with(|stack| {
2194 *stack.borrow_mut() = previous;
2195 });
2196 result
2197}
2198
2199pub(crate) fn trace_frame(
2200 name: String,
2201 namespace: Option<String>,
2202 site: Option<ExceptionSite>,
2203) -> TraceFrame {
2204 TraceFrame {
2205 name,
2206 namespace,
2207 site,
2208 }
2209}
2210
2211#[cfg(feature = "evaluation-journal")]
2212fn journal_preview(value: &Value) -> crate::journal::ValuePreview {
2213 EVALUATION_JOURNAL.with(|active| {
2214 active
2215 .borrow()
2216 .as_ref()
2217 .expect("evaluation journal must be active")
2218 .preview_value(portable_type_name(value), value.display())
2219 })
2220}
2221
2222#[cfg(feature = "evaluation-journal")]
2223fn evaluation_journal_enter(
2224 function: &Function,
2225 arguments: &[Value],
2226) -> Option<crate::journal::OperationId> {
2227 if EVALUATION_JOURNAL.with(|active| active.borrow().is_none()) {
2228 return None;
2229 }
2230 let values = arguments.iter().map(journal_preview).collect();
2231 let parent_operation = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().last().copied());
2232 let depth = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().len());
2233 EVALUATION_JOURNAL.with(|active| {
2234 let mut active = active.borrow_mut();
2235 let collector = active.as_mut()?;
2236 let operation = collector.next_operation_id();
2237 let mut event =
2238 crate::journal::JournalEvent::new(crate::journal::JournalEventKind::OperationEnter);
2239 event.operation = Some(operation);
2240 event.parent_operation = parent_operation;
2241 event.depth = depth;
2242 event.function = Some(
2243 function
2244 .name
2245 .clone()
2246 .unwrap_or_else(|| "<anonymous>".into()),
2247 );
2248 event.values = values;
2249 collector.record(event);
2250 EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow_mut().push(operation));
2251 Some(operation)
2252 })
2253}
2254
2255#[cfg(feature = "evaluation-journal")]
2256fn evaluation_journal_exit(
2257 operation: Option<crate::journal::OperationId>,
2258 function: &Function,
2259 result: Option<&Value>,
2260) {
2261 let Some(operation) = operation else { return };
2262 let value = result.map(journal_preview);
2263 EVALUATION_JOURNAL.with(|active| {
2264 if let Some(collector) = active.borrow_mut().as_mut() {
2265 let mut event = crate::journal::JournalEvent::new(
2266 crate::journal::JournalEventKind::OperationReturn,
2267 );
2268 event.operation = Some(operation);
2269 event.function = Some(
2270 function
2271 .name
2272 .clone()
2273 .unwrap_or_else(|| "<anonymous>".into()),
2274 );
2275 event.values = value.into_iter().collect();
2276 collector.record(event);
2277 }
2278 });
2279 EVALUATION_JOURNAL_STACK.with(|stack| {
2280 let popped = stack.borrow_mut().pop();
2281 debug_assert_eq!(popped, Some(operation));
2282 });
2283}
2284
2285#[cfg(feature = "evaluation-journal")]
2286fn evaluation_journal_macro(name: &str, source: &Form, expansion: &Form) {
2287 let parent_operation = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().last().copied());
2288 let depth = EVALUATION_JOURNAL_STACK.with(|stack| stack.borrow().len());
2289 EVALUATION_JOURNAL.with(|active| {
2290 if let Some(collector) = active.borrow_mut().as_mut() {
2291 let mut event =
2292 crate::journal::JournalEvent::new(crate::journal::JournalEventKind::MacroExpand);
2293 event.parent_operation = parent_operation;
2294 event.depth = depth;
2295 event.function = Some(name.into());
2296 event.values = vec![
2297 collector.preview_value("form", source.to_string()),
2298 collector.preview_value("form", expansion.to_string()),
2299 ];
2300 collector.record(event);
2301 }
2302 });
2303}
2304
2305struct StackTraceGuard {
2306 previous: bool,
2307}
2308
2309impl StackTraceGuard {
2310 fn enable() -> Self {
2311 let previous = TRACE_ENABLED.with(|enabled| {
2312 let previous = enabled.get();
2313 enabled.set(true);
2314 previous
2315 });
2316 TRACE_STACK.with(|stack| stack.borrow_mut().clear());
2317 TRACE_FAILURE_STACK.with(|stack| stack.borrow_mut().clear());
2318 Self { previous }
2319 }
2320}
2321
2322pub(crate) fn with_stack_trace<R>(operation: impl FnOnce() -> R) -> R {
2328 let _guard = StackTraceGuard::enable();
2329 operation()
2330}
2331
2332pub fn with_stack_trace_snapshot<R>(operation: impl FnOnce() -> R) -> (R, Vec<TraceFrame>) {
2337 let _guard = StackTraceGuard::enable();
2338 let result = operation();
2339 let trace = {
2340 let failure = trace_failure_snapshot();
2341 if failure.is_empty() {
2342 trace_stack_snapshot()
2343 } else {
2344 failure
2345 }
2346 };
2347 (result, trace)
2348}
2349
2350impl Drop for StackTraceGuard {
2351 fn drop(&mut self) {
2352 TRACE_STACK.with(|stack| stack.borrow_mut().clear());
2353 TRACE_FAILURE_STACK.with(|stack| stack.borrow_mut().clear());
2354 TRACE_ENABLED.with(|enabled| enabled.set(self.previous));
2355 }
2356}
2357
2358fn tracing_enabled() -> bool {
2359 TRACE_ENABLED.with(Cell::get)
2360}
2361
2362pub(crate) fn append_trace(error: String) -> String {
2363 if !tracing_enabled() {
2364 return error;
2365 }
2366 record_trace_failure();
2367 let frames = TRACE_STACK.with(|stack| stack.borrow().iter().rev().cloned().collect::<Vec<_>>());
2368 if frames.is_empty() {
2369 return error;
2370 }
2371 if error.contains("\n[hara stack]") {
2372 return error;
2373 }
2374 format!(
2375 "{error}\n[hara stack]\n{}",
2376 frames
2377 .iter()
2378 .map(|frame| format!(" at {}", frame.label()))
2379 .collect::<Vec<_>>()
2380 .join("\n")
2381 )
2382}
2383
2384#[derive(Debug, Clone)]
2385enum IteratorGenerator {
2386 Seq(PSeq<Result<Value, String>>),
2387 Constant(Value),
2388 Repeated(Value),
2389 Iterate(Value, Value),
2390 Take(Value, usize),
2391 Drop(Value, usize),
2392 Cycle(Value, Vec<Value>, usize, bool),
2393 TakeWhile(Value, Value),
2394 DropWhile(Value, Value, bool),
2395 Map(Value, Value, bool),
2396 Filter(Value, Value),
2397 Mapcat(Value, Value, Option<Value>),
2398 Keep(Value, Value),
2399 Prepend(Option<Value>, Value),
2400 Concat(Vec<Value>, usize),
2401 Zip(Vec<Value>),
2402 Interleave(Vec<Value>, usize),
2403 Interpose(Value, Value, bool, Option<Value>),
2404 Partition(Value, usize, bool),
2405}
2406
2407#[derive(Debug, Clone)]
2408pub struct IteratorState {
2409 values: Vec<Value>,
2410 index: usize,
2411 closed: bool,
2412 cycle: bool,
2413 lookahead: Option<Value>,
2414 generator: Option<IteratorGenerator>,
2415}
2416
2417fn close_iterator_source(value: &Value) {
2418 if let Value::Iterator(iterator) = value {
2419 if let Ok(mut state) = iterator.try_borrow_mut() {
2420 state.close();
2421 }
2422 }
2423}
2424
2425impl IteratorState {
2426 fn new(values: Vec<Value>) -> Self {
2427 Self {
2428 values,
2429 index: 0,
2430 closed: false,
2431 cycle: false,
2432 lookahead: None,
2433 generator: None,
2434 }
2435 }
2436 fn generated(generator: IteratorGenerator) -> Self {
2437 Self {
2438 values: Vec::new(),
2439 index: 0,
2440 closed: false,
2441 cycle: false,
2442 lookahead: None,
2443 generator: Some(generator),
2444 }
2445 }
2446 pub(crate) fn is_finite(&self) -> bool {
2447 if self.closed || self.generator.is_none() {
2448 return true;
2449 }
2450 match self.generator.as_ref().unwrap() {
2451 IteratorGenerator::Seq(_) => false,
2452 IteratorGenerator::Constant(_)
2453 | IteratorGenerator::Repeated(_)
2454 | IteratorGenerator::Iterate(_, _)
2455 | IteratorGenerator::Cycle(_, _, _, _) => false,
2456 IteratorGenerator::Take(_, _) => true,
2457 IteratorGenerator::Drop(source, _)
2458 | IteratorGenerator::TakeWhile(_, source)
2459 | IteratorGenerator::DropWhile(_, source, _)
2460 | IteratorGenerator::Map(_, source, _)
2461 | IteratorGenerator::Filter(_, source)
2462 | IteratorGenerator::Keep(_, source)
2463 | IteratorGenerator::Prepend(_, source)
2464 | IteratorGenerator::Interpose(source, _, _, _)
2465 | IteratorGenerator::Partition(source, _, _) => value_iterator_is_finite(source),
2466 IteratorGenerator::Mapcat(_, _, _) => false,
2467 IteratorGenerator::Concat(sources, _) | IteratorGenerator::Interleave(sources, _) => {
2468 sources.iter().all(value_iterator_is_finite)
2469 }
2470 IteratorGenerator::Zip(sources) => sources.iter().any(value_iterator_is_finite),
2471 }
2472 }
2473 fn has_next(&mut self) -> Result<bool, String> {
2474 if self.lookahead.is_some() {
2475 return Ok(true);
2476 }
2477 match self.pull_next()? {
2478 Some(value) => {
2479 self.lookahead = Some(value);
2480 Ok(true)
2481 }
2482 None => Ok(false),
2483 }
2484 }
2485 fn try_next(&mut self) -> Result<Option<Value>, String> {
2486 if let Some(value) = self.lookahead.take() {
2487 return Ok(Some(value));
2488 }
2489 self.pull_next()
2490 }
2491 fn pull_next(&mut self) -> Result<Option<Value>, String> {
2492 if self.closed {
2493 return Ok(None);
2494 }
2495 if let Some(generator) = &mut self.generator {
2496 return match generator {
2497 IteratorGenerator::Seq(sequence) => match sequence.peek_first() {
2498 None => {
2499 self.closed = true;
2500 Ok(None)
2501 }
2502 Some(result) => {
2503 *sequence = sequence.pop_first();
2504 result.map(Some)
2505 }
2506 },
2507 IteratorGenerator::Constant(value) => Ok(Some(value.clone())),
2508 IteratorGenerator::Repeated(function) => {
2509 call_value(function.clone(), Vec::new()).map(Some)
2510 }
2511 IteratorGenerator::Iterate(function, current) => {
2512 let output = current.clone();
2513 *current = call_value(function.clone(), vec![current.clone()])?;
2514 Ok(Some(output))
2515 }
2516 IteratorGenerator::Take(source, remaining) => {
2517 if *remaining == 0 {
2518 close_iterator_source(source);
2519 self.closed = true;
2520 Ok(None)
2521 } else {
2522 *remaining -= 1;
2523 let value = iterator_try_next(source)?;
2524 if value.is_none() {
2525 close_iterator_source(source);
2526 self.closed = true;
2527 }
2528 Ok(value)
2529 }
2530 }
2531 IteratorGenerator::Drop(source, remaining) => {
2532 while *remaining > 0 {
2533 if iterator_try_next(source)?.is_none() {
2534 close_iterator_source(source);
2535 self.closed = true;
2536 return Ok(None);
2537 }
2538 *remaining -= 1;
2539 }
2540 let value = iterator_try_next(source)?;
2541 if value.is_none() {
2542 close_iterator_source(source);
2543 self.closed = true;
2544 }
2545 Ok(value)
2546 }
2547 IteratorGenerator::Cycle(source, cache, index, exhausted) => {
2548 if *index < cache.len() {
2549 let value = cache[*index].clone();
2550 *index += 1;
2551 Ok(Some(value))
2552 } else if *exhausted {
2553 if cache.is_empty() {
2554 self.closed = true;
2555 Ok(None)
2556 } else {
2557 *index = 1;
2558 Ok(Some(cache[0].clone()))
2559 }
2560 } else {
2561 match iterator_try_next(source)? {
2562 Some(value) => {
2563 cache.push(value.clone());
2564 *index += 1;
2565 Ok(Some(value))
2566 }
2567 None => {
2568 close_iterator_source(source);
2569 *exhausted = true;
2570 if cache.is_empty() {
2571 self.closed = true;
2572 Ok(None)
2573 } else {
2574 *index = 1;
2575 Ok(Some(cache[0].clone()))
2576 }
2577 }
2578 }
2579 }
2580 }
2581 IteratorGenerator::TakeWhile(function, source) => {
2582 let Some(value) = iterator_try_next(source)? else {
2583 close_iterator_source(source);
2584 self.closed = true;
2585 return Ok(None);
2586 };
2587 if call_value(function.clone(), vec![value.clone()])?.truthy() {
2588 Ok(Some(value))
2589 } else {
2590 close_iterator_source(source);
2591 self.closed = true;
2592 Ok(None)
2593 }
2594 }
2595 IteratorGenerator::DropWhile(function, source, started) => loop {
2596 let Some(value) = iterator_try_next(source)? else {
2597 close_iterator_source(source);
2598 self.closed = true;
2599 break Ok(None);
2600 };
2601 if *started || !call_value(function.clone(), vec![value.clone()])?.truthy() {
2602 *started = true;
2603 break Ok(Some(value));
2604 }
2605 },
2606 IteratorGenerator::Map(function, source, spread) => {
2607 let Some(value) = iterator_try_next(source)? else {
2608 close_iterator_source(source);
2609 self.closed = true;
2610 return Ok(None);
2611 };
2612 match value {
2613 value if !*spread => call_value(function.clone(), vec![value]),
2614 Value::Tuple(values) => {
2615 call_value(function.clone(), values.iter().cloned().collect())
2616 }
2617 Value::Vector(values) => {
2618 call_value(function.clone(), values.iter().cloned().collect())
2619 }
2620 value => call_value(function.clone(), vec![value]),
2621 }
2622 .map(Some)
2623 }
2624 IteratorGenerator::Filter(function, source) => loop {
2625 let Some(value) = iterator_try_next(source)? else {
2626 close_iterator_source(source);
2627 self.closed = true;
2628 break Ok(None);
2629 };
2630 if call_value(function.clone(), vec![value.clone()])?.truthy() {
2631 break Ok(Some(value));
2632 }
2633 },
2634 IteratorGenerator::Mapcat(function, source, pending) => loop {
2635 if let Some(iterator) = pending {
2636 match iterator_try_next(iterator)? {
2637 Some(value) => break Ok(Some(value)),
2638 None => {
2639 close_iterator_source(iterator);
2640 *pending = None;
2641 }
2642 }
2643 }
2644 let Some(value) = iterator_try_next(source)? else {
2645 close_iterator_source(source);
2646 self.closed = true;
2647 break Ok(None);
2648 };
2649 *pending = Some(make_iterator(call_value(function.clone(), vec![value])?)?);
2650 },
2651 IteratorGenerator::Keep(function, source) => loop {
2652 let Some(value) = iterator_try_next(source)? else {
2653 close_iterator_source(source);
2654 self.closed = true;
2655 break Ok(None);
2656 };
2657 let mapped = call_value(function.clone(), vec![value])?;
2658 if !matches!(mapped, Value::Nil) {
2659 break Ok(Some(mapped));
2660 }
2661 },
2662 IteratorGenerator::Prepend(head, source) => {
2663 if let Some(value) = head.take() {
2664 Ok(Some(value))
2665 } else {
2666 let value = iterator_try_next(source)?;
2667 if value.is_none() {
2668 close_iterator_source(source);
2669 self.closed = true;
2670 }
2671 Ok(value)
2672 }
2673 }
2674 IteratorGenerator::Concat(sources, index) => {
2675 while *index < sources.len() {
2676 match iterator_try_next(&sources[*index])? {
2677 Some(value) => return Ok(Some(value)),
2678 None => {
2679 close_iterator_source(&sources[*index]);
2680 *index += 1;
2681 }
2682 }
2683 }
2684 self.closed = true;
2685 Ok(None)
2686 }
2687 IteratorGenerator::Zip(sources) => {
2688 for source in sources.iter() {
2689 if !matches!(iterator_has_next(source)?, Value::Bool(true)) {
2690 for source in sources.iter() {
2691 close_iterator_source(source);
2692 }
2693 self.closed = true;
2694 return Ok(None);
2695 }
2696 }
2697 let mut values = Vec::new();
2698 for source in sources.iter() {
2699 let Some(value) = iterator_try_next(source)? else {
2700 for source in sources.iter() {
2701 close_iterator_source(source);
2702 }
2703 self.closed = true;
2704 return Ok(None);
2705 };
2706 values.push(value);
2707 }
2708 Ok(Some(Value::Vector(values.into())))
2709 }
2710 IteratorGenerator::Interleave(sources, index) => {
2711 if sources.is_empty() {
2712 self.closed = true;
2713 return Ok(None);
2714 }
2715 if *index == 0 {
2716 for source in sources.iter() {
2717 if !matches!(iterator_has_next(source)?, Value::Bool(true)) {
2718 for source in sources.iter() {
2719 close_iterator_source(source);
2720 }
2721 self.closed = true;
2722 return Ok(None);
2723 }
2724 }
2725 }
2726 let source = &sources[*index];
2727 let Some(value) = iterator_try_next(source)? else {
2728 for source in sources.iter() {
2729 close_iterator_source(source);
2730 }
2731 self.closed = true;
2732 return Ok(None);
2733 };
2734 *index = (*index + 1) % sources.len();
2735 Ok(Some(value))
2736 }
2737 IteratorGenerator::Interpose(source, separator, first, pending) => {
2738 if let Some(value) = pending.take() {
2739 return Ok(Some(value));
2740 }
2741 match iterator_try_next(source)? {
2742 None => {
2743 close_iterator_source(source);
2744 self.closed = true;
2745 Ok(None)
2746 }
2747 Some(value) if *first => {
2748 *first = false;
2749 Ok(Some(value))
2750 }
2751 Some(value) => {
2752 *pending = Some(value);
2753 Ok(Some(separator.clone()))
2754 }
2755 }
2756 }
2757 IteratorGenerator::Partition(source, amount, all) => {
2758 let mut values = Vec::new();
2759 for _ in 0..*amount {
2760 match iterator_try_next(source)? {
2761 Some(value) => values.push(value),
2762 None => {
2763 close_iterator_source(source);
2764 self.closed = true;
2765 if values.is_empty() || !*all {
2766 return Ok(None);
2767 }
2768 break;
2769 }
2770 }
2771 }
2772 if values.is_empty() {
2773 self.closed = true;
2774 Ok(None)
2775 } else {
2776 Ok(Some(Value::Vector(values.into())))
2777 }
2778 }
2779 };
2780 }
2781 if self.values.is_empty() {
2782 self.closed = true;
2783 return Ok(None);
2784 }
2785 if self.cycle && self.index >= self.values.len() {
2786 self.index = 0;
2787 }
2788 if self.index >= self.values.len() {
2789 self.closed = true;
2790 return Ok(None);
2791 }
2792 let value = self.values[self.index].clone();
2793 self.index += 1;
2794 Ok(Some(value))
2795 }
2796 fn close(&mut self) {
2797 if self.closed {
2798 self.lookahead = None;
2799 return;
2800 }
2801 self.closed = true;
2802 self.lookahead = None;
2803 if let Some(generator) = &self.generator {
2804 match generator {
2805 IteratorGenerator::Constant(_)
2806 | IteratorGenerator::Repeated(_)
2807 | IteratorGenerator::Iterate(_, _)
2808 | IteratorGenerator::Seq(_) => {}
2809 IteratorGenerator::Take(source, _)
2810 | IteratorGenerator::Drop(source, _)
2811 | IteratorGenerator::Cycle(source, _, _, _)
2812 | IteratorGenerator::TakeWhile(_, source)
2813 | IteratorGenerator::DropWhile(_, source, _)
2814 | IteratorGenerator::Map(_, source, _)
2815 | IteratorGenerator::Filter(_, source)
2816 | IteratorGenerator::Keep(_, source)
2817 | IteratorGenerator::Prepend(_, source)
2818 | IteratorGenerator::Interpose(source, _, _, _)
2819 | IteratorGenerator::Partition(source, _, _) => close_iterator_source(source),
2820 IteratorGenerator::Mapcat(_, source, pending) => {
2821 close_iterator_source(source);
2822 if let Some(pending) = pending {
2823 close_iterator_source(pending);
2824 }
2825 }
2826 IteratorGenerator::Concat(sources, _)
2827 | IteratorGenerator::Zip(sources)
2828 | IteratorGenerator::Interleave(sources, _) => {
2829 for source in sources {
2830 close_iterator_source(source);
2831 }
2832 }
2833 }
2834 }
2835 }
2836}
2837
2838fn value_iterator_is_finite(value: &Value) -> bool {
2839 match value {
2840 Value::Iterator(iterator) => iterator.borrow().is_finite(),
2841 Value::Seq(_) => false,
2842 _ => true,
2843 }
2844}
2845
2846#[inline(never)]
2847fn sequential_equality(left: &Value, right: &Value) -> Option<bool> {
2848 fn items(value: &Value) -> Option<Vec<Value>> {
2849 match value {
2850 Value::Seq(values) => values.iter().collect::<Result<Vec<_>, _>>().ok(),
2851 Value::List(values) => Some(values.iter().cloned().collect()),
2852 Value::Cons(values) => Some(values.iter().collect()),
2853 Value::Queue(values) => Some(values.iter().cloned().collect()),
2854 Value::Deque(values) => Some(values.iter().cloned().collect()),
2855 Value::Tuple(values) => Some(values.iter().cloned().collect()),
2856 Value::Vector(values) => Some(values.iter().cloned().collect()),
2857 _ => None,
2858 }
2859 }
2860 Some(items(left)? == items(right)?)
2861}
2862
2863pub fn map_entries(value: &Value) -> Option<Vec<(Value, Value)>> {
2867 match value {
2868 Value::Map(values) => Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect()),
2869 Value::OrderedMap(values) => {
2870 Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
2871 }
2872 Value::SortedMap(values) => {
2873 Some(values.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
2874 }
2875 Value::PriorityMap(values) => Some(values.iter().collect()),
2876 Value::Trie(values) => Some(
2877 values
2878 .entries()
2879 .into_iter()
2880 .map(|(k, v)| (Value::String(k), v.clone()))
2881 .collect(),
2882 ),
2883 _ => None,
2884 }
2885}
2886
2887fn pointer_from_descriptor(descriptor: Value) -> Result<Value, String> {
2888 let entries =
2889 map_entries(&descriptor).ok_or_else(|| "pointer expects one descriptor map".to_string())?;
2890 let context_key = Value::Keyword(Keyword::from("context"));
2891 let mut context = None;
2892 let mut fields = Vec::new();
2893 for (key, value) in entries {
2894 if key == context_key {
2895 if context.is_some() {
2896 return Err("pointer descriptor contains duplicate :context".into());
2897 }
2898 context = match value {
2899 Value::Keyword(context) => Some(context),
2900 _ => return Err("pointer :context must be a keyword".into()),
2901 };
2902 } else {
2903 if !matches!(key, Value::Keyword(_)) {
2904 return Err("pointer descriptor fields must use keyword keys".into());
2905 }
2906 fields.push((key, value));
2907 }
2908 }
2909 let context = context.ok_or_else(|| "pointer descriptor requires :context".to_string())?;
2910 Ok(Value::Pointer(PPointer::new(
2911 context,
2912 fields.into_iter().collect(),
2913 )))
2914}
2915
2916pub(crate) fn session_transferable(value: &Value) -> bool {
2923 match value {
2924 Value::Number(_)
2925 | Value::Float(_)
2926 | Value::BigInteger(_)
2927 | Value::Character(_)
2928 | Value::Regex(_)
2929 | Value::Tagged(_)
2930 | Value::Bool(_)
2931 | Value::String(_)
2932 | Value::Keyword(_)
2933 | Value::Bytes(_)
2934 | Value::Symbol(_)
2935 | Value::Nil => true,
2936 value @ (Value::Map(_)
2937 | Value::OrderedMap(_)
2938 | Value::SortedMap(_)
2939 | Value::Trie(_)
2940 | Value::PriorityMap(_)) => map_entries(value).is_some_and(|entries| {
2941 entries
2942 .iter()
2943 .all(|(key, value)| session_transferable(key) && session_transferable(value))
2944 }),
2945 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => set_items(value)
2946 .is_some_and(|values| values.iter().all(|value| session_transferable(value))),
2947 Value::List(values) => values.iter().all(session_transferable),
2948 Value::Cons(values) => values.iter().all(|value| session_transferable(&value)),
2949 Value::Queue(values) => values.iter().all(session_transferable),
2950 Value::Deque(values) => values.iter().all(session_transferable),
2951 Value::Tuple(values) => values.iter().all(session_transferable),
2952 Value::Vector(values) => values.iter().all(session_transferable),
2953 Value::MapEntry(entry) => {
2954 session_transferable(entry.key()) && session_transferable(entry.value())
2955 }
2956 Value::Struct(value) => value.ordered_values().into_iter().all(session_transferable),
2957 Value::Pointer(value) => value
2958 .fields()
2959 .iter()
2960 .all(|(key, value)| session_transferable(key) && session_transferable(value)),
2961 Value::ExceptionInfo(value) => {
2962 session_transferable(&value.data)
2963 && value.cause.as_deref().map_or(true, session_transferable)
2964 }
2965 Value::ByteBuffer(_)
2966 | Value::Array(_)
2967 | Value::Object(_)
2968 | Value::Promise(_)
2969 | Value::Atom(_)
2970 | Value::Recur(_)
2971 | Value::Function(_)
2972 | Value::Seq(_)
2973 | Value::Iterator(_)
2974 | Value::Var(_)
2975 | Value::Namespace(_)
2976 | Value::Extension(_)
2977 | Value::StructType(_)
2978 | Value::MutableType(_)
2979 | Value::Mutable(_)
2980 | Value::Protocol(_)
2981 | Value::NativeType(_)
2982 | Value::Schema(_)
2983 | Value::Coroutine(_)
2984 | Value::Stream(_)
2985 | Value::Result(_)
2986 | Value::MutableCollection(_) => false,
2987 }
2988}
2989
2990fn map_value<'a>(value: &'a Value, key: &Value) -> Option<&'a Value> {
2991 match value {
2992 Value::Map(values) => values.get(key),
2993 Value::OrderedMap(values) => values.get(key),
2994 Value::SortedMap(values) => values.get(key),
2995 Value::PriorityMap(values) => values.get(key),
2996 Value::Trie(values) => match key {
2997 Value::String(key) => values.get(key),
2998 _ => None,
2999 },
3000 _ => None,
3001 }
3002}
3003
3004fn map_equality(left: &Value, right: &Value) -> Option<bool> {
3005 let left_entries = map_entries(left)?;
3006 let right_entries = map_entries(right)?;
3007 Some(
3008 left_entries.len() == right_entries.len()
3009 && left_entries
3010 .iter()
3011 .all(|(key, value)| map_value(right, key) == Some(value)),
3012 )
3013}
3014
3015fn set_items(value: &Value) -> Option<Vec<&Value>> {
3016 match value {
3017 Value::Set(values) => Some(values.iter().collect()),
3018 Value::OrderedSet(values) => Some(values.iter().collect()),
3019 Value::SortedSet(values) => Some(values.iter().collect()),
3020 _ => None,
3021 }
3022}
3023
3024fn set_equality(left: &Value, right: &Value) -> Option<bool> {
3025 let left_items = set_items(left)?;
3026 let right_items = set_items(right)?;
3027 Some(
3028 left_items.len() == right_items.len()
3029 && left_items.iter().all(|item| right_items.contains(item)),
3030 )
3031}
3032
3033fn map_assoc_value(collection: &Value, key: Value, value: Value) -> Result<Value, String> {
3034 Ok(match collection {
3035 Value::Map(values) => Value::Map(values.assoc_value(key, value)),
3036 Value::OrderedMap(values) => Value::OrderedMap(Box::new(values.assoc_value(key, value))),
3037 Value::SortedMap(values) => Value::SortedMap(Box::new(values.assoc_value(key, value))),
3038 Value::PriorityMap(values) => Value::PriorityMap(Box::new(values.assoc_value(key, value))),
3039 Value::Trie(values) => match key {
3040 Value::String(key) => Value::Trie(Box::new(values.assoc_value(key, value))),
3041 _ => return Err("trie expects string keys".into()),
3042 },
3043 _ => return Err("assoc expects a map".into()),
3044 })
3045}
3046
3047fn map_dissoc_value(collection: &Value, key: &Value) -> Result<Value, String> {
3048 Ok(match collection {
3049 Value::Map(values) => Value::Map(values.dissoc_value(key)),
3050 Value::OrderedMap(values) => Value::OrderedMap(Box::new(values.dissoc_value(key))),
3051 Value::SortedMap(values) => Value::SortedMap(Box::new(values.dissoc_value(key))),
3052 Value::PriorityMap(values) => Value::PriorityMap(Box::new(values.dissoc_value(key))),
3053 Value::Trie(values) => match key {
3054 Value::String(key) => Value::Trie(Box::new(values.dissoc_value(key))),
3055 _ => return Err("trie expects string keys".into()),
3056 },
3057 _ => return Err("dissoc expects a map".into()),
3058 })
3059}
3060
3061fn set_find(collection: &Value, key: &Value) -> Option<Value> {
3062 set_items(collection)?
3063 .into_iter()
3064 .find(|value| *value == key)
3065 .cloned()
3066}
3067
3068fn set_conj_value(collection: &Value, value: Value) -> Result<Value, String> {
3069 Ok(match collection {
3070 Value::Set(values) => Value::Set(values.conj_value(value)),
3071 Value::OrderedSet(values) => Value::OrderedSet(Box::new(values.conj_value(value))),
3072 Value::SortedSet(values) => Value::SortedSet(Box::new(values.conj_value(value))),
3073 _ => return Err("conj expects a set".into()),
3074 })
3075}
3076
3077fn set_dissoc_value(collection: &Value, value: &Value) -> Result<Value, String> {
3078 Ok(match collection {
3079 Value::Set(values) => Value::Set(values.dissoc_value(value)),
3080 Value::OrderedSet(values) => Value::OrderedSet(Box::new(values.dissoc_value(value))),
3081 Value::SortedSet(values) => Value::SortedSet(Box::new(values.dissoc_value(value))),
3082 _ => return Err("dissoc expects a set".into()),
3083 })
3084}
3085
3086fn collection_to_mutable(value: &Value) -> Result<Value, String> {
3087 let mutable = match value {
3088 Value::Map(values) => MutableCollection::Map(values.to_mutable()),
3089 Value::OrderedMap(values) => MutableCollection::OrderedMap(values.to_mutable()),
3090 Value::SortedMap(values) => MutableCollection::SortedMap(values.to_mutable()),
3091 Value::Trie(values) => MutableCollection::Trie(values.to_mutable()),
3092 Value::Set(values) => MutableCollection::Set(values.to_mutable()),
3093 Value::OrderedSet(values) => MutableCollection::OrderedSet(values.to_mutable()),
3094 Value::SortedSet(values) => MutableCollection::SortedSet(values.to_mutable()),
3095 Value::List(values) => MutableCollection::List(values.to_mutable()),
3096 Value::Queue(values) => MutableCollection::Queue(values.to_mutable()),
3097 Value::Vector(values) => MutableCollection::Vector(values.to_mutable()),
3098 Value::MutableCollection(_) => return Err("value is already mutable".into()),
3099 _ => return Err("to-mutable expects a persistent collection".into()),
3100 };
3101 Ok(Value::MutableCollection(Rc::new(RefCell::new(Some(
3102 mutable,
3103 )))))
3104}
3105
3106fn collection_to_persistent(value: &Value) -> Result<Value, String> {
3107 let Value::MutableCollection(collection) = value else {
3108 return Err("to-persistent expects a mutable collection".into());
3109 };
3110 let mut mutable = collection
3111 .borrow_mut()
3112 .take()
3113 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
3114 Ok(match &mut mutable {
3115 MutableCollection::Map(values) => Value::Map(values.to_persistent()),
3116 MutableCollection::OrderedMap(values) => {
3117 Value::OrderedMap(Box::new(values.to_persistent()))
3118 }
3119 MutableCollection::SortedMap(values) => Value::SortedMap(Box::new(values.to_persistent())),
3120 MutableCollection::Trie(values) => Value::Trie(Box::new(values.to_persistent())),
3121 MutableCollection::Set(values) => Value::Set(values.to_persistent()),
3122 MutableCollection::OrderedSet(values) => {
3123 Value::OrderedSet(Box::new(values.to_persistent()))
3124 }
3125 MutableCollection::SortedSet(values) => Value::SortedSet(Box::new(values.to_persistent())),
3126 MutableCollection::List(values) => Value::List(values.to_persistent()),
3127 MutableCollection::Queue(values) => Value::Queue(Box::new(values.to_persistent())),
3128 MutableCollection::Vector(values) => Value::Vector(values.to_persistent()),
3129 })
3130}
3131
3132fn protocol_to_mutable(arguments: &[Value]) -> Result<Value, String> {
3133 match arguments {
3134 [Value::Extension(receiver)] => extension_protocol_call(
3135 receiver,
3136 "std.protocol.itomutable.IToMutable",
3137 "to-mutable",
3138 arguments,
3139 ),
3140 [value] => collection_to_mutable(value),
3141 _ => Err("IToMutable/to-mutable expects one value".into()),
3142 }
3143}
3144
3145fn protocol_to_persistent(arguments: &[Value]) -> Result<Value, String> {
3146 match arguments {
3147 [Value::Extension(receiver)] => extension_protocol_call(
3148 receiver,
3149 "std.protocol.itopersistent.IToPersistent",
3150 "to-persistent",
3151 arguments,
3152 ),
3153 [value] => collection_to_persistent(value),
3154 _ => Err("IToPersistent/to-persistent expects one value".into()),
3155 }
3156}
3157
3158impl PartialEq for Value {
3159 fn eq(&self, other: &Self) -> bool {
3160 if let Some(equal) = sequential_equality(self, other) {
3161 return equal;
3162 }
3163 if let Some(equal) = map_equality(self, other) {
3164 return equal;
3165 }
3166 if let Some(equal) = set_equality(self, other) {
3167 return equal;
3168 }
3169 if let Some(equal) = numeric::numeric_equal(self, other) {
3170 return equal;
3171 }
3172 match (self, other) {
3173 (Value::Number(a), Value::Number(b)) => a == b,
3174 (Value::Float(a), Value::Float(b)) => a.to_bits() == b.to_bits(),
3175 (Value::BigInteger(a), Value::BigInteger(b)) => a == b,
3176 (Value::Character(a), Value::Character(b)) => a == b,
3177 (Value::Regex(a), Value::Regex(b)) => a == b,
3178 (Value::Tagged(a), Value::Tagged(b)) => a == b,
3179 (Value::Bool(a), Value::Bool(b)) => a == b,
3180 (Value::String(a), Value::String(b)) => a == b,
3181 (Value::Keyword(a), Value::Keyword(b)) => a == b,
3182 (Value::Bytes(a), Value::Bytes(b)) => a == b,
3183 (Value::ByteBuffer(a), Value::ByteBuffer(b)) => *a.borrow() == *b.borrow(),
3184 (Value::Array(a), Value::Array(b)) => Rc::ptr_eq(a, b),
3185 (Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b),
3186 (Value::Promise(a), Value::Promise(b)) => a.same_identity(b),
3187 (Value::Atom(a), Value::Atom(b)) => a.same_identity(b),
3188 (Value::Recur(a), Value::Recur(b)) => a == b,
3189 (Value::Map(a), Value::Map(b)) => a == b,
3190 (Value::Set(a), Value::Set(b)) => a == b,
3191 (Value::List(a), Value::List(b)) => a == b,
3192 (Value::Cons(a), Value::Cons(b)) => a == b,
3193 (Value::Symbol(a), Value::Symbol(b)) => a == b,
3194 (Value::Pointer(a), Value::Pointer(b)) => a == b,
3195 (Value::Function(a), Value::Function(b)) => Rc::ptr_eq(a, b),
3196 (Value::Tuple(a), Value::Tuple(b)) => a == b,
3197 (Value::Vector(a), Value::Vector(b)) => a == b,
3198 (Value::MapEntry(a), Value::MapEntry(b)) => a == b,
3199 (Value::MutableCollection(a), Value::MutableCollection(b)) => Rc::ptr_eq(a, b),
3200 (Value::Iterator(a), Value::Iterator(b)) => Rc::ptr_eq(a, b),
3201 (Value::Var(a), Value::Var(b)) => a.same_identity(b),
3202 (Value::Namespace(a), Value::Namespace(b)) => a.same_identity(b),
3203 (Value::Extension(a), Value::Extension(b)) => a == b,
3204 (Value::StructType(a), Value::StructType(b)) => Rc::ptr_eq(a, b),
3205 (Value::Struct(a), Value::Struct(b)) => {
3206 Rc::ptr_eq(&a.ty, &b.ty) && a.values == b.values
3207 }
3208 (Value::MutableType(a), Value::MutableType(b)) => Rc::ptr_eq(a, b),
3209 (Value::Mutable(a), Value::Mutable(b)) => a.same_identity(b),
3210 (Value::Protocol(a), Value::Protocol(b)) => Rc::ptr_eq(a, b),
3211 (Value::NativeType(a), Value::NativeType(b)) => a.name == b.name,
3212 (Value::Schema(a), Value::Schema(b)) => a.ast == b.ast,
3213 (Value::Coroutine(a), Value::Coroutine(b)) => Rc::ptr_eq(a, b),
3214 (Value::Stream(a), Value::Stream(b)) => Rc::ptr_eq(a, b),
3215 (Value::Result(a), Value::Result(b)) => a == b,
3216 (Value::ExceptionInfo(a), Value::ExceptionInfo(b)) => Rc::ptr_eq(a, b),
3217 (Value::Nil, Value::Nil) => true,
3218 _ => false,
3219 }
3220 }
3221}
3222
3223impl Eq for Value {}
3224impl PartialOrd for Value {
3225 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3226 Some(self.cmp(other))
3227 }
3228}
3229impl Ord for Value {
3230 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3231 if let Some(ordering) = numeric::numeric_total_compare(self, other) {
3232 return ordering;
3233 }
3234 if self == other {
3235 return std::cmp::Ordering::Equal;
3236 }
3237 match (self, other) {
3238 (Value::Number(left), Value::Number(right)) => return left.cmp(right),
3239 (Value::Float(left), Value::Float(right)) => return left.total_cmp(right),
3240 (Value::Character(left), Value::Character(right)) => return left.cmp(right),
3241 (Value::Bool(left), Value::Bool(right)) => return left.cmp(right),
3242 (Value::String(left), Value::String(right)) => return left.cmp(right),
3243 (Value::Keyword(left), Value::Keyword(right)) => return left.cmp(right),
3244 (Value::BigInteger(left), Value::BigInteger(right)) => return left.cmp(right),
3245 _ => {}
3246 }
3247 fn rank(value: &Value) -> u8 {
3248 match value {
3249 Value::Nil => 0,
3250 Value::Bool(_) => 1,
3251 Value::Number(_) => 2,
3252 Value::Float(_) => 3,
3253 Value::BigInteger(_) => 4,
3254 Value::Character(_) => 5,
3255 Value::String(_) => 7,
3256 Value::Keyword(_) => 8,
3257 Value::Symbol(_) => 9,
3258 Value::Pointer(_) => 9,
3259 Value::List(_)
3260 | Value::Cons(_)
3261 | Value::Queue(_)
3262 | Value::Deque(_)
3263 | Value::Tuple(_)
3264 | Value::Vector(_)
3265 | Value::MapEntry(_)
3266 | Value::Seq(_) => 10,
3267 Value::Map(_)
3268 | Value::OrderedMap(_)
3269 | Value::SortedMap(_)
3270 | Value::Trie(_)
3271 | Value::PriorityMap(_) => 11,
3272 Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_) => 12,
3273 Value::Bytes(_) => 13,
3274 Value::ByteBuffer(_) => 14,
3275 Value::Regex(_) => 15,
3276 Value::Tagged(_) => 16,
3277 Value::Array(_) => 17,
3278 Value::Object(_) => 18,
3279 Value::Promise(_) => 19,
3280 Value::Atom(_) => 26,
3281 Value::Recur(_) => 20,
3282 Value::Function(_) => 21,
3283 Value::Iterator(_) => 22,
3284 Value::Var(_) => 23,
3285 Value::Namespace(_) => 24,
3286 Value::Extension(_) => 25,
3287 Value::StructType(_) => 27,
3288 Value::Struct(_) => 28,
3289 Value::MutableType(_) => 29,
3290 Value::Mutable(_) => 30,
3291 Value::Protocol(_) => 31,
3292 Value::NativeType(_) => 32,
3293 Value::Schema(_) => 33,
3294 Value::Coroutine(_) => 33,
3295 Value::Stream(_) => 34,
3296 Value::Result(_) => 36,
3297 Value::ExceptionInfo(_) => 37,
3298 Value::MutableCollection(_) => 38,
3299 }
3300 }
3301 rank(self)
3302 .cmp(&rank(other))
3303 .then_with(|| self.display().cmp(&other.display()))
3304 .then_with(|| self.stable_hash().cmp(&other.stable_hash()))
3305 }
3306}
3307impl Hash for Value {
3308 fn hash<H: Hasher>(&self, state: &mut H) {
3309 if crate::lang::data::map::champ_placement_hashing() {
3312 if let Self::Number(value) = self {
3313 state.write_u64(crate::lang::hash::hash_long_placement(*value) as i64 as u64);
3314 return;
3315 }
3316 if let Self::Float(value) = self {
3317 if value.is_finite() && value.fract() == 0.0 {
3318 if let Ok(integer) = (*value).to_string().parse::<i64>() {
3319 state.write_u64(
3320 crate::lang::hash::hash_long_placement(integer) as i64 as u64,
3321 );
3322 return;
3323 }
3324 }
3325 }
3326 }
3327 if let Some(hash) = numeric::numeric_hash(self) {
3328 state.write_u64(hash as i64 as u64);
3329 return;
3330 }
3331 match self {
3332 Value::Bool(value) => state.write_u64(crate::lang::hash::hash_bool(*value) as u64),
3333 Value::Nil => state.write_u64(0),
3334 _ => state.write_u64(self.stable_hash()),
3335 }
3336 }
3337}
3338
3339impl crate::lang::hash::JavaHash for Value {
3340 fn java_hash(&self, hash_type: crate::lang::protocol::HashType) -> i64 {
3345 use crate::lang::hash as jh;
3346 use crate::lang::protocol::IHash;
3347
3348 fn opaque(
3352 tag: u64,
3353 write: impl FnOnce(&mut std::collections::hash_map::DefaultHasher),
3354 ) -> i64 {
3355 let mut state = std::collections::hash_map::DefaultHasher::new();
3356 tag.hash(&mut state);
3357 write(&mut state);
3358 state.finish() as i64
3359 }
3360
3361 match self {
3362 Self::Nil => 0,
3363 Self::Bool(v) => jh::hash_bool(*v) as i64,
3364 Self::Character(v) => jh::hash_char(*v) as i64,
3365 Self::String(v) => jh::java_string_hash(v) as i64,
3366 Self::Number(value) => jh::hash_long(*value) as i64,
3367 Self::Float(value) => jh::hash_double(*value) as i64,
3368 Self::BigInteger(value) => jh::canonical_decimal_str_hash(&value.to_string()) as i64,
3369 Self::Regex(v) => jh::java_string_hash(v) as i64,
3372 Self::Keyword(v) => v.java_hash(hash_type),
3373 Self::Symbol(v) => v.java_hash(hash_type),
3374 Self::Pointer(v) => v.java_hash(hash_type),
3375 Self::Bytes(v) => jh::hash_bytes(v) as i64,
3376 Self::ByteBuffer(v) => jh::hash_bytes(v.borrow().as_slice()) as i64,
3377 Self::Array(v) => jh::compose_ordered(
3379 "SEQUENTIAL",
3380 v.borrow().iter().map(|item| item.java_hash(hash_type)),
3381 ),
3382 Self::Object(v) => jh::compose_unordered(
3383 "MAP",
3384 v.borrow().iter().map(|(key, item)| {
3385 jh::compose_entry(jh::java_string_hash(key) as i64, item.java_hash(hash_type))
3386 }),
3387 ),
3388 Self::Recur(v) => {
3389 jh::compose_ordered("SEQUENTIAL", v.iter().map(|item| item.java_hash(hash_type)))
3390 }
3391 Self::Tagged(v) => jh::compose_ordered(
3392 "SEQUENTIAL",
3393 [v.tag().java_hash(hash_type), v.form().java_hash(hash_type)],
3394 ),
3395 Self::Map(v) => v.hash_calc(hash_type) as i64,
3396 Self::OrderedMap(v) => v.hash_calc(hash_type) as i64,
3397 Self::SortedMap(v) => v.hash_calc(hash_type) as i64,
3398 Self::PriorityMap(v) => v.hash_calc(hash_type) as i64,
3399 Self::Trie(v) => v.hash_calc(hash_type) as i64,
3400 Self::Set(v) => v.hash_calc(hash_type) as i64,
3401 Self::OrderedSet(v) => v.hash_calc(hash_type) as i64,
3402 Self::SortedSet(v) => v.hash_calc(hash_type) as i64,
3403 Self::List(v) => v.hash_calc(hash_type) as i64,
3404 Self::Cons(v) => v.hash_calc(hash_type) as i64,
3405 Self::Deque(v) => v.hash_calc(hash_type) as i64,
3406 Self::Queue(v) => v.hash_calc(hash_type) as i64,
3407 Self::Tuple(v) => v.hash_calc(hash_type) as i64,
3408 Self::Vector(v) => v.hash_calc(hash_type) as i64,
3409 Self::MapEntry(v) => v.hash_calc(hash_type) as i64,
3410 Self::Seq(v) => jh::compose_ordered(
3411 "SEQUENTIAL",
3412 v.iter().map(|item| match item {
3413 Ok(value) => value.java_hash(hash_type),
3414 Err(error) => jh::java_string_hash(&error) as i64,
3415 }),
3416 ),
3417 Self::MutableCollection(v) => opaque(32, |s| Rc::as_ptr(v).hash(s)),
3418 Self::Promise(v) => opaque(8, |s| v.identity_address().hash(s)),
3419 Self::Atom(v) => opaque(28, |s| v.identity_address().hash(s)),
3420 Self::Function(v) => opaque(14, |s| Rc::as_ptr(v).hash(s)),
3421 Self::Iterator(v) => opaque(16, |s| Rc::as_ptr(v).hash(s)),
3422 Self::Var(v) => opaque(17, |s| v.identity_address().hash(s)),
3423 Self::Namespace(v) => opaque(27, |s| v.identity_address().hash(s)),
3424 Self::Extension(v) => opaque(18, |s| {
3425 v.provider.hash(s);
3426 v.type_name.hash(s);
3427 v.handle.hash(s);
3428 }),
3429 Self::StructType(v) => opaque(26, |s| Rc::as_ptr(v).hash(s)),
3430 Self::Struct(v) => opaque(27, |s| {
3431 Rc::as_ptr(&v.ty).hash(s);
3432 for value in v.ordered_values() {
3433 value.hash(s);
3434 }
3435 }),
3436 Self::MutableType(v) => opaque(28, |s| Rc::as_ptr(v).hash(s)),
3437 Self::Mutable(v) => opaque(29, |s| v.identity_address().hash(s)),
3438 Self::Protocol(v) => opaque(30, |s| v.name.hash(s)),
3439 Self::NativeType(v) => opaque(31, |s| v.name.hash(s)),
3440 Self::Schema(v) => opaque(34, |s| v.form.to_string().hash(s)),
3441 Self::Coroutine(v) => opaque(32, |s| Rc::as_ptr(v).hash(s)),
3442 Self::Stream(v) => opaque(35, |s| Rc::as_ptr(v).hash(s)),
3443 Self::Result(v) => v.java_hash(hash_type),
3444 Self::ExceptionInfo(v) => opaque(33, |s| Rc::as_ptr(v).hash(s)),
3445 }
3446 }
3447}
3448
3449impl Value {
3450 pub fn display(&self) -> String {
3451 match self {
3452 Self::Number(v) => v.to_string(),
3453 Self::Float(v) => {
3454 assert!(v.is_finite(), "non-finite number");
3455 format!("(double {v})")
3456 }
3457 Self::BigInteger(v) => v.to_string(),
3458 Self::Character('\n') => "\\newline".into(),
3459 Self::Character(' ') => "\\space".into(),
3460 Self::Character('\t') => "\\tab".into(),
3461 Self::Character('\u{0008}') => "\\backspace".into(),
3462 Self::Character('\u{000c}') => "\\formfeed".into(),
3463 Self::Character('\r') => "\\return".into(),
3464 Self::Character(v) if v.is_control() => format!("\\u{:04X}", *v as u32),
3465 Self::Character(v) => format!("\\{v}"),
3466 Self::Regex(v) => crate::kernel::form::display_regex(v),
3467 Self::Tagged(value) => uuid_text_from_tagged(value).map_or_else(
3468 || format!("#{}{}", value.tag().as_str(), value.form().display()),
3469 |text| format!("#{UUID_TAG} {}", Self::String(text.to_owned()).display()),
3470 ),
3471 Self::Bool(v) => v.to_string(),
3472 Self::String(v) => crate::kernel::form::display_string(v),
3473 Self::Keyword(v) => format!(":{}", v.as_str()),
3474 Self::Bytes(values) => format!(
3475 "#bytes[{}]",
3476 values
3477 .iter()
3478 .map(|v| (*v as i8).to_string())
3479 .collect::<Vec<_>>()
3480 .join(" ")
3481 ),
3482 Self::ByteBuffer(values) => {
3483 let body = values
3484 .borrow()
3485 .iter()
3486 .map(|v| (*v as i8).to_string())
3487 .collect::<Vec<_>>()
3488 .join(" ");
3489 if body.is_empty() {
3490 "(bytes)".into()
3491 } else {
3492 format!("(bytes {body})")
3493 }
3494 }
3495 Self::Array(values) => format!(
3496 "#arr[{}]",
3497 values
3498 .borrow()
3499 .iter()
3500 .map(Value::display)
3501 .collect::<Vec<_>>()
3502 .join(" ")
3503 ),
3504 Self::Object(values) => format!(
3505 "#obj{{{}}}",
3506 values
3507 .borrow()
3508 .iter()
3509 .map(|(key, value)| format!(
3510 "{} {}",
3511 Value::String(key.clone()).display(),
3512 value.display()
3513 ))
3514 .collect::<Vec<_>>()
3515 .join(" ")
3516 ),
3517 Self::Promise(_) => "<promise>".into(),
3518 Self::Atom(value) => format!("#atom <{}>", value.deref_value().display()),
3519 Self::Recur(values) => format!(
3520 "<recur {}>",
3521 values
3522 .iter()
3523 .map(Value::display)
3524 .collect::<Vec<_>>()
3525 .join(" ")
3526 ),
3527 value @ (Self::Map(_)
3528 | Self::OrderedMap(_)
3529 | Self::SortedMap(_)
3530 | Self::PriorityMap(_)
3531 | Self::Trie(_)) => {
3532 format!(
3533 "{{{}}}",
3534 map_entries(value)
3535 .unwrap()
3536 .iter()
3537 .map(|(k, v)| format!("{} {}", k.display(), v.display()))
3538 .collect::<Vec<_>>()
3539 .join(" ")
3540 )
3541 }
3542 value @ (Self::Set(_) | Self::OrderedSet(_) | Self::SortedSet(_)) => format!(
3543 "#{{{}}}",
3544 set_items(value)
3545 .unwrap()
3546 .iter()
3547 .map(|item| item.display())
3548 .collect::<Vec<_>>()
3549 .join(" ")
3550 ),
3551 Self::Queue(values) => format!(
3552 "#queue[{}]",
3553 values
3554 .iter()
3555 .map(Value::display)
3556 .collect::<Vec<_>>()
3557 .join(" ")
3558 ),
3559 Self::Deque(values) => format!(
3560 "#deque[{}]",
3561 values
3562 .iter()
3563 .map(Value::display)
3564 .collect::<Vec<_>>()
3565 .join(" ")
3566 ),
3567 Self::Cons(values) => format!(
3568 "({})",
3569 values
3570 .iter()
3571 .map(|value| value.display())
3572 .collect::<Vec<_>>()
3573 .join(" ")
3574 ),
3575 Self::List(values) => format!(
3576 "({})",
3577 values
3578 .iter()
3579 .map(Value::display)
3580 .collect::<Vec<_>>()
3581 .join(" ")
3582 ),
3583 Self::Symbol(v) => v.as_str().to_owned(),
3584 Self::Pointer(v) => v.display(),
3585 Self::Function(_) => "<fn>".into(),
3586 Self::Tuple(values) => format!(
3587 "[{}]",
3588 values
3589 .iter()
3590 .map(Value::display)
3591 .collect::<Vec<_>>()
3592 .join(" ")
3593 ),
3594 Self::MapEntry(entry) => entry.display(),
3595 Self::Vector(values) => format!(
3596 "[{}]",
3597 values
3598 .iter()
3599 .map(Value::display)
3600 .collect::<Vec<_>>()
3601 .join(" ")
3602 ),
3603 Self::MutableCollection(values) => {
3604 let borrowed = values.borrow();
3605 let Some(values) = borrowed.as_ref() else {
3606 return "#<mutable-frozen>".into();
3607 };
3608 let kind = match values {
3609 MutableCollection::Map(_) => "map",
3610 MutableCollection::OrderedMap(_) => "ordered-map",
3611 MutableCollection::SortedMap(_) => "sorted-map",
3612 MutableCollection::Trie(_) => "trie",
3613 MutableCollection::Set(_) => "set",
3614 MutableCollection::OrderedSet(_) => "ordered-set",
3615 MutableCollection::SortedSet(_) => "sorted-set",
3616 MutableCollection::List(_) => "list",
3617 MutableCollection::Queue(_) => "queue",
3618 MutableCollection::Vector(_) => "vector",
3619 };
3620 format!("#<mutable-{kind}>")
3621 }
3622 Self::Seq(sequence) => {
3623 let mut values = sequence.iter();
3624 let mut displayed = Vec::new();
3625 for _ in 0..10 {
3626 match values.next() {
3627 Some(Ok(value)) => displayed.push(value.display()),
3628 Some(Err(error)) => {
3629 displayed.push(format!("#error[{}]", Value::String(error).display()));
3630 break;
3631 }
3632 None => break,
3633 }
3634 }
3635 if values.next().is_some() {
3636 displayed.push("...".into());
3637 }
3638 format!("({})", displayed.join(" "))
3639 }
3640 Self::Iterator(_) => "<iterator>".into(),
3641 Self::Var(value) => value.display(),
3642 Self::Namespace(value) => format!("#namespace[{}]", value.name().as_str()),
3643 Self::Extension(value) => format!("#ht[:handle {}]", value.handle),
3644 Self::StructType(value) => value.name.clone(),
3645 Self::Struct(value) => format!(
3646 "#{}{{{}}}",
3647 value.ty.name,
3648 value
3649 .ty
3650 .fields
3651 .iter()
3652 .filter_map(|field| value.get(field).map(|value| (field, value)))
3653 .map(|(field, value)| format!(":{field} {}", value.display()))
3654 .collect::<Vec<_>>()
3655 .join(" ")
3656 ),
3657 Self::MutableType(value) => value.name.clone(),
3658 Self::Mutable(value) => format!(
3659 "#{}{{{}}}",
3660 value.ty.name,
3661 value
3662 .ty
3663 .fields
3664 .iter()
3665 .zip(value.ordered_values())
3666 .map(|(field, value)| format!(":{field} {}", value.display()))
3667 .collect::<Vec<_>>()
3668 .join(" ")
3669 ),
3670 Self::Protocol(value) => format!("#protocol[{}]", value.name),
3671 Self::NativeType(value) => format!("#<native-type {}>", value.name),
3672 Self::Schema(value) => format!("(schema {})", value.form),
3673 Self::Coroutine(value) => {
3674 let status = match &*value.state.borrow() {
3675 CoroutineState::New(_) | CoroutineState::Suspended(_) => "suspended",
3676 CoroutineState::Running => "running",
3677 CoroutineState::Dead => "dead",
3678 };
3679 format!("#<coroutine {status}>")
3680 }
3681 Self::Stream(value) => format!(
3682 "#<stream {}>",
3683 if value.closed.get() {
3684 "closed"
3685 } else {
3686 "ready"
3687 }
3688 ),
3689 Self::Result(value) => value.display(),
3690 Self::ExceptionInfo(value) => {
3691 format!(
3692 "#ex[{} {}]",
3693 Self::String(value.message.clone()).display(),
3694 value.data.display()
3695 )
3696 }
3697 Self::Nil => "nil".into(),
3698 }
3699 }
3700 pub(crate) fn truthy(&self) -> bool {
3701 !matches!(self, Self::Nil | Self::Bool(false))
3702 }
3703
3704 pub fn stable_hash(&self) -> u64 {
3714 self.java_hash(crate::lang::hash::DEFAULT_HASH) as u64
3715 }
3716}