Skip to main content

nanvm_lib/vm/any/
call.rs

1use crate::vm::{Any, Array, Function, IVm};
2
3impl<A: IVm> Any<A> {
4    /// The EDAG's `()` (`['()', callee, args]`): `callee(...args)`, the
5    /// second operand spread. Both operands are values, as every EDAG
6    /// operand is: the callee a function and the arguments an array, and
7    /// either being anything else throws — the `TypeError` JavaScript throws
8    /// for calling what is not a function, or for spreading what is not
9    /// iterable — through the conversions `TryFrom<Any<A>>` already makes.
10    /// The result, answered or thrown, is the function's own
11    /// ([`IFunction::call`](crate::vm::IFunction::call)).
12    pub fn call(self, args: Any<A>) -> Result<Any<A>, Any<A>> {
13        Function::try_from(self)?.call(Array::try_from(args)?)
14    }
15}
16
17#[cfg(test)]
18mod tests {
19    use crate::vm::test::function::identity;
20    use crate::{
21        naive::Naive,
22        vm::{Any, Function, IVm, Nullish, ToAny, ToArray, error, unstable::f64_any},
23    };
24
25    type A = Naive;
26
27    #[test]
28    fn calls_with_the_arguments() {
29        let args: Any<A> = [
30            f64_any(0x3ff0_0000_0000_0000),
31            f64_any(0x4000_0000_0000_0000),
32        ]
33        .to_array()
34        .to_any();
35        assert_eq!(identity().call(args.clone()), Ok(args));
36    }
37
38    /// The code receives the function value it is the code of: answered as
39    /// a value, it is the very function that was called.
40    #[test]
41    fn code_receives_itself() {
42        let f: Any<A> = A::static_function(
43            |self_, _| Ok(Function::new(self_.clone()).to_any()),
44            0,
45            [].to_array(),
46            None,
47        )
48        .to_any();
49        assert_eq!(f.clone().call([].to_array().to_any()), Ok(f));
50    }
51
52    #[test]
53    fn a_non_function_callee_throws() {
54        let callee: Any<A> = f64_any(0x3ff0_0000_0000_0000);
55        assert_eq!(
56            callee.call([].to_array().to_any()),
57            Err(error::unexpected_type())
58        );
59    }
60
61    #[test]
62    fn non_array_arguments_throw() {
63        assert_eq!(
64            identity().call(Nullish::Null.to_any()),
65            Err(error::unexpected_type())
66        );
67    }
68}