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}