The tagged runtime representation of every JS value produced by the engine.
Int32 is the "fast path" for small integers that the JS spec still models
as Number(Double); the VM promotes to Number on overflow or non-integer
results. Bit operations (|, &, <<, >>>, ...) always land back in
Int32 per ES ToInt32 / ToUint32. This step (M1 Step 2) only defines
the representation — the arithmetic promotion rules live in the VM
(Step 8) and are intentionally not implemented here.
Str uses MoonBit String, which is already UTF-16 code units and matches
JS string semantics directly (s[i] gives a UInt16 charcode).
Object holds a heap-shared ObjectRef. ObjectRef and ShapeRef alias
their underlying structs rather than wrapping them in @ref.Ref: MoonBit
structs with mutable fields already have reference semantics (mutation
through any alias is visible through every alias), so the extra Ref
indirection design.md sketched would be pure overhead. This deviation is
noted in the design deviations section of the check report.
Equality is implemented manually rather than derived: primitives use
structural equality but Object requires identity (physical_equal) to
match JS === semantics for objects. Int32 and Number are treated as
distinct variants (never equal to each other) at this layer — the VM will
add ES Abstract Equality and Strict Equality conversions in Step 8.
The Function(Function) variant (added in M1 Step 8b1) is treated like
Object for equality: two distinct Function values with identical
chunk / upvalues are NOT equal — only same-reference is equal — matching
JS === on function values.
NativeFn(NativeFunction) (added in M1 Step 9) carries a MoonBit-defined
callable — Object / Error / TypeError / … constructors and any
other builtin function fall into this variant. Same physical-equality
rule as Function.