Skip to main content

nanvm_lib/vm/internal/
mod.rs

1mod icomplex;
2mod icontainer;
3mod ifunction;
4mod istatic_function;
5
6pub use icomplex::IComplex;
7pub use icontainer::IContainer;
8pub use ifunction::IFunction;
9pub use istatic_function::{IStaticFunction, StaticCode};
10
11use crate::{
12    sign::Sign,
13    vm::{Any, Array, Function, Property, Unpacked},
14};
15
16/// A VM's value representation.
17///
18/// A VM is built from an [`Unpacked`] value alone, so a number reaches it
19/// only as a [`Number`](crate::vm::Number), which holds one `NaN` by
20/// construction — there is no `From<f64>` here on purpose — so a NaN-boxing
21/// VM, which reads a negative quiet `NaN` as a boxed value, can store its
22/// bits as they are.
23///
24/// A VM is `'static`: a type with no lifetime, which a function's text
25/// names behind a `'static` reference. The runtime is not the VM's to
26/// bind: it is a value, [`runtime`](crate::vm::runtime), built once by
27/// whoever runs compiled modules and handed to each as its parameter, for
28/// any VM.
29pub trait IVm: Sized + Clone + From<Unpacked<Self>> + 'static {
30    // types
31    type InternalString: IContainer<Self, Header = (), Item = u16>;
32    type InternalBigInt: IContainer<Self, Header = Sign, Item = u64>;
33    type InternalObject: IContainer<Self, Header = (), Item = Property<Self>>;
34    type InternalArray: IContainer<Self, Header = (), Item = Any<Self>>;
35    type InternalFunction: IFunction<Self>;
36    // functions
37    fn to_unpacked(self) -> Unpacked<Self>;
38
39    /// Inspect the value without transferring ownership or cloning it.
40    ///
41    /// The view is valid only for the callback. A VM may borrow a stored
42    /// `Unpacked` or decode a temporary view of a packed representation;
43    /// callers cannot retain references to that view after the callback.
44    /// Keep `to_unpacked` for operations that need the owned payload.
45    ///
46    /// ```compile_fail
47    /// use nanvm_lib::{naive::Naive, vm::{IVm, Number, Unpacked}};
48    /// let value = Naive::from(Unpacked::Number(Number::from(1.0)));
49    /// let escaped = value.with_unpacked(|view| view);
50    /// ```
51    fn with_unpacked<R>(&self, f: impl FnOnce(&Unpacked<Self>) -> R) -> R;
52
53    /// A function made out of a Rust static function, [`StaticCode`], over
54    /// the frame it captures: what every closure of a compiled module is,
55    /// and what the runtime's member functions answer, a closure over the
56    /// receiver, which is why the capability is every VM's and not a
57    /// capability apart ([`IStaticFunction`] names it). `text` is the
58    /// function's text, what `String(f)` answers: the compiler renders it
59    /// from the function's EDAG, one `&'static str` per arrow in the source,
60    /// shared by every function the arrow makes. `None` is a function with
61    /// no text — a host or hand-written one, with no EDAG, or one whose body
62    /// the renderer cannot spell yet — whose conversion to a string is
63    /// refused.
64    fn static_function(
65        code: StaticCode<Self>,
66        length: u32,
67        frame: Array<Self>,
68        text: Option<&'static str>,
69    ) -> Function<Self>;
70    /// The frame `static_function` was given, read by the code through its `self_`.
71    fn frame(self_: &Self::InternalFunction) -> &Array<Self>;
72}