Skip to main content

espy_paws/
lib.rs

1mod error;
2
3pub use anyhow;
4pub use error::{DebugInfoError, Error, ErrorKind, InvalidBytecode};
5
6use espy_heart::prelude::*;
7use std::any::Any;
8use std::borrow::Borrow;
9use std::cell::RefCell;
10use std::mem;
11use std::num::NonZero;
12use std::rc::{Rc, Weak};
13
14#[macro_export]
15macro_rules! extern_impl {
16    {
17        $(#[espy(
18            $(debug = $description:literal)?
19        )])?
20        $vis:vis fn $this:ident <$host:lifetime> (&self, $argument:ident)
21            $body:tt
22    } => {
23        #[derive(
24            ::std::clone::Clone,
25            ::std::marker::Copy,
26            ::std::fmt::Debug,
27            ::std::default::Default
28        )]
29        $vis struct $this;
30
31        impl $crate::ExternFn for $this {
32            fn call<$host>(
33                &$host self, $argument: $crate::Value<$host>
34            ) -> ::std::result::Result<$crate::Value<$host>, $crate::Error>
35                $body
36
37            fn to_static(&self) -> ::std::option::Option<&'static dyn $crate::ExternFn> {
38                Some(&$this)
39            }
40
41            $($(
42                fn debug(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
43                    ::std::write!(f, $description)
44                }
45            )?)?
46        }
47    };
48    {
49        $(#[espy(
50            // Allows the user to set a debug string to be shown used by the Extern trait.
51            //
52            // This is a format string, and the `self` parameter may be bound
53            // by using square brackets after "debug".
54            // Using `self` directly will not work because it is not considered in scope of the macro.
55            $(debug$([$debug_name:ident])? = $description:literal)?
56        )])?
57        $vis:vis struct $this:ident {
58            $($name:ident: $value:expr),* $(,)?
59        }
60    } => {
61        #[derive(
62            ::std::clone::Clone,
63            ::std::marker::Copy,
64            ::std::fmt::Debug,
65            ::std::default::Default
66        )]
67        $vis struct $this;
68
69        impl $crate::Extern for $this {
70            fn index<'host>(
71                &'host self, index: $crate::Value<'host>
72            ) -> ::std::result::Result<$crate::Value<'host>, $crate::Error> {
73                let index = index.string()?;
74                match index.as_str() {
75                    $(stringify!($name) => Ok($crate::Value::from($value)),)*
76                    _ => Err($crate::Error::index_not_found(
77                        &$crate::Value::borrow(self),
78                        &index.into(),
79                    )),
80                }
81            }
82
83            fn to_static<'host>(&self) -> ::std::option::Option<&'static dyn $crate::Extern> {
84                ::std::option::Option::Some(&$this)
85            }
86
87            fn any(&self) -> ::std::option::Option<&dyn ::std::any::Any> {
88                ::std::option::Option::Some(self)
89            }
90
91            $($(
92                fn debug(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
93                    $(let $debug_name = self;)?
94                    ::std::write!(f, $description)
95                }
96            )?)?
97        }
98    };
99}
100
101fn rc_slice_try_from_iter_ordered<T, E>(
102    len: usize,
103    iter: impl Iterator<Item = Result<T, E>>,
104    rev: bool,
105) -> Result<Rc<[T]>, E> {
106    let mut tuple = Rc::new_uninit_slice(len);
107    // SAFETY: `get_mut` only returns `None` if the `Rc` has been cloned.
108    let mutable_tuple = unsafe { Rc::get_mut(&mut tuple).unwrap_unchecked() };
109    let mut count = 0;
110    // This condition exists to avoid copy/pasting the unsafe code in this function.
111    // It would be nice to make this generic somehow,
112    // but that's probably unsafe and definitely unecessary.
113    if rev {
114        for (entry, value) in mutable_tuple.iter_mut().rev().zip(iter) {
115            entry.write(value?);
116            count += 1;
117        }
118    } else {
119        for (entry, value) in mutable_tuple.iter_mut().zip(iter) {
120            entry.write(value?);
121            count += 1;
122        }
123    }
124    assert!(
125        count == len,
126        "iter did not produce enough values ({count}) to initialize slice of length {len}"
127    );
128    // SAFETY: Since `count` == `len`, the slice is initialized.
129    unsafe { Ok(tuple.assume_init()) }
130}
131
132fn rc_slice_try_from_iter<T, E>(
133    len: usize,
134    iter: impl Iterator<Item = Result<T, E>>,
135) -> Result<Rc<[T]>, E> {
136    rc_slice_try_from_iter_ordered(len, iter, false)
137}
138
139/// Same as rc_slice_try_from_iter, but inserts elements in reverse order.
140/// This is used to construct a function's captures using `stack.pop()`
141fn rc_slice_try_from_iter_rev<T, E>(
142    len: usize,
143    iter: impl Iterator<Item = Result<T, E>>,
144) -> Result<Rc<[T]>, E> {
145    rc_slice_try_from_iter_ordered(len, iter, true)
146}
147
148fn rc_slice_from_iter<T>(len: usize, iter: impl Iterator<Item = T>) -> Rc<[T]> {
149    rc_slice_try_from_iter(len, iter.map(Ok::<_, ()>)).expect("iter is always Ok")
150}
151
152/// The root type of every espy value. All interoperation starts here.
153///
154/// Don't be afraid to [`Clone`] this type;
155/// it contains only [`Copy`] types and [`Rc`]s.
156#[derive(Clone)]
157pub enum Value<'host> {
158    /// Unit is the absense of a value.
159    /// It can be thought of as both an empty tuple and an empty named tuple.
160    Unit,
161    Tuple(Tuple<Value<'host>>),
162
163    Borrow(&'host dyn Extern, Option<Rc<Value<'host>>>),
164    Owned(Rc<dyn ExternOwned>, Option<Rc<Value<'host>>>),
165    I64(i64),
166    Bool(bool),
167    String(String),
168    Function(Rc<Function<'host>>),
169    EnumVariant(Rc<EnumVariant<'host>>),
170    Option {
171        contents: Option<Rc<Value<'host>>>,
172        ty: ComplexType,
173    },
174    Mut(Mut<'host>),
175
176    Type(Type),
177}
178
179impl std::fmt::Debug for Value<'_> {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        match self {
182            Value::Unit => write!(f, "Unit"),
183            Value::Tuple(tuple) => write!(f, "{tuple:?}"),
184            Value::Borrow(external, partial_index) => {
185                write!(f, "Borrow(")?;
186                external.debug(f)?;
187                if let Some(partial_index) = partial_index {
188                    write!(f, ", {partial_index:?}")?;
189                }
190                write!(f, ")")
191            }
192            Value::Owned(external, partial_index) => {
193                write!(f, "Owned(")?;
194                external.debug(f)?;
195                if let Some(partial_index) = partial_index {
196                    write!(f, ", {partial_index:?}")?;
197                }
198                write!(f, ")")
199            }
200            Value::I64(i) => write!(f, "I64({i:?})"),
201            Value::Bool(i) => write!(f, "Bool({i:?})"),
202            Value::String(i) => write!(f, "String({i:?})"),
203            Value::Function(function) => write!(f, "{function:?}"),
204            Value::EnumVariant(enum_variant) => write!(f, "{enum_variant:?}"),
205            Value::Option { contents, ty: _ } => write!(f, "{contents:?}"),
206            Value::Mut(inner) => write!(f, "{inner:?}"),
207            Value::Type(t) => write!(f, "{t:?}"),
208        }
209    }
210}
211
212/// A version of [`Value`] with a static lifetime.
213///
214/// Must be cast back to a runtime-compatible [`Value`] using
215/// [`StaticValue::to_runtime`] to be used.
216///
217/// The difference between this type and [`Value<'static>`] is the lack
218/// of [`Mut`], which contains a [`RefCell`] and makes [`Value<'static>`]
219/// [invariant](https://doc.rust-lang.org/nomicon/subtyping.html#variance) over
220/// `'host`. This means that a [`Value<'static>`] cannot be combined with
221/// non `'static` values in the same runtime,  which would prevent useful things
222/// like a static [`Function`] accepting a borrowed [`Extern`] value with a
223/// non-`'static` lifetime.
224#[derive(Clone)]
225pub enum StaticValue {
226    Unit,
227    Tuple(Tuple<StaticValue>),
228
229    Borrow(&'static dyn Extern, Option<Rc<StaticValue>>),
230    Owned(Rc<dyn ExternOwned>, Option<Rc<StaticValue>>),
231    I64(i64),
232    Bool(bool),
233    String(String),
234    Function(Rc<StaticFunction>),
235    EnumVariant(Rc<StaticEnumVariant>),
236    Option {
237        contents: Option<Rc<StaticValue>>,
238        ty: ComplexType,
239    },
240
241    Type(Type),
242}
243
244impl std::fmt::Debug for StaticValue {
245    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246        write!(f, "{:?}", self.to_runtime())
247    }
248}
249
250impl StaticValue {
251    #[must_use]
252    pub fn to_runtime<'host>(&self) -> Value<'host> {
253        match self {
254            StaticValue::Unit => Value::Unit,
255            StaticValue::Tuple(tuple) => Value::Tuple(tuple.to_runtime()),
256            StaticValue::Borrow(extern_ref, partial_index) => Value::Borrow(
257                *extern_ref,
258                partial_index.as_ref().map(|x| x.to_runtime().into()),
259            ),
260            StaticValue::Owned(extern_owned, partial_index) => Value::Owned(
261                extern_owned.clone(),
262                partial_index.as_ref().map(|x| x.to_runtime().into()),
263            ),
264            StaticValue::I64(i) => Value::I64(*i),
265            StaticValue::Bool(i) => Value::Bool(*i),
266            StaticValue::String(i) => Value::String(i.clone()),
267            StaticValue::Function(static_function) => {
268                Value::Function(Rc::new(static_function.to_runtime()))
269            }
270            StaticValue::EnumVariant(static_enum_variant) => {
271                Value::EnumVariant(Rc::new(EnumVariant {
272                    contents: static_enum_variant.contents.clone().into(),
273                    variant: static_enum_variant.variant,
274                    definition: static_enum_variant.definition.clone(),
275                }))
276            }
277            StaticValue::Option { contents, ty } => Value::Option {
278                contents: contents.as_ref().map(|x| x.to_runtime().into()),
279                ty: ty.clone(),
280            },
281            StaticValue::Type(i) => Value::Type(i.clone()),
282        }
283    }
284}
285
286impl<'host, T: Borrow<StaticValue>> From<T> for Value<'host> {
287    fn from(value: T) -> Self {
288        value.borrow().to_runtime()
289    }
290}
291
292/// The type of a singular espy values.
293///
294/// This enum does *not* represent the type of tuples;
295/// for that, see [`ComplexType`]
296///
297/// [`Type`] itself is a type, [`Type::Type`], because it may appear within an espy value.
298///
299/// Note that [`Value::type_of`] returns [`Type::Any`] for [`Value::Borrow`]
300/// and [`Value::Owned`].
301#[derive(Clone, Debug)]
302pub enum Type {
303    /// Any is the type of a value with unknown capabilities.
304    ///
305    /// Any is the type of all external values because they have arbitrary, unknowable properties.
306    /// This means that external values must be casted to trait objects to interact with them.
307    Any,
308    I64,
309    Bool,
310    String,
311    Function(Rc<FunctionType>),
312    Enum(Rc<EnumType>),
313    Option(Rc<ComplexType>),
314    Mut(Rc<ComplexType>),
315
316    /// The type of types.
317    Type,
318    Unit,
319}
320
321impl PartialEq for Type {
322    fn eq(&self, other: &Self) -> bool {
323        match (self, other) {
324            (Self::Enum(l), Self::Enum(r)) => l == r,
325            (Self::Option(l), Self::Option(r)) => l == r,
326            _ => mem::discriminant(self) == mem::discriminant(other),
327        }
328    }
329}
330
331impl Eq for Type {}
332
333/// The type of any espy value.
334///
335/// [`ComplexType`] is usually the only form of [`Type`] that the espy
336/// interpreter is concerned with, but it cannot be represented within espy
337/// itself (tuples of types represent [`ComplexType`]s, instead).
338#[derive(Clone, Debug, PartialEq, Eq)]
339pub enum ComplexType {
340    Simple(Type),
341    Complex(Tuple<ComplexType>),
342}
343
344impl ComplexType {
345    #[must_use]
346    pub fn compare(&self, r: &Self) -> bool {
347        match (self, r) {
348            (ComplexType::Simple(Type::Any), _) | (_, ComplexType::Simple(Type::Any)) => true,
349            (ComplexType::Simple(l), ComplexType::Simple(r)) => l == r,
350            (ComplexType::Complex(l), ComplexType::Complex(r)) => {
351                l.values().zip(r.values()).all(|(l, r)| l.compare(r))
352            }
353            _ => false,
354        }
355    }
356}
357
358impl From<Type> for ComplexType {
359    fn from(value: Type) -> Self {
360        Self::Simple(value)
361    }
362}
363
364impl From<Tuple<ComplexType>> for ComplexType {
365    fn from(value: Tuple<ComplexType>) -> Self {
366        Self::Complex(value)
367    }
368}
369
370impl From<ComplexType> for Value<'_> {
371    fn from(value: ComplexType) -> Self {
372        match value {
373            ComplexType::Simple(ty) => ty.into(),
374            ComplexType::Complex(tuple) => Value::Tuple(tuple.into()),
375        }
376    }
377}
378
379impl From<Type> for Value<'_> {
380    fn from(t: Type) -> Self {
381        Self::Type(t)
382    }
383}
384
385impl<'host> Value<'host> {
386    /// Returns None if `self` contains any [`Value::Borrow`] or [`Value::Mut`].
387    ///
388    /// [`Value::Borrow`] is not static for obvious reasons,
389    /// and [`Value::Mut`] cannot be made static because of refcell subtyping.
390    /// Instead, hosts using to_static should provide mutable state outside of
391    /// the espy runtime.
392    ///
393    /// # Errors
394    ///
395    /// Returns an error if the value is mutable or an external value that
396    /// cannot be made static.
397    pub fn to_static(&self) -> Result<StaticValue, Error> {
398        match self {
399            Value::Unit => Ok(StaticValue::Unit),
400            Value::Tuple(tuple) => Ok(StaticValue::Tuple(tuple.to_static()?)),
401            Value::Borrow(extern_borrow, partial_index) => Ok(StaticValue::Borrow(
402                extern_borrow
403                    .to_static()
404                    .ok_or(Error::from(ErrorKind::NotStatic))?,
405                partial_index
406                    .as_ref()
407                    .map(|x| x.to_static().map(Rc::new))
408                    .transpose()?,
409            )),
410            Value::Owned(extern_owned, partial_index) => Ok(StaticValue::Owned(
411                extern_owned.clone(),
412                partial_index
413                    .as_ref()
414                    .map(|x| x.to_static().map(Rc::new))
415                    .transpose()?,
416            )),
417            Value::I64(x) => Ok(StaticValue::I64(*x)),
418            Value::Bool(x) => Ok(StaticValue::Bool(*x)),
419            Value::String(x) => Ok(StaticValue::String(x.clone())),
420            Value::Function(function) => Ok(StaticValue::Function(function.to_static()?.into())),
421            Value::EnumVariant(enum_variant) => {
422                Ok(StaticValue::EnumVariant(Rc::new(StaticEnumVariant {
423                    contents: enum_variant.contents.to_static()?,
424                    variant: enum_variant.variant,
425                    definition: enum_variant.definition.clone(),
426                })))
427            }
428            Value::Option { contents, ty } => Ok(StaticValue::Option {
429                contents: contents
430                    .as_ref()
431                    .map(|x| x.to_static())
432                    .transpose()?
433                    .map(Rc::new),
434                ty: ty.clone(),
435            }),
436            Value::Mut(_) => Err(ErrorKind::NotStatic.into()),
437            Value::Type(x) => Ok(StaticValue::Type(x.clone())),
438        }
439    }
440
441    /// Convenience method for indexing values of various types by an integer.
442    ///
443    /// Usually this is most useful for reading function arguments by index,
444    /// which are passed as a tuple by convention.
445    ///
446    /// # Errors
447    ///
448    /// Returns [`ErrorKind::IndexNotFound`] if `self` cannot be indexed or the index is out of range for the container.
449    ///
450    /// [`Extern`] and [`ExternOwned`] implementations may return arbitary errors.
451    pub fn try_get(&self, index: i64) -> Result<Value<'host>, Error> {
452        match self {
453            Value::Tuple(tuple) => usize::try_from(index)
454                .ok()
455                .and_then(|index| tuple.get(index))
456                .ok_or(Error::index_not_found(self, &index.into())),
457            Value::Type(Type::Enum(ty)) => usize::try_from(index)
458                .ok()
459                .filter(|index| *index < ty.variants.len())
460                .map(|index| {
461                    Value::Function(Rc::new(
462                        FunctionAction::Enum {
463                            variant: index,
464                            definition: ty.clone(),
465                        }
466                        .into(),
467                    ))
468                })
469                .ok_or_else(|| Error::index_not_found(self, &index.into())),
470            Value::Type(Type::Option(ty)) => match index {
471                0 => Ok(Value::Function(Rc::new(
472                    FunctionAction::OptionCase {
473                        some: true,
474                        ty: (**ty).clone(),
475                    }
476                    .into(),
477                ))),
478                1 => Ok(Value::Function(Rc::new(
479                    FunctionAction::OptionCase {
480                        some: false,
481                        ty: (**ty).clone(),
482                    }
483                    .into(),
484                ))),
485                _ => Err(Error::index_not_found(self, &index.into())),
486            },
487            _ => Err(Error::index_not_found(self, &index.into())),
488        }
489    }
490
491    #[must_use]
492    pub fn get(&self, index: i64) -> Option<Value<'host>> {
493        self.try_get(index).ok()
494    }
495
496    /// Convenience methods for indexing values of various types by a string.
497    ///
498    /// # Errors
499    ///
500    /// Returns [`Error::index_not_found`] if `self` cannot be indexed or the index is not found in the container.
501    ///
502    /// [`Value::Borrow`] and [`Value::Owned`] implementations may return arbitary errors.
503    pub fn try_find(&self, index: impl Into<String>) -> Result<Value<'host>, Error> {
504        let index = index.into();
505        match self {
506            Value::Tuple(tuple) => tuple
507                .find(index.clone())
508                .ok_or(Error::index_not_found(self, &index.into())),
509            Value::Type(Type::Enum(ty)) => {
510                if let Some(variant_id) = ty
511                    .variants
512                    .as_ref()
513                    .iter()
514                    .enumerate()
515                    .find(|(_, (variant, _))| *variant == index)
516                    .map(|(i, _)| i)
517                {
518                    Ok(Value::Function(Rc::new(
519                        FunctionAction::Enum {
520                            variant: variant_id,
521                            definition: ty.clone(),
522                        }
523                        .into(),
524                    )))
525                } else {
526                    Err(Error::index_not_found(self, &index.into()))
527                }
528            }
529            Value::Type(Type::Option(ty)) => match index.as_str() {
530                "Some" => Ok(Value::Function(Rc::new(
531                    FunctionAction::OptionCase {
532                        some: true,
533                        ty: (**ty).clone(),
534                    }
535                    .into(),
536                ))),
537                "None" => Ok(Value::Function(Rc::new(
538                    FunctionAction::OptionCase {
539                        some: false,
540                        ty: (**ty).clone(),
541                    }
542                    .into(),
543                ))),
544                _ => Err(Error::index_not_found(self, &index.into())),
545            },
546            _ => Err(Error::index_not_found(self, &index.into())),
547        }
548    }
549
550    #[must_use]
551    pub fn find(&self, index: impl Into<String>) -> Option<Value<'host>> {
552        self.try_find(index).ok()
553    }
554
555    /// Convenience methods for indexing values of various types.
556    ///
557    /// # Errors
558    ///
559    /// Returns [`Error::index_not_found`] if `self` cannot be indexed or the index is not found in the container.
560    ///
561    /// [`Value::Borrow`] and [`Value::Owned`] implementations may return arbitary errors.
562    pub fn index(&self, index: impl Into<Value<'host>>) -> Result<Value<'host>, Error> {
563        match (self, index.into()) {
564            (Value::Borrow(external, partial_index), index) => {
565                external.index(if let Some(partial_index) = partial_index {
566                    Value::concat((**partial_index).clone(), index)
567                } else {
568                    index
569                })
570            }
571            (Value::Owned(external, partial_index), index) => {
572                external
573                    .clone()
574                    .index(if let Some(partial_index) = partial_index {
575                        Value::concat((**partial_index).clone(), index)
576                    } else {
577                        index
578                    })
579            }
580            (_, Value::I64(index)) => self.try_get(index),
581            (_, Value::String(index)) => self.try_find(index),
582            (_, index) => Err(Error::index_not_found(self, &index)),
583        }
584    }
585
586    /// Attempts to downcast instances of [`Value::Borrow`] and [`Value::Owned`] into `&T`.
587    ///
588    /// Note that [`Extern`] and [`ExternOwned`] implementations have to opt into this behavior
589    /// by implementing their `any` functions.
590    /// The default `any` implementation will result in this function returning `None`.
591    #[must_use]
592    pub fn downcast_extern<T: Any>(&self) -> Option<&T> {
593        match self {
594            Value::Borrow(borrow, ..) => (*borrow).any()?.downcast_ref(),
595            Value::Owned(owned, ..) => (*owned).any()?.downcast_ref(),
596            _ => None,
597        }
598    }
599
600    /// # Errors
601    ///
602    /// Returns an error if `self` and `other` are incomparable.
603    pub fn eq(self, other: Self) -> Result<bool, Error> {
604        match (self, other) {
605            (Value::Unit, Value::Unit) => Ok(true),
606            (Value::Tuple(l), Value::Tuple(r)) if l.len() == r.len() => {
607                for (l, r) in l.values().zip(r.values()) {
608                    if !l.clone().eq(r.clone())? {
609                        return Ok(false);
610                    }
611                }
612                Ok(true)
613            }
614            (Value::I64(l), Value::I64(r)) => Ok(l == r),
615            (Value::Bool(l), Value::Bool(r)) => Ok(l == r),
616            (Value::String(l), Value::String(r)) => Ok(l == r),
617            (Value::EnumVariant(l), Value::EnumVariant(r)) => Ok(l.variant == r.variant
618                && Rc::ptr_eq(&l.definition, &r.definition)
619                && Rc::try_unwrap(l)
620                    .map_or_else(|l| l.contents.clone(), |l| l.contents)
621                    .eq(Rc::try_unwrap(r).map_or_else(|r| r.contents.clone(), |r| r.contents))?),
622            (
623                Value::Option {
624                    contents: l,
625                    ty: l_type,
626                },
627                Value::Option {
628                    contents: r,
629                    ty: r_type,
630                },
631            ) if l_type.compare(&r_type) => Ok(l.is_none() && r.is_none()
632                || l.zip(r).map_or(Ok(false), |(l, r)| {
633                    Rc::unwrap_or_clone(l).eq(Rc::unwrap_or_clone(r))
634                })?),
635            (Value::Type(l), Value::Type(r)) => Ok(l == r),
636            (this, other) => Err(Error::incomparable_values(&this, &other)),
637        }
638    }
639
640    /// # Errors
641    ///
642    /// Returns an error if a mutable reference is being mutably borrowed.
643    ///
644    /// This can be safely ignored by the host if it has not deliberately borrowed an espy value.
645    pub fn type_of(&self) -> Result<ComplexType, Error> {
646        Ok(match &self {
647            Value::Unit => Type::Unit.into(),
648            Value::Tuple(tuple) => {
649                let complex = match &tuple.0 {
650                    TupleStorage::Numeric(items) => Tuple(TupleStorage::Numeric(
651                        rc_slice_try_from_iter(items.len(), items.iter().map(Value::type_of))?,
652                    )),
653                    TupleStorage::Named(items) => {
654                        Tuple(TupleStorage::Named(rc_slice_try_from_iter(
655                            items.len(),
656                            items.iter().map(|(name, value)| {
657                                value.type_of().map(|value| (name.clone(), value))
658                            }),
659                        )?))
660                    }
661                };
662                // The type of a tuple containing only types is `type`, not `(type, type, ..)`
663                if complex
664                    .values()
665                    .all(|x| matches!(x, ComplexType::Simple(Type::Type)))
666                {
667                    Type::Type.into()
668                } else {
669                    complex.into()
670                }
671            }
672            Value::Borrow(..) | Value::Owned(..) => Type::Any.into(),
673            Value::I64(_) => Type::I64.into(),
674            Value::Bool(_) => Type::Bool.into(),
675            Value::String(_) => Type::String.into(),
676            Value::Function(function) => match &function.action {
677                FunctionAction::With { signature, .. } => {
678                    Type::Function(Rc::new(signature.clone())).into()
679                }
680                _ => Type::Function(Rc::new(FunctionType {
681                    input: Type::Any.into(),
682                    output: Type::Any.into(),
683                }))
684                .into(),
685            },
686            Value::EnumVariant(enum_variant) => Type::Enum(enum_variant.definition.clone()).into(),
687            Value::Option { contents: _, ty } => Type::Option(Rc::new(ty.clone())).into(),
688            Value::Mut(inner) => Type::Mut(
689                inner
690                    .upgrade()
691                    .ok_or(ErrorKind::OutOfScopeMut)?
692                    .try_borrow()
693                    .map_err(Error::other)?
694                    .type_of()?
695                    .into(),
696            )
697            .into(),
698            Value::Type(_) => Type::Type.into(),
699        })
700    }
701
702    #[must_use]
703    pub fn concat(self, r: Self) -> Self {
704        match (self, r) {
705            (
706                Value::Tuple(Tuple(TupleStorage::Numeric(l))),
707                Value::Tuple(Tuple(TupleStorage::Numeric(r))),
708            ) => Value::Tuple(Tuple(TupleStorage::Numeric(rc_slice_from_iter(
709                l.len() + r.len(),
710                l.iter().chain(r.iter()).cloned(),
711            )))),
712            (
713                Value::Tuple(Tuple(TupleStorage::Named(l))),
714                Value::Tuple(Tuple(TupleStorage::Named(r))),
715            ) => Value::Tuple(Tuple(TupleStorage::Named(rc_slice_from_iter(
716                l.len() + r.len(),
717                l.iter().chain(r.iter()).cloned(),
718            )))),
719            (l, Value::Unit) => l,
720            (Value::Unit, r) => r,
721            (Value::Tuple(Tuple(TupleStorage::Numeric(l))), r) => {
722                Value::Tuple(Tuple(TupleStorage::Numeric(rc_slice_from_iter(
723                    l.len() + 1,
724                    l.iter().cloned().chain([r]),
725                ))))
726            }
727            (l, Value::Tuple(Tuple(TupleStorage::Numeric(r)))) => {
728                Value::Tuple(Tuple(TupleStorage::Numeric(rc_slice_from_iter(
729                    1 + r.len(),
730                    [l].into_iter().chain(r.iter().cloned()),
731                ))))
732            }
733            (l, r) => Value::Tuple(Tuple(TupleStorage::Numeric(Rc::new([l, r])))),
734        }
735    }
736
737    pub fn borrow(external: &'host dyn Extern) -> Self {
738        Value::Borrow(external, None)
739    }
740
741    pub fn owned(external: Rc<dyn ExternOwned>) -> Self {
742        Value::Owned(external, None)
743    }
744}
745
746impl From<()> for Value<'_> {
747    fn from((): ()) -> Self {
748        Value::Unit
749    }
750}
751
752impl From<Option<()>> for Value<'_> {
753    fn from(value: Option<()>) -> Self {
754        Value::Option {
755            contents: value.map(|()| Rc::new(Value::Unit)),
756            ty: Type::Unit.into(),
757        }
758    }
759}
760
761impl From<bool> for Value<'_> {
762    fn from(value: bool) -> Self {
763        Value::Bool(value)
764    }
765}
766
767impl From<Option<bool>> for Value<'_> {
768    fn from(value: Option<bool>) -> Self {
769        Value::Option {
770            contents: value.map(|value| Rc::new(Value::Bool(value))),
771            ty: Type::Bool.into(),
772        }
773    }
774}
775
776impl From<i64> for Value<'_> {
777    fn from(i: i64) -> Self {
778        Value::I64(i)
779    }
780}
781
782impl From<Option<i64>> for Value<'_> {
783    fn from(value: Option<i64>) -> Self {
784        Value::Option {
785            contents: value.map(|value| Rc::new(Value::I64(value))),
786            ty: Type::I64.into(),
787        }
788    }
789}
790
791impl From<&'static str> for Value<'_> {
792    fn from(s: &'static str) -> Self {
793        Value::String(s.into())
794    }
795}
796
797impl From<Rc<str>> for Value<'_> {
798    fn from(s: Rc<str>) -> Self {
799        Value::String(s.into())
800    }
801}
802
803impl From<String> for Value<'_> {
804    fn from(s: String) -> Self {
805        Value::String(s)
806    }
807}
808
809impl<T: Into<String>> From<Option<T>> for Value<'_> {
810    fn from(value: Option<T>) -> Self {
811        Value::Option {
812            contents: value.map(|value| Rc::new(Value::String(value.into()))),
813            ty: Type::String.into(),
814        }
815    }
816}
817
818impl<'host> From<Rc<[Value<'host>]>> for Value<'host> {
819    fn from(value: Rc<[Value<'host>]>) -> Self {
820        Self::Tuple(Tuple::from(value))
821    }
822}
823
824impl<'host, T: Into<Value<'host>>, const N: usize> From<[T; N]> for Value<'host> {
825    fn from(value: [T; N]) -> Self {
826        let slice = rc_slice_from_iter(value.len(), value.into_iter().map(Into::into));
827        Self::Tuple(Tuple::from(slice))
828    }
829}
830
831impl<'host> From<Rc<[(String, Value<'host>)]>> for Value<'host> {
832    fn from(value: Rc<[(String, Value<'host>)]>) -> Self {
833        Self::Tuple(Tuple::from(value))
834    }
835}
836
837impl<'host> From<Tuple<Value<'host>>> for Value<'host> {
838    fn from(value: Tuple<Value<'host>>) -> Self {
839        Self::Tuple(value)
840    }
841}
842
843impl<'host, K: Into<String>, const N: usize> From<[(K, Value<'host>); N]> for Value<'host> {
844    fn from(value: [(K, Value<'host>); N]) -> Self {
845        Self::Tuple(Tuple::from(value))
846    }
847}
848
849impl<'host> From<Option<Value<'host>>> for Value<'host> {
850    fn from(value: Option<Self>) -> Self {
851        value.map(Rc::new).into()
852    }
853}
854
855impl<'host> From<Option<Rc<Value<'host>>>> for Value<'host> {
856    fn from(value: Option<Rc<Self>>) -> Self {
857        Value::Option {
858            contents: value,
859            ty: Type::Any.into(),
860        }
861    }
862}
863
864impl<'host> From<Rc<Function<'host>>> for Value<'host> {
865    fn from(f: Rc<Function<'host>>) -> Self {
866        Value::Function(f)
867    }
868}
869
870impl<'host> From<Function<'host>> for Value<'host> {
871    fn from(f: Function<'host>) -> Self {
872        Rc::new(f).into()
873    }
874}
875
876impl<'host> TryFrom<Value<'host>> for () {
877    type Error = Error;
878
879    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
880        if let Value::Unit = value {
881            Ok(())
882        } else {
883            Err(Error::type_error(&value, &Type::Unit.into()))
884        }
885    }
886}
887
888impl<'host> TryFrom<Value<'host>> for Tuple<Value<'host>> {
889    type Error = Error;
890
891    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
892        if let Value::Tuple(value) = value {
893            Ok(value)
894        } else {
895            Err(Error::expected_tuple(&value))
896        }
897    }
898}
899
900impl<'host> TryFrom<Value<'host>> for bool {
901    type Error = Error;
902
903    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
904        if let Value::Bool(bool) = value {
905            Ok(bool)
906        } else {
907            Err(Error::type_error(&value, &Type::Unit.into()))
908        }
909    }
910}
911
912impl<'host> TryFrom<Value<'host>> for i64 {
913    type Error = Error;
914
915    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
916        if let Value::I64(value) = value {
917            Ok(value)
918        } else {
919            Err(Error::type_error(&value, &Type::I64.into()))
920        }
921    }
922}
923
924impl<'host> TryFrom<Value<'host>> for String {
925    type Error = Error;
926
927    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
928        if let Value::String(value) = value {
929            Ok(value)
930        } else {
931            Err(Error::type_error(&value, &Type::String.into()))
932        }
933    }
934}
935
936impl<'host> TryFrom<Value<'host>> for Rc<Function<'host>> {
937    type Error = Error;
938    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
939        if let Value::Function(value) = value {
940            Ok(value)
941        } else {
942            Err(Error::expected_function(&value))
943        }
944    }
945}
946
947impl<'host> TryFrom<Value<'host>> for Function<'host> {
948    type Error = Error;
949
950    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
951        Ok(Rc::unwrap_or_clone(Rc::<Self>::try_from(value)?))
952    }
953}
954
955impl<'host> TryFrom<Value<'host>> for Rc<EnumVariant<'host>> {
956    type Error = Error;
957    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
958        if let Value::EnumVariant(value) = value {
959            Ok(value)
960        } else {
961            Err(Error::expected_enum_variant(&value))
962        }
963    }
964}
965
966impl<'host> TryFrom<Value<'host>> for EnumVariant<'host> {
967    type Error = Error;
968
969    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
970        Ok(Rc::unwrap_or_clone(Rc::<Self>::try_from(value)?))
971    }
972}
973
974impl<'host> TryFrom<Value<'host>> for ComplexType {
975    type Error = Error;
976
977    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
978        match value {
979            Value::Type(t) => Ok(t.into()),
980            Value::Tuple(tuple) => Ok(ComplexType::Complex(tuple.try_into()?)),
981            _ => Err(Error::type_error(&value, &Type::Type.into())),
982        }
983    }
984}
985
986impl<'host> TryFrom<Value<'host>> for Rc<EnumType> {
987    type Error = Error;
988    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
989        if let Value::Type(Type::Enum(value)) = value {
990            Ok(value)
991        } else {
992            Err(Error::expected_enum_type(&value))
993        }
994    }
995}
996
997impl<'host> TryFrom<Value<'host>> for EnumType {
998    type Error = Error;
999
1000    fn try_from(value: Value<'host>) -> Result<Self, Self::Error> {
1001        Ok(Rc::unwrap_or_clone(Rc::<Self>::try_from(value)?))
1002    }
1003}
1004
1005/// [`TryInto`] shortcuts
1006impl<'host> Value<'host> {
1007    /// # Errors
1008    ///
1009    /// Returns an error if `self` is not a [`Value::Unit`]
1010    pub fn unit(self) -> Result<(), Error> {
1011        self.try_into()
1012    }
1013
1014    /// # Errors
1015    ///
1016    /// Returns an error if `self` is not a [`Value::Tuple`]
1017    pub fn tuple(self) -> Result<Tuple<Value<'host>>, Error> {
1018        self.try_into()
1019    }
1020
1021    /// # Errors
1022    ///
1023    /// Returns an error if `self` is not a [`Value::Bool`]
1024    pub fn bool(self) -> Result<bool, Error> {
1025        self.try_into()
1026    }
1027
1028    /// # Errors
1029    ///
1030    /// Returns an error if `self` is not a [`Value::I64`]
1031    pub fn i64(self) -> Result<i64, Error> {
1032        self.try_into()
1033    }
1034
1035    /// # Errors
1036    ///
1037    /// Returns an error if `self` is not a [`Value::String`]
1038    pub fn string(self) -> Result<String, Error> {
1039        self.try_into()
1040    }
1041
1042    /// # Errors
1043    ///
1044    /// Returns an error if `self` is not a [`Value::Function`]
1045    pub fn function(self) -> Result<Function<'host>, Error> {
1046        self.try_into()
1047    }
1048
1049    /// # Errors
1050    ///
1051    /// Returns an error if `self` is not a [`Value::EnumVariant`]
1052    pub fn enum_variant(self) -> Result<Rc<EnumVariant<'host>>, Error> {
1053        self.try_into()
1054    }
1055
1056    /// # Errors
1057    ///
1058    /// Returns an error if `self` is not a [`Value::Option`]
1059    pub fn option(self) -> Result<Option<Value<'host>>, Error> {
1060        match self {
1061            Value::Option { contents, ty: _ } => Ok(contents.map(|x| (*x).clone())),
1062            _ => Err(Error::expected_option(&self)),
1063        }
1064    }
1065
1066    /// # Errors
1067    ///
1068    /// Returns an error if `self` is not a [`Value::Mut`]
1069    pub fn into_refcell(self) -> Result<Rc<RefCell<Value<'host>>>, Error> {
1070        match &self {
1071            Value::Mut(inner) => Ok(inner.upgrade().ok_or(ErrorKind::OutOfScopeMut)?),
1072            _ => Err(Error::expected_reference(&self)),
1073        }
1074    }
1075
1076    /// # Errors
1077    ///
1078    /// Returns an error if `self` is not a [`Value::Type`] or [`Value::Tuple`] of types.
1079    pub fn into_complex_type(self) -> Result<ComplexType, Error> {
1080        self.try_into()
1081    }
1082
1083    /// # Errors
1084    ///
1085    /// Returns an error if `self` is not a [`Value::Type`] containing a [`Type::Enum`]
1086    pub fn into_enum_type(self) -> Result<Rc<EnumType>, Error> {
1087        self.try_into()
1088    }
1089
1090    #[must_use]
1091    pub fn as_str(&self) -> Option<&str> {
1092        if let Value::String(s) = &self {
1093            Some(s.as_str())
1094        } else {
1095            None
1096        }
1097    }
1098
1099    /// Turns this value into a vector of values.
1100    ///
1101    /// [`Value::Tuple`]'s members will be collected into the vector.
1102    /// [`Value::Unit`] will produce an empty vector.
1103    /// All other variants will produce a vector with just one member.
1104    pub fn into_vec(self) -> Vec<Value<'host>> {
1105        match self {
1106            Value::Unit => Vec::new(),
1107            Value::Tuple(tup) => tup.values().map(Value::clone).collect(),
1108            _ => Vec::from([self]),
1109        }
1110    }
1111}
1112
1113#[derive(Clone)]
1114enum StringStorage {
1115    Static(&'static str),
1116    Floating(Rc<str>),
1117}
1118
1119/// An espy string.
1120///
1121/// This container abstracts the possible in-memory representations of espy
1122/// strings as a single type.
1123#[derive(Clone)]
1124pub struct String(StringStorage);
1125
1126impl String {
1127    /// View this string as a string slice.
1128    ///
1129    /// If you're trying to get an owned form of `str` and `Rc<str>` is
1130    /// acceptable, [`String::into_str`] may be cheaper if the espy string
1131    /// is already internally represented as one (due to concatenation, for
1132    /// example).
1133    #[must_use]
1134    pub fn as_str(&self) -> &str {
1135        match &self.0 {
1136            StringStorage::Static(s) => s,
1137            StringStorage::Floating(s) => s,
1138        }
1139    }
1140
1141    /// Convert this string to a reference-counted string slice.
1142    ///
1143    /// If an espy string is already represented as an `Rc<str>`, this method
1144    /// will unwrap it without allocating any new memory.
1145    #[must_use]
1146    pub fn into_str(self) -> Rc<str> {
1147        match self.0 {
1148            StringStorage::Static(s) => s.into(),
1149            StringStorage::Floating(s) => s,
1150        }
1151    }
1152
1153    /// Allocates an `Rc<str>` for `s` and wraps it in an espy string.
1154    #[must_use]
1155    pub fn owned(s: &str) -> Self {
1156        Rc::<str>::from(s).into()
1157    }
1158}
1159
1160impl Default for String {
1161    fn default() -> Self {
1162        Self::from("")
1163    }
1164}
1165
1166impl std::fmt::Display for String {
1167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1168        self.as_str().fmt(f)
1169    }
1170}
1171
1172impl std::fmt::Debug for String {
1173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1174        self.as_str().fmt(f)
1175    }
1176}
1177
1178impl PartialEq for String {
1179    fn eq(&self, other: &Self) -> bool {
1180        self.as_str() == other.as_str()
1181    }
1182}
1183
1184impl Eq for String {}
1185
1186impl From<&'static str> for String {
1187    fn from(value: &'static str) -> Self {
1188        Self(StringStorage::Static(value))
1189    }
1190}
1191
1192impl From<std::string::String> for String {
1193    fn from(value: std::string::String) -> Self {
1194        Self(StringStorage::Floating(value.into()))
1195    }
1196}
1197
1198impl From<Rc<str>> for String {
1199    fn from(value: Rc<str>) -> Self {
1200        Self(StringStorage::Floating(value))
1201    }
1202}
1203
1204impl From<String> for Rc<str> {
1205    fn from(value: String) -> Self {
1206        value.into_str()
1207    }
1208}
1209
1210impl Borrow<str> for &String {
1211    fn borrow(&self) -> &str {
1212        self.as_str()
1213    }
1214}
1215
1216impl std::ops::Deref for String {
1217    type Target = str;
1218
1219    fn deref(&self) -> &Self::Target {
1220        self.as_str()
1221    }
1222}
1223
1224#[derive(Clone, Debug, PartialEq, Eq)]
1225enum TupleStorage<T> {
1226    Numeric(Rc<[T]>),
1227    Named(Rc<[(String, T)]>),
1228}
1229
1230/// This type is used to store anything shaped like an espy tuple.
1231///
1232/// This includes:
1233/// - Tuple<[`Value`]> (an espy tuple)
1234/// - Tuple<[`StaticValue`]> (an espy tuple with a static lifetime)
1235/// - Tuple<[`ComplexType`]> (the type of an espy tuple)
1236///
1237/// It is either a "numeric" tuple (indexed only by order) or a "named" tuple
1238/// (indexed by both order and name).
1239#[derive(Clone, Debug, PartialEq, Eq)]
1240pub struct Tuple<T>(TupleStorage<T>);
1241
1242impl<T> Tuple<T> {
1243    #[must_use]
1244    pub fn len(&self) -> usize {
1245        match &self.0 {
1246            TupleStorage::Numeric(items) => items.len(),
1247            TupleStorage::Named(items) => items.len(),
1248        }
1249    }
1250
1251    #[must_use]
1252    pub fn is_empty(&self) -> bool {
1253        self.len() == 0
1254    }
1255
1256    #[must_use]
1257    pub fn get_ref(&self, index: usize) -> Option<&T> {
1258        match &self.0 {
1259            TupleStorage::Numeric(items) => items.get(index),
1260            TupleStorage::Named(items) => items.get(index).map(|(_name, value)| value),
1261        }
1262    }
1263
1264    #[must_use]
1265    pub fn find_ref(&self, name: impl Borrow<str>) -> Option<&T> {
1266        let TupleStorage::Named(items) = &self.0 else {
1267            return None;
1268        };
1269        items.iter().find_map(|(n, v)| {
1270            if n.as_str() == name.borrow() {
1271                Some(v)
1272            } else {
1273                None
1274            }
1275        })
1276    }
1277
1278    pub fn values(&self) -> impl Iterator<Item = &T> {
1279        (0..self.len()).map(|i| match &self.0 {
1280            TupleStorage::Numeric(items) => &items[i],
1281            TupleStorage::Named(items) => &items[i].1,
1282        })
1283    }
1284
1285    #[must_use]
1286    pub fn as_numeric(&self) -> Option<&[T]> {
1287        match &self.0 {
1288            TupleStorage::Numeric(items) => Some(items),
1289            TupleStorage::Named(_) => None,
1290        }
1291    }
1292
1293    #[must_use]
1294    pub fn as_named(&self) -> Option<&[(String, T)]> {
1295        match &self.0 {
1296            TupleStorage::Numeric(_) => None,
1297            TupleStorage::Named(items) => Some(items),
1298        }
1299    }
1300}
1301
1302impl<T: Clone> Tuple<T> {
1303    #[must_use]
1304    pub fn get(&self, index: usize) -> Option<T> {
1305        match &self.0 {
1306            TupleStorage::Numeric(items) => items.get(index).cloned(),
1307            TupleStorage::Named(items) => items.get(index).map(|(_name, value)| value).cloned(),
1308        }
1309    }
1310
1311    #[must_use]
1312    pub fn find(&self, name: impl Into<String>) -> Option<T> {
1313        let TupleStorage::Named(items) = &self.0 else {
1314            return None;
1315        };
1316        let name = name.into();
1317        items.iter().find_map(|(n, v)| {
1318            if n.as_str() == name.as_str() {
1319                Some(v.clone())
1320            } else {
1321                None
1322            }
1323        })
1324    }
1325}
1326
1327impl<'host> Tuple<Value<'host>> {
1328    /// # Errors
1329    ///
1330    /// Returns an error if the index is not found.
1331    pub fn try_get_ref(&self, index: usize) -> Result<&Value<'host>, Error> {
1332        let value = match &self.0 {
1333            TupleStorage::Numeric(items) => items.get(index),
1334            TupleStorage::Named(items) => items.get(index).map(|(_name, value)| value),
1335        };
1336        value
1337            .ok_or_else(|| Error::index_not_found(&self.clone().into(), &Value::from(index as i64)))
1338    }
1339
1340    /// # Errors
1341    ///
1342    /// Returns an error if the index is not found.
1343    pub fn try_find_ref(&self, name: impl Into<String>) -> Result<&Value<'host>, Error> {
1344        let name = name.into();
1345        if let TupleStorage::Named(items) = &self.0
1346            && let Some(value) = items.iter().find_map(|(n, v)| {
1347                if n.as_str() == name.as_str() {
1348                    Some(v)
1349                } else {
1350                    None
1351                }
1352            })
1353        {
1354            Ok(value)
1355        } else {
1356            Err(Error::index_not_found(&self.clone().into(), &name.into()))
1357        }
1358    }
1359
1360    /// # Errors
1361    ///
1362    /// Returns an error if the index is not found.
1363    pub fn try_get(&self, index: usize) -> Result<Value<'host>, Error> {
1364        self.try_get_ref(index).cloned()
1365    }
1366
1367    /// # Errors
1368    ///
1369    /// Returns an error if the index is not found.
1370    pub fn try_find(&self, name: impl Into<String>) -> Result<Value<'host>, Error> {
1371        self.try_find_ref(name).cloned()
1372    }
1373}
1374
1375impl<'host> Tuple<Value<'host>> {
1376    fn to_static(&self) -> Result<Tuple<StaticValue>, Error> {
1377        match &self.0 {
1378            TupleStorage::Numeric(items) => rc_slice_try_from_iter(
1379                items.len(),
1380                items.iter().map(|value: &Value| value.to_static()),
1381            )
1382            .map(TupleStorage::Numeric)
1383            .map(Tuple),
1384            TupleStorage::Named(items) => rc_slice_try_from_iter(
1385                items.len(),
1386                items
1387                    .iter()
1388                    .map(|(name, value)| value.to_static().map(|value| (name.clone(), value))),
1389            )
1390            .map(TupleStorage::Named)
1391            .map(Tuple),
1392        }
1393    }
1394}
1395
1396impl Tuple<StaticValue> {
1397    #[must_use]
1398    pub fn to_runtime<'host>(&self) -> Tuple<Value<'host>> {
1399        match &self.0 {
1400            TupleStorage::Numeric(items) => Tuple(TupleStorage::Numeric(rc_slice_from_iter(
1401                items.len(),
1402                items.iter().map(Value::from),
1403            ))),
1404            TupleStorage::Named(items) => Tuple(TupleStorage::Named(rc_slice_from_iter(
1405                items.len(),
1406                items
1407                    .iter()
1408                    .map(|(name, value)| (name.clone(), value.into())),
1409            ))),
1410        }
1411    }
1412}
1413
1414impl<'host, T: Borrow<Tuple<StaticValue>>> From<T> for Tuple<Value<'host>> {
1415    fn from(value: T) -> Self {
1416        value.borrow().to_runtime()
1417    }
1418}
1419
1420impl<'host> TryFrom<Tuple<Value<'host>>> for Tuple<ComplexType> {
1421    type Error = Error;
1422
1423    fn try_from(tuple: Tuple<Value<'host>>) -> Result<Self, Self::Error> {
1424        match &tuple.0 {
1425            TupleStorage::Numeric(items) => rc_slice_try_from_iter(
1426                items.len(),
1427                items.iter().map(|value| value.clone().try_into()),
1428            )
1429            .map(TupleStorage::Numeric)
1430            .map(Tuple),
1431            TupleStorage::Named(items) => rc_slice_try_from_iter(
1432                items.len(),
1433                items.iter().map(|(name, value)| {
1434                    value.clone().try_into().map(|value| (name.clone(), value))
1435                }),
1436            )
1437            .map(TupleStorage::Named)
1438            .map(Tuple),
1439        }
1440    }
1441}
1442
1443impl From<Tuple<ComplexType>> for Tuple<Value<'_>> {
1444    fn from(tuple: Tuple<ComplexType>) -> Self {
1445        match &tuple.0 {
1446            TupleStorage::Numeric(items) => Tuple(TupleStorage::Numeric(rc_slice_from_iter(
1447                items.len(),
1448                items.iter().map(|value| value.clone().into()),
1449            ))),
1450            TupleStorage::Named(items) => Tuple(TupleStorage::Named(rc_slice_from_iter(
1451                items.len(),
1452                items
1453                    .iter()
1454                    .map(|(name, value)| (name.clone(), value.clone().into())),
1455            ))),
1456        }
1457    }
1458}
1459
1460impl<'host> TryFrom<Tuple<Value<'host>>> for Tuple<Function<'host>> {
1461    type Error = Error;
1462
1463    fn try_from(tuple: Tuple<Value<'host>>) -> Result<Self, Self::Error> {
1464        match &tuple.0 {
1465            TupleStorage::Numeric(items) => rc_slice_try_from_iter(
1466                items.len(),
1467                items.iter().map(|value| value.clone().try_into()),
1468            )
1469            .map(TupleStorage::Numeric)
1470            .map(Tuple),
1471            TupleStorage::Named(items) => rc_slice_try_from_iter(
1472                items.len(),
1473                items.iter().map(|(name, value)| {
1474                    value.clone().try_into().map(|value| (name.clone(), value))
1475                }),
1476            )
1477            .map(TupleStorage::Named)
1478            .map(Tuple),
1479        }
1480    }
1481}
1482
1483impl<T> From<Rc<[T]>> for Tuple<T> {
1484    fn from(value: Rc<[T]>) -> Self {
1485        Self(TupleStorage::Numeric(value))
1486    }
1487}
1488
1489impl<const N: usize, T> From<[T; N]> for Tuple<T> {
1490    fn from(value: [T; N]) -> Self {
1491        Self(TupleStorage::Numeric(Rc::from(value)))
1492    }
1493}
1494
1495impl<T> From<Rc<[(String, T)]>> for Tuple<T> {
1496    fn from(value: Rc<[(String, T)]>) -> Self {
1497        Self(TupleStorage::Named(value))
1498    }
1499}
1500
1501impl<const N: usize, K: Into<String>, T> From<[(K, T); N]> for Tuple<T> {
1502    fn from(value: [(K, T); N]) -> Self {
1503        let slice = rc_slice_from_iter(value.len(), value.into_iter().map(|(k, v)| (k.into(), v)));
1504        Self(TupleStorage::Named(slice))
1505    }
1506}
1507
1508/// An function which is callable by espy or its host.
1509///
1510/// This differs from [`Program`] in that it may accept an argument;
1511/// use [`Function::pipe`] or [`Function::piped`] to provide one,
1512/// and [`Function::eval`] to evaluate the function.
1513///
1514/// To instead provide a Rust function to espy, use [`Function::borrow`] or
1515/// [`Function::owned`] with the [`ExternFn`] and [`ExternFnOwned`] traits,
1516/// respectively.
1517#[derive(Clone, Debug)]
1518pub struct Function<'host> {
1519    action: FunctionAction<'host>,
1520    argument: Value<'host>,
1521}
1522
1523/// A version of [`Function`] with a static lifetime.
1524///
1525/// See [`StaticValue`] for the difference between this and [`Function<'static>`].
1526#[derive(Clone)]
1527pub struct StaticFunction {
1528    action: StaticFunctionAction,
1529    argument: StaticValue,
1530}
1531
1532impl std::fmt::Debug for StaticFunction {
1533    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1534        write!(f, "{:?}", self.to_runtime())
1535    }
1536}
1537
1538impl StaticFunction {
1539    #[must_use]
1540    pub fn to_runtime<'host>(&self) -> Function<'host> {
1541        Function {
1542            action: match &self.action {
1543                StaticFunctionAction::With {
1544                    program,
1545                    block_id,
1546                    program_counter,
1547                    signature,
1548                    captures,
1549                } => FunctionAction::With {
1550                    program: program.clone(),
1551                    block_id: *block_id,
1552                    program_counter: *program_counter,
1553                    signature: signature.clone(),
1554                    captures: rc_slice_from_iter(
1555                        captures.len(),
1556                        captures
1557                            .iter()
1558                            .map(|value: &StaticValue| value.clone().into()),
1559                    ),
1560                },
1561                StaticFunctionAction::Never { signature } => FunctionAction::Never {
1562                    signature: signature.clone(),
1563                },
1564                StaticFunctionAction::Enum {
1565                    variant,
1566                    definition,
1567                } => FunctionAction::Enum {
1568                    variant: *variant,
1569                    definition: definition.clone(),
1570                },
1571                StaticFunctionAction::Mut => FunctionAction::Mut,
1572                StaticFunctionAction::OptionConstructor => FunctionAction::OptionConstructor,
1573                StaticFunctionAction::OptionCase { some, ty } => FunctionAction::OptionCase {
1574                    some: *some,
1575                    ty: ty.clone(),
1576                },
1577                StaticFunctionAction::Borrow(extern_fn) => FunctionAction::Borrow(*extern_fn),
1578                StaticFunctionAction::Owned(extern_fn_owned) => {
1579                    FunctionAction::Owned(extern_fn_owned.clone())
1580                }
1581            },
1582            argument: self.argument.to_runtime(),
1583        }
1584    }
1585}
1586
1587impl<'host, T: Borrow<StaticFunction>> From<T> for Function<'host> {
1588    fn from(value: T) -> Self {
1589        value.borrow().to_runtime()
1590    }
1591}
1592
1593impl StaticFunction {
1594    pub fn borrow(external: &'static dyn ExternFn) -> Self {
1595        StaticFunction {
1596            action: StaticFunctionAction::Borrow(external),
1597            argument: StaticValue::Unit,
1598        }
1599    }
1600
1601    pub fn owned(external: Rc<dyn ExternFnOwned>) -> Self {
1602        StaticFunction {
1603            action: StaticFunctionAction::Owned(external),
1604            argument: StaticValue::Unit,
1605        }
1606    }
1607}
1608
1609impl<'host> Function<'host> {
1610    pub fn borrow(external: &'host dyn ExternFn) -> Self {
1611        Function {
1612            action: FunctionAction::Borrow(external),
1613            argument: ().into(),
1614        }
1615    }
1616
1617    pub fn owned(external: Rc<dyn ExternFnOwned>) -> Self {
1618        Function {
1619            action: FunctionAction::Owned(external),
1620            argument: ().into(),
1621        }
1622    }
1623
1624    /// # Errors
1625    ///
1626    /// Returns an error if the value is mutable or an external value that
1627    /// cannot be made static.
1628    pub fn to_static(&self) -> Result<StaticFunction, Error> {
1629        Ok(StaticFunction {
1630            action: match &self.action {
1631                FunctionAction::With {
1632                    program,
1633                    block_id,
1634                    program_counter,
1635                    signature,
1636                    captures,
1637                } => StaticFunctionAction::With {
1638                    program: program.clone(),
1639                    block_id: *block_id,
1640                    program_counter: *program_counter,
1641                    signature: signature.clone(),
1642                    captures: captures
1643                        .iter()
1644                        .map(|x| x.to_static())
1645                        .collect::<Result<_, Error>>()?,
1646                },
1647                FunctionAction::Never { signature } => StaticFunctionAction::Never {
1648                    signature: signature.clone(),
1649                },
1650                FunctionAction::Enum {
1651                    variant,
1652                    definition,
1653                } => StaticFunctionAction::Enum {
1654                    variant: *variant,
1655                    definition: definition.clone(),
1656                },
1657                FunctionAction::Mut => StaticFunctionAction::Mut,
1658                FunctionAction::OptionConstructor => StaticFunctionAction::OptionConstructor,
1659                FunctionAction::OptionCase { some, ty } => StaticFunctionAction::OptionCase {
1660                    some: *some,
1661                    ty: ty.clone(),
1662                },
1663                FunctionAction::Borrow(extern_fn_borrow) => StaticFunctionAction::Borrow(
1664                    extern_fn_borrow
1665                        .to_static()
1666                        .ok_or(Error::from(ErrorKind::NotStatic))?,
1667                ),
1668                FunctionAction::Owned(extern_fn_owned) => {
1669                    StaticFunctionAction::Owned(extern_fn_owned.clone())
1670                }
1671            },
1672            argument: self.argument.to_static()?,
1673        })
1674    }
1675
1676    /// # Errors
1677    ///
1678    /// Returns an error if evaluating the function results in an error
1679    pub fn eval(self) -> Result<Value<'host>, Error> {
1680        let result = match self.action {
1681            FunctionAction::With {
1682                program,
1683                block_id,
1684                program_counter,
1685                signature: FunctionType { input, output },
1686                captures,
1687            } => {
1688                if !self.argument.type_of()?.compare(&input) {
1689                    return Err(Error::type_error(&self.argument, &input));
1690                }
1691                let result =
1692                    program.eval_block(block_id, program_counter, captures, self.argument)?;
1693                if !result.type_of()?.compare(&output) {
1694                    return Err(Error::type_error(&result, &output));
1695                }
1696                result
1697            }
1698            FunctionAction::Never { signature: _ } => {
1699                return Err(ErrorKind::CalledNeverFunction.into());
1700            }
1701            FunctionAction::Enum {
1702                variant,
1703                definition,
1704            } => {
1705                let ty = &definition.variants[variant].1;
1706                if *ty != Type::Any.into() && self.argument.type_of()? != *ty {
1707                    return Err(Error::type_error(&self.argument, ty));
1708                }
1709                Value::EnumVariant(Rc::new(EnumVariant {
1710                    contents: self.argument,
1711                    variant,
1712                    definition,
1713                }))
1714            }
1715            FunctionAction::Mut => {
1716                if let Ok(ty) = ComplexType::try_from(self.argument.clone()) {
1717                    Type::Mut(Rc::new(ty)).into()
1718                } else {
1719                    Value::Mut(Mut::new(Rc::new(RefCell::new(self.argument))))
1720                }
1721            }
1722            FunctionAction::OptionConstructor => {
1723                Type::Option(Rc::new(self.argument.into_complex_type()?)).into()
1724            }
1725            FunctionAction::OptionCase { some: true, ty } => {
1726                if self.argument.type_of()? != ty {
1727                    return Err(Error::type_error(&self.argument, &ty));
1728                }
1729                Value::Option {
1730                    contents: Some(Rc::new(self.argument)),
1731                    ty,
1732                }
1733            }
1734            FunctionAction::OptionCase { some: false, ty } => {
1735                self.argument.unit()?;
1736                Value::Option { contents: None, ty }
1737            }
1738            FunctionAction::Borrow(external) => external.call(self.argument)?,
1739            FunctionAction::Owned(external) => external.call(self.argument)?,
1740        };
1741        Ok(result)
1742    }
1743
1744    /// Concatentes the function's argument list with `argument`.
1745    pub fn pipe(&mut self, argument: Value<'host>) {
1746        let mut arguments = ().into();
1747        mem::swap(&mut arguments, &mut self.argument);
1748        arguments = Value::concat(arguments, argument);
1749        mem::swap(&mut arguments, &mut self.argument);
1750    }
1751
1752    #[must_use]
1753    pub fn piped(mut self, argument: Value<'host>) -> Self {
1754        self.pipe(argument);
1755        self
1756    }
1757}
1758
1759#[derive(Clone)]
1760enum FunctionAction<'host> {
1761    With {
1762        program: Program,
1763        block_id: usize,
1764        program_counter: usize,
1765        signature: FunctionType,
1766        captures: Rc<[Value<'host>]>,
1767    },
1768    Never {
1769        signature: FunctionType,
1770    },
1771    Enum {
1772        variant: usize,
1773        definition: Rc<EnumType>,
1774    },
1775    Mut,
1776    OptionConstructor,
1777    OptionCase {
1778        some: bool,
1779        ty: ComplexType,
1780    },
1781    Borrow(&'host dyn ExternFn),
1782    Owned(Rc<dyn ExternFnOwned>),
1783}
1784
1785#[derive(Clone)]
1786enum StaticFunctionAction {
1787    With {
1788        program: Program,
1789        block_id: usize,
1790        program_counter: usize,
1791        signature: FunctionType,
1792        captures: Rc<[StaticValue]>,
1793    },
1794    Never {
1795        signature: FunctionType,
1796    },
1797    Enum {
1798        variant: usize,
1799        definition: Rc<EnumType>,
1800    },
1801    Mut,
1802    OptionConstructor,
1803    OptionCase {
1804        some: bool,
1805        ty: ComplexType,
1806    },
1807    Borrow(&'static dyn ExternFn),
1808    Owned(Rc<dyn ExternFnOwned>),
1809}
1810
1811impl<'host> From<FunctionAction<'host>> for Function<'host> {
1812    fn from(action: FunctionAction<'host>) -> Self {
1813        Self {
1814            action,
1815            argument: ().into(),
1816        }
1817    }
1818}
1819
1820impl std::fmt::Debug for FunctionAction<'_> {
1821    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1822        match self {
1823            Self::With {
1824                program,
1825                block_id,
1826                program_counter,
1827                signature,
1828                captures,
1829            } => f
1830                .debug_struct("Block")
1831                .field("program", &Rc::as_ptr(&program.bytes))
1832                .field("block_id", block_id)
1833                .field("program_counter", program_counter)
1834                .field("signature", signature)
1835                .field("captures", captures)
1836                .finish(),
1837            Self::Never { signature } => f
1838                .debug_struct("Never")
1839                .field("signature", signature)
1840                .finish(),
1841            Self::Enum {
1842                variant,
1843                definition,
1844            } => f
1845                .debug_struct("Enum")
1846                .field("variant", variant)
1847                .field("definition", definition)
1848                .finish(),
1849            Self::Mut => write!(f, "Mut"),
1850            Self::OptionConstructor => write!(f, "Option"),
1851            Self::OptionCase { some: true, ty } => f.debug_tuple("Some").field(ty).finish(),
1852            Self::OptionCase { some: false, ty } => f.debug_tuple("None").field(ty).finish(),
1853            Self::Borrow(arg0) => arg0.debug(f),
1854            Self::Owned(arg0) => arg0.debug(f),
1855        }
1856    }
1857}
1858
1859#[derive(Debug)]
1860enum MutRefSource<'host> {
1861    Origin(Rc<RefCell<Value<'host>>>),
1862    Child(Weak<RefCell<Value<'host>>>),
1863}
1864
1865/// A mutable reference to an espy value.
1866///
1867/// espy does not have inherited mutability, only interior mutability.
1868/// This means that [`Mut`] contains a [`RefCell`].
1869///
1870/// Only the original [`Mut`] contains a strong [`Rc`] to its contained
1871/// value; any time the mutable reference is copied the copy is instead a weak
1872/// reference. This prevents reference cycles from being constructed by espy
1873/// programs to leak memory. However, [`Mut::upgrade`] is provided for hosts to
1874/// upgrade weak references into strong ones should the need arise.
1875#[derive(Debug)]
1876pub struct Mut<'host> {
1877    source: MutRefSource<'host>,
1878}
1879
1880impl<'host> Mut<'host> {
1881    pub fn new(rc: Rc<RefCell<Value<'host>>>) -> Self {
1882        Self {
1883            source: MutRefSource::Origin(rc),
1884        }
1885    }
1886
1887    /// Creates a strong reference to the mutable reference's origin if it still exists.
1888    ///
1889    /// This can be used to create reference cycles and leak memory,
1890    /// so it should only be exposed to trusted espy programs.
1891    #[must_use]
1892    pub fn upgrade(&self) -> Option<Rc<RefCell<Value<'host>>>> {
1893        match &self.source {
1894            MutRefSource::Origin(rc) => Some(rc.clone()),
1895            MutRefSource::Child(weak) => weak.upgrade(),
1896        }
1897    }
1898}
1899
1900impl Clone for Mut<'_> {
1901    fn clone(&self) -> Self {
1902        Self {
1903            source: MutRefSource::Child(match &self.source {
1904                MutRefSource::Origin(rc) => Rc::downgrade(rc),
1905                MutRefSource::Child(weak) => weak.clone(),
1906            }),
1907        }
1908    }
1909}
1910
1911/// The combined type of a [`Function`]'s input and output.
1912#[derive(Clone, Debug)]
1913pub struct FunctionType {
1914    pub input: ComplexType,
1915    pub output: ComplexType,
1916}
1917
1918/// An instance of an [`EnumType`].
1919///
1920/// Use [`EnumVariant::variant`] to determine which variant this is intended to be,
1921/// and [`EnumVariant::contents`] to read that variant's value.
1922///
1923/// If you're interested in the [`EnumType`] this variant corresponds to, you
1924/// can use [`EnumVariant::definition`]. Conversely if you care only about the
1925/// enum's reported name and value and not the type it originated from, use
1926/// [`EnumVariant::unwrap`].
1927#[derive(Clone, Debug)]
1928pub struct EnumVariant<'host> {
1929    contents: Value<'host>,
1930    variant: usize,
1931    definition: Rc<EnumType>,
1932}
1933
1934/// A version of [`EnumVariant`] with a static lifetime.
1935///
1936/// See [`StaticValue`] for the difference between this and [`EnumVariant<'static>`].
1937#[derive(Clone, Debug)]
1938pub struct StaticEnumVariant {
1939    contents: StaticValue,
1940    variant: usize,
1941    definition: Rc<EnumType>,
1942}
1943
1944impl StaticEnumVariant {
1945    #[must_use]
1946    pub fn to_runtime<'host>(&self) -> EnumVariant<'host> {
1947        EnumVariant {
1948            contents: self.contents.to_runtime(),
1949            variant: self.variant,
1950            definition: self.definition.clone(),
1951        }
1952    }
1953}
1954
1955impl<'host, T: Borrow<StaticEnumVariant>> From<T> for EnumVariant<'host> {
1956    fn from(value: T) -> Self {
1957        value.borrow().to_runtime()
1958    }
1959}
1960
1961impl<'host> EnumVariant<'host> {
1962    #[must_use]
1963    pub fn contents(&self) -> &Value<'host> {
1964        &self.contents
1965    }
1966
1967    #[must_use]
1968    pub fn definition(&self) -> &Rc<EnumType> {
1969        &self.definition
1970    }
1971
1972    #[must_use]
1973    pub fn variant(&self) -> usize {
1974        self.variant
1975    }
1976
1977    #[must_use]
1978    pub fn split(self) -> (String, Value<'host>) {
1979        (
1980            self.definition.variants[self.variant].0.clone(),
1981            self.contents,
1982        )
1983    }
1984}
1985
1986/// The definition of an espy enum.
1987///
1988/// See [`EnumVariant`] also.
1989#[derive(Clone, Debug, PartialEq, Eq)]
1990pub struct EnumType {
1991    pub variants: Rc<[(String, ComplexType)]>,
1992}
1993
1994impl From<Rc<EnumType>> for Type {
1995    fn from(value: Rc<EnumType>) -> Self {
1996        Type::Enum(value)
1997    }
1998}
1999
2000impl From<EnumType> for Type {
2001    fn from(value: EnumType) -> Self {
2002        Rc::new(value).into()
2003    }
2004}
2005
2006/// Reads a u32 and casts it to usize for convenience.
2007fn read_header(bytes: &[u8], at: usize) -> Result<usize, InvalidBytecode> {
2008    let (((a, b), c), d) = bytes
2009        .get(at)
2010        .zip(bytes.get(at + 1))
2011        .zip(bytes.get(at + 2))
2012        .zip(bytes.get(at + 3))
2013        .ok_or(InvalidBytecode::MalformedHeader)?;
2014    Ok(u32::from_le_bytes([*a, *b, *c, *d]) as usize)
2015}
2016
2017fn block_count(bytes: &[u8]) -> Result<usize, InvalidBytecode> {
2018    read_header(bytes, 0)
2019}
2020
2021fn string_count(bytes: &[u8]) -> Result<usize, InvalidBytecode> {
2022    read_header(bytes, size_of::<u32>())
2023}
2024
2025fn offsets(bytes: &[u8]) -> Result<&[u8], InvalidBytecode> {
2026    let offset_count = block_count(bytes)? + string_count(bytes)?;
2027    let first_offset = size_of::<u32>() * 2;
2028    let last_offset = first_offset + size_of::<u32>() * offset_count;
2029    bytes
2030        .get(first_offset..last_offset)
2031        .ok_or(InvalidBytecode::MalformedHeader)
2032}
2033
2034fn block(bytes: &[u8], block_id: usize) -> Result<&[u8], InvalidBytecode> {
2035    let offsets = offsets(bytes)?;
2036    let block_position = size_of::<u32>() * block_id;
2037    let start = read_header(offsets, block_position)?;
2038    let end = read_header(offsets, size_of::<u32>() + block_position).unwrap_or(bytes.len());
2039    bytes
2040        .get(start..end)
2041        .ok_or(InvalidBytecode::MalformedHeader)
2042}
2043
2044struct Frame<'a, 'host> {
2045    bytecode: &'a [u8],
2046    pc: usize,
2047    captures: Option<(Rc<[Value<'host>]>, NonZero<usize>)>,
2048    stack: Vec<Value<'host>>,
2049}
2050
2051impl<'host> Frame<'_, 'host> {
2052    fn next(&mut self) -> Result<u8, InvalidBytecode> {
2053        let next = self
2054            .bytecode
2055            .get(self.pc)
2056            .ok_or(InvalidBytecode::ProgramOutOfBounds)?;
2057        self.pc += 1;
2058        Ok(*next)
2059    }
2060
2061    fn next4(&mut self) -> Result<usize, InvalidBytecode> {
2062        Ok(u32::from_le_bytes([self.next()?, self.next()?, self.next()?, self.next()?]) as usize)
2063    }
2064
2065    fn next_i64(&mut self) -> Result<i64, InvalidBytecode> {
2066        Ok(i64::from_le_bytes([
2067            self.next()?,
2068            self.next()?,
2069            self.next()?,
2070            self.next()?,
2071            self.next()?,
2072            self.next()?,
2073            self.next()?,
2074            self.next()?,
2075        ]))
2076    }
2077
2078    fn stack_len(&self) -> usize {
2079        self.captures
2080            .as_ref()
2081            .map_or(0, |captures| captures.1.into())
2082            + self.stack.len()
2083    }
2084
2085    fn get(&self, index: usize) -> Result<&Value<'host>, InvalidBytecode> {
2086        if let Some((captures, len)) = &self.captures {
2087            if index < usize::from(*len) {
2088                captures.get(index)
2089            } else {
2090                self.stack.get(index - usize::from(*len))
2091            }
2092        } else {
2093            self.stack.get(index)
2094        }
2095        .ok_or(InvalidBytecode::StackOutOfBounds)
2096    }
2097
2098    fn push(&'_ mut self, value: Value<'host>) {
2099        self.stack.push(value);
2100    }
2101
2102    fn pop(&'_ mut self) -> Result<Value<'host>, Error> {
2103        self.stack.pop().map_or_else(
2104            || {
2105                if let Some((captures, len)) = &mut self.captures {
2106                    let capture = captures[usize::from(*len) - 1].clone();
2107                    if let Ok(new_len) = NonZero::try_from(usize::from(*len) - 1) {
2108                        *len = new_len;
2109                    } else {
2110                        self.captures = None;
2111                    }
2112                    Ok(capture)
2113                } else {
2114                    Err(InvalidBytecode::StackUnderflow.into())
2115                }
2116            },
2117            Ok,
2118        )
2119    }
2120
2121    fn into_bind(mut self, program: Program, block_id: usize) -> Result<Value<'host>, Error> {
2122        Ok(Value::Tuple(
2123            [
2124                self.pop()?,
2125                Function {
2126                    action: FunctionAction::With {
2127                        program,
2128                        block_id,
2129                        program_counter: self.pc,
2130                        signature: FunctionType {
2131                            input: Type::Any.into(),
2132                            output: Type::Any.into(),
2133                        },
2134                        captures: rc_slice_from_iter(
2135                            self.stack_len(),
2136                            self.captures
2137                                .iter()
2138                                .flat_map(|captures| {
2139                                    captures.0[0..captures.1.into()].iter().cloned()
2140                                })
2141                                .chain(self.stack),
2142                        ),
2143                    },
2144                    argument: Value::Unit,
2145                }
2146                .into(),
2147            ]
2148            .into(),
2149        ))
2150    }
2151}
2152
2153enum StepOutcome<'a, 'host> {
2154    Frame(Frame<'a, 'host>),
2155    Yield(Value<'host>),
2156}
2157
2158/// An espy program which has been loaded into memory and is ready to be executed.
2159///
2160/// This program will be kept alive by any [`Function`]s it produces. If you
2161/// intend on returning a small function from a large program and are concerned
2162/// about the memory usage, consider moving that function and its dependencies
2163/// to its own program, whose memory can then be managed separately.
2164#[derive(Clone, Debug)]
2165pub struct Program {
2166    pub(crate) bytes: Rc<[u8]>,
2167    owned_strings: Rc<[Rc<str>]>,
2168}
2169
2170impl TryFrom<Rc<[u8]>> for Program {
2171    type Error = Error;
2172
2173    fn try_from(bytes: Rc<[u8]>) -> Result<Self, Self::Error> {
2174        let string_count = string_count(&bytes)?;
2175        let owned_strings = (0..string_count)
2176            .map(|string| {
2177                let string = size_of::<u32>() * (string + block_count(&bytes)?);
2178                let offsets = offsets(&bytes)?;
2179                let start = read_header(offsets, string)?;
2180                let end = read_header(offsets, size_of::<u32>() + string).unwrap_or(bytes.len());
2181                let string_bytes = bytes
2182                    .get(start..end)
2183                    .ok_or(InvalidBytecode::MalformedHeader)?;
2184                let string = str::from_utf8(string_bytes).map_err(InvalidBytecode::Utf8Error)?;
2185                Ok(Rc::from(string))
2186            })
2187            .collect::<Result<_, Error>>()?;
2188        Ok(Self {
2189            bytes,
2190            owned_strings,
2191        })
2192    }
2193}
2194
2195impl Program {
2196    /// # Errors
2197    ///
2198    /// Returns an error if the evaluating the program results in an error
2199    pub fn eval<'host>(&self) -> Result<Value<'host>, Error> {
2200        self.eval_block(0, 0, None, None)
2201    }
2202
2203    fn eval_block<'host>(
2204        &self,
2205        block_id: usize,
2206        program_counter: usize,
2207        captures: impl Into<Option<Rc<[Value<'host>]>>>,
2208        argument: impl Into<Option<Value<'host>>>,
2209    ) -> Result<Value<'host>, Error> {
2210        let captures = captures
2211            .into()
2212            .and_then(|x| x.len().try_into().ok().map(|len| (x, len)));
2213        let mut frame = Frame {
2214            bytecode: block(&self.bytes, block_id)?,
2215            pc: program_counter,
2216            captures,
2217            stack: argument.into().into_iter().collect(),
2218        };
2219        // Program counter, ignoring block boundries.
2220        let absolute_program_counter =
2221            frame.bytecode.as_ptr() as usize - block(&self.bytes, 0)?.as_ptr() as usize;
2222
2223        // The program counter reaching the first (and only the first)
2224        // out-of-bounds byte should be considered a return.
2225        while frame.pc != frame.bytecode.len() {
2226            let pc = frame.pc;
2227            frame = match self
2228                .eval_step(block_id, frame)
2229                .map_err(|e| e.suggest_location(absolute_program_counter + pc))?
2230            {
2231                StepOutcome::Frame(frame) => frame,
2232                StepOutcome::Yield(value) => return Ok(value),
2233            }
2234        }
2235        frame.pop()
2236    }
2237
2238    fn eval_step<'a, 'host>(
2239        &self,
2240        block_id: usize,
2241        mut frame: Frame<'a, 'host>,
2242    ) -> Result<StepOutcome<'a, 'host>, Error> {
2243        macro_rules! bi_op {
2244            (let $l:ident, $r:ident: $type:ident => $expr_type:ident: $expr:expr) => {{
2245                let $r = frame.pop()?;
2246                let $l = frame.pop()?;
2247                match (&$l, &$r) {
2248                    (Value::$type($l), Value::$type($r)) => frame.push(Value::$expr_type($expr)),
2249                    _ => return Err(Error::expected_integers(&$l, &$r)),
2250                }
2251            }};
2252        }
2253        macro_rules! bi_num {
2254            (let $l:ident, $r:ident => $expr:expr) => {
2255                bi_op!(let $l, $r: I64 => I64: $expr)
2256            };
2257        }
2258        macro_rules! bi_cmp {
2259            (let $l:ident, $r:ident => $expr:expr) => {
2260                bi_op!(let $l, $r: I64 => Bool: $expr)
2261            };
2262        }
2263        let instruction = frame.next()?;
2264        match instruction {
2265            instruction::CLONE => {
2266                let index = frame.next4()?;
2267                #[allow(
2268                    clippy::cast_possible_truncation,
2269                    clippy::cast_possible_wrap,
2270                    reason = "next4 only returns 32 bits"
2271                )]
2272                match index as i32 {
2273                    0.. => {
2274                        let value = frame.get(index)?;
2275                        frame.push(value.clone());
2276                    }
2277                    builtins::ANY => {
2278                        frame.push(Type::Any.into());
2279                    }
2280                    builtins::UNIT => {
2281                        frame.push(Type::Unit.into());
2282                    }
2283                    builtins::I64 => {
2284                        frame.push(Type::I64.into());
2285                    }
2286                    builtins::STRING => {
2287                        frame.push(Type::String.into());
2288                    }
2289                    builtins::OPTION => {
2290                        frame.push(Value::Function(Rc::new(
2291                            FunctionAction::OptionConstructor.into(),
2292                        )));
2293                    }
2294                    builtins::MUT => {
2295                        frame.push(Value::Function(Rc::new(FunctionAction::Mut.into())));
2296                    }
2297                    _ => Err(InvalidBytecode::InvalidBuiltin)?,
2298                }
2299            }
2300            instruction::POP => {
2301                frame.pop()?;
2302            }
2303            instruction::COLLAPSE => {
2304                let value = frame.pop()?;
2305                for _ in 0..(frame.stack_len() - frame.next4()?) {
2306                    frame.pop()?;
2307                }
2308                frame.push(value);
2309            }
2310            instruction::JUMP => {
2311                frame.pc = frame.next4()?;
2312            }
2313            instruction::IF => {
2314                let target = frame.next4()?;
2315                if let Value::Bool(false) = frame.pop()? {
2316                    frame.pc = target;
2317                }
2318            }
2319
2320            instruction::PUSH_UNIT => {
2321                frame.push(().into());
2322            }
2323            instruction::PUSH_TRUE => {
2324                frame.push(true.into());
2325            }
2326            instruction::PUSH_FALSE => {
2327                frame.push(false.into());
2328            }
2329            instruction::PUSH_I64 => {
2330                let i = frame.next_i64()?.into();
2331                frame.push(i);
2332            }
2333            instruction::PUSH_STRING => {
2334                let string_id = frame.next4()?;
2335                let string = self
2336                    .owned_strings
2337                    .get(string_id)
2338                    .ok_or(InvalidBytecode::InvalidStringId)?
2339                    .clone();
2340                frame.push(string.into());
2341            }
2342            instruction::PUSH_FUNCTION => {
2343                let captures = frame.next4()?;
2344                let function = frame.next4()?;
2345                let output = frame.pop()?;
2346                let input = frame.pop()?;
2347                if function == 0 {
2348                    // ignore captures if the function will never be called.
2349                    for _ in 0..captures {
2350                        frame.pop()?;
2351                    }
2352                    frame.push(Value::Function(Rc::new(
2353                        FunctionAction::Never {
2354                            signature: FunctionType {
2355                                input: input.try_into()?,
2356                                output: output.try_into()?,
2357                            },
2358                        }
2359                        .into(),
2360                    )));
2361                } else {
2362                    let new_stack =
2363                        rc_slice_try_from_iter_rev(captures, (0..captures).map(|_| frame.pop()))?;
2364                    frame.push(Value::Function(Rc::new(
2365                        FunctionAction::With {
2366                            program: self.clone(),
2367                            signature: FunctionType {
2368                                input: input.try_into()?,
2369                                output: output.try_into()?,
2370                            },
2371                            block_id: function,
2372                            program_counter: 0,
2373                            captures: new_stack,
2374                        }
2375                        .into(),
2376                    )));
2377                }
2378            }
2379            instruction::PUSH_ENUM => {
2380                let variants = frame.pop()?;
2381                let Value::Tuple(Tuple(TupleStorage::Named(variants))) = variants else {
2382                    Err(Error::expected_named_tuple(&variants))?
2383                };
2384                let variants = rc_slice_try_from_iter(
2385                    variants.len(),
2386                    variants.iter().map(|(name, value)| {
2387                        value.clone().try_into().map(|value| (name.clone(), value))
2388                    }),
2389                )?;
2390                frame.push(Type::from(EnumType { variants }).into());
2391            }
2392
2393            instruction::ADD => bi_num!(let l, r => l + r),
2394            instruction::SUB => bi_num!(let l, r => l - r),
2395            instruction::MUL => bi_num!(let l, r => l * r),
2396            instruction::DIV => bi_num!(let l, r => l / r),
2397            instruction::BITWISE_AND => bi_num!(let l, r => l & r),
2398            instruction::BITWISE_OR => bi_num!(let l, r => l | r),
2399            instruction::BITWISE_XOR => bi_num!(let l, r => l ^ r),
2400            instruction::GREATER => bi_cmp!(let l, r => l > r),
2401            instruction::GREATER_EQUAL => bi_cmp!(let l, r => l >= r),
2402            instruction::LESSER => bi_cmp!(let l, r => l < r),
2403            instruction::LESSER_EQUAL => bi_cmp!(let l, r => l <= r),
2404            instruction::MATCHES => {
2405                let candidate = frame.pop()?;
2406                let subject = frame.pop()?;
2407                if let Value::EnumVariant(subject) = &subject
2408                    && let Value::Function(function) = &candidate
2409                    && let FunctionAction::Enum {
2410                        variant,
2411                        definition,
2412                    } = &function.action
2413                    && subject.definition == *definition
2414                {
2415                    // Destructuring changes the value forwarded to the match arm.
2416                    if subject.variant == *variant {
2417                        frame.pop()?;
2418                        frame.push(subject.contents.clone());
2419
2420                        frame.push(true.into());
2421                    } else {
2422                        frame.push(false.into());
2423                    }
2424                } else if let Value::Option { contents, ty } = &subject
2425                    && let Value::Function(function) = &candidate
2426                    && let FunctionAction::OptionCase {
2427                        some,
2428                        ty: expected_ty,
2429                    } = &function.action
2430                {
2431                    match (contents, some) {
2432                        (Some(contents), true) => {
2433                            if !ty.compare(expected_ty) {
2434                                return Err(Error::type_error(&subject, expected_ty));
2435                            }
2436                            // Destructuring changes the value forwarded to the match arm.
2437                            frame.pop()?;
2438                            frame.push((**contents).clone());
2439                            frame.push(true.into());
2440                        }
2441                        (None, false) => {
2442                            // Destructuring changes the value forwarded to the match arm.
2443                            frame.pop()?;
2444                            frame.push(().into());
2445                            frame.push(true.into());
2446                        }
2447                        _ => {
2448                            frame.push(false.into());
2449                        }
2450                    }
2451                } else {
2452                    frame.push(subject.clone().eq(candidate)?.into());
2453                }
2454            }
2455            instruction::EQUAL_TO => {
2456                let r = frame.pop()?;
2457                let l = frame.pop()?;
2458                frame.push(l.eq(r)?.into());
2459            }
2460            instruction::NOT_EQUAL_TO => {
2461                let r = frame.pop()?;
2462                let l = frame.pop()?;
2463                frame.push((!l.eq(r)?).into());
2464            }
2465            instruction::LOGICAL_AND => bi_op!(let l, r: Bool => Bool: *l && *r),
2466            instruction::LOGICAL_OR => bi_op!(let l, r: Bool => Bool: *l || *r),
2467            instruction::PIPE => {
2468                let mut function = Rc::<Function>::try_from(frame.pop()?)?;
2469                let argument = frame.pop()?;
2470                let function_mut = Rc::make_mut(&mut function);
2471                let mut arguments = ().into();
2472                mem::swap(&mut arguments, &mut function_mut.argument);
2473                arguments = Value::concat(arguments, argument);
2474                mem::swap(&mut arguments, &mut function_mut.argument);
2475                frame.push(Value::Function(function));
2476            }
2477
2478            instruction::CALL => {
2479                let argument = frame.pop()?;
2480                let function = frame.pop()?;
2481                let result = match function {
2482                    Value::Function(function) => Rc::<Function>::try_unwrap(function)
2483                        .unwrap_or_else(|function| (*function).clone())
2484                        .piped(argument)
2485                        .eval()?,
2486                    function => Err(Error::expected_function(&function))?,
2487                };
2488                frame.push(result);
2489            }
2490            instruction::JOIN => {
2491                let r = frame.pop()?;
2492                let l = frame.pop()?;
2493                frame.push(Value::concat(l, r));
2494            }
2495            instruction::LIST => {
2496                let length = frame.next4()?;
2497                let tuple = rc_slice_try_from_iter_rev(length, (0..length).map(|_| frame.pop()))?;
2498                frame.push(Tuple::from(tuple).into());
2499            }
2500            instruction::INDEX => {
2501                let index = frame.pop()?;
2502                let container = frame.pop()?;
2503                frame.push(container.index(index)?);
2504            }
2505            instruction::TRY_INDEX => {
2506                let index = frame.pop()?;
2507                let container = frame.pop()?;
2508                frame.push(container.index(index).ok().into());
2509            }
2510            instruction::NAME => {
2511                let name_id = frame.next4()?;
2512                let name = self
2513                    .owned_strings
2514                    .get(name_id)
2515                    .ok_or(InvalidBytecode::InvalidStringId)?
2516                    .clone();
2517                let value = frame.pop()?;
2518                frame.push(Value::Tuple(Tuple::from([(name, value)])));
2519            }
2520            instruction::NEGATIVE => {
2521                let value = frame.pop()?.i64()?;
2522                frame.push((-value).into());
2523            }
2524            instruction::DEREF => {
2525                let value = frame.pop()?.into_refcell()?;
2526                frame.push(value.try_borrow().map_err(Error::other)?.clone());
2527            }
2528            instruction::SET => {
2529                let value = frame.pop()?;
2530                let target = frame.pop()?.into_refcell()?;
2531                *target.borrow_mut() = value;
2532            }
2533            instruction::BIND => {
2534                let bind = frame.pop()?.function()?;
2535                return Ok(StepOutcome::Yield(
2536                    bind.piped(frame.into_bind(self.clone(), block_id)?)
2537                        .eval()?,
2538                ));
2539            }
2540            instruction::YIELD => {
2541                return Ok(StepOutcome::Yield(frame.into_bind(self.clone(), block_id)?));
2542            }
2543
2544            _ => Err(InvalidBytecode::InvalidInstruction)?,
2545        };
2546        Ok(StepOutcome::Frame(frame))
2547    }
2548}
2549
2550#[allow(clippy::missing_errors_doc)]
2551pub trait Extern {
2552    fn index<'host>(&'host self, index: Value<'host>) -> Result<Value<'host>, Error>;
2553
2554    fn to_static(&self) -> Option<&'static dyn Extern> {
2555        None
2556    }
2557
2558    /// Allows the [`Extern`] trait object to be downcasted back into its original type.
2559    ///
2560    /// Implementing this method is optional.
2561    /// The default implementation will always return `None` and reject all downcasting attempts via [`Value::downcast_extern`].
2562    fn any(&self) -> Option<&dyn Any> {
2563        None
2564    }
2565
2566    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2567        write!(f, "{{external value}}")
2568    }
2569}
2570
2571#[allow(clippy::missing_errors_doc)]
2572pub trait ExternOwned {
2573    /// Note that self's reference count will always be greater than one,
2574    /// so [`Rc::unwrap_or_clone`], [`Rc::get_mut`], etc. are useless.
2575    fn index<'host>(self: Rc<Self>, index: Value<'host>) -> Result<Value<'host>, Error>;
2576
2577    /// Allows the [`ExternOwned`] trait object to be downcasted back into its original type.
2578    ///
2579    /// Implementing this method is optional.
2580    /// The default implementation will always return `None` and reject all downcasting attempts via [`Value::downcast_extern`].
2581    ///
2582    /// There is no way to downcast from an [`Rc<dyn Any>`],
2583    /// so this functin has the same signature as [`Extern`]'s equivalent.
2584    fn any(&self) -> Option<&dyn Any> {
2585        None
2586    }
2587
2588    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2589        write!(f, "{{external value}}")
2590    }
2591}
2592
2593#[allow(clippy::missing_errors_doc)]
2594pub trait ExternFn {
2595    fn call<'host>(&'host self, argument: Value<'host>) -> Result<Value<'host>, Error>;
2596
2597    fn to_static(&self) -> Option<&'static dyn ExternFn> {
2598        None
2599    }
2600
2601    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2602        write!(f, "{{external function}}")
2603    }
2604}
2605
2606#[allow(clippy::missing_errors_doc)]
2607pub trait ExternFnOwned {
2608    /// Note that self's reference count will always be greater than one when a function is called from espy,
2609    /// so [`Rc::unwrap_or_clone`], [`Rc::get_mut`], etc. are useless.
2610    fn call<'host>(self: Rc<Self>, argument: Value<'host>) -> Result<Value<'host>, Error>;
2611
2612    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2613        write!(f, "{{external function}}")
2614    }
2615}