Skip to content

Fold record-literal projection in the IR, not on the Lua AST #153

Description

@Unisay

The Lua optimizer rule reduceTableDefinitionAccessor (added in #140) folds a field access into a table literal, rewriting { foo = 1, bar = 2 }.foo to 1. It fires only when the constructor is unambiguous: every row must be name-value (all isNameValue) and no field name may repeat. Both guards are there because the Lua table constructor is ambiguous at that level. A key-value row can carry an arbitrary expression key (["foo"] = …, [k] = …) that a name-keyed lookup cannot see, string and number keys coerce, and a repeated key resolves to the last assignment while a first-match fold would return the earliest.

None of that ambiguity exists one layer up, in the IR. LiteralObject carries [(PropName, Exp)], where PropName is a static label with no computed-key form, and PureScript's type system already forbids duplicate labels in a record literal. The optimizer assumes well-typed IR anyway (see Note [IR is assumed well-typed]). So the equivalent IR rewrite needs no guards at all:

ObjectProp _ (LiteralObject _ props) prop  ->  lookup prop props

Doing the fold in the IR is also better placed than the Lua-AST version:

  • It runs inside the optimize+dce fixpoint, so the folded value feeds straight back into constant folding, inlining, and dead-code elimination.
  • It has a live trigger. LiteralObject is a non-recursive literal, so inlineLocalBindings inlines let r = { foo: 1, bar: 2 } in r.foo into the projection site, producing ObjectProp (LiteralObject …) foo mid-fixpoint. That is created by the inliner on ordinary code, not a rare source shape.
  • It shrinks the IR before magicDo, flatten-deep-binds, and lowering, so the emitted Lua is already clean.

Proposal:

  • Add the rewrite (e.g. reduceObjectProp) to the rule chain in optimizedExpressionM.
  • Delete the Lua-AST reduceTableDefinitionAccessor and its spec as superseded. This supersedes the guard added in reduceTableDefinitionAccessor ignores TableRowKV rows and duplicate fields (folds to Nil) #140; that hardening was correct while the rule lived on the Lua AST.
  • Optionally handle ObjectProp (ObjectUpdate obj patches) prop: if prop is among the patches use the patched value, otherwise recurse into obj.

Evaluation order: the fold drops the evaluation of the discarded fields (bar above). That is the same move the current Lua-AST rule already makes, and it is consistent with the project's policy that DCE drops unused bindings unconditionally. The eval goldens remain the semantic oracle.

Found while reviewing the #140 guard: the guards are a symptom of doing a high-level, semantic optimization at the wrong altitude.

Metadata

Metadata

Assignees

Labels

area: irIR / optimizer / DCE / inlinerenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions