diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..259d2fc --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,31 @@ +name: Purescript Lua CI +on: + pull_request: +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: "📥 Checkout repository" + uses: actions/checkout@v3 + + - name: "❄ Install Nix" + uses: cachix/install-nix-action@v22 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + substituters = https://hydra.iohk.io https://cache.nixos.org/ + trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + + - uses: cachix/cachix-action@v12 + with: + name: purescript-lua + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + + - name: "🔨 Build & test" + run: >- + nix develop + --accept-flake-config + --allow-import-from-derivation + --command + cabal test all --test-show-details=direct diff --git a/lib/Language/PureScript/Backend/IR/DCE.hs b/lib/Language/PureScript/Backend/IR/DCE.hs index c6c5045..39ae031 100644 --- a/lib/Language/PureScript/Backend/IR/DCE.hs +++ b/lib/Language/PureScript/Backend/IR/DCE.hs @@ -19,17 +19,17 @@ import Language.PureScript.Backend.IR.Types , RawExp (..) , RewriteMod (..) , Rewritten (..) - , bindingNames + , annotateExpM + , groupingNames , listGrouping , rewriteExpTopDown ) import Language.PureScript.Names (ModuleName) -import Shower (shower) data EntryPoint = EntryPoint ModuleName [Name] deriving stock (Show) -deriving stock instance Show AExp +-- deriving stock instance Show AExp eliminateDeadCode ∷ UberModule → UberModule eliminateDeadCode uber@UberModule {..} = @@ -71,9 +71,9 @@ eliminateDeadCode uber@UberModule {..} = annotatedBindings ∷ [Grouping (Id, QName, AExp)] (annotatedExports, annotatedBindings) = runAnnM do annExports ← forM uberModuleExports \(name, expr) → - (,name,) <$> nextId <*> annotateExp expr + (,name,) <$> nextId <*> annotateExpWithIds expr annBindings ← forM uberModuleBindings $ traverse \(qname, expr) → - (,qname,) <$> nextId <*> annotateExp expr + (,qname,) <$> nextId <*> annotateExpWithIds expr pure (annExports, annBindings) dceAnnotatedExp ∷ AExp → Exp @@ -201,7 +201,7 @@ eliminateDeadCode uber@UberModule {..} = adjacencyListForExpr scope' body <> snd (foldl' adjacencyListForGrouping (scope, mempty) groupings) where - scope' = foldr addToScope scope (bindingNames =<< toList groupings) + scope' = foldr addToScope scope (groupingNames =<< toList groupings) addToScope (nameId, name) = addLocalToScope nameId name 0 where adjacencyListForGrouping @@ -288,39 +288,9 @@ nextId = AnnM do runAnnM ∷ AnnM a → a runAnnM = (`evalState` 0) . unAnnM -annotateExp ∷ Exp → AnnM AExp -annotateExp = \case - LiteralInt i → pure $ LiteralInt i - LiteralFloat f → pure $ LiteralFloat f - LiteralString s → pure $ LiteralString s - LiteralChar c → pure $ LiteralChar c - LiteralBool b → pure $ LiteralBool b - LiteralArray as → LiteralArray <$> traverse ann as - LiteralObject ps → LiteralObject <$> traverse (traverse ann) ps - ReflectCtor a → ReflectCtor <$> ann a - Eq a b → Eq <$> ann a <*> ann b - DataArgumentByIndex index a → DataArgumentByIndex index <$> ann a - ArrayLength a → ArrayLength <$> ann a - ArrayIndex a index → flip ArrayIndex index <$> ann a - ObjectProp a prop → flip ObjectProp prop <$> ann a - ObjectUpdate a ps → ObjectUpdate <$> ann a <*> traverse (traverse ann) ps - Abs param body → Abs <$> ann_ param <*> ann body - App a b → App <$> ann a <*> ann b - Ref qname index → pure $ Ref qname index - Let binds body → - Let - <$> traverse (traverse (bitraverse ann_ ann)) binds - <*> ann body - IfThenElse i t e → IfThenElse <$> ann i <*> ann t <*> ann e - Ctor aty ty ctor fs → pure $ Ctor aty ty ctor fs - Exception m → pure $ Exception m - ForeignImport m p → pure $ ForeignImport m p - where - ann ∷ Annotated Identity RawExp → AnnM (Id, AExp) - ann = liftA2 (,) nextId . annotateExp . runIdentity - - ann_ ∷ Identity a → AnnM (Id, a) - ann_ p = (,runIdentity p) <$> nextId +annotateExpWithIds ∷ Exp → AnnM (RawExp ((,) Id)) +annotateExpWithIds = + annotateExpM identity (const nextId) (const nextId) (const nextId) deannotateExp ∷ AExp → Exp deannotateExp = \case diff --git a/lib/Language/PureScript/Backend/IR/Linker.hs b/lib/Language/PureScript/Backend/IR/Linker.hs index c3ad9a6..7d74a6d 100644 --- a/lib/Language/PureScript/Backend/IR/Linker.hs +++ b/lib/Language/PureScript/Backend/IR/Linker.hs @@ -13,7 +13,7 @@ import Language.PureScript.Backend.IR.Types , QName (QName) , Qualified (Imported, Local) , RawExp (..) - , bindingNames + , groupingNames , objectProp , ref , refImported @@ -92,7 +92,7 @@ qualifiedModuleBindings Module {moduleName, moduleBindings, moduleForeigns} = qualifyBinding = bimap (QName moduleName) (qualifyTopRefs moduleName topRefs) where topRefs ∷ Map Name Index = Map.fromList do - (,0) <$> ((moduleBindings >>= bindingNames) <> moduleForeigns) + (,0) <$> ((moduleBindings >>= groupingNames) <> moduleForeigns) qualifyTopRefs ∷ ModuleName → Map Name Index → Exp → Exp qualifyTopRefs moduleName = go @@ -127,7 +127,7 @@ qualifyTopRefs moduleName = go qualifyBody = go topNames' where topNames' = foldr (Map.adjust (+ 1) . unAnn) topNames boundNames - boundNames = toList groupings >>= bindingNames + boundNames = toList groupings >>= groupingNames App argument function → App (go' <$> argument) (go' <$> function) LiteralArray as → LiteralArray (go' <<$>> as) LiteralObject props → LiteralObject (fmap go' <<$>> props) diff --git a/lib/Language/PureScript/Backend/IR/Optimizer.hs b/lib/Language/PureScript/Backend/IR/Optimizer.hs index 3b47c3c..f2f7d9f 100644 --- a/lib/Language/PureScript/Backend/IR/Optimizer.hs +++ b/lib/Language/PureScript/Backend/IR/Optimizer.hs @@ -1,8 +1,11 @@ module Language.PureScript.Backend.IR.Optimizer where +import Data.List.NonEmpty qualified as NE import Data.Map qualified as Map +import Data.Set qualified as Set import Language.PureScript.Backend.IR.DCE qualified as DCE import Language.PureScript.Backend.IR.Linker (UberModule (..)) +import Language.PureScript.Backend.IR.Query (collectBoundNames) import Language.PureScript.Backend.IR.Types ( Annotated , Exp @@ -25,9 +28,131 @@ import Language.PureScript.Backend.IR.Types , thenRewrite , unAnn ) +import Language.PureScript.Backend.IR.Types qualified as IR optimizedUberModule ∷ UberModule → UberModule -optimizedUberModule = idempotently $ DCE.eliminateDeadCode . optimizeModule +optimizedUberModule = + renameShadowedNames . idempotently (DCE.eliminateDeadCode . optimizeModule) + +renameShadowedNames ∷ UberModule → UberModule +renameShadowedNames UberModule {..} = + UberModule + { uberModuleBindings = uberModuleBindings' + , uberModuleExports = uberModuleExports' + } + where + uberModuleBindings' ∷ [Grouping (QName, Exp)] = uberModuleBindings + uberModuleExports' ∷ [(Name, Exp)] = + renameShadowedNamesInExpr mempty <<$>> uberModuleExports + +type RenamesInScope = Map Name [Name] + +renameShadowedNamesInExpr ∷ RenamesInScope → RawExp Identity → RawExp Identity +renameShadowedNamesInExpr scope = go + where + go = \case + IR.LiteralInt i → + IR.LiteralInt i + IR.LiteralFloat f → + IR.LiteralFloat f + IR.LiteralString s → + IR.LiteralString s + IR.LiteralChar c → + IR.LiteralChar c + IR.LiteralBool b → + IR.LiteralBool b + IR.LiteralArray as → + IR.LiteralArray (go <<$>> as) + IR.LiteralObject ps → + IR.LiteralObject ((go <$>) <<$>> ps) + IR.ReflectCtor a → + IR.ReflectCtor (go <$> a) + IR.Eq a b → + IR.Eq (go <$> a) (go <$> b) + IR.DataArgumentByIndex index a → + IR.DataArgumentByIndex index (go <$> a) + IR.ArrayLength a → + IR.ArrayLength (go <$> a) + IR.ArrayIndex a index → + IR.ArrayIndex (go <$> a) index + IR.ObjectProp a prop → + IR.ObjectProp (go <$> a) prop + IR.ObjectUpdate a ps → + IR.ObjectUpdate (go <$> a) ((go <$>) <<$>> ps) + IR.Abs param body → + IR.Abs param' (renameShadowedNamesInExpr scope' <$> body) + where + (param', scope') = + case IR.unAnn param of + IR.ParamUnused → + (param, scope) + IR.ParamNamed name → + first + (pure . IR.ParamNamed) + (withScopedName (IR.unAnn body) scope name) + IR.App a b → + IR.App (go <$> a) (go <$> b) + IR.Ref qname index → + case qname of + IR.Local lname + | Just renames ← Map.lookup lname scope + , Just rename ← renames !!? fromIntegral (IR.unIndex index) → + IR.Ref (IR.Local rename) 0 + _ → IR.Ref qname index + IR.Let binds body → + IR.Let (NE.fromList (reverse binds')) body' + where + scope' ∷ RenamesInScope + binds' ∷ [Grouping (Identity Name, Identity Exp)] + (scope', binds') = foldl' f (scope, []) (toList binds) + f + ∷ (RenamesInScope, [Grouping (Identity Name, Identity Exp)]) + → Grouping (Identity Name, Identity Exp) + → (RenamesInScope, [Grouping (Identity Name, Identity Exp)]) + f (sc, bs) = \case + Standalone (IR.unAnn → name, expr) → + withScopedName (IR.unAnn expr) sc name & \(name', sc') → + let expr' = renameShadowedNamesInExpr sc <$> expr + in (sc', Standalone (pure name', expr') : bs) + RecursiveGroup (toList → recGroup) → + (: bs) . RecursiveGroup . NE.fromList <$> foldl' g (sc, []) recGroup + where + g + ∷ (RenamesInScope, [(Identity Name, Identity Exp)]) + → (Identity Name, Identity Exp) + → (RenamesInScope, [(Identity Name, Identity Exp)]) + g (sc', recBinds) (IR.unAnn → name, expr) = + withScopedName (IR.unAnn expr) sc' name & \(name', sc'') → + let expr' = renameShadowedNamesInExpr sc' <$> expr + in (sc'', (pure name', expr') : recBinds) + body' = renameShadowedNamesInExpr scope' <$> body + IR.IfThenElse i t e → + IR.IfThenElse (go <$> i) (go <$> t) (go <$> e) + IR.Ctor aty ty ctr fs → + IR.Ctor aty ty ctr fs + IR.Exception m → + IR.Exception m + IR.ForeignImport m p → + IR.ForeignImport m p + where + withScopedName ∷ Exp → Map Name [Name] → Name → (Name, Map Name [Name]) + withScopedName e sc name = case Map.lookup name sc of + Nothing → (name, Map.insert name [name] sc) + Just renames → + ( rename + , Map.insert rename [] $ Map.insert name (rename : renames) sc + ) + where + nextIndex = length renames + usedNames = Map.keysSet sc <> collectBoundNames e + rename = uniqueName usedNames name nextIndex + + uniqueName ∷ Set Name → Name → Int → Name + uniqueName usedNames n i = + let nextName = Name (nameToText n <> show i) + in if Set.member nextName usedNames + then uniqueName usedNames n (i + 1) + else nextName idempotently ∷ Eq a ⇒ (a → a) → a → a idempotently = fix $ \i f a → @@ -43,7 +168,6 @@ optimizeModule UberModule {..} = UberModule { uberModuleBindings = uberModuleBindings' , uberModuleExports = uberModuleExports' - , .. } where (uberModuleBindings', uberModuleExports') = diff --git a/lib/Language/PureScript/Backend/IR/Query.hs b/lib/Language/PureScript/Backend/IR/Query.hs index 6cf5799..18da18e 100644 --- a/lib/Language/PureScript/Backend/IR/Query.hs +++ b/lib/Language/PureScript/Backend/IR/Query.hs @@ -1,6 +1,8 @@ module Language.PureScript.Backend.IR.Query where +import Control.Monad.Trans.Accum (Accum, add, execAccum) import Data.Map qualified as Map +import Data.Set qualified as Set import Language.PureScript.Backend.IR.Linker (UberModule (..)) import Language.PureScript.Backend.IR.Types ( Exp @@ -8,8 +10,11 @@ import Language.PureScript.Backend.IR.Types , Qualified (..) , countFreeRef , countFreeRefs + , groupingNames , listGrouping + , traverseExpBottomUp ) +import Language.PureScript.Backend.IR.Types qualified as IR import Language.PureScript.Names (runModuleName) usesRuntimeLazy ∷ UberModule → Bool @@ -37,3 +42,18 @@ findPrimModuleInExpr expr = Map.keys (countFreeRefs expr) & any \case Local _name → False Imported moduleName _name → runModuleName moduleName == "Prim" + +collectBoundNames ∷ Exp → Set Name +collectBoundNames = + (`execAccum` Set.empty) . traverseExpBottomUp @_ @(Accum (Set Name)) \e → + case e of + IR.Abs (IR.unAnn → IR.ParamNamed name) _body → + e <$ add (Set.singleton name) + IR.Let groupings _body → + e <$ add do + Set.fromList + [ IR.unAnn iname + | grouping ← toList groupings + , iname ← groupingNames grouping + ] + _ → pure e diff --git a/lib/Language/PureScript/Backend/IR/Types.hs b/lib/Language/PureScript/Backend/IR/Types.hs index a72d598..69016ea 100644 --- a/lib/Language/PureScript/Backend/IR/Types.hs +++ b/lib/Language/PureScript/Backend/IR/Types.hs @@ -32,8 +32,8 @@ listGrouping = \case Standalone a → [a] RecursiveGroup as → toList as -bindingNames ∷ Grouping (name, exp) → [name] -bindingNames = fmap fst . listGrouping +groupingNames ∷ Grouping (name, exp) → [name] +groupingNames = fmap fst . listGrouping bindingExprs ∷ Grouping (name, Exp) → [Exp] bindingExprs = fmap snd . listGrouping @@ -187,7 +187,8 @@ abstraction p e = Abs (pure p) (pure e) identity ∷ Exp identity = abstraction (ParamNamed name) (refLocal name 0) where name = Name "x" -lets ∷ Applicative n ⇒ NonEmpty (Grouping (Name, RawExp n)) → RawExp n → RawExp n +lets + ∷ Applicative n ⇒ NonEmpty (Grouping (Name, RawExp n)) → RawExp n → RawExp n lets binds body = Let (bimap pure pure <<$>> binds) (pure body) application ∷ Applicative n ⇒ RawExp n → RawExp n → RawExp n @@ -281,12 +282,57 @@ literalObject ps = LiteralObject (pure <<$>> ps) -------------------------------------------------------------------------------- -- Traversals ------------------------------------------------------------------ +annotateExpM + ∷ ∀ b m + . Applicative m + ⇒ (∀ x. m x → m x) + → (RawExp Identity → m b) + → (Parameter → m b) + → (Name → m b) + → (RawExp Identity → m (RawExp ((,) b))) +annotateExpM around annotateExp annotateParam annotateName = + around . \case + LiteralInt i → pure $ LiteralInt i + LiteralFloat f → pure $ LiteralFloat f + LiteralString s → pure $ LiteralString s + LiteralChar c → pure $ LiteralChar c + LiteralBool b → pure $ LiteralBool b + LiteralArray as → LiteralArray <$> traverse ann as + LiteralObject ps → LiteralObject <$> traverse (traverse ann) ps + ReflectCtor a → ReflectCtor <$> ann a + Eq a b → Eq <$> ann a <*> ann b + DataArgumentByIndex index a → DataArgumentByIndex index <$> ann a + ArrayLength a → ArrayLength <$> ann a + ArrayIndex a index → flip ArrayIndex index <$> ann a + ObjectProp a prop → flip ObjectProp prop <$> ann a + ObjectUpdate a ps → ObjectUpdate <$> ann a <*> traverse (traverse ann) ps + Abs param body → Abs <$> annParam param <*> ann body + App a b → App <$> ann a <*> ann b + Ref qname index → pure $ Ref qname index + Let binds body → + Let <$> traverse (traverse (bitraverse annLetName ann)) binds <*> ann body + IfThenElse i t e → IfThenElse <$> ann i <*> ann t <*> ann e + Ctor aty ty ctr fs → pure $ Ctor aty ty ctr fs + Exception m → pure $ Exception m + ForeignImport m p → pure $ ForeignImport m p + where + ann ∷ Identity (RawExp Identity) → m (b, RawExp ((,) b)) + ann (unAnn → expr) = + (,) + <$> annotateExp expr + <*> annotateExpM around annotateExp annotateParam annotateName expr + + annParam ∷ Identity Parameter → m (b, Parameter) + annParam (unAnn → param) = (,param) <$> annotateParam param + + annLetName ∷ Identity Name → m (b, Name) + annLetName (unAnn → name) = (,name) <$> annotateName name + traverseExpBottomUp ∷ ∀ n m . (Monad m, Traversable n) ⇒ (RawExp n → m (RawExp n)) - → RawExp n - → m (RawExp n) + → (RawExp n → m (RawExp n)) traverseExpBottomUp visit = go where go ∷ RawExp n → m (RawExp n) @@ -436,7 +482,7 @@ countFreeRefs = fmap getSum . MMap.toMap . countFreeRefs' mempty where minIndexes' = foldr (\name → Map.insertWith (+) name 1) minIndexes $ - toList binds >>= fmap (Local . runIdentity) . bindingNames + toList binds >>= fmap (Local . runIdentity) . groupingNames countsInBinds = toList binds >>= \case Standalone (unAnn → boundName, expr) → @@ -548,7 +594,7 @@ substitute name idx replacement = substitute' idx boundNames = runIdentity . fst <$> grouping body' = substitute name index' replacement' <$> body where - boundNames = toList binds >>= fmap runIdentity . bindingNames + boundNames = toList binds >>= fmap runIdentity . groupingNames index' = if name `elem` fmap Local boundNames then index + 1 else index replacement' = foldr (\n r → shift 1 n 0 r) replacement boundNames App argument function → App (go <$> argument) (go <$> function) @@ -619,7 +665,7 @@ shift offset namespace minIndex expression = | otherwise = minIndex body' = shift offset namespace minIndex' <$> body where - boundNames' = toList binds >>= fmap unAnn . bindingNames + boundNames' = toList binds >>= fmap unAnn . groupingNames minIndex' | namespace `elem` boundNames' = minIndex + 1 | otherwise = minIndex diff --git a/lib/Language/PureScript/Backend/Lua.hs b/lib/Language/PureScript/Backend/Lua.hs index 18ee140..2ed346c 100644 --- a/lib/Language/PureScript/Backend/Lua.hs +++ b/lib/Language/PureScript/Backend/Lua.hs @@ -92,6 +92,12 @@ fromQName modname name = qualifyName modname (fromName name) fromName ∷ HasCallStack ⇒ IR.Name → Lua.Name fromName = Name.makeSafe . IR.nameToText +fromNameWithIndex ∷ HasCallStack ⇒ IR.Name → IR.Index → Lua.Name +fromNameWithIndex name (IR.unIndex → index) = + if index == 0 + then fromName name + else Name.makeSafe $ IR.nameToText name <> show index + fromModuleName ∷ ModuleName → Lua.Name fromModuleName = Name.makeSafe . runModuleName @@ -163,14 +169,14 @@ fromExp foreigns topLevelNames modname ir = case ir of e ← go $ IR.unAnn expr a ← go $ IR.unAnn param pure $ Lua.functionCall e [a] - IR.Ref qualifiedName _index → + IR.Ref qualifiedName index → pure case qualifiedName of IR.Local name | topLevelName ← fromQName modname name , Set.member topLevelName topLevelNames → Lua.varName topLevelName IR.Local name → - Lua.varName (fromName name) + Lua.varName (fromNameWithIndex name index) IR.Imported modname' name → Lua.varName (fromQName modname' name) IR.Let bindings bodyExp → do diff --git a/lib/Language/PureScript/Backend/Lua/Optimizer.hs b/lib/Language/PureScript/Backend/Lua/Optimizer.hs index db09b26..7362984 100644 --- a/lib/Language/PureScript/Backend/Lua/Optimizer.hs +++ b/lib/Language/PureScript/Backend/Lua/Optimizer.hs @@ -25,21 +25,7 @@ import Language.PureScript.Backend.Lua.Types qualified as Lua import Prelude hiding (return) optimizeChunk ∷ Chunk → Chunk -optimizeChunk = fmap optimizeStatement >>> inlineTopLevelLocalDefs - -inlineTopLevelLocalDefs ∷ Chunk → Chunk -inlineTopLevelLocalDefs = snd . foldr inlineTopLevelLocalDef mempty - where - inlineTopLevelLocalDef - ∷ Statement - → (Map Lua.Name (Sum Natural), Chunk) - → (Map Lua.Name (Sum Natural), Chunk) - inlineTopLevelLocalDef statement (counts, result) = - case statement of - Local name (Just value) - | Just (Sum 1) ← Map.lookup name counts → - (counts, substituteVarForValue name (Lua.unAnn value) result) - other → (countRefs other <> counts, other : result) +optimizeChunk = fmap optimizeStatement substituteVarForValue ∷ Lua.Name → Exp → Chunk → Chunk substituteVarForValue name inlinee = diff --git a/nix/hix.nix b/nix/hix.nix index cb773ac..779bc5b 100644 --- a/nix/hix.nix +++ b/nix/hix.nix @@ -40,6 +40,7 @@ purescript spago treefmt + upx ]; }; } diff --git a/scripts/prepare_release b/scripts/prepare_release new file mode 100755 index 0000000..65d171a --- /dev/null +++ b/scripts/prepare_release @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +nix build '.#static' +mkdir -p dist +rm -f -- dist/pslua-linux_x86_64.tar.gz +rm -f -- dist/pslua +upx --best ./result/bin/pslua -o ./dist/pslua +rm -rf ./result +tar -czcf dist/pslua-linux_x86_64.tar.gz -C ./dist pslua diff --git a/test/Language/PureScript/Backend/IR/OptimizerSpec.hs b/test/Language/PureScript/Backend/IR/OptimizerSpec.hs index 1ea6ae3..6774837 100644 --- a/test/Language/PureScript/Backend/IR/OptimizerSpec.hs +++ b/test/Language/PureScript/Backend/IR/OptimizerSpec.hs @@ -9,13 +9,16 @@ import Language.PureScript.Backend.IR.Linker qualified as Linker import Language.PureScript.Backend.IR.Optimizer ( optimizedExpression , optimizedUberModule + , renameShadowedNamesInExpr ) import Language.PureScript.Backend.IR.Types ( Exp , Grouping (Standalone) , Module (..) , Name (..) + , Parameter (..) , RawExp (..) + , abstraction , application , eq , ifThenElse @@ -23,6 +26,7 @@ import Language.PureScript.Backend.IR.Types , lets , literalBool , literalInt + , refLocal , refLocal0 ) import Language.PureScript.Names (moduleNameFromString) @@ -102,6 +106,92 @@ spec = describe "IR Optimizer" do annotateShow expected optimizedUberModule original === expected + describe "renames shadowed names" do + test "nested λ-abstractions" do + name ← forAll Gen.name + let + name1 = Name $ nameToText name <> "1" + name2 = Name $ nameToText name <> "2" + name3 = Name $ nameToText name <> "3" + + let original = + abstraction + (ParamNamed name) + ( abstraction + (ParamNamed name) + ( application + (refLocal name 0) + ( abstraction + (ParamNamed name) + ( abstraction + (ParamNamed name1) + ( application + (refLocal name 0) + (refLocal name 2) + ) + ) + ) + ) + ) + + renamed = + abstraction + (ParamNamed name) + ( abstraction + (ParamNamed name2) + ( application + (refLocal name2 0) + ( abstraction + (ParamNamed name3) + ( abstraction + (ParamNamed name1) + ( application + (refLocal name3 0) + (refLocal name 0) + ) + ) + ) + ) + ) + renameShadowedNamesInExpr mempty original === renamed + + test "nested let-bindings" do + nameA ← forAll Gen.name + nameB ← forAll $ mfilter (/= nameA) Gen.name + valueA ← forAll Gen.literalNonRecursiveExp + valueB ← forAll Gen.literalNonRecursiveExp + let original = + lets + (Standalone (nameA, valueA) :| [Standalone (nameB, valueB)]) + ( lets + ( Standalone (nameA, refLocal nameA 0) + :| [Standalone (nameB, refLocal nameB 0)] + ) + ( application + (application (refLocal nameA 0) (refLocal nameA 1)) + (application (refLocal nameB 0) (refLocal nameB 1)) + ) + ) + + nameA1 = Name $ nameToText nameA <> "1" + nameB1 = Name $ nameToText nameB <> "1" + + renamed = + lets + ( Standalone (nameA, valueA) + :| [Standalone (nameB, valueB)] + ) + ( lets + ( Standalone (nameA1, refLocal nameA 0) + :| [Standalone (nameB1, refLocal nameB 0)] + ) + ( application + (application (refLocal nameA1 0) (refLocal nameA 0)) + (application (refLocal nameB1 0) (refLocal nameB 0)) + ) + ) + renameShadowedNamesInExpr mempty original === renamed + -------------------------------------------------------------------------------- -- Helpers --------------------------------------------------------------------- diff --git a/test/ps/golden/Golden/TestNameShadowing.purs b/test/ps/golden/Golden/TestNameShadowing.purs new file mode 100644 index 0000000..04504e3 --- /dev/null +++ b/test/ps/golden/Golden/TestNameShadowing.purs @@ -0,0 +1,15 @@ +module Golden.TestNameShadowing (b, c) where + +a :: Int -> Int +a x = f x 1 + +b :: Int -> Int -> Int +b x x1 = f (f x x1) (a 42) + +c ∷ Int -> Int -> Int +c = \x -> (\y -> \x -> f x y) x + +f :: Int -> Int -> Int +f 1 _ = 1 +f _ 1 = 2 +f _ _ = 3 diff --git a/test/ps/output/Golden.TestCaseStatements/golden.lua b/test/ps/output/Golden.TestCaseStatements/golden.lua index b4b4d05..595e886 100644 --- a/test/ps/output/Golden.TestCaseStatements/golden.lua +++ b/test/ps/output/Golden.TestCaseStatements/golden.lua @@ -1,12 +1,13 @@ +local Golden_TestValues_I_f = function(unused0) return true end return { a = 1, b = "b", c = (function() local v = function(unused1) return 0 end return (function() - if true == (function(unused0) return true end)(2) then + if true == Golden_TestValues_I_f(2) then return (function() - if true == (function(unused0) return true end)(1) then + if true == Golden_TestValues_I_f(1) then return 42 else return v(true) diff --git a/test/ps/output/Golden.TestHelloPrelude/golden.ir b/test/ps/output/Golden.TestHelloPrelude/golden.ir index 6d2c2d7..eb2b277 100644 --- a/test/ps/output/Golden.TestHelloPrelude/golden.ir +++ b/test/ps/output/Golden.TestHelloPrelude/golden.ir @@ -406,7 +406,7 @@ UberModule ( ObjectProp ( Identity ( ForeignImport - ( ModuleName "Data.Unit" ) ".spago/prelude/v6.0.3/src/Data/Unit.purs" + ( ModuleName "Data.Unit" ) ".spago/prelude/v6.0.2/src/Data/Unit.purs" ) ) ( PropName "unit" ) diff --git a/test/ps/output/Golden.TestHelloPrelude/golden.lua b/test/ps/output/Golden.TestHelloPrelude/golden.lua index cbdd003..4b75a62 100644 --- a/test/ps/output/Golden.TestHelloPrelude/golden.lua +++ b/test/ps/output/Golden.TestHelloPrelude/golden.lua @@ -1,196 +1,123 @@ -local Effect_I_monadEffect -local Effect_I_bindEffect -local Effect_I_applicativeEffect -local Effect_I__S___lazy_functorEffect -local Effect_I__S___lazy_applyEffect -Effect_I_monadEffect = { - Applicative0 = function(unused0) return Effect_I_applicativeEffect end, - Bind1 = function(unused1) return Effect_I_bindEffect end -} -Effect_I_bindEffect = { - bind = ((function() - return { - - pureE = function(a) - return function() - return a +local Prim_I_undefined = nil +local _S___runtime_lazy = function(name) + return function(init) + return function() + local state = 0 + local val = nil + if state == 2 then + return val + else + if state == 1 then + return error(name .. " was needed before it finished initializing") + else + state = 1 + val = init() + state = 2 + return val end end + end + end +end +local Effect_I_foreign = (function() + return { - , bindE = function(a) - return function(f) - return function() - return f(a())() - end - end + pureE = function(a) + return function() + return a end + end - , untilE = function(f) + , bindE = function(a) + return function(f) return function() - while not f() do end + return f(a())() end end + end - , whileE = function(f) - return function(a) - return function() - while f() do - a() - end - end - end + , untilE = function(f) + return function() + while not f() do end end + end - , forE = function(lo) - return function(hi) - return function(f) - return function() - for i = lo, hi do - f(i)() - end - end + , whileE = function(f) + return function(a) + return function() + while f() do + a() end end end + end - , foreachE = function(as) + , forE = function(lo) + return function(hi) return function(f) return function() - for i, v in ipairs(as) do - f(v)() + for i = lo, hi do + f(i)() end end end end + end - } - end)()).bindE, - Apply0 = function(unused2) return Effect_I__S___lazy_applyEffect(0) end -} -Effect_I_applicativeEffect = { - pure = ((function() - return { - - pureE = function(a) - return function() - return a - end - end - - , bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end - - , untilE = function(f) + , foreachE = function(as) + return function(f) return function() - while not f() do end - end - end - - , whileE = function(f) - return function(a) - return function() - while f() do - a() - end - end - end - end - - , forE = function(lo) - return function(hi) - return function(f) - return function() - for i = lo, hi do - f(i)() - end - end - end - end - end - - , foreachE = function(as) - return function(f) - return function() - for i, v in ipairs(as) do - f(v)() - end + for i, v in ipairs(as) do + f(v)() end end end + end - } - end)()).pureE, + } +end)() +local Control_Applicative_I_pure = function(dict) return dict.pure end +local Effect_I_monadEffect +local Effect_I_bindEffect +local Effect_I_applicativeEffect +local Effect_I__S___lazy_functorEffect +local Effect_I__S___lazy_applyEffect +Effect_I_monadEffect = { + Applicative0 = function(unused0) return Effect_I_applicativeEffect end, + Bind1 = function(unused1) return Effect_I_bindEffect end +} +Effect_I_bindEffect = { + bind = Effect_I_foreign.bindE, + Apply0 = function(unused2) return Effect_I__S___lazy_applyEffect(0) end +} +Effect_I_applicativeEffect = { + pure = Effect_I_foreign.pureE, Apply0 = function(unused3) return Effect_I__S___lazy_applyEffect(0) end } -Effect_I__S___lazy_functorEffect = (function(name) - return function(init) - return function() - local state = 0 - local val = nil - if state == 2 then - return val - else - if state == 1 then - return error(name .. " was needed before it finished initializing") - else - state = 1 - val = init() - state = 2 - return val - end - end - end - end -end)("functorEffect")(function(unused4) +Effect_I__S___lazy_functorEffect = _S___runtime_lazy("functorEffect")(function( unused4 ) return { map = (function(dictApplicative) return function(f) return function(a) return (function(dict) return dict.apply - end)(dictApplicative.Apply0(nil))((function(dict) - return dict.pure - end)(dictApplicative)(f))(a) + end)(dictApplicative.Apply0(Prim_I_undefined))(Control_Applicative_I_pure(dictApplicative)(f))(a) end end end)(Effect_I_applicativeEffect) } end) -Effect_I__S___lazy_applyEffect = (function(name) - return function(init) - return function() - local state = 0 - local val = nil - if state == 2 then - return val - else - if state == 1 then - return error(name .. " was needed before it finished initializing") - else - state = 1 - val = init() - state = 2 - return val - end - end - end - end -end)("applyEffect")(function(unused6) +Effect_I__S___lazy_applyEffect = _S___runtime_lazy("applyEffect")(function( unused6 ) return { apply = (function(dictMonad) return function(f) - local bind = (function(dict) return dict.bind end)(dictMonad.Bind1(nil)) + local bind = (function(dict) + return dict.bind + end)(dictMonad.Bind1(Prim_I_undefined)) return function(a) return bind(f)(function(fPrime) return bind(a)(function(aPrime) - return (function(dict) - return dict.pure - end)(dictMonad.Applicative0(nil))(fPrime(aPrime)) + return Control_Applicative_I_pure(dictMonad.Applicative0(Prim_I_undefined))(fPrime(aPrime)) end) end) end @@ -201,7 +128,7 @@ end)("applyEffect")(function(unused6) end) return { main = (function(dictApplicative) - return (function(dict) return dict.pure end)(dictApplicative)(((function() + return Control_Applicative_I_pure(dictApplicative)(((function() return {unit = nil} end)()).unit) end)(Effect_I_applicativeEffect) diff --git a/test/ps/output/Golden.TestNameShadowing/corefn.json b/test/ps/output/Golden.TestNameShadowing/corefn.json new file mode 100644 index 0000000..a017df4 --- /dev/null +++ b/test/ps/output/Golden.TestNameShadowing/corefn.json @@ -0,0 +1 @@ +{"builtWith":"0.15.9","comments":[],"decls":[{"annotation":{"meta":null,"sourceSpan":{"end":[12,23],"start":[12,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[12,23],"start":[12,1]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[12,23],"start":[12,1]}},"argument":"v1","body":{"annotation":{"meta":null,"sourceSpan":{"end":[12,23],"start":[12,1]}},"caseAlternatives":[{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[13,4],"start":[13,3]}},"binderType":"LiteralBinder","literal":{"literalType":"IntLiteral","value":1}},{"annotation":{"meta":null,"sourceSpan":{"end":[13,6],"start":[13,5]}},"binderType":"NullBinder"}],"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[13,10],"start":[13,9]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},"isGuarded":false},{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[14,4],"start":[14,3]}},"binderType":"NullBinder"},{"annotation":{"meta":null,"sourceSpan":{"end":[14,6],"start":[14,5]}},"binderType":"LiteralBinder","literal":{"literalType":"IntLiteral","value":1}}],"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[14,10],"start":[14,9]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},"isGuarded":false},{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[15,4],"start":[15,3]}},"binderType":"NullBinder"},{"annotation":{"meta":null,"sourceSpan":{"end":[15,6],"start":[15,5]}},"binderType":"NullBinder"}],"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[15,10],"start":[15,9]}},"type":"Literal","value":{"literalType":"IntLiteral","value":3}},"isGuarded":false}],"caseExpressions":[{"annotation":{"meta":null,"sourceSpan":{"end":[13,10],"start":[13,1]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}},{"annotation":{"meta":null,"sourceSpan":{"end":[13,10],"start":[13,1]}},"type":"Var","value":{"identifier":"v1","sourcePos":[0,0]}}],"type":"Case"},"type":"Abs"},"type":"Abs"},"identifier":"f"},{"annotation":{"meta":null,"sourceSpan":{"end":[9,22],"start":[9,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[10,32],"start":[10,5]}},"argument":"x","body":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[10,29],"start":[10,12]}},"argument":"y","body":{"annotation":{"meta":null,"sourceSpan":{"end":[10,29],"start":[10,18]}},"argument":"x1","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[10,25],"start":[10,24]}},"type":"Var","value":{"identifier":"f","moduleName":["Golden","TestNameShadowing"]}},"annotation":{"meta":null,"sourceSpan":{"end":[10,27],"start":[10,24]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[10,27],"start":[10,26]}},"type":"Var","value":{"identifier":"x1","sourcePos":[10,19]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[10,29],"start":[10,24]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[10,29],"start":[10,28]}},"type":"Var","value":{"identifier":"y","sourcePos":[10,13]}},"type":"App"},"type":"Abs"},"type":"Abs"},"annotation":{"meta":null,"sourceSpan":{"end":[10,32],"start":[10,11]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[10,32],"start":[10,31]}},"type":"Var","value":{"identifier":"x","sourcePos":[10,6]}},"type":"App"},"type":"Abs"},"identifier":"c"},{"annotation":{"meta":null,"sourceSpan":{"end":[3,16],"start":[3,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[3,16],"start":[3,1]}},"argument":"x","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[4,8],"start":[4,7]}},"type":"Var","value":{"identifier":"f","moduleName":["Golden","TestNameShadowing"]}},"annotation":{"meta":null,"sourceSpan":{"end":[4,10],"start":[4,7]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[4,10],"start":[4,9]}},"type":"Var","value":{"identifier":"x","sourcePos":[4,1]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[4,13],"start":[4,7]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[4,13],"start":[4,12]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},"type":"App"},"type":"Abs"},"identifier":"a"},{"annotation":{"meta":null,"sourceSpan":{"end":[6,23],"start":[6,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[6,23],"start":[6,1]}},"argument":"x","body":{"annotation":{"meta":null,"sourceSpan":{"end":[6,23],"start":[6,1]}},"argument":"x1","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[7,11],"start":[7,10]}},"type":"Var","value":{"identifier":"f","moduleName":["Golden","TestNameShadowing"]}},"annotation":{"meta":null,"sourceSpan":{"end":[7,20],"start":[7,10]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[7,14],"start":[7,13]}},"type":"Var","value":{"identifier":"f","moduleName":["Golden","TestNameShadowing"]}},"annotation":{"meta":null,"sourceSpan":{"end":[7,16],"start":[7,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[7,16],"start":[7,15]}},"type":"Var","value":{"identifier":"x","sourcePos":[7,1]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[7,19],"start":[7,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[7,19],"start":[7,17]}},"type":"Var","value":{"identifier":"x1","sourcePos":[7,1]}},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[7,27],"start":[7,10]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[7,23],"start":[7,22]}},"type":"Var","value":{"identifier":"a","moduleName":["Golden","TestNameShadowing"]}},"annotation":{"meta":null,"sourceSpan":{"end":[7,26],"start":[7,22]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[7,26],"start":[7,24]}},"type":"Literal","value":{"literalType":"IntLiteral","value":42}},"type":"App"},"type":"App"},"type":"Abs"},"type":"Abs"},"identifier":"b"}],"exports":["b","c"],"foreign":[],"imports":[{"annotation":{"meta":null,"sourceSpan":{"end":[15,10],"start":[1,1]}},"moduleName":["Golden","TestNameShadowing"]},{"annotation":{"meta":null,"sourceSpan":{"end":[15,10],"start":[1,1]}},"moduleName":["Prim"]}],"moduleName":["Golden","TestNameShadowing"],"modulePath":"golden/Golden/TestNameShadowing.purs","reExports":{},"sourceSpan":{"end":[15,10],"start":[1,1]}} \ No newline at end of file diff --git a/test/ps/output/Golden.TestNameShadowing/golden.ir b/test/ps/output/Golden.TestNameShadowing/golden.ir new file mode 100644 index 0000000..6857619 --- /dev/null +++ b/test/ps/output/Golden.TestNameShadowing/golden.ir @@ -0,0 +1,137 @@ +UberModule + { uberModuleBindings = + [ Standalone + ( QName + { qnameModuleName = ModuleName "Golden.TestNameShadowing", qnameName = Name "f" }, Abs + ( Identity ( ParamNamed ( Name "v" ) ) ) + ( Identity + ( Abs + ( Identity ( ParamNamed ( Name "v1" ) ) ) + ( Identity + ( IfThenElse + ( Identity + ( Eq ( Identity ( LiteralInt 1 ) ) ( Identity ( Ref ( Local ( Name "v" ) ) 0 ) ) ) + ) + ( Identity ( LiteralInt 1 ) ) + ( Identity + ( IfThenElse + ( Identity + ( Eq + ( Identity ( LiteralInt 1 ) ) + ( Identity ( Ref ( Local ( Name "v1" ) ) 0 ) ) + ) + ) + ( Identity ( LiteralInt 2 ) ) + ( Identity ( LiteralInt 3 ) ) + ) + ) + ) + ) + ) + ) + ) + ], uberModuleExports = + [ + ( Name "b", Abs + ( Identity ( ParamNamed ( Name "x" ) ) ) + ( Identity + ( Abs + ( Identity ( ParamNamed ( Name "x1" ) ) ) + ( Identity + ( App + ( Identity + ( App + ( Identity + ( Ref ( Imported ( ModuleName "Golden.TestNameShadowing" ) ( Name "f" ) ) 0 ) + ) + ( Identity + ( App + ( Identity + ( App + ( Identity + ( Ref + ( Imported + ( ModuleName "Golden.TestNameShadowing" ) + ( Name "f" ) + ) 0 + ) + ) + ( Identity ( Ref ( Local ( Name "x" ) ) 0 ) ) + ) + ) + ( Identity ( Ref ( Local ( Name "x1" ) ) 0 ) ) + ) + ) + ) + ) + ( Identity + ( App + ( Identity + ( Abs + ( Identity ( ParamNamed ( Name "x2" ) ) ) + ( Identity + ( App + ( Identity + ( App + ( Identity + ( Ref + ( Imported + ( ModuleName "Golden.TestNameShadowing" ) + ( Name "f" ) + ) 0 + ) + ) + ( Identity ( Ref ( Local ( Name "x2" ) ) 0 ) ) + ) + ) + ( Identity ( LiteralInt 1 ) ) + ) + ) + ) + ) + ( Identity ( LiteralInt 42 ) ) + ) + ) + ) + ) + ) + ) + ), + ( Name "c", Abs + ( Identity ( ParamNamed ( Name "x" ) ) ) + ( Identity + ( App + ( Identity + ( Abs + ( Identity ( ParamNamed ( Name "y" ) ) ) + ( Identity + ( Abs + ( Identity ( ParamNamed ( Name "x1" ) ) ) + ( Identity + ( App + ( Identity + ( App + ( Identity + ( Ref + ( Imported + ( ModuleName "Golden.TestNameShadowing" ) + ( Name "f" ) + ) 0 + ) + ) + ( Identity ( Ref ( Local ( Name "x1" ) ) 0 ) ) + ) + ) + ( Identity ( Ref ( Local ( Name "y" ) ) 0 ) ) + ) + ) + ) + ) + ) + ) + ( Identity ( Ref ( Local ( Name "x" ) ) 0 ) ) + ) + ) + ) + ] + } \ No newline at end of file diff --git a/test/ps/output/Golden.TestNameShadowing/golden.lua b/test/ps/output/Golden.TestNameShadowing/golden.lua new file mode 100644 index 0000000..1d4ef59 --- /dev/null +++ b/test/ps/output/Golden.TestNameShadowing/golden.lua @@ -0,0 +1,23 @@ +local Golden_TestNameShadowing_I_f = function(v) + return function(v1) + if 1 == v then + return 1 + else + return (function() if 1 == v1 then return 2 else return 3 end end)() + end + end +end +return { + b = function(x) + return function(x1) + return Golden_TestNameShadowing_I_f(Golden_TestNameShadowing_I_f(x)(x1))((function( x2 ) + return Golden_TestNameShadowing_I_f(x2)(1) + end)(42)) + end + end, + c = function(x) + return (function(y) + return function(x1) return Golden_TestNameShadowing_I_f(x1)(y) end + end)(x) + end +} diff --git a/test/ps/output/Golden.TestNewtype/golden.lua b/test/ps/output/Golden.TestNewtype/golden.lua index f79c30d..4050845 100644 --- a/test/ps/output/Golden.TestNewtype/golden.lua +++ b/test/ps/output/Golden.TestNewtype/golden.lua @@ -1,5 +1,6 @@ +local Golden_TestNewtype_I_NT = function(x) return x end return { - NT = function(x) return x end, + NT = Golden_TestNewtype_I_NT, f = function(v) return v.foo end, - g = function(x) return x end + g = Golden_TestNewtype_I_NT } diff --git a/test/ps/output/Golden.TestRecDataDefs/golden.lua b/test/ps/output/Golden.TestRecDataDefs/golden.lua index 1b1ae6d..e974762 100644 --- a/test/ps/output/Golden.TestRecDataDefs/golden.lua +++ b/test/ps/output/Golden.TestRecDataDefs/golden.lua @@ -1,20 +1,23 @@ +local Golden_TestRecDataDefs_I_A = function() + return { ["$ctor"] = "Golden_TestRecDataDefs.A" } +end +local Golden_TestRecDataDefs_I_AB = function(value0) + return { ["$ctor"] = "Golden_TestRecDataDefs.AB", value0 = value0 } +end +local Golden_TestRecDataDefs_I_B = function() + return { ["$ctor"] = "Golden_TestRecDataDefs.B" } +end +local Golden_TestRecDataDefs_I_BA = function(value0) + return { ["$ctor"] = "Golden_TestRecDataDefs.BA", value0 = value0 } +end +local Golden_TestRecDataDefs_I_ab = Golden_TestRecDataDefs_I_AB(Golden_TestRecDataDefs_I_B) return { - A = function() return { ["$ctor"] = "Golden_TestRecDataDefs.A" } end, - AB = function(value0) - return { ["$ctor"] = "Golden_TestRecDataDefs.AB", value0 = value0 } - end, - B = function() return { ["$ctor"] = "Golden_TestRecDataDefs.B" } end, - BA = function(value0) - return { ["$ctor"] = "Golden_TestRecDataDefs.BA", value0 = value0 } - end, - a = function() return { ["$ctor"] = "Golden_TestRecDataDefs.A" } end, - b = function() return { ["$ctor"] = "Golden_TestRecDataDefs.B" } end, - ab = (function(value0) - return { ["$ctor"] = "Golden_TestRecDataDefs.AB", value0 = value0 } - end)(function() return { ["$ctor"] = "Golden_TestRecDataDefs.B" } end), - ba = (function(value0) - return { ["$ctor"] = "Golden_TestRecDataDefs.BA", value0 = value0 } - end)((function(value0) - return { ["$ctor"] = "Golden_TestRecDataDefs.AB", value0 = value0 } - end)(function() return { ["$ctor"] = "Golden_TestRecDataDefs.B" } end)) + A = Golden_TestRecDataDefs_I_A, + AB = Golden_TestRecDataDefs_I_AB, + B = Golden_TestRecDataDefs_I_B, + BA = Golden_TestRecDataDefs_I_BA, + a = Golden_TestRecDataDefs_I_A, + b = Golden_TestRecDataDefs_I_B, + ab = Golden_TestRecDataDefs_I_ab, + ba = Golden_TestRecDataDefs_I_BA(Golden_TestRecDataDefs_I_ab) } diff --git a/test/ps/output/Golden.TestRecordsAccess/golden.lua b/test/ps/output/Golden.TestRecordsAccess/golden.lua index 29343f7..16c3fde 100644 --- a/test/ps/output/Golden.TestRecordsAccess/golden.lua +++ b/test/ps/output/Golden.TestRecordsAccess/golden.lua @@ -1,6 +1,7 @@ +local Golden_TestRecordsAccess_I_r = { x = 1, y = true } return { - r = { x = 1, y = true }, - test1 = ({ x = 1, y = true }).x, + r = Golden_TestRecordsAccess_I_r, + test1 = Golden_TestRecordsAccess_I_r.x, test2 = function(v) return v.x end, test3 = function(v) return v.x end, test4 = function(v) return v.x end diff --git a/test/ps/output/Golden.TestRecursiveBindings/golden.ir b/test/ps/output/Golden.TestRecursiveBindings/golden.ir index fe0ca14..f7befb1 100644 --- a/test/ps/output/Golden.TestRecursiveBindings/golden.ir +++ b/test/ps/output/Golden.TestRecursiveBindings/golden.ir @@ -5,7 +5,7 @@ UberModule ( RecursiveGroup ( ( Identity - ( Name "yes" ), Identity + ( Name "no" ), Identity ( Abs ( Identity ( ParamNamed ( Name "v" ) ) ) ( Identity @@ -18,7 +18,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) ( Identity ( LiteralBool False ) ) ) ) @@ -32,7 +32,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) ( Identity ( LiteralBool True ) ) ) ) @@ -45,7 +45,7 @@ UberModule ) :| [ ( Identity - ( Name "no" ), Identity + ( Name "yes" ), Identity ( Abs ( Identity ( ParamNamed ( Name "v" ) ) ) ( Identity @@ -58,7 +58,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) ( Identity ( LiteralBool False ) ) ) ) @@ -72,7 +72,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) ( Identity ( LiteralBool True ) ) ) ) @@ -94,7 +94,7 @@ UberModule ( RecursiveGroup ( ( Identity - ( Name "yes" ), Identity + ( Name "no" ), Identity ( Abs ( Identity ( ParamNamed ( Name "v" ) ) ) ( Identity @@ -107,7 +107,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) ( Identity ( LiteralBool False ) ) ) ) @@ -121,7 +121,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) ( Identity ( LiteralBool True ) ) ) ) @@ -134,7 +134,7 @@ UberModule ) :| [ ( Identity - ( Name "no" ), Identity + ( Name "yes" ), Identity ( Abs ( Identity ( ParamNamed ( Name "v" ) ) ) ( Identity @@ -147,7 +147,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) ( Identity ( LiteralBool False ) ) ) ) @@ -161,7 +161,7 @@ UberModule ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "yes" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "no" ) ) 0 ) ) ( Identity ( LiteralBool True ) ) ) ) @@ -185,11 +185,11 @@ UberModule [ RecursiveGroup ( ( Identity - ( Name "b" ), Identity + ( Name "a" ), Identity ( Abs ( Identity ParamUnused ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "a" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "b" ) ) 0 ) ) ( Identity ( Ref ( Local ( Name "z" ) ) 0 ) ) ) ) @@ -197,11 +197,11 @@ UberModule ) :| [ ( Identity - ( Name "a" ), Identity + ( Name "b" ), Identity ( Abs ( Identity ParamUnused ) ( Identity ( App - ( Identity ( Ref ( Local ( Name "b" ) ) 0 ) ) + ( Identity ( Ref ( Local ( Name "a" ) ) 0 ) ) ( Identity ( Ref ( Local ( Name "z" ) ) 0 ) ) ) ) diff --git a/test/ps/output/Golden.TestRecursiveBindings/golden.lua b/test/ps/output/Golden.TestRecursiveBindings/golden.lua index be86e52..2df347d 100644 --- a/test/ps/output/Golden.TestRecursiveBindings/golden.lua +++ b/test/ps/output/Golden.TestRecursiveBindings/golden.lua @@ -1,27 +1,27 @@ return { letRec = (function() - local yes local no - yes = function(v) + local yes + no = function(v) if true == v then - return no(false) + return yes(false) else return (function() if false == v then - return no(true) + return yes(true) else return error("No patterns matched") end end)() end end - no = function(v) + yes = function(v) if true == v then - return yes(false) + return no(false) else return (function() if false == v then - return yes(true) + return no(true) else return error("No patterns matched") end @@ -31,28 +31,28 @@ return { return no(false) end)(), whereRec = (function() - local yes local no - yes = function(v) + local yes + no = function(v) if true == v then - return no(false) + return yes(false) else return (function() if false == v then - return no(true) + return yes(true) else return error("No patterns matched") end end)() end end - no = function(v) + yes = function(v) if true == v then - return yes(false) + return no(false) else return (function() if false == v then - return yes(true) + return no(true) else return error("No patterns matched") end @@ -63,10 +63,10 @@ return { end)(), letRecMixed = (function() local z = 1 - local b local a - b = function(unused0) return a(z) end - a = function(unused1) return b(z) end + local b + a = function(unused0) return b(z) end + b = function(unused1) return a(z) end local f = function(unused2) return function(k) return a(k) end end local y = f(z)(z) return f(f(y)(y))(f(y)(0)) diff --git a/test/ps/output/Golden.TestUnbinding/golden.lua b/test/ps/output/Golden.TestUnbinding/golden.lua index 17924d1..3f37867 100644 --- a/test/ps/output/Golden.TestUnbinding/golden.lua +++ b/test/ps/output/Golden.TestUnbinding/golden.lua @@ -1,8 +1,9 @@ +local Golden_TestUnbinding_I_f = function(unused1) + return function(unused0) return 3 end +end return { a = 1, b = 2, - f = function(unused1) return function(unused0) return 3 end end, - c = (function(unused1) - return function(unused0) return 3 end - end)(1)((function(unused1) return function(unused0) return 3 end end)(2)(1)) + f = Golden_TestUnbinding_I_f, + c = Golden_TestUnbinding_I_f(1)(Golden_TestUnbinding_I_f(2)(1)) } diff --git a/test/ps/packages.dhall b/test/ps/packages.dhall index 80d6676..a307bb6 100644 --- a/test/ps/packages.dhall +++ b/test/ps/packages.dhall @@ -1,5 +1,5 @@ let upstream = - https://github.com/Unisay/purescript-lua-package-sets/releases/download/psc-0.15.9-20230702/packages.dhall - sha256:c7a990e4a0100976f5d0b2e6dd2839391b5f960933bcfe72726f15923b2f9731 + https://github.com/Unisay/purescript-lua-package-sets/releases/download/psc-0.15.9-20230706/packages.dhall + sha256:de2604dd3797c479420a154955209e008fe2cd3fc8452a0bd4b32a2ca00a2ff6 in upstream