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).
Golden.CharLiterals.Test's golden.lua (after #153) still contains this shape forData.Eq.eqChar's foreign import, which declares aheader(alocal refEq = ...helper) alongside its exports:A
ForeignImportwith a header lowers to a chunk ([ForeignSourceStat fh, return exportsTable]), and any projection into one of its fields,ObjectProp (ForeignImport ...) propin the IR, lowers throughasExpression'schunkToExpressioninto a call whose result is immediately projected:(function() ...; return exportsTable end)().prop.Neither the IR rule
reduceObjectProp(#153) nor the Lua-AST rulereduceTableDefinitionAccessorsees 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 ofbodyisReturn e, replacing it withReturn (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, theData.Eq.eqCharforeign import).