IR.Abs lowering (Lua.hs, the IR.Abs case) computes the body via goExp, which is asExpression <<$>> go. When the body lowers to a chunk rather than a bare expression, for example a Let or an IfThenElse, asExpression wraps it through Lua.chunkToExpression into a niladic IIFE: (function() chunk end)(). Abs then wraps that single expression in Lua.return, producing:
function(params)
return (function()
chunk
end)()
end
removeScopeWhenInsideEmptyFunction in Lua/Optimizer.hs exists specifically to undo this: it matches Function outerArgs [Return (FunctionCall (Function [] body) [])] and rewrites it back to Function outerArgs body. Every lambda whose body is a Let or IfThenElse pays for this wrapping and then immediately pays again to unwrap it.
Proposal: give IR.Abs lowering a chunk-aware path. When the body lowers to Left chunk, emit Lua.functionDef luaParams chunk directly instead of routing it through asExpression/Lua.return. Only fall back to the wrap-and-return form when the body lowers to Right expr. Once nothing produces the wrapped shape, removeScopeWhenInsideEmptyFunction and its spec become dead and can be deleted.
Noticed while implementing #153: same pattern as #146 (a rule that's a symptom of an avoidable encoding introduced during lowering, rather than something that belongs at the AST level).
IR.Abslowering (Lua.hs, theIR.Abscase) computes the body viagoExp, which isasExpression <<$>> go. When the body lowers to a chunk rather than a bare expression, for example aLetor anIfThenElse,asExpressionwraps it throughLua.chunkToExpressioninto a niladic IIFE:(function() chunk end)().Absthen wraps that single expression inLua.return, producing:removeScopeWhenInsideEmptyFunctioninLua/Optimizer.hsexists specifically to undo this: it matchesFunction outerArgs [Return (FunctionCall (Function [] body) [])]and rewrites it back toFunction outerArgs body. Every lambda whose body is aLetorIfThenElsepays for this wrapping and then immediately pays again to unwrap it.Proposal: give
IR.Abslowering a chunk-aware path. When the body lowers toLeft chunk, emitLua.functionDef luaParams chunkdirectly instead of routing it throughasExpression/Lua.return. Only fall back to the wrap-and-return form when the body lowers toRight expr. Once nothing produces the wrapped shape,removeScopeWhenInsideEmptyFunctionand its spec become dead and can be deleted.Noticed while implementing #153: same pattern as #146 (a rule that's a symptom of an avoidable encoding introduced during lowering, rather than something that belongs at the AST level).