Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions changelog.d/20260703_180000_unisay_guc_unique_names.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Changed

- Local names in the IR pipeline follow the global-uniqueness condition
(GUC): a `uniquify` entry pass makes every local binder unique within
its top-level binding, and all later passes keep it that way
(term-duplicating rewrites freshen the binders of each inserted
copy). A local reference resolves to its binder by name alone: the
per-name De Bruijn index is gone from the IR `Ref` node, along with
the per-pass index arithmetic (`shift`/`unshift`, capture-avoiding
substitution, index-keyed DCE scopes) that caused issues #37, #56,
#133 and #134. Generated Lua changes only in the choice of local
variable names; behaviour is unchanged (#139).

- The `--lint-ir` flag (and the always-on test-suite checks) verify the
new `UniqueBinders` invariant at every pass boundary in addition to
well-scopedness (#139).
22 changes: 5 additions & 17 deletions exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import Data.Tagged (Tagged (..))
import Language.PureScript.Backend (CompilationResult (..))
import Language.PureScript.Backend qualified as Backend
import Language.PureScript.Backend.IR qualified as IR
import Language.PureScript.Backend.IR.Pass (PassCheckFailure (..))
import Language.PureScript.Backend.IR.Pass
( PassCheckFailure
, renderPassCheckFailure
)
import Language.PureScript.Backend.Lua qualified as Lua
import Language.PureScript.Backend.Lua.Printer qualified as Printer
import Language.PureScript.Backend.Lua.Run qualified as Run
Expand Down Expand Up @@ -119,28 +122,13 @@ handlePassCheckFailure
∷ ExceptT (Oops.Variant (PassCheckFailure ': e)) IO a
→ ExceptT (Oops.Variant e) IO a
handlePassCheckFailure =
Oops.catch \PassCheckFailure {failedPassName, failedPhase, failedViolations} →
die . toString . unlines $
[ "IR invariants violated "
<> show failedPhase
<> " optimizer pass "
<> failedPassName
<> ":"
]
<> (show <$> toList failedViolations)
Oops.catch (die . toString . renderPassCheckFailure)

handleLuaError
∷ ExceptT (Oops.Variant (Lua.Error ': e)) IO a
→ ExceptT (Oops.Variant e) IO a
handleLuaError =
Oops.catch \case
Lua.UnexpectedRefBound modname expr →
die . toString . unwords $
[ "Unexpected bound reference:"
, show expr
, "in module"
, runModuleName modname
]
Lua.LinkerErrorForeign e →
die $ "Linker error:\n" <> show e
Lua.AppEntryPointNotFound modname ident →
Expand Down
Loading
Loading