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