pub struct Any<A: IVm>(/* private fields */);Expand description
use nanvm_lib::{
vm::{Any, IVm, ToAny, String, Array, ToArray, ToObject, Object, Nullish, Number, BigInt},
naive::Naive
};
fn any_test<A: IVm>() {
let b: Any<A> = true.to_any();
let n: Any<A> = Nullish::Null.to_any();
let n: Any<A> = Number::from(42.0).to_any();
let c: String<A> = "Hello".into();
let m: Any<A> = c.to_any();
let a: Array<A> = [].to_array();
let o: Any<A> = a.to_any();
let x: Object<A> = [].to_object();
let p: Any<A> = x.to_any();
let u: BigInt<A> = 123u64.into();
let q: Any<A> = u.to_any();
}
any_test::<Naive>();Implementations§
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn call(self, args: Any<A>) -> Result<Any<A>, Any<A>>
pub fn call(self, args: Any<A>) -> Result<Any<A>, Any<A>>
The EDAG’s () (['()', callee, args]): callee(...args), the
second operand spread. Both operands are values, as every EDAG
operand is: the callee a function and the arguments an array, and
either being anything else throws — the TypeError JavaScript throws
for calling what is not a function, or for spreading what is not
iterable — through the conversions TryFrom<Any<A>> already makes.
The result, answered or thrown, is the function’s own
(IFunction::call).
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn conditional(
self,
consequent: impl FnOnce() -> Result<Self, Self>,
alternate: impl FnOnce() -> Result<Self, Self>,
) -> Result<Self, Self>
pub fn conditional( self, consequent: impl FnOnce() -> Result<Self, Self>, alternate: impl FnOnce() -> Result<Self, Self>, ) -> Result<Self, Self>
?:. Not a core::ops trait — Rust has no operator for a ternary
conditional (if/else takes a bool, not an Any<A>) — so this
is a plain method over the native VM’s values.
Coerces self via ToBoolean, establishes the arm that selects —
consequent or alternate — and returns its value. The arms are
thunks because JavaScript establishes exactly one of them:
true ? 1 : (1n / 0n) is 1, not a throw. FnOnce, since an arm is
established at most once; a Result, since establishing it may
throw, and that throw is this operation’s.
https://tc39.es/ecma262/#sec-conditional-operator
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn member_present(self, key: Self, runtime: &Self) -> Result<Self, Self>
pub fn member_present(self, key: Self, runtime: &Self) -> Result<Self, Self>
The internal member-presence query. Both operands are established before lookup; this performs the optional member-call guard without evaluating call arguments or checking that the answer is callable.
Sourcepub fn dot(self, key: Self) -> PropertyLambda<A>
pub fn dot(self, key: Self) -> PropertyLambda<A>
The EDAG’s . node, ['.', receiver, key] or with a continuation,
['.', receiver, key, k]: the property step, as a chain a
continuation may follow (fjs/edag/README.md, Chains).
dot(a, key).end() is a.b, the one spelling of the node whether
or not a continuation follows, and the one property read nanvm-lib
has; dot(a, key).end_call(&runtime, args) is the method call
a.b(...args), the property called on its receiver, the runtime
value asked for the body of a name the receiver does not own. The
key is a value: a[k] evaluates both operands whatever they are.
A nullish receiver throws here, before any continuation’s arguments
— the throw waits in the lambda until end or end_call surfaces
it, so a.b(...c) on a nullish a throws with c untouched. What
a live step reads or calls is [Member]’s.
Sourcepub fn option_dot(
self,
key: impl FnOnce() -> Result<Self, Self>,
) -> OptionPropertyLambda<A>
pub fn option_dot( self, key: impl FnOnce() -> Result<Self, Self>, ) -> OptionPropertyLambda<A>
The EDAG’s ?. node, ['?.', receiver, key, k]: a?.b, opening a
short-circuit region. A nullish receiver skips the key and the rest
of the chain — u?.[todo()] never calls todo — which is why the
key is a thunk. Any other receiver takes the step dot takes.
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn get_iterator(self) -> Result<IteratorRecord<A>, Any<A>>
pub fn get_iterator(self) -> Result<IteratorRecord<A>, Any<A>>
ECMAScript’s GetIterator(self, sync)
(https://tc39.es/ecma262/#sec-getiterator), restricted to the values
a FunctionalScript module can build: an array’s elements, or a
string’s code points, each a string. Every other value — null,
undefined, a boolean, a number, a bigint, an object, a function —
is not iterable, and the TypeError is raised here, before any
element. No object is iterable: a module cannot spell
Symbol.iterator.
The one protocol behind array spread, call spread and array
destructuring. Not Array::concat, which keeps a non-array item
whole: [...'ab'] is ['a', 'b'], not ['ab'], and [...{}]
throws.
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn instanceof_(self, constructor: Constructor) -> Result<Any<A>, Any<A>>
pub fn instanceof_(self, constructor: Constructor) -> Result<Any<A>, Any<A>>
instanceof, against a built-in constructor. Not a core::ops
trait — Rust has no operator to spell it with — so this is a plain
method, named as typeof_ is: a trailing underscore keeps the
reserved-word spelling recognizable. Never throws: the right side is
a constructor by construction, so JavaScript’s TypeError for a
non-callable right operand has no case here; stays a Result to
match every other operator’s shape.
https://tc39.es/ecma262/#sec-instanceofoperator
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn object_spread(self) -> ObjectSpread<A> ⓘ
pub fn object_spread(self) -> ObjectSpread<A> ⓘ
What {...self} copies: the source side of ECMAScript’s
CopyDataProperties
(https://tc39.es/ecma262/#sec-copydataproperties), the own
enumerable string-keyed properties of self in [[OwnPropertyKeys]]
order. An object gives its entries, each key once with its last
value; an array its elements keyed "0", "1", …; a string one
entry per UTF-16 code unit; and a number, a bigint, a boolean, a
function, null and undefined none.
Never throws, unlike Any::get_iterator: {...null} is {}, where
Object.entries(null) and object rest destructuring both throw. So
an executor may evaluate an object spread whose result goes unused
and lose nothing.
Sourcepub fn entries(self) -> Result<Self, Self>
pub fn entries(self) -> Result<Self, Self>
Object.entries(self): what Any::object_spread copies, each
entry a fresh [key, value] array, in a fresh array — an object’s
entries, an array’s elements and a string’s code units under their
index strings, nothing for a number, a bigint, a boolean or a
function. Unlike the spread it throws on null and undefined,
as ToObject does (member_access::non_nullish_receiver).
The code of the static function no FunctionalScript body defines,
enumerating keys being what the language has no other way to do:
Object.entries in the runtime value is a closure over it
(fjs/js/runtime/README.md, “How NaNVM finds it”).
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn option_call(
self,
args: impl FnOnce() -> Result<Self, Self>,
) -> OptionLambda<A>
pub fn option_call( self, args: impl FnOnce() -> Result<Self, Self>, ) -> OptionLambda<A>
The EDAG’s ?.() node, ['?.()', callee, args, k]: a?.(...args),
opening a short-circuit region. A nullish callee skips the arguments
and the rest of the chain, which is why they are a thunk; any other
callee has them evaluated first and is then called as Any::call
calls it — 1?.(...args) is the TypeError 1(...args) is, after
the arguments.
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn same_value(&self, other: &Self) -> bool
pub fn same_value(&self, other: &Self) -> bool
SameValue (https://tc39.es/ecma262/#sec-samevalue), the equality
of Object.is: ===, except that NaN equals NaN and 0 does
not equal -0. Every NaN is the one quiet NaN
(Number::NAN), so equal bits are equal values.
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn to_json(self) -> Result<String, JsonError>
pub fn to_json(self) -> Result<String, JsonError>
An Any<A> -> JSON serializer covering everything with a direct JSON
counterpart: numbers, strings, booleans, null, and arrays/objects
recursed into. See JsonError for what’s deliberately unhandled.
The containers being written are a stack on the heap and the text goes into one buffer, so traversal does not recurse with nesting and does not copy each container’s text into its parent’s buffer.
Destruction still depends on the VM. With Naive, consuming a sole-owned
deeply nested value can overflow the stack when its containers are
released, including on an error. See nanvm/lib/todo/array-deep-nesting.md.
An object’s entries are its own, in [[OwnPropertyKeys]] order, each
key once with its last value: the view JSON.stringify and an object
spread both read (Object::own_entries).
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn typeof_(self) -> Result<Any<A>, Any<A>>
pub fn typeof_(self) -> Result<Any<A>, Any<A>>
typeof. Not a core::ops trait — Rust has no unary operator to
spell it with — so this is a plain method, the same as unary_plus.
Named typeof_, not type_of: typeof is itself a reserved word, and
a trailing underscore — the convention FJS and JS both use for this —
resolves the collision while keeping the name recognizable. Never
throws, but stays a Result to match every other operator’s shape.
https://tc39.es/ecma262/#sec-typeof-operator
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn is_nullish(&self) -> bool
pub fn is_nullish(&self) -> bool
Whether self is undefined or null: Unpacked::is_nullish over
one unpack of a clone. A caller that already holds the Unpacked asks
it instead and keeps its single conversion.
Sourcepub fn defined(self) -> Option<Self>
pub fn defined(self) -> Option<Self>
None for undefined, Some(self) for every other value, null
included: the argument an optional parameter was passed, if it was
passed one. Unpacked::is_undefined over one unpack of a clone.
Sourcepub fn unary_plus(self) -> Result<Any<A>, Any<A>>
pub fn unary_plus(self) -> Result<Any<A>, Any<A>>
Unary plus is nothing but coercion to number. We use unary_plus as ECMAScript unary plus operator, and we use coerce_to_number for internals in places where ECMAScript’s abstract function ToNumber is needed, and also when we need Result<Number, Any> result type; here unary_plus returns Result<Any, Any> to match public API type of unary plus operator. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus https://tc39.es/ecma262/#sec-unary-plus-operator
Sourcepub fn number(self) -> Result<Any<A>, Any<A>>
pub fn number(self) -> Result<Any<A>, Any<A>>
Number(value): ToNumeric of the value, a bigint converted to the
nearest number and anything else as unary_plus has it. They differ in
the bigint alone: +1n throws, Number(1n) is 1.
https://tc39.es/ecma262/#sec-number-constructor-number-value
Sourcepub fn bigint(self) -> Result<Any<A>, Any<A>>
pub fn bigint(self) -> Result<Any<A>, Any<A>>
BigInt(value): ordinary primitive conversion with the number hint,
then an exact integer conversion. This is an operator, not a value.
https://tc39.es/ecma262/#sec-bigint-constructor
Sourcepub fn pow(self, rhs: Self) -> Result<Self, Self>
pub fn pow(self, rhs: Self) -> Result<Self, Self>
**. Not a core::ops trait — Rust has no operator for
exponentiation, so this is a plain method, the same as unary_plus.
Sourcepub fn bitwise_not(self) -> Result<Self, Self>
pub fn bitwise_not(self) -> Result<Self, Self>
~. Not a core::ops trait — Not is already claimed by this
type’s own logical ! (any/not.rs) — so this is a plain method,
the same as unary_plus/pow.
https://tc39.es/ecma262/#sec-bitwise-not-operator
Sourcepub fn unsigned_right_shift(self, rhs: Self) -> Result<Self, Self>
pub fn unsigned_right_shift(self, rhs: Self) -> Result<Self, Self>
>>>. Not a core::ops trait — Rust has no unsigned-right-shift
operator — so this is a plain method, the same as pow/bitwise_not.
https://tc39.es/ecma262/#sec-unsigned-right-shift-operator
Sourcepub fn entry(self, key: Self) -> Result<Self, Self>
pub fn entry(self, key: Self) -> Result<Self, Self>
The entry helper, (a, b) => { const x = Object.getOwnPropertyDescriptor(a, b); return x?.enumerable ? x.value : undefined; }, as a method: the value of the enumerable own property
the key names — an Object’s field (Object::own_property), an
Array’s element or a String’s code unit by its canonical index
string (Array::entry, String::entry) — and undefined for none,
an entry holding undefined included, which Any::has_entry tells
apart, and for nothing a value owns without enumerating it — never a
length, and nothing of a function. No getter invocation and no
prototype chain (nanvm-lib objects have no __proto__ to walk in
the first place). Not a core::ops trait — no Rust operator fits a
keyed property lookup — so this is a plain method, the same as
pow/bitwise_not/unsigned_right_shift.
The receiver is checked before the key is converted
(member_access::non_nullish_receiver), so a nullish receiver
throws regardless of what the key is, and a key whose conversion
throws does so under a receiver that is not. The key converts as
ToPropertyKey converts it, which is to_string here, the language
having no symbols: 0 and "0" name one entry, and an object
converts through its own toString. A Number, Boolean or
BigInt receiver owns no entry and answers undefined, as every
absent key does.
Sourcepub fn has_entry(self, key: Self) -> Result<bool, Self>
pub fn has_entry(self, key: Self) -> Result<bool, Self>
The hasEntry helper: whether the enumerable own property key
names is there, true for an entry holding undefined, which
Any::entry reads as none, the receiver and the key treated as
entry treats them, so a nullish receiver throws and a key converts
first (spec/property-access/entries/README.md).
pub fn to_string(self) -> Result<String<A>, Any<A>>
Sourcepub fn to_string_unused(self) -> Result<(), Any<A>>
pub fn to_string_unused(self) -> Result<(), Any<A>>
ToString where the algorithm discards the result: its throws still
happen, and an object with its own toString is still refused, but a
function’s text, which cannot throw and is never read here, is not
needed — so [].join(f) answers "", as it does in JavaScript
(nanvm/lib/todo/to-primitive.md, Stage 1). An array converts
through its elements alone, since it owns no toString, so a
function inside one is skipped too: [].join([f]) is "".
pub fn to_number(self) -> Result<Number, Any<A>>
Sourcepub fn to_boolean(self) -> bool
pub fn to_boolean(self) -> bool
Never fails, unlike to_number/to_string/to_numeric — ToBoolean
inspects the operand’s type directly and never calls ToPrimitive.
pub fn to_numeric(self) -> Result<Numeric<A>, Any<A>>
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn to_integer_or_infinity(self) -> Result<f64, Any<A>>
pub fn to_integer_or_infinity(self) -> Result<f64, Any<A>>
ToIntegerOrInfinity(ToNumber(self)), the reading every index, count
and position argument starts from. The one throw is ToNumber’s, a
bigint’s TypeError among them.
Source§impl<A: IVm> Any<A>
impl<A: IVm> Any<A>
Sourcepub fn to_primitive(
self,
preferred_type: Option<ToPrimitivePreferredType>,
) -> Result<Primitive<A>, Any<A>>
pub fn to_primitive( self, preferred_type: Option<ToPrimitivePreferredType>, ) -> Result<Primitive<A>, Any<A>>
Coerces the value to a primitive type Primitive<A>, possibly producing an error result.
https://tc39.es/ecma262/#sec-toprimitive
Trait Implementations§
Source§impl<A: IVm> Not for Any<A>
!. Coerces via ToBoolean and negates. Never throws — ToBoolean
itself cannot fail — but stays a Result to match every other
operator’s shape.
https://tc39.es/ecma262/#sec-logical-not-operator
impl<A: IVm> Not for Any<A>
!. Coerces via ToBoolean and negates. Never throws — ToBoolean
itself cannot fail — but stays a Result to match every other
operator’s shape.
https://tc39.es/ecma262/#sec-logical-not-operator