ReviewOS

zig-utils/zig-js

Compiler: lower primitive-literal default parameters into VM frames

#738
Closed chris opened this 9 days ago ·
9 days ago

Parents: #465, #498 Related: #735, #736

Implemented by d95aaf63.

Problem

Every ordinary function with a top-level default formal is still rejected as plain_rejected_parameter_prologue, including primitive-literal Initializers whose separate parameter/body Environment is not observable: they create no closure, perform no name lookup/call, expose no user object, and cannot abruptly complete through user code. BigInt's internal cell allocation remains a real OOM edge and must unwind normally. The VM already has exact raw activation inputs, non-simple arguments metadata, native frame stores, and ordered destructuring entry prologues; the remaining work for this exact grammar is undefined selection and immutable metadata validation.

Scope

  • Admit top-level default Initializers only for the exact source primitive literal nodes: Number, BigInt, String, Boolean, and Null. A source identifier spelled undefined remains expression-bearing because lexical shadowing is observable.
  • Permit those defaults beside simple parameters and initializer-free array/object patterns, executing every pattern/default entry operation strictly left-to-right.
  • Record sorted default-formal indices in immutable Chunk metadata and validate them exactly against the Function AST before activation execution.
  • Preserve provided-null/provided-falsy bypass, missing/undefined substitution, function length, unmapped non-simple arguments with poison callee, body var/function collision behavior, closures created in the body, recursion/reentrancy, arrows, methods, eligible base constructors, moving GC, and shared-chunk no-GIL execution.
  • Keep named rest mixed with either patterns or defaults behind the explicit entry-order barrier.

Expression-bearing Initializers (including identifiers, calls, member access, unary/binary expressions, function/class/object/array literals, direct eval, this, super, and new.target) remain explicit #465 barriers because their parameter Environment, TDZ, naming, allocation, abrupt completion, or ordering can be observable.

No-workaround rules

  • No tree-walker callback from admitted bytecode, Environment allocation presented as a frame fast path, source rewriting, eager evaluation at compile time, truthiness substitution for exact undefined, guessed metadata, swallowed OOM/throw, or widening beyond the enumerated AST literals.
  • No activation-eliding native/quick kernel may accept the non-simple metadata.
  • No stacks, queues, jobs, Promise, microtask, Worker lifecycle, or Map/Set iterator changes.

Acceptance

  • Compiler tests prove the exact accepted literal grammar, stable rejection for every expression-bearing/default-rest barrier, exact input/binding/default metadata, and no bind_pattern.
  • Forced tree-walker and required bytecode agree on selection, ordering, arguments, collisions/closures, function length, methods/arrows/base constructors, recursion/reentrancy, BigInt OOM, and moving GC.
  • Shared-chunk no-GIL/TSan witnesses preserve immutable metadata and lane-local default selection.
  • 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, #735, and #736.
9 days ago

Completed in d95aaf63 and pushed directly to main.

Evidence:

  • exact Test262 accounting: 10,296 → 10,296 passes with byte-identical diagnostics across full function declaration/expression, arrow, object-method, class declaration/expression, and Function-constructor boundaries; 0 gains/regressions;
  • full Debug units: 1,879 passed, 1 skipped, 0 failed/leaked across 1,880 tests;
  • compiler 87/87, frontend 17/17, VM 4/4;
  • semantic, BigInt OOM/malformed-metadata, shared-chunk no-GIL, and activation-elision witnesses pass normally and under TSan;
  • default and TSan threadfuzz: 400 seeded programs each, 0 failures.

Only Number, BigInt, String, Boolean, Null, and internal synthetic undefined literal nodes are admitted. A source identifier spelled undefined, every expression-bearing Initializer, nested pattern expression, and every rest mixture remains an explicit fail-closed #465 barrier. No stacks, queues, jobs, Promise, microtask, Worker lifecycle, or Map/Set iterator surfaces changed.

9 days ago

Follow-up #739 is complete in feat(compiler): lower closed default expressions (#739), extending #738’s exact default-index frame machinery from primitive leaves to recursively closed primitive expression trees without constant folding.

9 days ago

#741 extends #738’s ordered default-index machinery in feat(compiler): lower earlier parameter defaults (#741): a later bare reference can read an earlier initialized formal, with self/later/outer references still blocked.

Sign in to comment on this issue.