ReviewOS

zig-utils/zig-js

Compiler: lower closed primitive default expressions into VM frames

#739
Closed chris opened this 8 days ago ·
8 days ago

Parents: #465, #498 Depends on: #738 Related: #736

Implemented by: 840e24af

Problem

#738 admits source primitive literals, but equally environment-inert closed primitive expression trees remain rejected. Defaults such as -1, 1 + 2, false ? 1 : 2, and void 0 contain no identifier, call, member access, closure, class, object/array/regex creation, or dynamic lookup. Their operations may still allocate internal primitive backing or throw (for example BigInt division by zero), so they must execute normally in the ordered VM prologue rather than be folded or pre-evaluated.

Scope

  • Admit a recursively closed grammar containing primitive literal leaves plus unary, binary, logical, conditional, and sequence expression nodes whose children are all in the same grammar.
  • Evaluate the expression at every call only when the raw argument is exactly undefined, preserving short-circuiting, coercion, abrupt completion, BigInt behavior, and left-to-right entry ordering beside initializer-free patterns.
  • Reuse #738’s exact immutable default-index metadata, unmapped arguments contract, malformed-layout validation, activation roots, and native/quick activation-elision guards.
  • Cover signed Number/BigInt, arithmetic/comparison/bitwise/logical/conditional/sequence/void forms, provided-value bypass, throws/catches, methods/arrows/base constructors, recursion/reentrancy, moving GC, and shared-chunk no-GIL execution.

Identifiers (including source undefined), this, new.target, member/call/new expressions, functions/classes, object/array/regex/template literals, assignment/update/delete, yield/await, imports, and nested pattern expressions remain explicit barriers.

No-workaround rules

  • No constant folding, host evaluation, source rewriting, tree-walker callback, truthiness substitution for undefined, swallowed throw/OOM, broadened grammar by a permissive default arm, or alternate metadata path.
  • A newly added AST expression kind remains rejected until it receives an explicit semantic ruling.
  • No stacks, queues, jobs, Promise, microtask, Worker lifecycle, or Map/Set iterator changes.

Acceptance

  • Compiler tests prove every accepted recursive node family and stable rejection for every excluded family/rest mixture.
  • Forced tree-walker and required bytecode agree on values, short-circuiting, abrupt completion, bypass, ordering, arguments, constructors/methods/arrows, recursion/reentrancy, and moving GC.
  • Shared-chunk no-GIL/TSan and internal-allocation OOM witnesses remain exact.
  • Full units, focused compiler/frontend/VM, threadfuzz, and exact nonzero Test262 default-parameter accounting pass with zero regressions.
  • Conventional commit lands directly on main and cross-links #465, #498, #738, and #736.
8 days ago

Landed on main as feat(compiler): lower closed default expressions (#739). Closed primitive unary, binary, logical, conditional, and sequence defaults now execute in the ordered VM parameter prologue only for raw undefined; observable environment/allocation/mutation forms and rest mixtures remain explicit barriers. There is no constant folding or tree-walker callback.

Verification on the landed tree: full units 1,879 passed / 1 skipped / 0 failed / 0 leaked; focused frontend 18/18; compiler, VM/OOM, semantic parity, and shared no-GIL witnesses pass normally and under TSan; deterministic threadfuzz is 400/0 in default and TSan profiles. Exact nonzero Test262 default-parameter accounting is byte-identical at 10,296 → 10,296 across function expressions/statements, arrows, object methods, class expressions/statements, and the Function constructor.

8 days ago

All acceptance criteria are complete on main; closing as implemented.

8 days ago

Follow-up #740 is complete in feat(compiler): lower invocation defaults (#740), extending the same exact default-index prologue to whole invocation-context leaves without broadening #739’s recursive primitive grammar.

8 days ago

#741 is complete in feat(compiler): lower earlier parameter defaults (#741). It adds a separate exact earlier-binding leaf rule without broadening #739’s recursive closed-primitive grammar.

8 days ago

The follow-on composition issue #742 has landed on main in 54c54afe, reusing this issue's proven leaf semantics inside a fail-closed recursive expression grammar. Test262 remained byte-identical at 10296 -> 10296; full units, TSan, shared no-GIL, allocation-failure restoration, and 400-iteration default/TSan threadfuzz all passed.

8 days ago

The follow-on public property-read slice #743 has landed on main in 1b7e8e58, composing this issue's proven parameter-default semantics through canonical named/computed [[Get]]. Test262 remained byte-identical at 10296 -> 10296; full units, TSan, shared no-GIL, getter-OOM restoration, and default/TSan threadfuzz all passed.

8 days ago

The follow-on parameter-local call slice #744 has landed on main in 402e805a, composing this issue's proven defaults through canonical value and receiver-preserving call opcodes. Test262 remained byte-identical at 10296 -> 10296; full units, TSan, shared no-GIL, nested-call OOM restoration, and default/TSan threadfuzz all passed.

8 days ago

Follow-up #745 landed on main as feat(compiler): lower parameter construction defaults (#745). It composes the parameter-safe value/property/call grammar into canonical non-spread new_call lowering, remains fail-closed for unsupported forms, and records 10,296 -> 10,296 exact relevant Test262 cases with 0 flips. Derived and field-initializing constructor activations are separated into #746.

Sign in to comment on this issue.