Skip to content

Fold a field projection through a foreign-header scope IIFE #159

Description

@Unisay

Golden.CharLiterals.Test's golden.lua (after #153) still contains this shape for Data.Eq.eqChar's foreign import, which declares a header (a local refEq = ... helper) alongside its exports:

((function()
  local refEq = function(r1) return function(r2) return r1 == r2 end end
  return { eqCharImpl = refEq }
end)()).eqCharImpl

A ForeignImport with a header lowers to a chunk ([ForeignSourceStat fh, return exportsTable]), and any projection into one of its fields, ObjectProp (ForeignImport ...) prop in the IR, lowers through asExpression's chunkToExpression into a call whose result is immediately projected: (function() ...; return exportsTable end)().prop.

Neither the IR rule reduceObjectProp (#153) nor the Lua-AST rule reduceTableDefinitionAccessor sees through this, because the projected value is a function call, not a table constructor, at either level.

The rewrite is sound and general: for Var (VarField (FunctionCall (Function [] body) []) prop), if the last statement of body is Return e, replacing it with Return (varField e prop) and keeping the leading statements ahead of it unchanged is equivalent. Projecting the field after the call returns versus before it returns is the same value, and no side effect crosses the call boundary since both happen within the same activation.

This only helps when a single field of a multi-export header is projected at a given call site; the header's other locals still get evaluated once per call site either way, same as today. That's an existing cost, not one this rewrite introduces.

Found while implementing #153 (Golden.CharLiterals.Test, the Data.Eq.eqChar foreign import).

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions