nanvm_lib/vm/function/mod.rs
1mod debug;
2mod member_access;
3mod partial_eq;
4
5use crate::vm::{Any, Array, IFunction, IVm, String, error};
6
7/// A function value: it can be called, it has a `length`, it has a text,
8/// and it has an identity. Nothing else. It holds a VM's own value, laid
9/// out as [`Unpacked`](crate::vm::Unpacked) lays out every value, which the
10/// VM constructs through its own capability, such as
11/// [`IStaticFunction`](crate::vm::IStaticFunction), and [`Function::new`]
12/// wraps.
13///
14/// Compared by identity, an `Rc` in `naive`: every construction is a new
15/// function, as JavaScript makes a new function of every evaluation of an
16/// arrow, and `(() => 1) === (() => 1)` is `false`. A built-in is no kind
17/// apart: it is a closure of the runtime value, `vm::runtime`, built once
18/// and read from the value, so `Object.is === Object.is` holds because
19/// both reads find the one closure, and its text is the NativeFunction
20/// text the compiled runtime gave it (`fjs/js/runtime/README.md`, "How
21/// NaNVM finds it").
22#[derive(Clone)]
23pub struct Function<A: IVm>(A::InternalFunction);
24
25impl<A: IVm> Function<A> {
26 pub fn new(internal: A::InternalFunction) -> Self {
27 Function(internal)
28 }
29 /// Call the function with an arguments array. No user function reads
30 /// `this`, so there is no receiver to pass.
31 pub fn call(&self, args: Array<A>) -> Result<Any<A>, Any<A>> {
32 self.0.call(args)
33 }
34 /// `f.length`.
35 pub fn length(&self) -> u32 {
36 self.0.length()
37 }
38 /// `String(f)`: the text the function was given, or the refusal of a
39 /// function without one (`error::function_text`).
40 pub fn text(&self) -> Result<String<A>, Any<A>> {
41 self.0
42 .text()
43 .map(Into::into)
44 .ok_or_else(error::function_text)
45 }
46 /// The VM's own value.
47 pub(crate) fn internal(&self) -> &A::InternalFunction {
48 &self.0
49 }
50}