You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ordering constraint: the pipeline comment states magicDo must run after DCE (the statements it introduces for discard look like dead let _ = bindings) and after the optimize fixpoint (the shapes must survive it). Consequently no optimize+dce round can legally run after magicDo — a tax on pipeline evolution that grows with every new pass.
Approach
Recognize bind/pure/discard applications of Effect/ST by qualified name (the Effect.bindEffect dictionary, the pureE/bindE foreigns, their ST counterparts) at CoreFn→IR translation — the same QName-keyed technique as the #178 allowlist — and mark them with dedicated annotations (or normalize to a canonical form). magicDo then consumes marks instead of guessing shapes: a mark lives on the node and survives any rewrite, a "dead" let _ = carrying an effect mark stops being a DCE candidate, and the ordering constraint dissolves — running a fixpoint after magicDo becomes legal.
Design record: first-class Effect in the IR — considered and deferred
The alternative is making Effect structural: EffectBind/EffectPure IR constructors, as purs-backend-es does (together with its UncurriedEffectApp). Deferred because: recognition is symbol-driven either way (CoreFn carries no reliable types, so "this is Effect" is a QName question regardless of representation); the current thunk encoding keeps Effect values pure values, so every optimizer pass stays sound on plain lambda calculus without effect-awareness; and new IR constructors tax every traversal (uniquify, countFreeRefs, alphaEq, linter, DCE, the rewrite driver, lowering).
Revisit conditions: (a) effect-loop fusion becomes a goal — compiling forE/whileE/tailRecM-over-Effect into native loops on top of #181 is shorter with structural effect nodes; (b) magicDo keeps missing chains systematically despite marks, as visible in #172.
Prerequisites / Relations
Independent in the dependency graph — no hard prerequisites. It is an enabler: recognising Effect/ST by qualified name removes the post-DCE / post-fixpoint ordering constraint, so an optimize+dce fixpoint may legally run after magicDo. That restored pipeline freedom is what the #178–#180 inlining series benefits from. Reuses the same QName-keyed recognition as the #178 allowlist. Relates to #172, which would carry the miss counter (and is also the trigger for revisit condition (b) above).
Verification / Measurement
#172 tracks a magicDo-miss counter on the goldens as a smoke check: zero Effect chains left in thunk form.
Problem
Two layers.
discardlook like deadlet _ =bindings) and after the optimize fixpoint (the shapes must survive it). Consequently no optimize+dce round can legally run after magicDo — a tax on pipeline evolution that grows with every new pass.Approach
Recognize
bind/pure/discardapplications of Effect/ST by qualified name (theEffect.bindEffectdictionary, thepureE/bindEforeigns, their ST counterparts) at CoreFn→IR translation — the same QName-keyed technique as the #178 allowlist — and mark them with dedicated annotations (or normalize to a canonical form). magicDo then consumes marks instead of guessing shapes: a mark lives on the node and survives any rewrite, a "dead"let _ =carrying an effect mark stops being a DCE candidate, and the ordering constraint dissolves — running a fixpoint after magicDo becomes legal.Design record: first-class Effect in the IR — considered and deferred
The alternative is making Effect structural:
EffectBind/EffectPureIR constructors, as purs-backend-es does (together with itsUncurriedEffectApp). Deferred because: recognition is symbol-driven either way (CoreFn carries no reliable types, so "this is Effect" is a QName question regardless of representation); the current thunk encoding keeps Effect values pure values, so every optimizer pass stays sound on plain lambda calculus without effect-awareness; and new IR constructors tax every traversal (uniquify, countFreeRefs, alphaEq, linter, DCE, the rewrite driver, lowering).Revisit conditions: (a) effect-loop fusion becomes a goal — compiling
forE/whileE/tailRecM-over-Effect into native loops on top of #181 is shorter with structural effect nodes; (b) magicDo keeps missing chains systematically despite marks, as visible in #172.Prerequisites / Relations
Independent in the dependency graph — no hard prerequisites. It is an enabler: recognising Effect/ST by qualified name removes the post-DCE / post-fixpoint ordering constraint, so an optimize+dce fixpoint may legally run after magicDo. That restored pipeline freedom is what the #178–#180 inlining series benefits from. Reuses the same QName-keyed recognition as the #178 allowlist. Relates to #172, which would carry the miss counter (and is also the trigger for revisit condition (b) above).
Verification / Measurement
#172 tracks a magicDo-miss counter on the goldens as a smoke check: zero Effect chains left in thunk form.