Commit Graph
6 Commits
Author SHA1 Message Date
Chris Tate c7c8f5d45e Run lone array callbacks as loops with their bodies inlined 2026-10-23 09:25:07 -05:00
Chris Tate 79684d0ef4 Name lowered helpers and closures independently of lowering order
Lowering named helpers by the size of their registry at first use
(%union.retag.N, %arr.map.N, ...), lifted closures and optional-chain
locals by compiler-wide counters (%fnN, chain.N), generic instances by
their instance count, and records and unions by creation order (rN, uN).
Class expressions, mixin instances, function-local generics, non-exported
namespace segments and some module globals carried the byte offset of their
declaration. A name therefore depended on which unit lowered first and on
the positions of unrelated code.

Helpers, instances, records and unions are now named by a hash of the key
they are interned by (keyedHelperName). Closures and optional-chain ids are
named by their lowering unit, their structural position and a count per
key within the unit. Offset-based names use the structural position: the
chain of enclosing named declarations (each with its kind, name and
ordinal) and the node's ordinal among same-kind nodes inside the nearest
one, so an edit outside that declaration leaves the name unchanged.
Interfaces and type aliases anchor the positions inside them, and default
library files are named by their base name, so tsgo and tsc-ts, which
install them in different directories, give the same positions.

Recursive record and union placeholders are named by the printed type, the
structural position of the declaration and the same for up to three levels
of type arguments; a description that two types still share gets a
numbered suffix for the later one. A generic class instance keyed by a
literal type argument is named by the literal's text or the argument's
description instead of its checker type id. Two different keys with the
same name throw an InternalCompilerError.

The SC6101 performance warning recognizes the new closure names
(fn.<hash>, with _<name> for a named function expression) and lists the
functions that rank alike in source order. The module lists its records
and unions by id. The generated program is unchanged apart from these
names and that order, and test:lowering-order now fails on any name
difference.
2026-10-22 03:44:38 -05:00
Chris Tate 777bfb43f2 Revert "Name lowered helpers and closures independently of lowering order"
This reverts #1750 (05e2f404d), which made main CI fail.
2026-10-22 01:40:17 -05:00
Chris Tate 61f1329b32 Name lowered helpers and closures independently of lowering order
Lowering named helpers by the size of their registry at first use
(%union.retag.N, %arr.map.N, ...), lifted closures and optional-chain
locals by compiler-wide counters (%fnN, chain.N), generic instances by
their instance count, and records and unions by creation order (rN, uN).
Class expressions, mixin instances, function-local generics, non-exported
namespace segments and some module globals carried the byte offset of their
declaration. A name therefore depended on which unit lowered first and on
the positions of unrelated code.

Helpers, instances, records and unions are now named by a hash of the key
they are interned by (keyedHelperName), and recursive records and unions by
their printed type and declaration. Closures and optional-chain ids are
named by their lowering unit, their structural position and a count per
key within the unit. Offset-based names use the structural position: the
chain of enclosing named declarations and the node's ordinal among
same-kind nodes inside the nearest one, so an edit outside that
declaration leaves the name unchanged. Two different keys with the same
name throw an InternalCompilerError. The module lists its records and
unions by id. The generated program is unchanged apart from these names
and that order, and test:lowering-order now fails on any name difference.
2026-10-21 23:26:29 -05:00
Chris Tate 3b5e233618 Lower to the same IR whatever order reachable bodies lower in 2026-10-21 20:28:16 -05:00
Chris Tate 29f21ffeca Evaluate a %f boolean or unit argument without lowering it twice
The util.format %f branch for boolean and unit arguments discarded the
lowered value and lowered the argument node again as a statement, so
anything lowering builds for the argument (lifted array helpers,
closures) was built twice, one copy dead. It now evaluates the value it
already lowered as a statement, and drops it when evaluating it has no
observable effect.

The same branch now also covers void calls and null | undefined unions,
which Node formats as NaN like undefined and null; they were refused.
2026-10-15 21:58:33 -05:00