Skip to main content

hara_native/core/
value.rs

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