From c4cbc64854dc491484be21e0648c95d7f20c2e34 Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Sun, 14 Jun 2026 15:37:25 +0200 Subject: [PATCH 1/9] fix: array-literal pattern binders read 1-based Lua indices (#49) --- lib/Language/PureScript/Backend/Lua.hs | 7 +- .../golden/Golden/ArrayPatternMatch/Test.purs | 26 + .../Golden.ArrayPatternMatch.Test/corefn.json | 1 + .../eval/.gitignore | 1 + .../eval/golden.txt | 4 + .../Golden.ArrayPatternMatch.Test/golden.ir | 490 ++++++++++++++++++ .../Golden.ArrayPatternMatch.Test/golden.lua | 128 +++++ 7 files changed, 654 insertions(+), 3 deletions(-) create mode 100644 test/ps/golden/Golden/ArrayPatternMatch/Test.purs create mode 100644 test/ps/output/Golden.ArrayPatternMatch.Test/corefn.json create mode 100644 test/ps/output/Golden.ArrayPatternMatch.Test/eval/.gitignore create mode 100644 test/ps/output/Golden.ArrayPatternMatch.Test/eval/golden.txt create mode 100644 test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir create mode 100644 test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua diff --git a/lib/Language/PureScript/Backend/Lua.hs b/lib/Language/PureScript/Backend/Lua.hs index 9ef7321..1a59af8 100644 --- a/lib/Language/PureScript/Backend/Lua.hs +++ b/lib/Language/PureScript/Backend/Lua.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE QuasiQuotes #-} - module Language.PureScript.Backend.Lua ( fromUberModule , fromIR @@ -177,7 +175,10 @@ fromIR foreigns topLevelNames modname ir = case ir of IR.ArrayLength _ann e → Right . Lua.hash <$> goExp e IR.ArrayIndex _ann expr index → - Right . flip Lua.varIndex (Lua.Integer (fromIntegral index)) <$> goExp expr + -- IR array indices are 0-based (de Bruijn-style, like the source language), + -- but Lua tables are 1-based, so shift by one. This mirrors the arrays FFI + -- `indexImpl`, which reads `xs[i + 1]`. See issue #49. + Right . flip Lua.varIndex (Lua.Integer (fromIntegral index + 1)) <$> goExp expr IR.ObjectProp _ann expr propName → Right . flip Lua.varField (fromPropName propName) <$> goExp expr IR.ObjectUpdate _ann expr propValues → do diff --git a/test/ps/golden/Golden/ArrayPatternMatch/Test.purs b/test/ps/golden/Golden/ArrayPatternMatch/Test.purs new file mode 100644 index 0000000..b5de225 --- /dev/null +++ b/test/ps/golden/Golden/ArrayPatternMatch/Test.purs @@ -0,0 +1,26 @@ +module Golden.ArrayPatternMatch.Test where + +import Prelude + +import Effect (Effect) +import Effect.Console (logShow) + +-- Matching an array-literal pattern destructures by index. The binders must +-- read 1-based Lua slots; the regression in #49 read them 0-based, so the +-- first element came back nil and the match crashed at runtime. +firstTwo :: Array Int -> Int +firstTwo = case _ of + [ a, b ] -> a + b + _ -> -1 + +lastOfThree :: Array Int -> Int +lastOfThree = case _ of + [ _, _, c ] -> c + _ -> -1 + +main :: Effect Unit +main = do + logShow (firstTwo [ 10, 20 ]) + logShow (firstTwo [ 1, 2, 3 ]) + logShow (firstTwo []) + logShow (lastOfThree [ 7, 8, 9 ]) diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/corefn.json b/test/ps/output/Golden.ArrayPatternMatch.Test/corefn.json new file mode 100644 index 0000000..17e6160 --- /dev/null +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/corefn.json @@ -0,0 +1 @@ +{"builtWith":"0.15.16","comments":[],"decls":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[19,10],"start":[19,8]}},"type":"Var","value":{"identifier":"negate","moduleName":["Data","Ring"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[19,10],"start":[19,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"ringInt","moduleName":["Data","Ring"]}},"type":"App"},"identifier":"negate"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[13,18],"start":[13,17]}},"type":"Var","value":{"identifier":"add","moduleName":["Data","Semiring"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[13,20],"start":[13,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"semiringInt","moduleName":["Data","Semiring"]}},"type":"App"},"identifier":"add"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,32],"start":[23,3]}},"type":"Var","value":{"identifier":"discard","moduleName":["Control","Bind"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discardUnit","moduleName":["Control","Bind"]}},"type":"App"},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"bindEffect","moduleName":["Effect"]}},"type":"App"},"identifier":"discard"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,10],"start":[23,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow"},{"annotation":{"meta":null,"sourceSpan":{"end":[16,32],"start":[16,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[19,10],"start":[17,15]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[19,10],"start":[17,15]}},"caseAlternatives":[{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[18,14],"start":[18,3]}},"binderType":"LiteralBinder","literal":{"literalType":"ArrayLiteral","value":[{"annotation":{"meta":null,"sourceSpan":{"end":[18,6],"start":[18,5]}},"binderType":"NullBinder"},{"annotation":{"meta":null,"sourceSpan":{"end":[18,9],"start":[18,8]}},"binderType":"NullBinder"},{"annotation":{"meta":null,"sourceSpan":{"end":[18,12],"start":[18,11]}},"binderType":"VarBinder","identifier":"c"}]}}],"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[18,19],"start":[18,18]}},"type":"Var","value":{"identifier":"c","sourcePos":[18,11]}},"isGuarded":false},{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[19,4],"start":[19,3]}},"binderType":"NullBinder"}],"expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"negate","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[19,10],"start":[19,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[19,10],"start":[19,9]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},"type":"App"},"isGuarded":false}],"caseExpressions":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}}],"type":"Case"},"type":"Abs"},"identifier":"lastOfThree"},{"annotation":{"meta":null,"sourceSpan":{"end":[11,29],"start":[11,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[14,10],"start":[12,12]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[14,10],"start":[12,12]}},"caseAlternatives":[{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[13,11],"start":[13,3]}},"binderType":"LiteralBinder","literal":{"literalType":"ArrayLiteral","value":[{"annotation":{"meta":null,"sourceSpan":{"end":[13,6],"start":[13,5]}},"binderType":"VarBinder","identifier":"a"},{"annotation":{"meta":null,"sourceSpan":{"end":[13,9],"start":[13,8]}},"binderType":"VarBinder","identifier":"b"}]}}],"expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"add","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[13,20],"start":[13,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[13,16],"start":[13,15]}},"type":"Var","value":{"identifier":"a","sourcePos":[13,5]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[13,20],"start":[13,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[13,20],"start":[13,19]}},"type":"Var","value":{"identifier":"b","sourcePos":[13,8]}},"type":"App"},"isGuarded":false},{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[14,4],"start":[14,3]}},"binderType":"NullBinder"}],"expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"negate","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[14,10],"start":[14,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[14,10],"start":[14,9]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},"type":"App"},"isGuarded":false}],"caseExpressions":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}}],"type":"Case"},"type":"Abs"},"identifier":"firstTwo"},{"annotation":{"meta":null,"sourceSpan":{"end":[21,20],"start":[21,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[23,20],"start":[23,12]}},"type":"Var","value":{"identifier":"firstTwo","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[23,31],"start":[23,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[23,31],"start":[23,21]}},"type":"Literal","value":{"literalType":"ArrayLiteral","value":[{"annotation":{"meta":null,"sourceSpan":{"end":[23,25],"start":[23,23]}},"type":"Literal","value":{"literalType":"IntLiteral","value":10}},{"annotation":{"meta":null,"sourceSpan":{"end":[23,29],"start":[23,27]}},"type":"Literal","value":{"literalType":"IntLiteral","value":20}}]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[23,32],"start":[23,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[24,33],"start":[24,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[24,33],"start":[24,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[24,20],"start":[24,12]}},"type":"Var","value":{"identifier":"firstTwo","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[24,32],"start":[24,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[24,32],"start":[24,21]}},"type":"Literal","value":{"literalType":"ArrayLiteral","value":[{"annotation":{"meta":null,"sourceSpan":{"end":[24,24],"start":[24,23]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},{"annotation":{"meta":null,"sourceSpan":{"end":[24,27],"start":[24,26]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},{"annotation":{"meta":null,"sourceSpan":{"end":[24,30],"start":[24,29]}},"type":"Literal","value":{"literalType":"IntLiteral","value":3}}]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[24,33],"start":[24,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[24,33],"start":[24,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[25,24],"start":[25,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[25,24],"start":[25,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[25,20],"start":[25,12]}},"type":"Var","value":{"identifier":"firstTwo","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[25,23],"start":[25,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[25,23],"start":[25,21]}},"type":"Literal","value":{"literalType":"ArrayLiteral","value":[]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[25,24],"start":[25,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[25,24],"start":[25,3]}},"argument":"$__unused","body":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[26,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[26,23],"start":[26,12]}},"type":"Var","value":{"identifier":"lastOfThree","moduleName":["Golden","ArrayPatternMatch","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[26,35],"start":[26,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[26,35],"start":[26,24]}},"type":"Literal","value":{"literalType":"ArrayLiteral","value":[{"annotation":{"meta":null,"sourceSpan":{"end":[26,27],"start":[26,26]}},"type":"Literal","value":{"literalType":"IntLiteral","value":7}},{"annotation":{"meta":null,"sourceSpan":{"end":[26,30],"start":[26,29]}},"type":"Literal","value":{"literalType":"IntLiteral","value":8}},{"annotation":{"meta":null,"sourceSpan":{"end":[26,33],"start":[26,32]}},"type":"Literal","value":{"literalType":"IntLiteral","value":9}}]}},"type":"App"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"identifier":"main"}],"exports":["firstTwo","lastOfThree","main"],"foreign":[],"imports":[{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Control","Bind"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Data","Ring"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Data","Semiring"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Data","Show"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Effect"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Effect","Console"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Golden","ArrayPatternMatch","Test"]},{"annotation":{"meta":null,"sourceSpan":{"end":[3,15],"start":[3,1]}},"moduleName":["Prelude"]},{"annotation":{"meta":null,"sourceSpan":{"end":[26,36],"start":[1,1]}},"moduleName":["Prim"]}],"moduleName":["Golden","ArrayPatternMatch","Test"],"modulePath":"golden/Golden/ArrayPatternMatch/Test.purs","reExports":{},"sourceSpan":{"end":[26,36],"start":[1,1]}} \ No newline at end of file diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/eval/.gitignore b/test/ps/output/Golden.ArrayPatternMatch.Test/eval/.gitignore new file mode 100644 index 0000000..d2dc29b --- /dev/null +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/eval/.gitignore @@ -0,0 +1 @@ +actual.txt diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/eval/golden.txt b/test/ps/output/Golden.ArrayPatternMatch.Test/eval/golden.txt new file mode 100644 index 0000000..45bdfe9 --- /dev/null +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/eval/golden.txt @@ -0,0 +1,4 @@ +30 +-1 +-1 +9 diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir new file mode 100644 index 0000000..1764425 --- /dev/null +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir @@ -0,0 +1,490 @@ +UberModule + { uberModuleBindings = + [ Standalone + ( QName + { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" + }, ForeignImport Nothing + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" + }, ForeignImport Nothing + ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "semiringInt" + }, LiteralObject Nothing + [ + ( PropName "add", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Data.Semiring" ) ( Name "foreign" ) ) 0 ) + ( PropName "intAdd" ) + ), + ( PropName "zero", LiteralInt Nothing 0 ), + ( PropName "mul", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Data.Semiring" ) ( Name "foreign" ) ) 0 ) + ( PropName "intMul" ) + ), + ( PropName "one", LiteralInt Nothing 1 ) + ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Applicative", qnameName = Name "pure" + }, Abs Nothing + ( ParamNamed Nothing ( Name "dict" ) ) + ( ObjectProp Nothing ( Ref Nothing ( Local ( Name "dict" ) ) 0 ) ( PropName "pure" ) ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Bind", qnameName = Name "bind" }, Abs Nothing + ( ParamNamed Nothing ( Name "dict" ) ) + ( ObjectProp Nothing ( Ref Nothing ( Local ( Name "dict" ) ) 0 ) ( PropName "bind" ) ) + ), RecursiveGroup + ( + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "monadEffect" + }, LiteralObject Nothing + [ + ( PropName "Applicative0", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "applicativeEffect" ) ) 0 ) + ), + ( PropName "Bind1", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 ) + ) + ] + ) :| + [ + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "bindEffect" + }, LiteralObject Nothing + [ + ( PropName "bind", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "foreign" ) ) 0 ) + ( PropName "bindE" ) + ), + ( PropName "Apply0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_applyEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "applicativeEffect" + }, LiteralObject Nothing + [ + ( PropName "pure", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "foreign" ) ) 0 ) + ( PropName "pureE" ) + ), + ( PropName "Apply0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_applyEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "Lazy_functorEffect" + }, App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "PSLUA_runtime_lazy" ) ) 0 ) + ( LiteralString Nothing "functorEffect" ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( LiteralObject Nothing + [ + ( PropName "map", Abs Nothing + ( ParamNamed Nothing ( Name "f" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Effect" ) + ( Name "applicativeEffect" ) + ) 0 + ) + ( PropName "Apply0" ) + ) + ( Ref Nothing + ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 + ) + ) + ( PropName "apply" ) + ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Control.Applicative" ) ( Name "pure" ) ) 0 + ) + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "applicativeEffect" ) ) 0 + ) + ) + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ) + ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ) + ) + ] + ) + ) + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "Lazy_applyEffect" + }, App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "PSLUA_runtime_lazy" ) ) 0 ) + ( LiteralString Nothing "applyEffect" ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( LiteralObject Nothing + [ + ( PropName "apply", Let Nothing + ( Standalone + ( Nothing, Name "bind", App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 + ) + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "monadEffect" ) ) 0 + ) + ( PropName "Bind1" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 ) + ) + ) :| [] + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "f" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "f'" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a'" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Applicative" ) + ( Name "pure" ) + ) 0 + ) + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Effect" ) + ( Name "monadEffect" ) + ) 0 + ) + ( PropName "Applicative0" ) + ) + ( Ref Nothing + ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 + ) + ) + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "f'" ) ) 0 ) + ( Ref Nothing ( Local ( Name "a'" ) ) 0 ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + ( PropName "Functor0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_functorEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ) + ) + ) + ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.ArrayPatternMatch.Test", qnameName = Name "negate" + }, Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "sub", ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + [ ( Nothing, Name "intSub" ) ] + ) + ( PropName "intSub" ) + ), + ( PropName "Semiring0", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing + ( Imported ( ModuleName "Data.Semiring" ) ( Name "semiringInt" ) ) 0 + ) + ) + ] + ) + ( PropName "sub" ) + ) + ( ObjectProp Nothing + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "sub", ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + [ ( Nothing, Name "intSub" ) ] + ) + ( PropName "intSub" ) + ), + ( PropName "Semiring0", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing + ( Imported ( ModuleName "Data.Semiring" ) ( Name "semiringInt" ) ) 0 + ) + ) + ] + ) + ( PropName "Semiring0" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 ) + ) + ( PropName "zero" ) + ) + ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.ArrayPatternMatch.Test", qnameName = Name "discard" + }, App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "discard", Abs Nothing + ( ParamNamed Nothing ( Name "dictBind" ) ) + ( App Nothing + ( Ref Nothing ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Local ( Name "dictBind" ) ) 0 ) + ) + ) + ] + ) + ( PropName "discard" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.ArrayPatternMatch.Test", qnameName = Name "logShow" + }, Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + [ ( Nothing, Name "log" ) ] + ) + ( PropName "log" ) + ) + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "show", ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + [ ( Nothing, Name "showIntImpl" ) ] + ) + ( PropName "showIntImpl" ) + ) + ] + ) + ( PropName "show" ) + ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.ArrayPatternMatch.Test", qnameName = Name "lastOfThree" + }, Abs Nothing + ( ParamNamed Nothing ( Name "v" ) ) + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralInt Nothing 3 ) + ( ArrayLength Nothing ( Ref Nothing ( Local ( Name "v" ) ) 0 ) ) + ) + ( ArrayIndex Nothing ( Ref Nothing ( Local ( Name "v" ) ) 0 ) 2 ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "negate" ) ) 0 + ) + ( LiteralInt Nothing 1 ) + ) + ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.ArrayPatternMatch.Test", qnameName = Name "firstTwo" + }, Abs Nothing + ( ParamNamed Nothing ( Name "v" ) ) + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralInt Nothing 2 ) + ( ArrayLength Nothing ( Ref Nothing ( Local ( Name "v" ) ) 0 ) ) + ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported ( ModuleName "Data.Semiring" ) ( Name "semiringInt" ) ) 0 + ) + ( PropName "add" ) + ) + ( ArrayIndex Nothing ( Ref Nothing ( Local ( Name "v" ) ) 0 ) 0 ) + ) + ( ArrayIndex Nothing ( Ref Nothing ( Local ( Name "v" ) ) 0 ) 1 ) + ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "negate" ) ) 0 + ) + ( LiteralInt Nothing 1 ) + ) + ) + ) + ], uberModuleForeigns = [], uberModuleExports = + [ + ( Name "firstTwo", Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "firstTwo" ) ) 0 + ), + ( Name "lastOfThree", Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "lastOfThree" ) ) 0 + ), + ( Name "main", App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "discard" ) ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "logShow" ) ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "firstTwo" ) ) 0 + ) + ( LiteralArray Nothing [ LiteralInt Nothing 10, LiteralInt Nothing 20 ] ) + ) + ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "discard" ) ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "logShow" ) ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.ArrayPatternMatch.Test" ) + ( Name "firstTwo" ) + ) 0 + ) + ( LiteralArray Nothing + [ LiteralInt Nothing 1, LiteralInt Nothing 2, LiteralInt Nothing 3 ] + ) + ) + ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.ArrayPatternMatch.Test" ) ( Name "discard" ) ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.ArrayPatternMatch.Test" ) + ( Name "logShow" ) + ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.ArrayPatternMatch.Test" ) + ( Name "firstTwo" ) + ) 0 + ) + ( LiteralArray Nothing [] ) + ) + ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.ArrayPatternMatch.Test" ) + ( Name "logShow" ) + ) 0 + ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.ArrayPatternMatch.Test" ) + ( Name "lastOfThree" ) + ) 0 + ) + ( LiteralArray Nothing + [ LiteralInt Nothing 7, LiteralInt Nothing 8, LiteralInt Nothing 9 ] + ) + ) + ) + ) + ) + ) + ) + ) + ) + ] + } \ No newline at end of file diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua new file mode 100644 index 0000000..84b8d23 --- /dev/null +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua @@ -0,0 +1,128 @@ +local function PSLUA_runtime_lazy(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 M = {} +M.Data_Semiring_foreign = { + intAdd = function(x) return function(y) return x + y end end, + intMul = function(x) return function(y) return x * y end end +} +M.Effect_foreign = { + pureE = function(a) + return function() + return a + end + end, + bindE = function(a) + return function(f) + return function() + return f(a())() + end + end + end +} +M.Data_Semiring_semiringInt = { + add = M.Data_Semiring_foreign.intAdd, + zero = 0, + mul = M.Data_Semiring_foreign.intMul, + one = 1 +} +M.Control_Applicative_pure = function(dict) return dict.pure end +M.Control_Bind_bind = function(dict) return dict.bind end +M.Effect_monadEffect = { + Applicative0 = function() return M.Effect_applicativeEffect end, + Bind1 = function() return M.Effect_bindEffect end +} +M.Effect_bindEffect = { + bind = M.Effect_foreign.bindE, + Apply0 = function() return M.Effect_Lazy_applyEffect(0) end +} +M.Effect_applicativeEffect = { + pure = M.Effect_foreign.pureE, + Apply0 = function() return M.Effect_Lazy_applyEffect(0) end +} +M.Effect_Lazy_functorEffect = PSLUA_runtime_lazy("functorEffect")(function() + return { + map = function(f) + return function(a) + return (M.Effect_applicativeEffect.Apply0()).apply(M.Control_Applicative_pure(M.Effect_applicativeEffect)(f))(a) + end + end + } +end) +M.Effect_Lazy_applyEffect = PSLUA_runtime_lazy("applyEffect")(function() + return { + apply = (function() + return function(f) + local bind = M.Control_Bind_bind(M.Effect_monadEffect.Bind1()) + return function(a) + return bind(f)(function(fPrime) + return bind(a)(function(aPrime) + return M.Control_Applicative_pure(M.Effect_monadEffect.Applicative0())(fPrime(aPrime)) + end) + end) + end + end + end)(), + Functor0 = function() return M.Effect_Lazy_functorEffect(0) end + } +end) +M.Golden_ArrayPatternMatch_Test_negate = function(a) + return (function(x) return function(y) return x - y end end)(((function() + return M.Data_Semiring_semiringInt + end)()).zero)(a) +end +M.Golden_ArrayPatternMatch_Test_discard = (function(dictBind) + return M.Control_Bind_bind(dictBind) +end)(M.Effect_bindEffect) +M.Golden_ArrayPatternMatch_Test_logShow = function(a) + return (function(s) return function() print(s) end end)((function(n) return tostring(n) end)(a)) +end +M.Golden_ArrayPatternMatch_Test_lastOfThree = function(v) + if 3 == #(v) then + return v[3] + else + return M.Golden_ArrayPatternMatch_Test_negate(1) + end +end +M.Golden_ArrayPatternMatch_Test_firstTwo = function(v) + if 2 == #(v) then + return M.Data_Semiring_semiringInt.add(v[1])(v[2]) + else + return M.Golden_ArrayPatternMatch_Test_negate(1) + end +end +return M.Golden_ArrayPatternMatch_Test_discard(M.Golden_ArrayPatternMatch_Test_logShow(M.Golden_ArrayPatternMatch_Test_firstTwo({ + [1] = 10, + [2] = 20 +})))(function() + return M.Golden_ArrayPatternMatch_Test_discard(M.Golden_ArrayPatternMatch_Test_logShow(M.Golden_ArrayPatternMatch_Test_firstTwo({ + [1] = 1, + [2] = 2, + [3] = 3 + })))(function() + return M.Golden_ArrayPatternMatch_Test_discard(M.Golden_ArrayPatternMatch_Test_logShow(M.Golden_ArrayPatternMatch_Test_firstTwo({})))(function( ) + return M.Golden_ArrayPatternMatch_Test_logShow(M.Golden_ArrayPatternMatch_Test_lastOfThree({ + [1] = 7, + [2] = 8, + [3] = 9 + })) + end) + end) +end)() From 7e1a8529bbe90961249ba026cac26d8ef19a50cb Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Sun, 14 Jun 2026 16:42:59 +0200 Subject: [PATCH 2/9] fix: lower De Bruijn indices when a binder is removed (#56) The IR uses per-name De Bruijn indices: a `Ref (Local n) k` selects the k-th enclosing binder named `n`. Two optimizer passes removed a binder without lowering the references that had skipped over it, leaving them pointing one binder too far out -- an unbound local that the Lua backend rejects with `UnexpectedRefBound`. This aborts `Data.Array` compilation (`foldRecM`, #56): * beta reduction drops the applied lambda; * dead-code elimination blanks an unused named binder to `ParamUnused`. Both now repair the survivors with a new `unshift`, the inverse of `shift 1`. `shift` is refactored to share its scope-tracking traversal (`overFreeIndex`) with `unshift` so the two cannot drift apart. Tests: property and example coverage for shift/unshift/substitute, including the classic capture-avoiding cases (Types spec); a well-scopedness invariant over a well-scoped expression generator (this found the DCE sibling bug) plus deterministic regressions for both passes (Optimizer spec); and an eval golden `Golden.TailRecM2Shadow` over the `foldRecM` shape that triggered #56. --- lib/Language/PureScript/Backend/IR/DCE.hs | 12 +- .../PureScript/Backend/IR/Optimizer.hs | 7 +- lib/Language/PureScript/Backend/IR/Types.hs | 171 ++-- test/Language/PureScript/Backend/IR/Gen.hs | 70 ++ .../PureScript/Backend/IR/Optimizer/Spec.hs | 149 +++- .../PureScript/Backend/IR/Types/Spec.hs | 108 ++- .../golden/Golden/TailRecM2Shadow/Test.purs | 25 + .../Golden.TailRecM2Shadow.Test/corefn.json | 1 + .../eval/.gitignore | 1 + .../eval/golden.txt | 1 + .../Golden.TailRecM2Shadow.Test/golden.ir | 741 ++++++++++++++++++ .../Golden.TailRecM2Shadow.Test/golden.lua | 188 +++++ test/ps/spago.dhall | 1 + 13 files changed, 1397 insertions(+), 78 deletions(-) create mode 100644 test/ps/golden/Golden/TailRecM2Shadow/Test.purs create mode 100644 test/ps/output/Golden.TailRecM2Shadow.Test/corefn.json create mode 100644 test/ps/output/Golden.TailRecM2Shadow.Test/eval/.gitignore create mode 100644 test/ps/output/Golden.TailRecM2Shadow.Test/eval/golden.txt create mode 100644 test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir create mode 100644 test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua diff --git a/lib/Language/PureScript/Backend/IR/DCE.hs b/lib/Language/PureScript/Backend/IR/DCE.hs index 7f95c96..0b5239d 100644 --- a/lib/Language/PureScript/Backend/IR/DCE.hs +++ b/lib/Language/PureScript/Backend/IR/DCE.hs @@ -30,6 +30,7 @@ import Language.PureScript.Backend.IR.Types , getAnn , listGrouping , rewriteExpTopDown + , unshift ) data EntryPoint = EntryPoint ModuleName [Name] @@ -122,16 +123,19 @@ eliminateDeadCode uber@UberModule {..} = pure . \case Abs ann param b | not (paramId `member` reachableIds) → - Rewritten Recurse (Abs ann param' b) + Rewritten Recurse (Abs ann param' b') where paramId ∷ Id = case param of ParamUnused (pid, _) → pid ParamNamed (pid, _) _name → pid - param' = + -- Blanking an unused named binder drops a slot from that name's + -- De Bruijn namespace, so references in the body that skipped over it + -- (index ≥ 1) must be lowered, just as in beta reduction (issue #56). + (param', b') = case param of - ParamUnused pann → ParamUnused pann - ParamNamed pann _name → ParamUnused pann + ParamUnused pann → (ParamUnused pann, b) + ParamNamed pann name → (ParamUnused pann, unshift name 0 b) Let ann binds body → Rewritten Recurse case NE.nonEmpty preservedBinds of Nothing → body diff --git a/lib/Language/PureScript/Backend/IR/Optimizer.hs b/lib/Language/PureScript/Backend/IR/Optimizer.hs index cce95af..58fd0ab 100644 --- a/lib/Language/PureScript/Backend/IR/Optimizer.hs +++ b/lib/Language/PureScript/Backend/IR/Optimizer.hs @@ -32,6 +32,7 @@ import Language.PureScript.Backend.IR.Types , substitute , thenRewrite , unIndex + , unshift ) optimizedUberModule ∷ UberModule → UberModule @@ -301,7 +302,11 @@ betaReduce ∷ RewriteRule Ann betaReduce = pure . \case App _ (Abs _ (ParamNamed _ param) body) r → - Rewritten Recurse $ substitute (Local param) 0 r body + -- Removing the λ closes a binder for 'param', so any reference to it + -- that the substitution shifted past the binder must be lowered back + -- with 'unshift'; otherwise it is left pointing one binder too far out + -- and reaches the Lua backend as an unbound local (issue #56). + Rewritten Recurse . unshift param 0 $ substitute (Local param) 0 r body _ → NoChange {- Note [Eta reduction is unsound] diff --git a/lib/Language/PureScript/Backend/IR/Types.hs b/lib/Language/PureScript/Backend/IR/Types.hs index c1c2b8c..b278507 100644 --- a/lib/Language/PureScript/Backend/IR/Types.hs +++ b/lib/Language/PureScript/Backend/IR/Types.hs @@ -736,7 +736,87 @@ substitute name idx replacement = substitute' idx where go = substitute' index --- | Increase the index of all bound variables matching the given variable name +{- | Rewrite the De Bruijn index of every reference to @namespace@ that is free +with respect to @minIndex@, using @adjust minIndex index@. Binders for other +names are transparent; a binder for @namespace@ raises @minIndex@ by one (see +Note [Sequential scoping of Let bindings] for the @Let@ case). This is the +shared traversal behind 'shift' (which makes room for a new binder) and +'unshift' (which closes the gap left by a removed one); keeping both on one +traversal stops them from drifting apart. +-} +overFreeIndex + ∷ (Index → Index → Index) + -- ^ Given the current @minIndex@ and a reference's index, the new index + → Name + -- ^ The variable name to match (a.k.a. the namespace) + → Index + -- ^ The minimum bound at or above which references are considered free + → RawExp ann + → RawExp ann +overFreeIndex adjust namespace = go + where + go minIndex expression = + case expression of + Ref ann (Local name) index + | name == namespace → + Ref ann (Local name) (adjust minIndex index) + Abs ann argument body → + Abs ann argument (go minIndex' body) + where + minIndex' + | paramName argument == Just namespace = minIndex + 1 + | otherwise = minIndex + -- See Note [Sequential scoping of Let bindings] + Let ann binds body → + Let ann binds' body' + where + (bodyMinIndex, binds') = mapAccumL withGrouping minIndex binds + body' = go bodyMinIndex body + withGrouping minIdx grouping = + case grouping of + Standalone (annotation, boundName, expr) → + ( if boundName == namespace then minIdx + 1 else minIdx + , Standalone (annotation, boundName, go minIdx expr) + ) + RecursiveGroup recBinds → + ( minIdx' + , RecursiveGroup $ + recBinds <&> \(nameAnn, boundName, expr) → + (nameAnn, boundName, go minIdx' expr) + ) + where + minIdx' = + minIdx + + fromIntegral + (length (filter (== namespace) (bindingNames grouping))) + App ann argument function → + App ann (go minIndex argument) (go minIndex function) + LiteralArray ann as → + LiteralArray ann (go minIndex <$> as) + LiteralObject ann props → + LiteralObject ann (go minIndex <<$>> props) + ReflectCtor ann a → + ReflectCtor ann (go minIndex a) + DataArgumentByIndex ann idx a → + DataArgumentByIndex ann idx (go minIndex a) + Eq ann a b → + Eq ann (go minIndex a) (go minIndex b) + ArrayLength ann a → + ArrayLength ann (go minIndex a) + ArrayIndex ann a indx → + ArrayIndex ann (go minIndex a) indx + ObjectProp ann a prop → + ObjectProp ann (go minIndex a) prop + ObjectUpdate ann a patches → + ObjectUpdate ann (go minIndex a) (go minIndex <<$>> patches) + IfThenElse ann p th el → + IfThenElse ann (go minIndex p) (go minIndex th) (go minIndex el) + _ → expression + +{- | Increase the index of all references to the given name bound at or above +@minIndex@. Used to make room when a new binder for that name is introduced, +e.g. when substituting a term under a λ that shadows the name. +-} shift ∷ Int -- ^ The amount to shift by @@ -747,72 +827,29 @@ shift → RawExp ann -- ^ The expression to shift → RawExp ann -shift offset namespace minIndex expression = - case expression of - Ref ann (Local name) index → - Ref ann (Local name) $ - index - + if name == namespace && minIndex <= index - then fromIntegral offset - else 0 - Abs ann argument body → - Abs ann argument (shift offset namespace minIndex' body) - where - minIndex' - | paramName argument == Just namespace = minIndex + 1 - | otherwise = minIndex - -- See Note [Sequential scoping of Let bindings] - Let ann binds body → - Let ann binds' body' - where - (bodyMinIndex, binds') = mapAccumL withGrouping minIndex binds - body' = shift offset namespace bodyMinIndex body - withGrouping minIdx grouping = - case grouping of - Standalone (annotation, boundName, expr) → - ( if boundName == namespace then minIdx + 1 else minIdx - , Standalone - ( annotation - , boundName - , shift offset namespace minIdx expr - ) - ) - RecursiveGroup recBinds → - ( minIdx' - , RecursiveGroup $ - recBinds <&> \(nameAnn, boundName, expr) → - (nameAnn, boundName, shift offset namespace minIdx' expr) - ) - where - minIdx' = - minIdx - + fromIntegral - (length (filter (== namespace) (bindingNames grouping))) - App ann argument function → - App ann (go argument) (go function) - LiteralArray ann as → - LiteralArray ann (go <$> as) - LiteralObject ann props → - LiteralObject ann (go <<$>> props) - ReflectCtor ann a → - ReflectCtor ann (go a) - DataArgumentByIndex ann idx a → - DataArgumentByIndex ann idx (go a) - Eq ann a b → - Eq ann (go a) (go b) - ArrayLength ann a → - ArrayLength ann (go a) - ArrayIndex ann a indx → - ArrayIndex ann (go a) indx - ObjectProp ann a prop → - ObjectProp ann (go a) prop - ObjectUpdate ann a patches → - ObjectUpdate ann (go a) (go <<$>> patches) - IfThenElse ann p th el → - IfThenElse ann (go p) (go th) (go el) - _ → expression - where - go = shift offset namespace minIndex +shift offset = + overFreeIndex \minIndex index → + if minIndex <= index then index + fromIntegral offset else index + +{- | Decrease by one the index of references to the given name bound strictly +above @minIndex@: the inverse of @shift 1@, to be applied after a binder for +the name is removed (e.g. by beta reduction) so that references which pointed +past that binder are lowered back into place. References at exactly @minIndex@ +are the removed binder itself and have already been consumed by the +accompanying substitution, so the strict @minIndex < index@ guard both leaves +genuine inner references untouched and keeps the 'Natural' index from +underflowing. +-} +unshift + ∷ Name + -- ^ The variable name to match (a.k.a. the namespace) + → Index + -- ^ References bound strictly above this bound are lowered + → RawExp ann + → RawExp ann +unshift = + overFreeIndex \minIndex index → + if minIndex < index then index - 1 else index $(makePrisms ''AlgebraicType) $(makePrisms ''Parameter) diff --git a/test/Language/PureScript/Backend/IR/Gen.hs b/test/Language/PureScript/Backend/IR/Gen.hs index 2f8bf82..a7e9498 100644 --- a/test/Language/PureScript/Backend/IR/Gen.hs +++ b/test/Language/PureScript/Backend/IR/Gen.hs @@ -1,5 +1,6 @@ module Language.PureScript.Backend.IR.Gen where +import Data.Map.Strict qualified as Map import Data.Text qualified as Text import Hedgehog (MonadGen) import Hedgehog.Corpus qualified as Corpus @@ -57,6 +58,75 @@ exp = ) ] +{- | A generation-time scope: each local name in scope mapped to the number of +enclosing binders for it. Lets 'scopedExp' emit only references that resolve +to a binder (a valid De Bruijn index for that name). +-} +type Scope = Map IR.Name Natural + +{- | Generate a closed, well-scoped expression: every local reference has an +index below the number of enclosing binders of that name. Restricted to +λ / application / if / object / reference / scalar, which is enough to +exercise beta reduction and name shadowing (the surface of issues #37 and +#56) while keeping well-scopedness easy to guarantee by construction. 'Let' +is intentionally left out; its sequential scoping is covered by the +hand-written specs. +-} +scopedExp ∷ ∀ m. MonadGen m ⇒ m IR.Exp +scopedExp = + -- Cap the size hard: beta reduction duplicates substituted arguments, so an + -- unbounded term can blow the optimizer up exponentially in memory. Small + -- terms are plenty to surface scoping bugs (issues #37 / #56 both shrink to + -- a handful of binders). + Gen.scale (min 8) (scopedExpIn mempty) + +scopedExpIn ∷ ∀ m. MonadGen m ⇒ Scope → m IR.Exp +scopedExpIn scope = + Gen.recursiveFrequency + ((4, scalarExp) : [(5, scopedRef) | not (null inScope)]) + [ (6, IR.application <$> scopedExpIn scope <*> scopedExpIn scope) + , + ( 3 + , IR.ifThenElse + <$> scopedExpIn scope + <*> scopedExpIn scope + <*> scopedExpIn scope + ) + , (5, genAbs) + , (4, genRedex) + , + ( 2 + , IR.literalObject + <$> Gen.list + (Range.linear 1 4) + ((,) <$> genPropName <*> scopedExpIn scope) + ) + ] + where + inScope = [(nm, count) | (nm, count) ← Map.toList scope, count > 0] + scopedRef = do + (nm, count) ← Gen.element inScope + index ← Gen.integral (Range.linear 0 (fromIntegral count - 1)) + pure (IR.refLocal nm index) + genAbs = do + (param, body) ← genBinderBody + pure (IR.abstraction param body) + -- An immediately-applied λ: a beta redex. Generating these directly (rather + -- than hoping an application's head happens to be a λ) is what makes the + -- well-scopedness property actually exercise beta reduction, including the + -- shadowing case behind issue #56. + genRedex = do + (param, body) ← genBinderBody + arg ← scopedExpIn scope + pure (IR.application (IR.abstraction param body) arg) + genBinderBody = do + param ← parameter + let scope' = case param of + IR.ParamNamed _ nm → Map.insertWith (+) nm 1 scope + IR.ParamUnused _ → scope + body ← scopedExpIn scope' + pure (param, body) + binding ∷ MonadGen m ⇒ m IR.Binding binding = Gen.frequency [(8, standaloneBinding), (2, recursiveBinding)] diff --git a/test/Language/PureScript/Backend/IR/Optimizer/Spec.hs b/test/Language/PureScript/Backend/IR/Optimizer/Spec.hs index bb98952..3b1d24f 100644 --- a/test/Language/PureScript/Backend/IR/Optimizer/Spec.hs +++ b/test/Language/PureScript/Backend/IR/Optimizer/Spec.hs @@ -1,14 +1,15 @@ module Language.PureScript.Backend.IR.Optimizer.Spec where -import Control.Lens (universeOf) +import Control.Lens (toListOf, universeOf) import Data.Map qualified as Map -import Hedgehog (annotateShow, forAll, (===)) +import Hedgehog (PropertyT, annotateShow, forAll, (===)) import Hedgehog.Gen qualified as Gen import Language.PureScript.Backend.IR.Gen qualified as Gen import Language.PureScript.Backend.IR.Linker (LinkMode (..)) import Language.PureScript.Backend.IR.Linker qualified as Linker import Language.PureScript.Backend.IR.Names ( Name (..) + , PropName (..) , QName (..) , Qualified (Local) , moduleNameFromString @@ -20,7 +21,8 @@ import Language.PureScript.Backend.IR.Optimizer ) import Language.PureScript.Backend.IR.Types ( Exp - , Grouping (Standalone) + , Grouping (..) + , Index , Module (..) , RawExp (..) , abstraction @@ -31,17 +33,59 @@ import Language.PureScript.Backend.IR.Types , lets , literalBool , literalInt + , literalObject , noAnn + , paramName , paramNamed , paramUnused , refImported , refLocal , refLocal0 , subexpressions + , unIndex ) -import Test.Hspec (Spec, describe) +import Test.Hspec (Spec, SpecWith, describe, it) +import Test.Hspec.Hedgehog (hedgehog, modifyMaxShrinks, modifyMaxSuccess) import Test.Hspec.Hedgehog.Extended (test) +-- | Like 'test', but runs the property over many generated inputs. +prop ∷ String → PropertyT IO () → SpecWith () +prop title = + modifyMaxShrinks (const 20) + . modifyMaxSuccess (const 100) + . it title + . hedgehog + +{- | Local references whose De Bruijn index points past every enclosing binder +of that name: unbound locals, which the Lua backend rejects (see +Note [Locals are uniquely named after renameShadowedNames]). An empty result +means the expression is well-scoped. The binder bookkeeping mirrors +'shift'/'unshift'; see Note [Sequential scoping of Let bindings] for 'Let'. +-} +unboundLocals ∷ Exp → [(Name, Index)] +unboundLocals = go Map.empty + where + go ∷ Map Name Natural → Exp → [(Name, Index)] + go scope = \case + Ref _ (Local nm) index + | unIndex index < Map.findWithDefault 0 nm scope → [] + | otherwise → [(nm, index)] + Abs _ param body → go (bindName (paramName param) scope) body + Let _ binds body → + let (bodyScope, errs) = foldl' letGrouping (scope, []) (toList binds) + in errs <> go bodyScope body + other → foldMap (go scope) (toListOf subexpressions other) + where + bindName Nothing sc = sc + bindName (Just nm) sc = Map.insertWith (+) nm 1 sc + letGrouping (sc, errs) = \case + Standalone (_ann, nm, e) → + (Map.insertWith (+) nm 1 sc, errs <> go sc e) + RecursiveGroup recBinds → + let names = (\(_ann, nm, _e) → nm) <$> toList recBinds + sc' = foldr (\nm → Map.insertWith (+) nm 1) sc names + in (sc', errs <> foldMap (\(_ann, _nm, e) → go sc' e) recBinds) + spec ∷ Spec spec = describe "IR Optimizer" do describe "optimizes expressions" do @@ -212,6 +256,103 @@ spec = describe "IR Optimizer" do annotateShow optimized unboundLocalRefs === [] + -- Issue #56: beta reduction removes a binder, so any reference that the + -- substitution shifted past it must be lowered back. Here `b` is bound by + -- an outer λ, while the reduced inner λ is *also* named `b`; reducing it + -- must drop the outer reference from index 1 back to 0 rather than leave it + -- unbound. This is the IR shape `Data.Array.foldRecM` boils down to. + test "beta reduction does not unbind a reference shadowed by the binder" do + let a = Name "a" + b = Name "b" + inner = + abstraction (paramNamed a) $ + abstraction (paramNamed b) $ + literalObject + [ (PropName "p", refLocal a 0) + , (PropName "q", refLocal b 0) + ] + -- (\b -> (\a -> \b -> { p: a, q: b }) b 0) + shadowed = + abstraction (paramNamed b) $ + application + (application inner (refLocal b 0)) + (literalInt 0) + original = + Linker.UberModule + { uberModuleForeigns = [] + , uberModuleBindings = [] + , uberModuleExports = [(Name "foldRecMShape", shadowed)] + } + -- After the redexes are reduced only the outer λ remains, so the + -- surviving reference is `b` at index 0. + expected = + abstraction (paramNamed b) $ + literalObject + [ (PropName "p", refLocal b 0) + , (PropName "q", literalInt 0) + ] + optimized = optimizedUberModule original + offending = + foldMap (unboundLocals . snd) (Linker.uberModuleExports optimized) + annotateShow optimized + offending === [] + Linker.uberModuleExports optimized === [(Name "foldRecMShape", expected)] + + -- Sibling of #56 in the DCE pass (found by the property below). Dead-code + -- elimination blanks an unused named binder to ParamUnused. Here the inner + -- λj is unused, yet the body references the *outer* j (at index 1, skipping + -- the inner one); blanking the inner binder must lower that reference to 0, + -- otherwise it is left unbound. + test "blanking an unused shadowing binder keeps outer references bound" do + let j = Name "j" + k = Name "k" + -- \j -> (\k -> { foo: (\_ -> \j -> k) 0 }) j + shadowed = + abstraction (paramNamed j) $ + application + ( abstraction (paramNamed k) $ + literalObject + [ + ( PropName "foo" + , application + ( abstraction paramUnused $ + abstraction (paramNamed j) (refLocal k 0) + ) + (literalInt 0) + ) + ] + ) + (refLocal j 0) + original = + Linker.UberModule + { uberModuleForeigns = [] + , uberModuleBindings = [] + , uberModuleExports = [(Name "shape", shadowed)] + } + optimized = optimizedUberModule original + offending = + foldMap (unboundLocals . snd) (Linker.uberModuleExports optimized) + annotateShow optimized + offending === [] + + -- The general invariant behind #37 and #56: optimizing a well-scoped + -- expression must never produce an unbound local reference. Runs through the + -- whole 'optimizedUberModule' pipeline (not a single 'optimizedExpression' + -- pass) because the #56 dangling reference only surfaces once an enclosing + -- redex is reduced on a later iteration. + prop "optimization keeps expressions well-scoped" do + e ← forAll Gen.scopedExp + annotateShow e + unboundLocals e === [] -- the generator only emits well-scoped terms + let optimized = + optimizedUberModule + Linker.UberModule + { Linker.uberModuleForeigns = [] + , Linker.uberModuleBindings = [] + , Linker.uberModuleExports = [(Name "root", e)] + } + foldMap (unboundLocals . snd) (Linker.uberModuleExports optimized) === [] + describe "renames shadowed names" do test "nested λ-abstractions" do name ← forAll Gen.name diff --git a/test/Language/PureScript/Backend/IR/Types/Spec.hs b/test/Language/PureScript/Backend/IR/Types/Spec.hs index 01d0f70..54aae3a 100644 --- a/test/Language/PureScript/Backend/IR/Types/Spec.hs +++ b/test/Language/PureScript/Backend/IR/Types/Spec.hs @@ -1,7 +1,10 @@ module Language.PureScript.Backend.IR.Types.Spec where import Data.Map qualified as Map -import Hedgehog ((===)) +import Hedgehog (PropertyT, annotateShow, forAll, (===)) +import Hedgehog.Gen qualified as Gen +import Hedgehog.Range qualified as Range +import Language.PureScript.Backend.IR.Gen qualified as Gen import Language.PureScript.Backend.IR.Names ( ModuleName (..) , Name (..) @@ -10,6 +13,7 @@ import Language.PureScript.Backend.IR.Names import Language.PureScript.Backend.IR.Types ( Exp , Grouping (..) + , Index , abstraction , application , countFreeRef @@ -23,10 +27,23 @@ import Language.PureScript.Backend.IR.Types , refLocal , shift , substitute + , unshift ) -import Test.Hspec (Spec, describe) +import Test.Hspec (Spec, SpecWith, describe, it) +import Test.Hspec.Hedgehog (hedgehog, modifyMaxShrinks, modifyMaxSuccess) import Test.Hspec.Hedgehog.Extended (test) +{- | Like 'test', but runs the property over many generated inputs. The bare +'test' helper pins maxSuccess to 1, which is fine for example-based checks +but too weak for the algebraic laws below. +-} +prop ∷ String → PropertyT IO () → SpecWith () +prop title = + modifyMaxShrinks (const 20) + . modifyMaxSuccess (const 100) + . it title + . hedgehog + spec ∷ Spec spec = describe "Types" do test "countFreeRefs" do @@ -98,6 +115,93 @@ spec = describe "Types" do lets (Standalone (noAnn, x, literalInt 42) :| []) (literalInt 0) substitute (Local x) 0 (literalInt 42) original === expected + describe "shift / unshift (De Bruijn re-indexing)" do + let x = Name "x" + y = Name "y" + + -- 'unshift' is the inverse of 'shift 1': raising every free reference to a + -- name and then lowering it again must return the original expression. + prop "unshift undoes shift 1 (round-trip)" do + e ← forAll Gen.exp + n ← forAll Gen.name + minIndex ← forAll (Gen.integral (Range.linear (0 ∷ Index) 3)) + annotateShow e + unshift n minIndex (shift 1 n minIndex e) === e + + test "unshift: a reference bound above minIndex is lowered" do + unshift x 0 (refLocal x 2) === refLocal x 1 + + test "unshift: the reference at minIndex (removed binder) is left alone" do + unshift x 1 (refLocal x 1) === refLocal x 1 + + test "unshift: a reference to a different name is untouched" do + unshift x 0 (refLocal y 3) === refLocal y 3 + + test "unshift: only references free under a shadowing binder are lowered" do + -- under \x the inner reference x@0 is bound by it (left alone), while the + -- outer reference x@2 is free and must drop to x@1. + unshift x 0 (abstraction (paramNamed x) (refLocal x 0)) + === abstraction (paramNamed x) (refLocal x 0) + unshift x 0 (abstraction (paramNamed x) (refLocal x 2)) + === abstraction (paramNamed x) (refLocal x 1) + + describe "substitute (capture-avoiding)" do + -- Replacing a variable by a reference to itself (at the same index) is the + -- identity: this exercises the capture-avoiding shifting that 'substitute' + -- performs as it descends under same-named binders. + prop "substituting a variable for itself is the identity" do + e ← forAll Gen.exp + n ← forAll Gen.name + index ← forAll (Gen.integral (Range.linear (0 ∷ Index) 3)) + annotateShow e + substitute (Local n) index (refLocal n index) e === e + + -- The classic textbook cases the property above can only sample at random. + let x = Name "x" + y = Name "y" + z = Name "z" + + -- (λy. x)[x ≔ y] must not capture the free y: in De Bruijn terms the + -- replacement's y is shifted to index 1 so it keeps referring to the outer + -- y rather than the λ that now encloses it. + test "a free variable is not captured by a binder of its name" do + substitute + (Local x) + 0 + (refLocal y 0) + (abstraction (paramNamed y) (refLocal x 0)) + === abstraction (paramNamed y) (refLocal y 1) + + -- (λz. x)[x ≔ y]: z shadows neither x nor y, so the result is just (λz. y). + test "substitution passes through an unrelated binder unchanged" do + substitute + (Local x) + 0 + (refLocal y 0) + (abstraction (paramNamed z) (refLocal x 0)) + === abstraction (paramNamed z) (refLocal y 0) + + -- (λx. x)[x ≔ 42]: the inner x is bound by its own λx, not the variable + -- being substituted, so the redex is left untouched. + test "a shadowing binder of the same name stops the substitution" do + substitute + (Local x) + 0 + (literalInt 42) + (abstraction (paramNamed x) (refLocal x 0)) + === abstraction (paramNamed x) (refLocal x 0) + + -- (λx. x⟨outer⟩)[x ≔ y]: here the body's reference points past the binder + -- (index 1), so it is the one being substituted; the replacement y is not + -- captured by λx, so it stays at index 0. + test "a reference reaching past a shadowing binder is substituted" do + substitute + (Local x) + 0 + (refLocal y 0) + (abstraction (paramNamed x) (refLocal x 1)) + === abstraction (paramNamed x) (refLocal y 0) + expr ∷ Exp expr = abstraction diff --git a/test/ps/golden/Golden/TailRecM2Shadow/Test.purs b/test/ps/golden/Golden/TailRecM2Shadow/Test.purs new file mode 100644 index 0000000..bf78834 --- /dev/null +++ b/test/ps/golden/Golden/TailRecM2Shadow/Test.purs @@ -0,0 +1,25 @@ +module Golden.TailRecM2Shadow.Test where + +import Prelude + +import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2) +import Effect (Effect) +import Effect.Console (logShow) + +-- Regression for #56. The outer parameter is named `b`, and `tailRecM2`'s own +-- third parameter is also `b`. `tailRecM2` is a single-use dictionary accessor, +-- so the optimizer inlines and beta-reduces it; reducing under the inner `b` +-- capture-shifts the outer reference to index 1, and removing that binder must +-- lower it back to 0. The optimizer used to skip the lowering, leaving an +-- unbound `Local b index 1` that aborted Lua codegen for `Data.Array.foldRecM`. +sumFrom :: forall m. MonadRec m => Int -> Int -> m Int +sumFrom b n = tailRecM2 go b 0 + where + go acc i + | i >= n = pure (Done acc) + | otherwise = pure (Loop { a: acc + i, b: i + 1 }) + +main :: Effect Unit +main = do + r <- sumFrom 0 5 + logShow r diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/corefn.json b/test/ps/output/Golden.TailRecM2Shadow.Test/corefn.json new file mode 100644 index 0000000..83854c4 --- /dev/null +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/corefn.json @@ -0,0 +1 @@ +{"builtWith":"0.15.16","comments":[],"decls":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[19,11],"start":[19,9]}},"type":"Var","value":{"identifier":"greaterThanOrEq","moduleName":["Data","Ord"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[19,13],"start":[19,7]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"ordInt","moduleName":["Data","Ord"]}},"type":"App"},"identifier":"greaterThanOrEq"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[20,40],"start":[20,39]}},"type":"Var","value":{"identifier":"add","moduleName":["Data","Semiring"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[20,42],"start":[20,35]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"semiringInt","moduleName":["Data","Semiring"]}},"type":"App"},"identifier":"add"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[25,10],"start":[25,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[25,12],"start":[25,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow"},{"annotation":{"meta":null,"sourceSpan":{"end":[15,55],"start":[15,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[15,55],"start":[15,1]}},"argument":"dictMonadRec","body":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"binds":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[19,20],"start":[19,16]}},"type":"Var","value":{"identifier":"pure","moduleName":["Control","Applicative"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[19,31],"start":[19,16]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[19,31],"start":[19,16]}},"expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[19,31],"start":[19,16]}},"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"dictMonadRec","sourcePos":[0,0]}},"fieldName":"Monad0","type":"Accessor"},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[19,31],"start":[19,16]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"undefined","moduleName":["Prim"]}},"type":"App"},"fieldName":"Applicative0","type":"Accessor"},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[19,31],"start":[19,16]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"undefined","moduleName":["Prim"]}},"type":"App"},"type":"App"},"identifier":"pure"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[16,24],"start":[16,15]}},"type":"Var","value":{"identifier":"tailRecM2","moduleName":["Control","Monad","Rec","Class"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[16,27],"start":[16,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"dictMonadRec","sourcePos":[0,0]}},"type":"App"},"identifier":"tailRecM2"}],"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[15,55],"start":[15,1]}},"argument":"b","body":{"annotation":{"meta":null,"sourceSpan":{"end":[15,55],"start":[15,1]}},"argument":"n","body":{"annotation":{"meta":{"metaType":"IsWhere"},"sourceSpan":{"end":[16,31],"start":[16,15]}},"binds":[{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"argument":"acc","body":{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"argument":"i","body":{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"caseAlternatives":[{"binders":[{"annotation":{"meta":null,"sourceSpan":{"end":[18,9],"start":[18,6]}},"binderType":"VarBinder","identifier":"acc1"},{"annotation":{"meta":null,"sourceSpan":{"end":[18,11],"start":[18,10]}},"binderType":"VarBinder","identifier":"i1"}],"expressions":[{"expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"pure","sourcePos":[0,0]}},"annotation":{"meta":null,"sourceSpan":{"end":[19,31],"start":[19,16]}},"argument":{"abstraction":{"annotation":{"meta":{"constructorType":"SumType","identifiers":["value0"],"metaType":"IsConstructor"},"sourceSpan":{"end":[19,26],"start":[19,22]}},"type":"Var","value":{"identifier":"Done","moduleName":["Control","Monad","Rec","Class"]}},"annotation":{"meta":null,"sourceSpan":{"end":[19,30],"start":[19,22]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[19,30],"start":[19,27]}},"type":"Var","value":{"identifier":"acc1","sourcePos":[18,6]}},"type":"App"},"type":"App"},"guard":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"greaterThanOrEq","moduleName":["Golden","TailRecM2Shadow","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[19,13],"start":[19,7]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[19,8],"start":[19,7]}},"type":"Var","value":{"identifier":"i1","sourcePos":[18,10]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[19,13],"start":[19,7]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[19,13],"start":[19,12]}},"type":"Var","value":{"identifier":"n","sourcePos":[16,1]}},"type":"App"}},{"expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"pure","sourcePos":[0,0]}},"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[20,19]}},"argument":{"abstraction":{"annotation":{"meta":{"constructorType":"SumType","identifiers":["value0"],"metaType":"IsConstructor"},"sourceSpan":{"end":[20,29],"start":[20,25]}},"type":"Var","value":{"identifier":"Loop","moduleName":["Control","Monad","Rec","Class"]}},"annotation":{"meta":null,"sourceSpan":{"end":[20,54],"start":[20,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[20,54],"start":[20,30]}},"type":"Literal","value":{"literalType":"ObjectLiteral","value":[["a",{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"add","moduleName":["Golden","TailRecM2Shadow","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[20,42],"start":[20,35]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[20,38],"start":[20,35]}},"type":"Var","value":{"identifier":"acc1","sourcePos":[18,6]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[20,42],"start":[20,35]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[20,42],"start":[20,41]}},"type":"Var","value":{"identifier":"i1","sourcePos":[18,10]}},"type":"App"}],["b",{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"add","moduleName":["Golden","TailRecM2Shadow","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[20,52],"start":[20,47]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[20,48],"start":[20,47]}},"type":"Var","value":{"identifier":"i1","sourcePos":[18,10]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[20,52],"start":[20,47]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[20,52],"start":[20,51]}},"type":"Literal","value":{"literalType":"IntLiteral","value":1}},"type":"App"}]]}},"type":"App"},"type":"App"},"guard":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[20,16],"start":[20,7]}},"type":"Var","value":{"identifier":"otherwise","moduleName":["Data","Boolean"]}}}],"isGuarded":true}],"caseExpressions":[{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"type":"Var","value":{"identifier":"acc","sourcePos":[18,6]}},{"annotation":{"meta":null,"sourceSpan":{"end":[20,55],"start":[18,3]}},"type":"Var","value":{"identifier":"i","sourcePos":[18,10]}}],"type":"Case"},"type":"Abs"},"type":"Abs"},"identifier":"go"}],"expression":{"abstraction":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"tailRecM2","sourcePos":[0,0]}},"annotation":{"meta":null,"sourceSpan":{"end":[16,27],"start":[16,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[16,27],"start":[16,25]}},"type":"Var","value":{"identifier":"go","sourcePos":[18,3]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[16,29],"start":[16,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[16,29],"start":[16,28]}},"type":"Var","value":{"identifier":"b","sourcePos":[16,1]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[16,31],"start":[16,15]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[16,31],"start":[16,30]}},"type":"Literal","value":{"literalType":"IntLiteral","value":0}},"type":"App"},"type":"Let"},"type":"Abs"},"type":"Abs"},"type":"Let"},"type":"Abs"},"identifier":"sumFrom"},{"annotation":{"meta":null,"sourceSpan":{"end":[22,20],"start":[22,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[24,19],"start":[24,3]}},"type":"Var","value":{"identifier":"bind","moduleName":["Control","Bind"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[24,19],"start":[24,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"bindEffect","moduleName":["Effect"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[24,19],"start":[24,3]}},"argument":{"abstraction":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[24,15],"start":[24,8]}},"type":"Var","value":{"identifier":"sumFrom","moduleName":["Golden","TailRecM2Shadow","Test"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[24,17],"start":[24,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"monadRecEffect","moduleName":["Control","Monad","Rec","Class"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[24,17],"start":[24,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[24,17],"start":[24,16]}},"type":"Literal","value":{"literalType":"IntLiteral","value":0}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[24,19],"start":[24,8]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[24,19],"start":[24,18]}},"type":"Literal","value":{"literalType":"IntLiteral","value":5}},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[24,19],"start":[24,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[24,19],"start":[24,3]}},"argument":"r","body":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","TailRecM2Shadow","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[25,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[25,11]}},"type":"Var","value":{"identifier":"r","sourcePos":[24,3]}},"type":"App"},"type":"Abs"},"type":"App"},"identifier":"main"}],"exports":["sumFrom","main"],"foreign":[],"imports":[{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Control","Applicative"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Control","Bind"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Control","Monad","Rec","Class"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Data","Boolean"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Data","Ord"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Data","Semiring"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Data","Show"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Effect"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Effect","Console"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Golden","TailRecM2Shadow","Test"]},{"annotation":{"meta":null,"sourceSpan":{"end":[3,15],"start":[3,1]}},"moduleName":["Prelude"]},{"annotation":{"meta":null,"sourceSpan":{"end":[25,12],"start":[1,1]}},"moduleName":["Prim"]}],"moduleName":["Golden","TailRecM2Shadow","Test"],"modulePath":"golden/Golden/TailRecM2Shadow/Test.purs","reExports":{},"sourceSpan":{"end":[25,12],"start":[1,1]}} \ No newline at end of file diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/eval/.gitignore b/test/ps/output/Golden.TailRecM2Shadow.Test/eval/.gitignore new file mode 100644 index 0000000..d2dc29b --- /dev/null +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/eval/.gitignore @@ -0,0 +1 @@ +actual.txt diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/eval/golden.txt b/test/ps/output/Golden.TailRecM2Shadow.Test/eval/golden.txt new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/eval/golden.txt @@ -0,0 +1 @@ +10 diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir new file mode 100644 index 0000000..794ecc5 --- /dev/null +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir @@ -0,0 +1,741 @@ +UberModule + { uberModuleBindings = + [ Standalone + ( QName + { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" + }, ForeignImport Nothing + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" + }, ForeignImport Nothing + ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ), ( Nothing, Name "untilE" ) ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Effect.Ref", qnameName = Name "foreign" + }, ForeignImport Nothing + ( ModuleName "Effect.Ref" ) ".spago/refs/v6.1.0/src/Effect/Ref.purs" + [ ( Nothing, Name "_new" ), ( Nothing, Name "read" ), ( Nothing, Name "write" ) ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Applicative", qnameName = Name "pure" + }, Abs Nothing + ( ParamNamed Nothing ( Name "dict" ) ) + ( ObjectProp Nothing ( Ref Nothing ( Local ( Name "dict" ) ) 0 ) ( PropName "pure" ) ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Bind", qnameName = Name "bind" }, Abs Nothing + ( ParamNamed Nothing ( Name "dict" ) ) + ( ObjectProp Nothing ( Ref Nothing ( Local ( Name "dict" ) ) 0 ) ( PropName "bind" ) ) + ), RecursiveGroup + ( + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "monadEffect" + }, LiteralObject Nothing + [ + ( PropName "Applicative0", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "applicativeEffect" ) ) 0 ) + ), + ( PropName "Bind1", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 ) + ) + ] + ) :| + [ + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "bindEffect" + }, LiteralObject Nothing + [ + ( PropName "bind", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "foreign" ) ) 0 ) + ( PropName "bindE" ) + ), + ( PropName "Apply0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_applyEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "applicativeEffect" + }, LiteralObject Nothing + [ + ( PropName "pure", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "foreign" ) ) 0 ) + ( PropName "pureE" ) + ), + ( PropName "Apply0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_applyEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "Lazy_functorEffect" + }, App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "PSLUA_runtime_lazy" ) ) 0 ) + ( LiteralString Nothing "functorEffect" ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( LiteralObject Nothing + [ + ( PropName "map", Abs Nothing + ( ParamNamed Nothing ( Name "f" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Effect" ) + ( Name "applicativeEffect" ) + ) 0 + ) + ( PropName "Apply0" ) + ) + ( Ref Nothing + ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 + ) + ) + ( PropName "apply" ) + ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Control.Applicative" ) ( Name "pure" ) ) 0 + ) + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "applicativeEffect" ) ) 0 + ) + ) + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ) + ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ) + ) + ] + ) + ) + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "Lazy_applyEffect" + }, App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "PSLUA_runtime_lazy" ) ) 0 ) + ( LiteralString Nothing "applyEffect" ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( LiteralObject Nothing + [ + ( PropName "apply", Let Nothing + ( Standalone + ( Nothing, Name "bind", App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 + ) + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "monadEffect" ) ) 0 + ) + ( PropName "Bind1" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 ) + ) + ) :| [] + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "f" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "f'" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing ( Local ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a'" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Applicative" ) + ( Name "pure" ) + ) 0 + ) + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Effect" ) + ( Name "monadEffect" ) + ) 0 + ) + ( PropName "Applicative0" ) + ) + ( Ref Nothing + ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 + ) + ) + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "f'" ) ) 0 ) + ( Ref Nothing ( Local ( Name "a'" ) ) 0 ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + ( PropName "Functor0", Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "Lazy_functorEffect" ) ) 0 + ) + ( LiteralInt Nothing 0 ) + ) + ) + ] + ) + ) + ), + ( QName + { qnameModuleName = ModuleName "Effect", qnameName = Name "functorEffect" + }, App Nothing + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "Lazy_functorEffect" ) ) 0 ) + ( LiteralInt Nothing 0 ) + ) + ] + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Monad.Rec.Class", qnameName = Name "bind" + }, App Nothing + ( Ref Nothing ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Control.Monad.Rec.Class", qnameName = Name "pure" + }, App Nothing + ( Ref Nothing ( Imported ( ModuleName "Control.Applicative" ) ( Name "pure" ) ) 0 ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "applicativeEffect" ) ) 0 ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.TailRecM2Shadow.Test", qnameName = Name "add" + }, ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "add", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Data.Semiring" ) ( Name "foreign" ) ) 0 ) + ( PropName "intAdd" ) + ), + ( PropName "zero", LiteralInt Nothing 0 ), + ( PropName "mul", ObjectProp ( Just Always ) + ( Ref Nothing ( Imported ( ModuleName "Data.Semiring" ) ( Name "foreign" ) ) 0 ) + ( PropName "intMul" ) + ), + ( PropName "one", LiteralInt Nothing 1 ) + ] + ) + ( PropName "add" ) + ), Standalone + ( QName + { qnameModuleName = ModuleName "Golden.TailRecM2Shadow.Test", qnameName = Name "sumFrom" + }, Abs Nothing + ( ParamNamed Nothing ( Name "dictMonadRec" ) ) + ( Let Nothing + ( Standalone + ( Nothing, Name "pure", App Nothing + ( Ref Nothing ( Imported ( ModuleName "Control.Applicative" ) ( Name "pure" ) ) 0 ) + ( App Nothing + ( ObjectProp Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "dictMonadRec" ) ) 0 ) + ( PropName "Monad0" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 ) + ) + ( PropName "Applicative0" ) + ) + ( Ref Nothing ( Imported ( ModuleName "Prim" ) ( Name "undefined" ) ) 0 ) + ) + ) :| [] + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "b" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "n" ) ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "dictMonadRec" ) ) 0 ) + ( PropName "tailRecM" ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "o" ) ) + ( IfThenElse Nothing + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralString Nothing "Data.Ordering∷Ordering.LT" ) + ( ReflectCtor Nothing + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "compare", App Nothing + ( App Nothing + ( App Nothing + ( ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Ord" ) ".spago/prelude/v7.2.1/src/Data/Ord.purs" + [ ( Nothing, Name "ordIntImpl" ) ] + ) + ( PropName "ordIntImpl" ) + ) + ( Ctor Nothing SumType + ( ModuleName "Data.Ordering" ) + ( TyName "Ordering" ) + ( CtorName "LT" ) [] + ) + ) + ( Ctor Nothing SumType + ( ModuleName "Data.Ordering" ) + ( TyName "Ordering" ) + ( CtorName "EQ" ) [] + ) + ) + ( Ctor Nothing SumType + ( ModuleName "Data.Ordering" ) + ( TyName "Ordering" ) + ( CtorName "GT" ) [] + ) + ), + ( PropName "Eq0", Abs Nothing ( ParamUnused Nothing ) + ( LiteralObject Nothing + [ + ( PropName "eq", ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + [ ( Nothing, Name "eqIntImpl" ) ] + ) + ( PropName "eqIntImpl" ) + ) + ] + ) + ) + ] + ) + ( PropName "compare" ) + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "o" ) ) 0 ) + ( PropName "b" ) + ) + ) + ( Ref Nothing ( Local ( Name "n" ) ) 0 ) + ) + ) + ) ( LiteralBool Nothing False ) ( LiteralBool Nothing True ) + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "pure" ) ) 0 ) + ( App Nothing + ( Ctor Nothing SumType + ( ModuleName "Control.Monad.Rec.Class" ) + ( TyName "Step" ) + ( CtorName "Done" ) + [ FieldName "value0" ] + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "o" ) ) 0 ) + ( PropName "a" ) + ) + ) + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "pure" ) ) 0 ) + ( App Nothing + ( Ctor Nothing SumType + ( ModuleName "Control.Monad.Rec.Class" ) + ( TyName "Step" ) + ( CtorName "Loop" ) + [ FieldName "value0" ] + ) + ( LiteralObject Nothing + [ + ( PropName "a", App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.TailRecM2Shadow.Test" ) + ( Name "add" ) + ) 0 + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "o" ) ) 0 ) + ( PropName "a" ) + ) + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "o" ) ) 0 ) + ( PropName "b" ) + ) + ), + ( PropName "b", App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Golden.TailRecM2Shadow.Test" ) + ( Name "add" ) + ) 0 + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "o" ) ) 0 ) + ( PropName "b" ) + ) + ) + ( LiteralInt Nothing 1 ) + ) + ] + ) + ) + ) + ) + ) + ) + ( LiteralObject Nothing + [ + ( PropName "a", Ref Nothing ( Local ( Name "b" ) ) 0 ), + ( PropName "b", LiteralInt Nothing 0 ) + ] + ) + ) + ) + ) + ) + ) + ], uberModuleForeigns = [], uberModuleExports = + [ + ( Name "sumFrom", Ref Nothing + ( Imported ( ModuleName "Golden.TailRecM2Shadow.Test" ) ( Name "sumFrom" ) ) 0 + ), + ( Name "main", App Nothing + ( App Nothing + ( App Nothing + ( Ref Nothing ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 ) + ) + ( App Nothing + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Golden.TailRecM2Shadow.Test" ) ( Name "sumFrom" ) ) 0 + ) + ( LiteralObject Nothing + [ + ( PropName "tailRecM", Abs Nothing + ( ParamNamed Nothing ( Name "f" ) ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "a" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "bind" ) + ) 0 + ) + ( App Nothing + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported ( ModuleName "Control.Bind" ) ( Name "bind" ) ) 0 + ) + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 + ) + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ( Ref Nothing ( Local ( Name "a" ) ) 0 ) + ) + ) + ( ObjectProp ( Just Always ) + ( Ref Nothing + ( Imported ( ModuleName "Effect.Ref" ) ( Name "foreign" ) ) 0 + ) + ( PropName "_new" ) + ) + ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "r" ) ) + ( App Nothing + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "discard", Abs Nothing + ( ParamNamed Nothing ( Name "dictBind" ) ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Bind" ) + ( Name "bind" ) + ) 0 + ) + ( Ref Nothing ( Local ( Name "dictBind" ) ) 0 ) + ) + ) + ] + ) + ( PropName "discard" ) + ) + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "bindEffect" ) ) 0 + ) + ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( Ref Nothing + ( Imported ( ModuleName "Effect" ) ( Name "foreign" ) ) 0 + ) + ( PropName "untilE" ) + ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "bind" ) + ) 0 + ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( Ref Nothing + ( Imported + ( ModuleName "Effect.Ref" ) + ( Name "foreign" ) + ) 0 + ) + ( PropName "read" ) + ) + ( Ref Nothing ( Local ( Name "r" ) ) 0 ) + ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "v" ) ) + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralString Nothing "Control.Monad.Rec.Class∷Step.Loop" ) + ( ReflectCtor Nothing + ( Ref Nothing ( Local ( Name "v" ) ) 0 ) + ) + ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "bind" ) + ) 0 + ) + ( App Nothing + ( Ref Nothing ( Local ( Name "f" ) ) 0 ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "v" ) ) 0 ) + ( PropName "value0" ) + ) + ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "e" ) ) + ( App Nothing + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "bind" ) + ) 0 + ) + ( App Nothing + ( App Nothing + ( ObjectProp ( Just Always ) + ( Ref Nothing + ( Imported + ( ModuleName "Effect.Ref" ) + ( Name "foreign" ) + ) 0 + ) + ( PropName "write" ) + ) + ( Ref Nothing ( Local ( Name "e" ) ) 0 ) + ) + ( Ref Nothing ( Local ( Name "r" ) ) 0 ) + ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "pure" ) + ) 0 + ) ( LiteralBool Nothing False ) + ) + ) + ) + ) + ) + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralString Nothing "Control.Monad.Rec.Class∷Step.Done" ) + ( ReflectCtor Nothing + ( Ref Nothing ( Local ( Name "v" ) ) 0 ) + ) + ) + ( App Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Control.Monad.Rec.Class" ) + ( Name "pure" ) + ) 0 + ) ( LiteralBool Nothing True ) + ) + ( Exception Nothing "No patterns matched" ) + ) + ) + ) + ) + ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( App Nothing + ( App Nothing + ( ObjectProp Nothing + ( Ref Nothing + ( Imported + ( ModuleName "Effect" ) + ( Name "functorEffect" ) + ) 0 + ) + ( PropName "map" ) + ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Partial.Unsafe" ) ".spago/partial/v4.1.0/src/Partial/Unsafe.purs" + [ ( Nothing, Name "_unsafePartial" ) ] + ) + ( PropName "_unsafePartial" ) + ) + ( Abs Nothing ( ParamUnused Nothing ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "v" ) ) + ( IfThenElse Nothing + ( Eq Nothing + ( LiteralString Nothing "Control.Monad.Rec.Class∷Step.Done" ) + ( ReflectCtor Nothing + ( Ref Nothing ( Local ( Name "v" ) ) 0 ) + ) + ) + ( ObjectProp Nothing + ( Ref Nothing ( Local ( Name "v" ) ) 0 ) + ( PropName "value0" ) + ) + ( Exception Nothing "No patterns matched" ) + ) + ) + ) + ) + ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( Ref Nothing + ( Imported + ( ModuleName "Effect.Ref" ) + ( Name "foreign" ) + ) 0 + ) + ( PropName "read" ) + ) + ( Ref Nothing ( Local ( Name "r" ) ) 0 ) + ) + ) + ) + ) + ) + ) + ) + ), + ( PropName "Monad0", Abs Nothing ( ParamUnused Nothing ) + ( Ref Nothing ( Imported ( ModuleName "Effect" ) ( Name "monadEffect" ) ) 0 ) + ) + ] + ) + ) + ( LiteralInt Nothing 0 ) + ) + ( LiteralInt Nothing 5 ) + ) + ) + ( Abs Nothing + ( ParamNamed Nothing ( Name "r" ) ) + ( App Nothing + ( ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + [ ( Nothing, Name "log" ) ] + ) + ( PropName "log" ) + ) + ( App Nothing + ( ObjectProp Nothing + ( LiteralObject Nothing + [ + ( PropName "show", ObjectProp ( Just Always ) + ( ForeignImport Nothing + ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + [ ( Nothing, Name "showIntImpl" ) ] + ) + ( PropName "showIntImpl" ) + ) + ] + ) + ( PropName "show" ) + ) + ( Ref Nothing ( Local ( Name "r" ) ) 0 ) + ) + ) + ) + ) + ] + } \ No newline at end of file diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua new file mode 100644 index 0000000..2b9e127 --- /dev/null +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua @@ -0,0 +1,188 @@ +local function PSLUA_runtime_lazy(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 M = {} +M.Data_Semiring_foreign = { + intAdd = function(x) return function(y) return x + y end end, + intMul = function(x) return function(y) return x * y end end +} +M.Effect_foreign = { + 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) + return function() + while not f() do + end + end + end +} +M.Effect_Ref_foreign = { + _new = function(val) return function() return {value = val} end end, + read = function(ref) return function() return ref.value end end, + write = function(val) + return function(ref) return function() ref.value = val end end + end +} +M.Control_Applicative_pure = function(dict) return dict.pure end +M.Control_Bind_bind = function(dict) return dict.bind end +M.Effect_monadEffect = { + Applicative0 = function() return M.Effect_applicativeEffect end, + Bind1 = function() return M.Effect_bindEffect end +} +M.Effect_bindEffect = { + bind = M.Effect_foreign.bindE, + Apply0 = function() return M.Effect_Lazy_applyEffect(0) end +} +M.Effect_applicativeEffect = { + pure = M.Effect_foreign.pureE, + Apply0 = function() return M.Effect_Lazy_applyEffect(0) end +} +M.Effect_Lazy_functorEffect = PSLUA_runtime_lazy("functorEffect")(function() + return { + map = function(f) + return function(a) + return (M.Effect_applicativeEffect.Apply0()).apply(M.Control_Applicative_pure(M.Effect_applicativeEffect)(f))(a) + end + end + } +end) +M.Effect_Lazy_applyEffect = PSLUA_runtime_lazy("applyEffect")(function() + return { + apply = (function() + return function(f) + local bind = M.Control_Bind_bind(M.Effect_monadEffect.Bind1()) + return function(a) + return bind(f)(function(fPrime) + return bind(a)(function(aPrime) + return M.Control_Applicative_pure(M.Effect_monadEffect.Applicative0())(fPrime(aPrime)) + end) + end) + end + end + end)(), + Functor0 = function() return M.Effect_Lazy_functorEffect(0) end + } +end) +M.Effect_functorEffect = M.Effect_Lazy_functorEffect(0) +M.Control_Monad_Rec_Class_bind = M.Control_Bind_bind(M.Effect_bindEffect) +M.Control_Monad_Rec_Class_pure = M.Control_Applicative_pure(M.Effect_applicativeEffect) +M.Golden_TailRecM2Shadow_Test_add = M.Data_Semiring_foreign.intAdd +M.Golden_TailRecM2Shadow_Test_sumFrom = function(dictMonadRec) + return function(b) + local pure = M.Control_Applicative_pure((dictMonadRec.Monad0()).Applicative0()) + return function(n) + return dictMonadRec.tailRecM(function(o) + if (function() + if "Data.Ordering∷Ordering.LT" == (((function() + local unsafeCoerceImpl = function(lt) + return function(eq) + return function(gt) + return function(x) + return function(y) + if x < y then + return lt + elseif x == y then + return eq + else + return gt + end + end + end + end + end + end + return { ordIntImpl = unsafeCoerceImpl } + end)()).ordIntImpl({ ["$ctor"] = "Data.Ordering∷Ordering.LT" })({ + ["$ctor"] = "Data.Ordering∷Ordering.EQ" + })({ ["$ctor"] = "Data.Ordering∷Ordering.GT" })(o.b)(n))["$ctor"] then + return false + else + return true + end + end)() then + return pure((function(value0) + return { + ["$ctor"] = "Control.Monad.Rec.Class∷Step.Done", + value0 = value0 + } + end)(o.a)) + else + return pure((function(value0) + return { + ["$ctor"] = "Control.Monad.Rec.Class∷Step.Loop", + value0 = value0 + } + end)({ + a = M.Golden_TailRecM2Shadow_Test_add(o.a)(o.b), + b = M.Golden_TailRecM2Shadow_Test_add(o.b)(1) + })) + end + end)({ a = b, b = 0 }) + end + end +end +return M.Control_Bind_bind(M.Effect_bindEffect)(M.Golden_TailRecM2Shadow_Test_sumFrom({ + tailRecM = function(f) + return function(a) + return M.Control_Monad_Rec_Class_bind(M.Control_Bind_bind(M.Effect_bindEffect)(f(a))(M.Effect_Ref_foreign._new))(function( r ) + return (function(dictBind) + return M.Control_Bind_bind(dictBind) + end)(M.Effect_bindEffect)(M.Effect_foreign.untilE(M.Control_Monad_Rec_Class_bind(M.Effect_Ref_foreign.read(r))(function( v ) + if "Control.Monad.Rec.Class∷Step.Loop" == v["$ctor"] then + return M.Control_Monad_Rec_Class_bind(f(v.value0))(function(e) + return M.Control_Monad_Rec_Class_bind(M.Effect_Ref_foreign.write(e)(r))(function( ) + return M.Control_Monad_Rec_Class_pure(false) + end) + end) + else + if "Control.Monad.Rec.Class∷Step.Done" == v["$ctor"] then + return M.Control_Monad_Rec_Class_pure(true) + else + return error("No patterns matched") + end + end + end)))(function() + return M.Effect_functorEffect.map((function(f) return f(); end)(function( ) + return function(v) + if "Control.Monad.Rec.Class∷Step.Done" == v["$ctor"] then + return v.value0 + else + return error("No patterns matched") + end + end + end))(M.Effect_Ref_foreign.read(r)) + end) + end) + end + end, + Monad0 = function() return M.Effect_monadEffect end +})(0)(5))(function(r) + return (function(s) return function() print(s) end end)((function(n) return tostring(n) end)(r)) +end)() diff --git a/test/ps/spago.dhall b/test/ps/spago.dhall index e2214cb..abaca65 100644 --- a/test/ps/spago.dhall +++ b/test/ps/spago.dhall @@ -10,6 +10,7 @@ , "prelude" , "profunctor" , "strings" + , "tailrec" ] , packages = ./packages.dhall , sources = [ "golden/**/*.purs" ] From c0414366cdc791b1d67a7d5df89658aff2438521 Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Sun, 14 Jun 2026 20:39:55 +0200 Subject: [PATCH 3/9] chore: point package-set + fork links at purescript-lua org The package set, the prelude/strings forks, and this compiler repo moved from Unisay/* to the purescript-lua org. Update the README badges and links, the CLAUDE.md references, the test package-set URL, and a golden test comment. The template and example repos stay under Unisay, so their links are left unchanged. --- CLAUDE.md | 4 ++-- README.md | 14 +++++++------- test/ps/golden/Golden/StringCodePoints/Test.purs | 2 +- test/ps/packages.dhall | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d48cef5..13a4027 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -296,7 +296,7 @@ The project uses Hedgehog for property-based testing: edit `compiler-nix-name` / `easy-ps.purs-*` in `flake.nix`. 2. PureScript package sets live in `test/ps/packages.dhall` as `upstream-ps // upstream-lua`. The right operand wins: `upstream-lua` - (releases of `Unisay/purescript-lua-package-sets`) overrides core + (releases of `purescript-lua/purescript-lua-package-sets`) overrides core packages with Lua forks that ship `.lua` FFI files. 3. After changing package sets or `purs`: `cd test/ps && spago build -u '-g corefn'`, then `cabal test all`. Drop the `sha256:` annotations @@ -311,7 +311,7 @@ The project uses Hedgehog for property-based testing: - **`unit` must not be `nil`**: Lua tables cannot hold `nil` values, so `Array Unit` silently collapses to an empty table if the prelude defines - `unit = nil`. Requires `Unisay/purescript-lua-prelude` ≥ v7.2.0, where + `unit = nil`. Requires `purescript-lua/purescript-lua-prelude` ≥ v7.2.0, where `unit = {}`. If eval goldens for unit arrays start printing `0`, a package set downgraded the prelude — do not accept such goldens. - A generated-Lua change that only passes `luacheck` is not verified: diff --git a/README.md b/README.md index e298c27..8502488 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Purescript Backend for Lua -[![Purescript Lua CI](https://github.com/Unisay/purescript-lua/actions/workflows/ci.yaml/badge.svg)](https://github.com/Unisay/purescript-lua/actions/workflows/ci.yaml) +[![Purescript Lua CI](https://github.com/purescript-lua/purescript-lua/actions/workflows/ci.yaml/badge.svg)](https://github.com/purescript-lua/purescript-lua/actions/workflows/ci.yaml) 🔋 Status: (2024-04-20) the project is in the "_ready to be experimented with_" state (read: it likely contains bugs but is already usable). 💡 If you have an idea on how to use Purescript to Lua compilation please contribute it here: -https://github.com/Unisay/purescript-lua/discussions/categories/ideas +https://github.com/purescript-lua/purescript-lua/discussions/categories/ideas ## Features @@ -13,7 +13,7 @@ https://github.com/Unisay/purescript-lua/discussions/categories/ideas - [x] FFI with Lua. - [x] Dead Code Elimination (DCE). - [x] Code inlining. -- [x] [Package Set](https://github.com/Unisay/purescript-lua-package-sets) for PureScript/Lua libs. +- [x] [Package Set](https://github.com/purescript-lua/purescript-lua-package-sets) for PureScript/Lua libs. - [x] All core libs added to the package set. ## Quick Start @@ -56,15 +56,15 @@ Assuming that `pslua` executable is already available on your PATH ### Using nix with flakes ``` -nix run 'github:Unisay/purescript-lua' -- --help +nix run 'github:purescript-lua/purescript-lua' -- --help ``` ## Installation -If you're on a x86 64bit Linux system then you can download a pre-built executable from the [releases](https://github.com/Unisay/purescript-lua/releases) page: +If you're on a x86 64bit Linux system then you can download a pre-built executable from the [releases](https://github.com/purescript-lua/purescript-lua/releases) page: ``` -wget -c https://github.com/Unisay/purescript-lua/releases/download/0.1.1-alpha/pslua-linux_x86_64.tar.gz -O - | tar -xz +wget -c https://github.com/purescript-lua/purescript-lua/releases/download/0.1.1-alpha/pslua-linux_x86_64.tar.gz -O - | tar -xz ``` alternatively, @@ -72,7 +72,7 @@ alternatively, ### Using nix with flakes ``` -nix profile install 'github:Unisay/purescript-lua' +nix profile install 'github:purescript-lua/purescript-lua' ``` will make `pslua` executable available for use. diff --git a/test/ps/golden/Golden/StringCodePoints/Test.purs b/test/ps/golden/Golden/StringCodePoints/Test.purs index 32b68ff..9204b68 100644 --- a/test/ps/golden/Golden/StringCodePoints/Test.purs +++ b/test/ps/golden/Golden/StringCodePoints/Test.purs @@ -1,5 +1,5 @@ -- Exercises Data.String.CodePoints end to end on the released package set --- (Unisay/purescript-lua-strings v6.2.0). The test string mixes UTF-8 widths +-- (purescript-lua/purescript-lua-strings v6.2.0). The test string mixes UTF-8 widths -- 1..4: 'a' (1 byte), 'é' (2), 'Я' (2, Cyrillic), '𝐀' (4, astral), 'z' (1). -- Output is all Ints/Bools via fromEnum so the golden stays ASCII and does -- not depend on how strings are shown. diff --git a/test/ps/packages.dhall b/test/ps/packages.dhall index b6e98a0..e4f599e 100644 --- a/test/ps/packages.dhall +++ b/test/ps/packages.dhall @@ -3,7 +3,7 @@ let upstream-ps = sha256:e48c9b283ca89ec994453459fb74c4b5b5a9432349f83a2e104f39dd869a0f6e let upstream-lua = - https://github.com/Unisay/purescript-lua-package-sets/releases/download/psc-0.15.15-20260613-2/packages.dhall + https://github.com/purescript-lua/purescript-lua-package-sets/releases/download/psc-0.15.15-20260613-2/packages.dhall sha256:b006e1fd8aa8cd290faf65852f37f62ad3bf5fe97fa3a7c30c97ff7ddfa49807 in upstream-ps // upstream-lua From 31f792f4f8bd1139851191d2e9b69e42ebcc559c Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 10:12:33 +0200 Subject: [PATCH 4/9] chore: add .claude/settings.local.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3cc8bf0..58eb197 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ result-* .envrc.local .hspec-failures .local/ +.claude/settings.local.json From 061baa18dbdab065a8bd268d5fe3cb9c57ae1bdd Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 10:56:27 +0200 Subject: [PATCH 5/9] chore: wire `nix fmt` (treefmt-nix) + robust pre-commit hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert treefmt.toml → treefmt.nix and expose `nix fmt` / `formatter`: cabal-fmt, nixfmt, yamlfmt, and dhall (test/ps/{packages,spago}.dhall). fourmolu is deliberately left OUT of `nix fmt`: its `--haddock-style` is global (single/multi/multi-compact) with no per-comment or by-length mode, so any choice rewrites the source's deliberate Haddock mix (short `-- |`, long `{- | … -}`). Haskell stays a manual `fourmolu -i lib/ exe/ test/` step. Excludes test/ps/output goldens and .hlint.yaml (yamlfmt strips its trailing template comments). CI gains a content-based format check (`nix fmt && git diff --exit-code`). The pre-commit hook is now a tracked .githooks/pre-commit wired via `git config core.hooksPath` — worktree/ submodule-safe, never clobbers an existing .git/hooks, and surfaces `nix fmt` failures instead of swallowing them. cabal-fmt/nixfmt reflow pslua.cabal/shell.nix. --- .githooks/pre-commit | 19 +++++++++++++++++++ .github/workflows/ci.yaml | 2 ++ CLAUDE.md | 8 ++++---- flake.lock | 23 ++++++++++++++++++++++- flake.nix | 10 +++++++++- pslua.cabal | 9 +++++---- shell.nix | 3 +-- treefmt.nix | 27 +++++++++++++++++++++++++++ treefmt.toml | 28 ---------------------------- 9 files changed, 89 insertions(+), 40 deletions(-) create mode 100755 .githooks/pre-commit create mode 100644 treefmt.nix delete mode 100644 treefmt.toml diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..72cb16f --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# Content-based format gate. CI's `nix fmt && git diff --exit-code` is +# authoritative; this hook is just a local convenience. +# +# Tracked under .githooks/ and wired via `git config core.hooksPath .githooks` +# in the dev-shell shellHook — robust across git worktrees and submodules +# (where .git is a file) and it never clobbers a developer's .git/hooks. +set -u +command -v nix >/dev/null 2>&1 || exit 0 # no nix here → skip; CI still gates + +before=$(git diff) +if ! nix fmt >/dev/null 2>&1; then + echo "pre-commit: 'nix fmt' failed — fix the formatter error, then commit." >&2 + exit 1 +fi +if [ "$before" != "$(git diff)" ]; then + echo "pre-commit: 'nix fmt' reformatted files — re-stage them, then commit." >&2 + exit 1 +fi diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3b6c524..8621234 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,3 +24,5 @@ jobs: - name: "🔨 Build & test" run: >- nix develop --accept-flake-config --allow-import-from-derivation --command cabal test all --test-show-details=direct + - name: "🎨 Format check" + run: nix --accept-flake-config fmt && git diff --exit-code diff --git a/CLAUDE.md b/CLAUDE.md index 13a4027..7a6408e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -84,11 +84,11 @@ This finds all files named `golden.*` in `test/ps/output` and deletes them, then ### Code Formatting & Linting ```bash -# Format Haskell code with Fourmolu -fourmolu -i lib/ exe/ test/ +# Format Cabal/Nix/YAML/Dhall via treefmt +nix fmt -# Or use treefmt to format all files -treefmt +# Haskell is formatted separately with Fourmolu (NOT part of `nix fmt`) +fourmolu -i lib/ exe/ test/ # Run HLint hlint lib/ exe/ test/ diff --git a/flake.lock b/flake.lock index 8e7fce8..957e9bc 100644 --- a/flake.lock +++ b/flake.lock @@ -647,7 +647,8 @@ "nixpkgs": [ "haskellNix", "nixpkgs-unstable" - ] + ], + "treefmt-nix": "treefmt-nix" } }, "stackage": { @@ -695,6 +696,26 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780220602, + "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index d09efd3..1b7be9e 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,8 @@ nixpkgs.follows = "haskellNix/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; easy-purescript-nix.url = "github:justinwoo/easy-purescript-nix"; + treefmt-nix.url = "github:numtide/treefmt-nix"; + treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = { @@ -12,6 +14,7 @@ flake-utils, haskellNix, easy-purescript-nix, + treefmt-nix, }: let supportedSystems = [ "x86_64-linux" ]; @@ -60,10 +63,13 @@ lua51Packages.lua lua51Packages.luacheck nil - treefmt upx yamlfmt ]; + # `nix fmt` runs treefmt (treefmt.nix). Robust pre-commit hook: + # point git at the tracked .githooks/ dir (works in worktrees/ + # submodules; never clobbers an existing .git/hooks/pre-commit). + shellHook = "git config core.hooksPath .githooks"; }; crossPlatforms = @@ -75,12 +81,14 @@ }) ]; flake = pkgs.psluaProject.flake { }; + treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix; in flake // { legacyPackages = pkgs; packages.default = flake.packages."pslua:exe:pslua"; packages.static = flake.ciJobs.x86_64-unknown-linux-musl.packages."pslua:exe:pslua"; + formatter = treefmtEval.config.build.wrapper; } ); diff --git a/pslua.cabal b/pslua.cabal index 66c11f7..5df7ff5 100644 --- a/pslua.cabal +++ b/pslua.cabal @@ -12,10 +12,11 @@ extra-source-files: common shared ghc-options: -O2 -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns - -Werror=missing-fields -Werror=missing-methods -Werror=missing-signatures - -Wmissing-deriving-strategies -Wunused-foralls -Wunused-foralls - -fprint-explicit-foralls -fprint-explicit-kinds -Wcompat - -Widentities -Werror=incomplete-patterns -Wredundant-constraints + -Werror=missing-fields -Werror=missing-methods + -Werror=missing-signatures -Wmissing-deriving-strategies + -Wunused-foralls -Wunused-foralls -fprint-explicit-foralls + -fprint-explicit-kinds -Wcompat -Widentities + -Werror=incomplete-patterns -Wredundant-constraints -Wpartial-fields -Wtabs -Wmissing-local-signatures -fhelpful-errors -fprint-expanded-synonyms -fwarn-unused-do-bind diff --git a/shell.nix b/shell.nix index 0f9438a..8745f50 100644 --- a/shell.nix +++ b/shell.nix @@ -1,2 +1 @@ -(builtins.getFlake - ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default +(builtins.getFlake ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 0000000..c420122 --- /dev/null +++ b/treefmt.nix @@ -0,0 +1,27 @@ +{ pkgs, ... }: +{ + projectRootFile = "flake.nix"; + + # Haskell (fourmolu) is deliberately NOT wired into `nix fmt`. fourmolu's + # --haddock-style is global (single-line | multi-line | multi-line-compact) + # with no per-comment or by-length mode, so any choice rewrites the + # hand-authored Haddock — single-line line-prefixes long block comments + # (annoying to copy), while multi-line bloats short ones. The source keeps a + # deliberate mix (short `-- |`, long `{- | … -}`), so Haskell stays a manual + # `fourmolu -i lib/ exe/ test/` step the author runs when they choose. + programs.cabal-fmt.enable = true; + programs.nixfmt.enable = true; + programs.yamlfmt.enable = true; + programs.dhall.enable = true; # test/ps/{packages,spago}.dhall + + # Generated goldens are committed; never reformat them. (test/ps/.spago is + # gitignored, so treefmt's git-aware walk already skips it.) + settings.global.excludes = [ + "test/ps/output/**" + "dist-newstyle/**" + "result" + # yamlfmt strips the trailing template comments from .hlint.yaml; keep it + # hand-maintained. + ".hlint.yaml" + ]; +} diff --git a/treefmt.toml b/treefmt.toml deleted file mode 100644 index a4b1470..0000000 --- a/treefmt.toml +++ /dev/null @@ -1,28 +0,0 @@ -[formatter.haskell] -command = "fourmolu" -options = [ - "--ghc-opt", - "-XImportQualifiedPost", - "--ghc-opt", - "-XTypeApplications", - "--record-brace-space", - "true", - "--single-constraint-parens", - "never", - "--mode", - "inplace", -] -includes = ["*.hs"] - -[formatter.cabal] -command = "cabal-fmt" -options = ["--inplace"] -includes = ["*.cabal"] - -[formatter.nix] -command = "nixfmt" -includes = ["*.nix"] - -[formatter.yaml] -command = "yamlfmt" -includes = ["*.yaml", "*.yml" ] From 62e36537ecafd35081f521a7d49a7b1ae2e13ff7 Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 12:32:46 +0200 Subject: [PATCH 6/9] ci: isolate format check into its own job The format check ran in the tests job after 'cabal test all', which regenerates test/ps/output/*/corefn.json (treefmt excludes that path). 'git diff --exit-code' then tripped on the regenerated corefn rather than on any formatting issue. Move it to a dedicated job with a clean checkout. --- .github/workflows/ci.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8621234..7cc3ff3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,5 +24,20 @@ jobs: - name: "🔨 Build & test" run: >- nix develop --accept-flake-config --allow-import-from-derivation --command cabal test all --test-show-details=direct + format: + runs-on: ubuntu-latest + steps: + - name: "📥 Checkout repository" + uses: actions/checkout@v4 + - name: "❄ Install Nix" + uses: cachix/install-nix-action@v26 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + - uses: cachix/cachix-action@v14 + with: + name: purescript-lua + # Run on a clean checkout so `git diff` sees only what treefmt changed — + # the `tests` job regenerates test/ps/output/*/corefn.json (which treefmt + # excludes), and that churn would otherwise trip `git diff --exit-code`. - name: "🎨 Format check" run: nix --accept-flake-config fmt && git diff --exit-code From de17ec0f0e5ca685befa6ff1d271f1973f389697 Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 15:12:21 +0200 Subject: [PATCH 7/9] test(ps): repoint the golden set at psc-0.15.15-20260615 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Points test/ps at the new Lua package-set release (the FFI-audit fixes) and regenerates the goldens. Churn is cosmetic and behaviour-preserving: - golden.ir: only `.spago//` source-path bumps. - golden.lua: only foreign-table content from the bumped forks (chiefly effect's pureE/bindE reformatting; plus the audited FFI fixes where they survive DCE). - one corefn.json: a source-comment org rename (Unisay -> purescript-lua). - All eval/golden.txt are unchanged — runtime output is identical across every executable golden, so no behaviour changed. --- .../output/Golden.ArrayOfUnits.Test/golden.ir | 12 +++---- .../Golden.ArrayOfUnits.Test/golden.lua | 14 ++------ .../Golden.ArrayPatternMatch.Test/golden.ir | 12 +++---- .../Golden.ArrayPatternMatch.Test/golden.lua | 14 ++------ .../Golden.BugListGenericEq.Test/golden.ir | 10 +++--- .../Golden.BugListGenericEq.Test/golden.lua | 14 ++------ .../output/Golden.CharLiterals.Test/golden.ir | 10 +++--- .../Golden.CharLiterals.Test/golden.lua | 14 ++------ .../Golden.DerivedFunctor.Test/golden.ir | 8 ++--- .../Golden.DerivedFunctor.Test/golden.lua | 14 ++------ .../ps/output/Golden.Fibonacci.Test/golden.ir | 8 ++--- .../Golden.GenericEqTwoTypes.Test/golden.ir | 10 +++--- .../Golden.GenericEqTwoTypes.Test/golden.lua | 14 ++------ .../output/Golden.HelloPrelude.Test/golden.ir | 4 +-- .../Golden.HelloPrelude.Test/golden.lua | 14 ++------ test/ps/output/Golden.Issue37.Test/golden.ir | 4 +-- test/ps/output/Golden.Issue37.Test/golden.lua | 14 ++------ .../output/Golden.MaybeChain.Test/golden.ir | 6 ++-- .../output/Golden.MaybeChain.Test/golden.lua | 14 ++------ .../Golden.ProfunctorDictLens.Test/golden.ir | 10 +++--- .../Golden.ProfunctorDictLens.Test/golden.lua | 14 ++------ .../Golden.StringCodePoints.Test/corefn.json | 2 +- .../Golden.StringCodePoints.Test/golden.ir | 28 +++++++-------- .../Golden.StringCodePoints.Test/golden.lua | 34 ++++++++++++------- .../Golden.TailRecM2Shadow.Test/golden.ir | 12 +++---- .../Golden.TailRecM2Shadow.Test/golden.lua | 21 ++---------- test/ps/packages.dhall | 4 +-- 27 files changed, 114 insertions(+), 221 deletions(-) diff --git a/test/ps/output/Golden.ArrayOfUnits.Test/golden.ir b/test/ps/output/Golden.ArrayOfUnits.Test/golden.ir index 6244fc6..e4eaa4a 100644 --- a/test/ps/output/Golden.ArrayOfUnits.Test/golden.ir +++ b/test/ps/output/Golden.ArrayOfUnits.Test/golden.ir @@ -4,25 +4,25 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Unit", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Unit" ) ".spago/prelude/v7.2.1/src/Data/Unit.purs" + ( ModuleName "Data.Unit" ) ".spago/prelude/v7.3.0/src/Data/Unit.purs" [ ( Just Always, Name "unit" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Foldable", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Foldable" ) ".spago/foldable-traversable/v6.1.0/src/Data/Foldable.purs" + ( ModuleName "Data.Foldable" ) ".spago/foldable-traversable/v6.1.1/src/Data/Foldable.purs" [ ( Nothing, Name "foldrArray" ), ( Nothing, Name "foldlArray" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -356,7 +356,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -552,7 +552,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.ArrayOfUnits.Test/golden.lua b/test/ps/output/Golden.ArrayOfUnits.Test/golden.lua index 8bf2834..65f5a34 100644 --- a/test/ps/output/Golden.ArrayOfUnits.Test/golden.lua +++ b/test/ps/output/Golden.ArrayOfUnits.Test/golden.lua @@ -47,18 +47,8 @@ M.Data_Foldable_foreign = { end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Control_Semigroupoid_semigroupoidFn = { compose = function(f) diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir index 1764425..fa44fa3 100644 --- a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -248,7 +248,7 @@ UberModule [ ( PropName "sub", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.3.0/src/Data/Ring.purs" [ ( Nothing, Name "intSub" ) ] ) ( PropName "intSub" ) @@ -269,7 +269,7 @@ UberModule [ ( PropName "sub", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.3.0/src/Data/Ring.purs" [ ( Nothing, Name "intSub" ) ] ) ( PropName "intSub" ) @@ -317,7 +317,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -328,7 +328,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua index 84b8d23..2d7cdf3 100644 --- a/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua +++ b/test/ps/output/Golden.ArrayPatternMatch.Test/golden.lua @@ -24,18 +24,8 @@ M.Data_Semiring_foreign = { intMul = function(x) return function(y) return x * y end end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Data_Semiring_semiringInt = { add = M.Data_Semiring_foreign.intAdd, diff --git a/test/ps/output/Golden.BugListGenericEq.Test/golden.ir b/test/ps/output/Golden.BugListGenericEq.Test/golden.ir index f1dc37f..a32d044 100644 --- a/test/ps/output/Golden.BugListGenericEq.Test/golden.ir +++ b/test/ps/output/Golden.BugListGenericEq.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.HeytingAlgebra", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.2.1/src/Data/HeytingAlgebra.purs" + ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.3.0/src/Data/HeytingAlgebra.purs" [ ( Nothing, Name "boolConj" ), ( Nothing, Name "boolDisj" ), ( Nothing, Name "boolNot" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -120,7 +120,7 @@ UberModule ( Nothing, Name "get", App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Record.Unsafe" ) ".spago/prelude/v7.2.1/src/Record/Unsafe.purs" + ( ModuleName "Record.Unsafe" ) ".spago/prelude/v7.3.0/src/Record/Unsafe.purs" [ ( Nothing, Name "unsafeGet" ) ] ) ( PropName "unsafeGet" ) @@ -454,7 +454,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -883,7 +883,7 @@ UberModule [ ( PropName "eq", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.3.0/src/Data/Eq.purs" [ ( Nothing, Name "eqIntImpl" ) ] ) ( PropName "eqIntImpl" ) diff --git a/test/ps/output/Golden.BugListGenericEq.Test/golden.lua b/test/ps/output/Golden.BugListGenericEq.Test/golden.lua index f5acb82..2a0dae4 100644 --- a/test/ps/output/Golden.BugListGenericEq.Test/golden.lua +++ b/test/ps/output/Golden.BugListGenericEq.Test/golden.lua @@ -25,18 +25,8 @@ M.Data_HeytingAlgebra_foreign = { boolNot = function(b) return not b end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Type_Proxy_Proxy = { ["$ctor"] = "Type.Proxy∷Proxy.Proxy" } M.Data_HeytingAlgebra_heytingAlgebraBoolean = { diff --git a/test/ps/output/Golden.CharLiterals.Test/golden.ir b/test/ps/output/Golden.CharLiterals.Test/golden.ir index 2d1b1fa..38dcea0 100644 --- a/test/ps/output/Golden.CharLiterals.Test/golden.ir +++ b/test/ps/output/Golden.CharLiterals.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect.Console", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ), Standalone ( QName @@ -19,7 +19,7 @@ UberModule [ ( PropName "eq", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.3.0/src/Data/Eq.purs" [ ( Nothing, Name "eqCharImpl" ) ] ) ( PropName "eqCharImpl" ) @@ -266,7 +266,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showCharImpl" ) ] ) ( PropName "showCharImpl" ) @@ -511,7 +511,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ord" ) ".spago/prelude/v7.2.1/src/Data/Ord.purs" + ( ModuleName "Data.Ord" ) ".spago/prelude/v7.3.0/src/Data/Ord.purs" [ ( Nothing, Name "ordCharImpl" ) ] ) ( PropName "ordCharImpl" ) diff --git a/test/ps/output/Golden.CharLiterals.Test/golden.lua b/test/ps/output/Golden.CharLiterals.Test/golden.lua index 363105b..a51ecc6 100644 --- a/test/ps/output/Golden.CharLiterals.Test/golden.lua +++ b/test/ps/output/Golden.CharLiterals.Test/golden.lua @@ -20,18 +20,8 @@ local function PSLUA_runtime_lazy(name) end local M = {} M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Effect_Console_foreign = { log = function(s) return function() print(s) end end diff --git a/test/ps/output/Golden.DerivedFunctor.Test/golden.ir b/test/ps/output/Golden.DerivedFunctor.Test/golden.ir index 3c06bf6..1c55384 100644 --- a/test/ps/output/Golden.DerivedFunctor.Test/golden.ir +++ b/test/ps/output/Golden.DerivedFunctor.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -274,7 +274,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -285,7 +285,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.DerivedFunctor.Test/golden.lua b/test/ps/output/Golden.DerivedFunctor.Test/golden.lua index 98a7157..842a85d 100644 --- a/test/ps/output/Golden.DerivedFunctor.Test/golden.lua +++ b/test/ps/output/Golden.DerivedFunctor.Test/golden.lua @@ -24,18 +24,8 @@ M.Data_Semiring_foreign = { intMul = function(x) return function(y) return x * y end end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Data_Semiring_semiringInt = { add = M.Data_Semiring_foreign.intAdd, diff --git a/test/ps/output/Golden.Fibonacci.Test/golden.ir b/test/ps/output/Golden.Fibonacci.Test/golden.ir index e4d6877..758f919 100644 --- a/test/ps/output/Golden.Fibonacci.Test/golden.ir +++ b/test/ps/output/Golden.Fibonacci.Test/golden.ir @@ -4,7 +4,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName @@ -30,7 +30,7 @@ UberModule [ ( PropName "sub", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.3.0/src/Data/Ring.purs" [ ( Nothing, Name "intSub" ) ] ) ( PropName "intSub" ) @@ -103,7 +103,7 @@ UberModule ( Name "main", App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -114,7 +114,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.ir b/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.ir index a1c6973..0cdfdf1 100644 --- a/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.ir +++ b/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.HeytingAlgebra", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.2.1/src/Data/HeytingAlgebra.purs" + ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.3.0/src/Data/HeytingAlgebra.purs" [ ( Nothing, Name "boolConj" ), ( Nothing, Name "boolDisj" ), ( Nothing, Name "boolNot" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -90,7 +90,7 @@ UberModule [ ( PropName "eq", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.3.0/src/Data/Eq.purs" [ ( Nothing, Name "eqIntImpl" ) ] ) ( PropName "eqIntImpl" ) @@ -132,7 +132,7 @@ UberModule ( Nothing, Name "get", App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Record.Unsafe" ) ".spago/prelude/v7.2.1/src/Record/Unsafe.purs" + ( ModuleName "Record.Unsafe" ) ".spago/prelude/v7.3.0/src/Record/Unsafe.purs" [ ( Nothing, Name "unsafeGet" ) ] ) ( PropName "unsafeGet" ) @@ -676,7 +676,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) diff --git a/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.lua b/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.lua index 5f1c3f7..3521b57 100644 --- a/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.lua +++ b/test/ps/output/Golden.GenericEqTwoTypes.Test/golden.lua @@ -25,18 +25,8 @@ M.Data_HeytingAlgebra_foreign = { boolNot = function(b) return not b end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Type_Proxy_Proxy = { ["$ctor"] = "Type.Proxy∷Proxy.Proxy" } M.Data_HeytingAlgebra_heytingAlgebraBoolean = { diff --git a/test/ps/output/Golden.HelloPrelude.Test/golden.ir b/test/ps/output/Golden.HelloPrelude.Test/golden.ir index 15b9f39..b45d2f9 100644 --- a/test/ps/output/Golden.HelloPrelude.Test/golden.ir +++ b/test/ps/output/Golden.HelloPrelude.Test/golden.ir @@ -4,7 +4,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -217,7 +217,7 @@ UberModule ) ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Unit" ) ".spago/prelude/v7.2.1/src/Data/Unit.purs" + ( ModuleName "Data.Unit" ) ".spago/prelude/v7.3.0/src/Data/Unit.purs" [ ( Just Always, Name "unit" ) ] ) ( PropName "unit" ) diff --git a/test/ps/output/Golden.HelloPrelude.Test/golden.lua b/test/ps/output/Golden.HelloPrelude.Test/golden.lua index 8b4fad2..ba1958e 100644 --- a/test/ps/output/Golden.HelloPrelude.Test/golden.lua +++ b/test/ps/output/Golden.HelloPrelude.Test/golden.lua @@ -20,18 +20,8 @@ local function PSLUA_runtime_lazy(name) end local M = {} M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Control_Applicative_pure = function(dict) return dict.pure end M.Effect_monadEffect = { diff --git a/test/ps/output/Golden.Issue37.Test/golden.ir b/test/ps/output/Golden.Issue37.Test/golden.ir index 54bed84..5846454 100644 --- a/test/ps/output/Golden.Issue37.Test/golden.ir +++ b/test/ps/output/Golden.Issue37.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Unit", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Unit" ) ".spago/prelude/v7.2.1/src/Data/Unit.purs" + ( ModuleName "Data.Unit" ) ".spago/prelude/v7.3.0/src/Data/Unit.purs" [ ( Just Always, Name "unit" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName diff --git a/test/ps/output/Golden.Issue37.Test/golden.lua b/test/ps/output/Golden.Issue37.Test/golden.lua index cf75054..63ff611 100644 --- a/test/ps/output/Golden.Issue37.Test/golden.lua +++ b/test/ps/output/Golden.Issue37.Test/golden.lua @@ -21,18 +21,8 @@ end local M = {} M.Data_Unit_foreign = { unit = {} } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Control_Applicative_pure = function(dict) return dict.pure end M.Control_Bind_bind = function(dict) return dict.bind end diff --git a/test/ps/output/Golden.MaybeChain.Test/golden.ir b/test/ps/output/Golden.MaybeChain.Test/golden.ir index 6461efd..f18e58b 100644 --- a/test/ps/output/Golden.MaybeChain.Test/golden.ir +++ b/test/ps/output/Golden.MaybeChain.Test/golden.ir @@ -4,7 +4,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -268,7 +268,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -279,7 +279,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.MaybeChain.Test/golden.lua b/test/ps/output/Golden.MaybeChain.Test/golden.lua index 8c97669..42fadfd 100644 --- a/test/ps/output/Golden.MaybeChain.Test/golden.lua +++ b/test/ps/output/Golden.MaybeChain.Test/golden.lua @@ -20,18 +20,8 @@ local function PSLUA_runtime_lazy(name) end local M = {} M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Control_Applicative_pure = function(dict) return dict.pure end M.Control_Bind_bind = function(dict) return dict.bind end diff --git a/test/ps/output/Golden.ProfunctorDictLens.Test/golden.ir b/test/ps/output/Golden.ProfunctorDictLens.Test/golden.ir index 16df027..d3471e9 100644 --- a/test/ps/output/Golden.ProfunctorDictLens.Test/golden.ir +++ b/test/ps/output/Golden.ProfunctorDictLens.Test/golden.ir @@ -4,7 +4,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName @@ -16,7 +16,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName @@ -357,7 +357,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -368,7 +368,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) @@ -556,7 +556,7 @@ UberModule [ ( PropName "sub", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.3.0/src/Data/Ring.purs" [ ( Nothing, Name "intSub" ) ] ) ( PropName "intSub" ) diff --git a/test/ps/output/Golden.ProfunctorDictLens.Test/golden.lua b/test/ps/output/Golden.ProfunctorDictLens.Test/golden.lua index cbc4b27..0b60332 100644 --- a/test/ps/output/Golden.ProfunctorDictLens.Test/golden.lua +++ b/test/ps/output/Golden.ProfunctorDictLens.Test/golden.lua @@ -25,18 +25,8 @@ M.Data_Semiring_foreign = { } M.Unsafe_Coerce_foreign = { unsafeCoerce = function(x) return x end } M.Effect_foreign = { - pureE = function(a) - return function() - return a - end - end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end - end - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end } M.Data_Semiring_semiringInt = { add = M.Data_Semiring_foreign.intAdd, diff --git a/test/ps/output/Golden.StringCodePoints.Test/corefn.json b/test/ps/output/Golden.StringCodePoints.Test/corefn.json index 2de48cb..c141882 100644 --- a/test/ps/output/Golden.StringCodePoints.Test/corefn.json +++ b/test/ps/output/Golden.StringCodePoints.Test/corefn.json @@ -1 +1 @@ -{"builtWith":"0.15.16","comments":[{"LineComment":" Exercises Data.String.CodePoints end to end on the released package set"},{"LineComment":" (Unisay/purescript-lua-strings v6.2.0). The test string mixes UTF-8 widths"},{"LineComment":" 1..4: 'a' (1 byte), 'é' (2), 'Я' (2, Cyrillic), '𝐀' (4, astral), 'z' (1)."},{"LineComment":" Output is all Ints/Bools via fromEnum so the golden stays ASCII and does"},{"LineComment":" not depend on how strings are shown."}],"decls":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,32],"start":[48,29]}},"type":"Var","value":{"identifier":"compose","moduleName":["Control","Semigroupoid"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"semigroupoidFn","moduleName":["Control","Semigroupoid"]}},"type":"App"},"identifier":"compose"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,28],"start":[48,20]}},"type":"Var","value":{"identifier":"fromJust","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"type":"Var","value":{"identifier":"undefined","moduleName":["Prim"]}},"type":"App"},"identifier":"fromJust"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,21],"start":[23,13]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Data","Enum"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,21],"start":[23,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"boundedEnumCodePoint","moduleName":["Data","String","CodePoints"]}},"type":"App"},"identifier":"fromEnum"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"type":"Var","value":{"identifier":"discard","moduleName":["Control","Bind"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discardUnit","moduleName":["Control","Bind"]}},"type":"App"},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"bindEffect","moduleName":["Effect"]}},"type":"App"},"identifier":"discard"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Data","Show"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"showArray"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[28,10],"start":[28,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"identifier":"logShow"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[30,10],"start":[30,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow1"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,10],"start":[36,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showMaybe","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"type":"App"},"identifier":"logShow2"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,24],"start":[36,21]}},"type":"Var","value":{"identifier":"map","moduleName":["Data","Functor"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"functorMaybe","moduleName":["Data","Maybe"]}},"type":"App"},"identifier":"map"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[41,10],"start":[41,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showMaybe","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"identifier":"logShow3"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,10],"start":[43,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showBoolean","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow4"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,64],"start":[43,62]}},"type":"Var","value":{"identifier":"eq","moduleName":["Data","Eq"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"eqString","moduleName":["Data","Eq"]}},"type":"App"},"identifier":"eq"},{"annotation":{"meta":null,"sourceSpan":{"end":[19,14],"start":[19,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[20,14],"start":[20,7]}},"type":"Literal","value":{"literalType":"StringLiteral","value":"aéЯ𝐀z"}},"identifier":"str"},{"annotation":{"meta":null,"sourceSpan":{"end":[47,23],"start":[47,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,19],"start":[48,6]}},"type":"Var","value":{"identifier":"unsafePartial","moduleName":["Partial","Unsafe"]}},"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":"$__unused","body":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromJust","moduleName":["Golden","StringCodePoints","Test"]}},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,39],"start":[48,33]}},"type":"Var","value":{"identifier":"toEnum","moduleName":["Data","Enum"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,39],"start":[48,33]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"boundedEnumCodePoint","moduleName":["Data","String","CodePoints"]}},"type":"App"},"type":"App"},"identifier":"cp"},{"annotation":{"meta":null,"sourceSpan":{"end":[22,29],"start":[22,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[23,46],"start":[23,9]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,12],"start":[23,9]}},"type":"Var","value":{"identifier":"map","moduleName":["Data","Functor"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,21],"start":[23,9]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"functorArray","moduleName":["Data","Functor"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[23,21],"start":[23,9]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[23,46],"start":[23,9]}},"argument":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,46],"start":[23,26]}},"type":"Var","value":{"identifier":"toCodePointArray","moduleName":["Data","String","CodePoints"]}},"type":"App"},"identifier":"codes"},{"annotation":{"meta":null,"sourceSpan":{"end":[25,20],"start":[25,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[28,17],"start":[28,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,21],"start":[28,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[28,21],"start":[28,18]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow1","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[30,22],"start":[30,12]}},"type":"Var","value":{"identifier":"length","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,26],"start":[30,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[30,26],"start":[30,23]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow1","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[31,22],"start":[31,12]}},"type":"Var","value":{"identifier":"length","moduleName":["Data","String","CodeUnits"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,26],"start":[31,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[31,26],"start":[31,23]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[33,17],"start":[33,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,34],"start":[33,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[33,27],"start":[33,19]}},"type":"Var","value":{"identifier":"take","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,29],"start":[33,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,29],"start":[33,28]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[33,33],"start":[33,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,33],"start":[33,30]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[34,17],"start":[34,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,34],"start":[34,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[34,27],"start":[34,19]}},"type":"Var","value":{"identifier":"drop","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,29],"start":[34,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,29],"start":[34,28]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[34,33],"start":[34,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,33],"start":[34,30]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,40],"start":[36,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,42],"start":[36,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,42],"start":[36,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":0}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[37,40],"start":[37,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,42],"start":[37,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,42],"start":[37,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":3}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[38,40],"start":[38,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,42],"start":[38,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,42],"start":[38,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":5}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,26]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,26]}},"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}},"fieldName":"head","type":"Accessor"},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[40,48],"start":[40,38]}},"type":"Var","value":{"identifier":"uncons","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,38]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,49]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow3","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,18],"start":[41,13]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,23]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,23]}},"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}},"fieldName":"tail","type":"Accessor"},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[41,45],"start":[41,35]}},"type":"Var","value":{"identifier":"uncons","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,35]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,46]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow4","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"eq","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,34],"start":[43,12]}},"type":"Var","value":{"identifier":"fromCodePointArray","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,61],"start":[43,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,56],"start":[43,36]}},"type":"Var","value":{"identifier":"toCodePointArray","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,60],"start":[43,36]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,60],"start":[43,57]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,65]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":"$__unused","body":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,47],"start":[45,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[45,17],"start":[45,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,46],"start":[45,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[45,32],"start":[45,19]}},"type":"Var","value":{"identifier":"singleton","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,45],"start":[45,19]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[45,36],"start":[45,34]}},"type":"Var","value":{"identifier":"cp","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,44],"start":[45,34]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[45,44],"start":[45,37]}},"type":"Literal","value":{"literalType":"IntLiteral","value":119808}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"identifier":"main"}],"exports":["str","codes","main","cp"],"foreign":[],"imports":[{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Control","Bind"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Control","Semigroupoid"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Enum"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Eq"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Functor"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Maybe"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Show"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","String","CodePoints"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","String","CodeUnits"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Effect"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Effect","Console"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Golden","StringCodePoints","Test"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Partial","Unsafe"]},{"annotation":{"meta":null,"sourceSpan":{"end":[8,15],"start":[8,1]}},"moduleName":["Prelude"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Prim"]}],"moduleName":["Golden","StringCodePoints","Test"],"modulePath":"golden/Golden/StringCodePoints/Test.purs","reExports":{},"sourceSpan":{"end":[48,39],"start":[6,1]}} \ No newline at end of file +{"builtWith":"0.15.16","comments":[{"LineComment":" Exercises Data.String.CodePoints end to end on the released package set"},{"LineComment":" (purescript-lua/purescript-lua-strings v6.2.0). The test string mixes UTF-8 widths"},{"LineComment":" 1..4: 'a' (1 byte), 'é' (2), 'Я' (2, Cyrillic), '𝐀' (4, astral), 'z' (1)."},{"LineComment":" Output is all Ints/Bools via fromEnum so the golden stays ASCII and does"},{"LineComment":" not depend on how strings are shown."}],"decls":[{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,32],"start":[48,29]}},"type":"Var","value":{"identifier":"compose","moduleName":["Control","Semigroupoid"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"semigroupoidFn","moduleName":["Control","Semigroupoid"]}},"type":"App"},"identifier":"compose"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,28],"start":[48,20]}},"type":"Var","value":{"identifier":"fromJust","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"type":"Var","value":{"identifier":"undefined","moduleName":["Prim"]}},"type":"App"},"identifier":"fromJust"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,21],"start":[23,13]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Data","Enum"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,21],"start":[23,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"boundedEnumCodePoint","moduleName":["Data","String","CodePoints"]}},"type":"App"},"identifier":"fromEnum"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"type":"Var","value":{"identifier":"discard","moduleName":["Control","Bind"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discardUnit","moduleName":["Control","Bind"]}},"type":"App"},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"bindEffect","moduleName":["Effect"]}},"type":"App"},"identifier":"discard"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Data","Show"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"showArray"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[28,10],"start":[28,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"identifier":"logShow"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[30,10],"start":[30,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow1"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,10],"start":[36,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showMaybe","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showInt","moduleName":["Data","Show"]}},"type":"App"},"type":"App"},"identifier":"logShow2"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,24],"start":[36,21]}},"type":"Var","value":{"identifier":"map","moduleName":["Data","Functor"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"functorMaybe","moduleName":["Data","Maybe"]}},"type":"App"},"identifier":"map"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[41,10],"start":[41,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showMaybe","moduleName":["Data","Maybe"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showArray","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"identifier":"logShow3"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,10],"start":[43,3]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Effect","Console"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"showBoolean","moduleName":["Data","Show"]}},"type":"App"},"identifier":"logShow4"},{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"bindType":"NonRec","expression":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,64],"start":[43,62]}},"type":"Var","value":{"identifier":"eq","moduleName":["Data","Eq"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"eqString","moduleName":["Data","Eq"]}},"type":"App"},"identifier":"eq"},{"annotation":{"meta":null,"sourceSpan":{"end":[19,14],"start":[19,1]}},"bindType":"NonRec","expression":{"annotation":{"meta":null,"sourceSpan":{"end":[20,14],"start":[20,7]}},"type":"Literal","value":{"literalType":"StringLiteral","value":"aéЯ𝐀z"}},"identifier":"str"},{"annotation":{"meta":null,"sourceSpan":{"end":[47,23],"start":[47,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,19],"start":[48,6]}},"type":"Var","value":{"identifier":"unsafePartial","moduleName":["Partial","Unsafe"]}},"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[48,28],"start":[48,6]}},"argument":"$__unused","body":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromJust","moduleName":["Golden","StringCodePoints","Test"]}},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[48,6]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[48,39],"start":[48,33]}},"type":"Var","value":{"identifier":"toEnum","moduleName":["Data","Enum"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[48,39],"start":[48,33]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"boundedEnumCodePoint","moduleName":["Data","String","CodePoints"]}},"type":"App"},"type":"App"},"identifier":"cp"},{"annotation":{"meta":null,"sourceSpan":{"end":[22,29],"start":[22,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[23,46],"start":[23,9]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,12],"start":[23,9]}},"type":"Var","value":{"identifier":"map","moduleName":["Data","Functor"]}},"annotation":{"meta":{"metaType":"IsSyntheticApp"},"sourceSpan":{"end":[23,21],"start":[23,9]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"functorArray","moduleName":["Data","Functor"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[23,21],"start":[23,9]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[23,46],"start":[23,9]}},"argument":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[23,46],"start":[23,26]}},"type":"Var","value":{"identifier":"toCodePointArray","moduleName":["Data","String","CodePoints"]}},"type":"App"},"identifier":"codes"},{"annotation":{"meta":null,"sourceSpan":{"end":[25,20],"start":[25,1]}},"bindType":"NonRec","expression":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[28,17],"start":[28,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[28,21],"start":[28,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[28,21],"start":[28,18]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[28,22],"start":[28,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow1","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[30,22],"start":[30,12]}},"type":"Var","value":{"identifier":"length","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[30,26],"start":[30,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[30,26],"start":[30,23]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[30,27],"start":[30,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow1","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[31,22],"start":[31,12]}},"type":"Var","value":{"identifier":"length","moduleName":["Data","String","CodeUnits"]}},"annotation":{"meta":null,"sourceSpan":{"end":[31,26],"start":[31,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[31,26],"start":[31,23]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[31,27],"start":[31,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[33,17],"start":[33,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,34],"start":[33,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[33,27],"start":[33,19]}},"type":"Var","value":{"identifier":"take","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[33,29],"start":[33,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,29],"start":[33,28]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[33,33],"start":[33,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,33],"start":[33,30]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[33,35],"start":[33,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[34,17],"start":[34,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,34],"start":[34,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[34,27],"start":[34,19]}},"type":"Var","value":{"identifier":"drop","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[34,29],"start":[34,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,29],"start":[34,28]}},"type":"Literal","value":{"literalType":"IntLiteral","value":2}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[34,33],"start":[34,19]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,33],"start":[34,30]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[34,35],"start":[34,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[36,40],"start":[36,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[36,42],"start":[36,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,42],"start":[36,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":0}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,46],"start":[36,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[36,47],"start":[36,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[37,40],"start":[37,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[37,42],"start":[37,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,42],"start":[37,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":3}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,46],"start":[37,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[37,47],"start":[37,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[38,40],"start":[38,25]}},"type":"Var","value":{"identifier":"codePointAt","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[38,42],"start":[38,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,42],"start":[38,41]}},"type":"Literal","value":{"literalType":"IntLiteral","value":5}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,25]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,46],"start":[38,43]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[38,47],"start":[38,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow2","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"fromEnum","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,26]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[40,32],"start":[40,26]}},"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}},"fieldName":"head","type":"Accessor"},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[40,48],"start":[40,38]}},"type":"Var","value":{"identifier":"uncons","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,38]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,52],"start":[40,49]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[40,53],"start":[40,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow3","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"map","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,12]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"compose","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,18],"start":[41,13]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,13]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,23]}},"argument":"v","body":{"annotation":{"meta":null,"sourceSpan":{"end":[41,29],"start":[41,23]}},"expression":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"v","sourcePos":[0,0]}},"fieldName":"tail","type":"Accessor"},"type":"Abs"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[41,45],"start":[41,35]}},"type":"Var","value":{"identifier":"uncons","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,35]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,49],"start":[41,46]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[41,50],"start":[41,3]}},"argument":"$__unused","body":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"discard","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow4","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"abstraction":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"eq","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,34],"start":[43,12]}},"type":"Var","value":{"identifier":"fromCodePointArray","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,61],"start":[43,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[43,56],"start":[43,36]}},"type":"Var","value":{"identifier":"toCodePointArray","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[43,60],"start":[43,36]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,60],"start":[43,57]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,12]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,68],"start":[43,65]}},"type":"Var","value":{"identifier":"str","moduleName":["Golden","StringCodePoints","Test"]}},"type":"App"},"type":"App"},"type":"App"},"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[43,69],"start":[43,3]}},"argument":"$__unused","body":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[0,0],"start":[0,0]}},"type":"Var","value":{"identifier":"logShow","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,47],"start":[45,3]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[45,17],"start":[45,12]}},"type":"Var","value":{"identifier":"codes","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,46],"start":[45,12]}},"argument":{"abstraction":{"annotation":{"meta":{"metaType":"IsForeign"},"sourceSpan":{"end":[45,32],"start":[45,19]}},"type":"Var","value":{"identifier":"singleton","moduleName":["Data","String","CodePoints"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,45],"start":[45,19]}},"argument":{"abstraction":{"annotation":{"meta":null,"sourceSpan":{"end":[45,36],"start":[45,34]}},"type":"Var","value":{"identifier":"cp","moduleName":["Golden","StringCodePoints","Test"]}},"annotation":{"meta":null,"sourceSpan":{"end":[45,44],"start":[45,34]}},"argument":{"annotation":{"meta":null,"sourceSpan":{"end":[45,44],"start":[45,37]}},"type":"Literal","value":{"literalType":"IntLiteral","value":119808}},"type":"App"},"type":"App"},"type":"App"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"type":"Abs"},"type":"App"},"identifier":"main"}],"exports":["str","codes","main","cp"],"foreign":[],"imports":[{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Control","Bind"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Control","Semigroupoid"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Enum"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Eq"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Functor"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Maybe"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","Show"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","String","CodePoints"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Data","String","CodeUnits"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Effect"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Effect","Console"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Golden","StringCodePoints","Test"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Partial","Unsafe"]},{"annotation":{"meta":null,"sourceSpan":{"end":[8,15],"start":[8,1]}},"moduleName":["Prelude"]},{"annotation":{"meta":null,"sourceSpan":{"end":[48,39],"start":[6,1]}},"moduleName":["Prim"]}],"moduleName":["Golden","StringCodePoints","Test"],"modulePath":"golden/Golden/StringCodePoints/Test.purs","reExports":{},"sourceSpan":{"end":[48,39],"start":[6,1]}} \ No newline at end of file diff --git a/test/ps/output/Golden.StringCodePoints.Test/golden.ir b/test/ps/output/Golden.StringCodePoints.Test/golden.ir index 7701eac..a5580bd 100644 --- a/test/ps/output/Golden.StringCodePoints.Test/golden.ir +++ b/test/ps/output/Golden.StringCodePoints.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.HeytingAlgebra", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.2.1/src/Data/HeytingAlgebra.purs" + ( ModuleName "Data.HeytingAlgebra" ) ".spago/prelude/v7.3.0/src/Data/HeytingAlgebra.purs" [ ( Nothing, Name "boolConj" ), ( Nothing, Name "boolDisj" ), ( Nothing, Name "boolNot" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Eq", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.3.0/src/Data/Eq.purs" [ ( Nothing, Name "eqIntImpl" ), ( Nothing, Name "eqCharImpl" ), @@ -20,43 +20,43 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Show", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ), ( Nothing, Name "showArrayImpl" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Ord", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Ord" ) ".spago/prelude/v7.2.1/src/Data/Ord.purs" + ( ModuleName "Data.Ord" ) ".spago/prelude/v7.3.0/src/Data/Ord.purs" [ ( Nothing, Name "ordIntImpl" ), ( Nothing, Name "ordCharImpl" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Bounded", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Bounded" ) ".spago/prelude/v7.2.1/src/Data/Bounded.purs" + ( ModuleName "Data.Bounded" ) ".spago/prelude/v7.3.0/src/Data/Bounded.purs" [ ( Nothing, Name "topChar" ), ( Nothing, Name "bottomChar" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.EuclideanRing", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.EuclideanRing" ) ".spago/prelude/v7.2.1/src/Data/EuclideanRing.purs" + ( ModuleName "Data.EuclideanRing" ) ".spago/prelude/v7.3.0/src/Data/EuclideanRing.purs" [ ( Nothing, Name "intDegree" ), ( Nothing, Name "intDiv" ), ( Nothing, Name "intMod" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Data.Enum", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Enum" ) ".spago/enums/v6.1.0/src/Data/Enum.purs" + ( ModuleName "Data.Enum" ) ".spago/enums/v6.1.1/src/Data/Enum.purs" [ ( Nothing, Name "toCharCode" ), ( Nothing, Name "fromCharCode" ) ] ), Standalone ( QName @@ -192,7 +192,7 @@ UberModule [ ( PropName "append", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Semigroup" ) ".spago/prelude/v7.2.1/src/Data/Semigroup.purs" + ( ModuleName "Data.Semigroup" ) ".spago/prelude/v7.3.0/src/Data/Semigroup.purs" [ ( Nothing, Name "concatString" ) ] ) ( PropName "concatString" ) @@ -272,7 +272,7 @@ UberModule [ ( PropName "sub", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ring" ) ".spago/prelude/v7.2.1/src/Data/Ring.purs" + ( ModuleName "Data.Ring" ) ".spago/prelude/v7.3.0/src/Data/Ring.purs" [ ( Nothing, Name "intSub" ) ] ) ( PropName "intSub" ) @@ -2296,7 +2296,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -2435,7 +2435,7 @@ UberModule [ ( PropName "map", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Functor" ) ".spago/prelude/v7.2.1/src/Data/Functor.purs" + ( ModuleName "Data.Functor" ) ".spago/prelude/v7.3.0/src/Data/Functor.purs" [ ( Nothing, Name "arrayMap" ) ] ) ( PropName "arrayMap" ) @@ -2493,7 +2493,7 @@ UberModule ) ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Array" ) ".spago/arrays/v7.3.0/src/Data/Array.purs" + ( ModuleName "Data.Array" ) ".spago/arrays/v7.4.1/src/Data/Array.purs" [ ( Nothing, Name "length" ) ] ) ( PropName "length" ) diff --git a/test/ps/output/Golden.StringCodePoints.Test/golden.lua b/test/ps/output/Golden.StringCodePoints.Test/golden.lua index 9a0c9ce..09d452d 100644 --- a/test/ps/output/Golden.StringCodePoints.Test/golden.lua +++ b/test/ps/output/Golden.StringCodePoints.Test/golden.lua @@ -93,23 +93,31 @@ M.Data_EuclideanRing_foreign = (function() } end)() M.Effect_foreign = { - pureE = function(a) - return function() - return a - end + pureE = function(a) return function() return a end end, + bindE = function(a) return function(f) return function() return f(a())() end end end +} +M.Data_Enum_foreign = { + toCharCode = function(c) + -- pslua compiles a PureScript Char as a string of its UTF-8 bytes, so decode + -- the first code point (JS does c.charCodeAt(0)) rather than the first byte. + local b1 = c:byte(1) + if b1 < 0x80 then return b1 end + if b1 < 0xE0 then return (b1 - 0xC0) * 0x40 + (c:byte(2) - 0x80) end + if b1 < 0xF0 then return (b1 - 0xE0) * 0x1000 + (c:byte(2) - 0x80) * 0x40 + (c:byte(3) - 0x80) end + return (b1 - 0xF0) * 0x40000 + (c:byte(2) - 0x80) * 0x1000 + (c:byte(3) - 0x80) * 0x40 + (c:byte(4) - 0x80) end, - bindE = function(a) - return function(f) - return function() - return f(a())() - end + fromCharCode = function(n) + -- Encode the code point as UTF-8 (JS String.fromCharCode over 0..65535); + -- string.char alone errors above 255 and emits a raw byte for 128..255. + if n < 0x80 then return string.char(n) end + if n < 0x800 then return string.char(0xC0 + math.floor(n / 0x40), 0x80 + (n % 0x40)) end + if n < 0x10000 then + return string.char(0xE0 + math.floor(n / 0x1000), 0x80 + (math.floor(n / 0x40) % 0x40), 0x80 + (n % 0x40)) end + return string.char(0xF0 + math.floor(n / 0x40000), 0x80 + (math.floor(n / 0x1000) % 0x40), + 0x80 + (math.floor(n / 0x40) % 0x40), 0x80 + (n % 0x40)) end } -M.Data_Enum_foreign = { - toCharCode = function(c) return c:byte() end, - fromCharCode = string.char -} M.Data_String_CodeUnits_foreign = (function() -- PureScript indices are 0-based, Lua string positions are 1-based; -- the exports below convert between the two. Pattern arguments are diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir index 794ecc5..7955b36 100644 --- a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.ir @@ -4,13 +4,13 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Semiring", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.2.1/src/Data/Semiring.purs" + ( ModuleName "Data.Semiring" ) ".spago/prelude/v7.3.0/src/Data/Semiring.purs" [ ( Nothing, Name "intAdd" ), ( Nothing, Name "intMul" ) ] ), Standalone ( QName { qnameModuleName = ModuleName "Effect", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Effect" ) ".spago/effect/v4.1.0/src/Effect.purs" + ( ModuleName "Effect" ) ".spago/effect/v4.1.3/src/Effect.purs" [ ( Nothing, Name "pureE" ), ( Nothing, Name "bindE" ), ( Nothing, Name "untilE" ) ] ), Standalone ( QName @@ -314,7 +314,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Ord" ) ".spago/prelude/v7.2.1/src/Data/Ord.purs" + ( ModuleName "Data.Ord" ) ".spago/prelude/v7.3.0/src/Data/Ord.purs" [ ( Nothing, Name "ordIntImpl" ) ] ) ( PropName "ordIntImpl" ) @@ -342,7 +342,7 @@ UberModule [ ( PropName "eq", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Eq" ) ".spago/prelude/v7.2.1/src/Data/Eq.purs" + ( ModuleName "Data.Eq" ) ".spago/prelude/v7.3.0/src/Data/Eq.purs" [ ( Nothing, Name "eqIntImpl" ) ] ) ( PropName "eqIntImpl" ) @@ -712,7 +712,7 @@ UberModule ( App Nothing ( ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Effect.Console" ) ".spago/console/v6.1.0/src/Effect/Console.purs" + ( ModuleName "Effect.Console" ) ".spago/console/v6.1.1/src/Effect/Console.purs" [ ( Nothing, Name "log" ) ] ) ( PropName "log" ) @@ -723,7 +723,7 @@ UberModule [ ( PropName "show", ObjectProp ( Just Always ) ( ForeignImport Nothing - ( ModuleName "Data.Show" ) ".spago/prelude/v7.2.1/src/Data/Show.purs" + ( ModuleName "Data.Show" ) ".spago/prelude/v7.3.0/src/Data/Show.purs" [ ( Nothing, Name "showIntImpl" ) ] ) ( PropName "showIntImpl" ) diff --git a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua index 2b9e127..ca93c8e 100644 --- a/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua +++ b/test/ps/output/Golden.TailRecM2Shadow.Test/golden.lua @@ -24,24 +24,9 @@ M.Data_Semiring_foreign = { intMul = function(x) return function(y) return x * y end end } M.Effect_foreign = { - 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) - return function() - while not f() do - end - end - end + 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) return function() while not f() do end end end } M.Effect_Ref_foreign = { _new = function(val) return function() return {value = val} end end, diff --git a/test/ps/packages.dhall b/test/ps/packages.dhall index e4f599e..1399e89 100644 --- a/test/ps/packages.dhall +++ b/test/ps/packages.dhall @@ -3,7 +3,7 @@ let upstream-ps = sha256:e48c9b283ca89ec994453459fb74c4b5b5a9432349f83a2e104f39dd869a0f6e let upstream-lua = - https://github.com/purescript-lua/purescript-lua-package-sets/releases/download/psc-0.15.15-20260613-2/packages.dhall - sha256:b006e1fd8aa8cd290faf65852f37f62ad3bf5fe97fa3a7c30c97ff7ddfa49807 + https://github.com/purescript-lua/purescript-lua-package-sets/releases/download/psc-0.15.15-20260615/packages.dhall + sha256:76624f5210200039e6510b8b7666851cfe4d665fab75bf65707474bd53ca5c8a in upstream-ps // upstream-lua From 331b2b8d4d940a7bacf24eb87d156aa39352172a Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 15:53:10 +0200 Subject: [PATCH 8/9] test: bound golden-diff memory and cap the test RTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The golden suite spiked to ~21 GiB (and got OOM-killed) when many goldens differed: hspec held two full pretty-printed blobs plus their diff per failure. Two changes: - Test.Hspec.Golden now reports a bounded, line-oriented summary by default (first differing line + a small window + line counts + the actual-file path); set PSLUA_GOLDEN_FULL_DIFF=1 for the complete expected/actual diff. - The test suite's RTS opts go from -N (all 24 cores → parallel-GC RSS scales with core count) to -N4 -c -M16g, so peak residency is bounded and a runaway heap-overflows cleanly instead of OOM-killing the machine. Full suite: 233 examples, 0 failures. --- pslua.cabal | 11 ++- test/Test/Hspec/Golden.hs | 77 +++++++++++++++++-- .../Golden.StringCodePoints.Test/golden.ir | 2 +- .../Golden.StringCodePoints.Test/golden.lua | 18 +++-- test/ps/packages.dhall | 4 +- 5 files changed, 95 insertions(+), 17 deletions(-) diff --git a/pslua.cabal b/pslua.cabal index 5df7ff5..2bdd954 100644 --- a/pslua.cabal +++ b/pslua.cabal @@ -181,7 +181,16 @@ test-suite spec Test.Hspec.Hedgehog.Extended hs-source-dirs: test - ghc-options: -threaded -rtsopts -fprof-auto -with-rtsopts=-N + + -- Bound the test runner's memory. -N (= all cores) made the parallel GC's + -- peak RSS scale with the core count (24 here); -N4 caps that. -c compacts + -- the oldest generation to lower peak residency, and -M16g turns a runaway + -- (e.g. a large golden mismatch) into a clean "heap overflow" instead of an + -- OOM kill that takes the whole machine down. See Test.Hspec.Golden for the + -- bounded golden-diff that keeps failures cheap. + ghc-options: + -threaded -rtsopts -fprof-auto "-with-rtsopts=-N4 -c -M16g" + build-depends: , call-stack ^>=0.4.0 , exceptions ^>=0.10.8 diff --git a/test/Test/Hspec/Golden.hs b/test/Test/Hspec/Golden.hs index 381ac97..5b93c30 100644 --- a/test/Test/Hspec/Golden.hs +++ b/test/Test/Hspec/Golden.hs @@ -8,6 +8,7 @@ module Test.Hspec.Golden ) where +import Data.Text qualified as Text import Path (Abs, File, Path, parent, toFilePath) import Path.IO (createDirIfMissing, doesFileExist) import Test.Hspec.Core.Spec @@ -17,6 +18,15 @@ import Test.Hspec.Core.Spec , ResultStatus (..) ) +{- | Env var that opts back into the full expected/actual diff. By default a +golden mismatch reports only a bounded, line-oriented summary (the first +differing line plus a small window) so a run with many mismatches does not +hold two full pretty-printed blobs — and their diff — per failure. Set this +(to anything) for the complete diff, à la tasty-golden's options. +-} +fullDiffEnvVar ∷ String +fullDiffEnvVar = "PSLUA_GOLDEN_FULL_DIFF" + {- | Golden tests parameters @ @@ -86,6 +96,10 @@ fromGoldenResult = \case Result "Files golden and actual not match" (Failure Nothing (ExpectedButGot Nothing expected actual)) + MissmatchSummary summary → + Result + "Files golden and actual not match" + (Failure Nothing (Reason summary)) defaultGolden ∷ Path Abs File @@ -95,7 +109,7 @@ defaultGolden defaultGolden goldenFile actualFile produceOutput = Golden { produceOutput - , encodePretty = show + , encodePretty = toString , writeToFile = \f → writeFileBS (toFilePath f) . encodeUtf8 , readFromFile = fmap decodeUtf8 . readFileBS . toFilePath , goldenFile @@ -106,10 +120,48 @@ defaultGolden goldenFile actualFile produceOutput = -- | Possible results from a golden test execution data GoldenResult = MissmatchOutput String String + | -- | A bounded, line-oriented mismatch summary (the default). + MissmatchSummary String | SameOutput | FirstExecutionSucceed | FirstExecutionFail +{- | A bounded, line-oriented summary of a golden mismatch: the first differing +line, a small window of each side, the line counts, and a pointer to the actual +file. Keeps each failure O(window) instead of retaining two full blobs (and +their diff). Set 'fullDiffEnvVar' for the complete expected/actual diff. +-} +boundedSummary ∷ Maybe (Path Abs File) → String → String → String +boundedSummary mActual expected actual = + let els = Text.lines (toText expected) + als = Text.lines (toText actual) + common = length (takeWhile (uncurry (==)) (zip els als)) + win = 8 + numbered ls = + [ " " <> show (common + i + 1) <> " | " <> toString l + | (i, l) ← zip [0 ..] (take win (drop common ls)) + ] + in toString . Text.unlines . fmap toText . concat $ + [ + [ "Golden mismatch (first difference at line " + <> show (common + 1) + <> ")." + , " expected: " + <> show (length els) + <> " line(s); actual: " + <> show (length als) + <> " line(s)." + , " expected, from the first difference:" + ] + , numbered els + , [" actual, from the first difference:"] + , numbered als + , + [ " full actual output: " <> maybe "(not written)" toFilePath mActual + , " re-run with " <> fullDiffEnvVar <> "=1 for the complete diff." + ] + ] + -- | Runs a Golden test. runGolden ∷ Eq str ⇒ Golden str → IO GoldenResult runGolden Golden {..} = do @@ -134,10 +186,19 @@ runGolden Golden {..} = do else FirstExecutionSucceed else do contentGolden ← readFromFile goldenFile - pure - if contentGolden == output - then SameOutput - else - MissmatchOutput - (encodePretty contentGolden) - (encodePretty output) + if contentGolden == output + then pure SameOutput + else do + wantFull ← isJust <$> lookupEnv fullDiffEnvVar + pure + if wantFull + then + MissmatchOutput + (encodePretty contentGolden) + (encodePretty output) + else + MissmatchSummary $ + boundedSummary + actualFile + (encodePretty contentGolden) + (encodePretty output) diff --git a/test/ps/output/Golden.StringCodePoints.Test/golden.ir b/test/ps/output/Golden.StringCodePoints.Test/golden.ir index a5580bd..b18b624 100644 --- a/test/ps/output/Golden.StringCodePoints.Test/golden.ir +++ b/test/ps/output/Golden.StringCodePoints.Test/golden.ir @@ -56,7 +56,7 @@ UberModule ( QName { qnameModuleName = ModuleName "Data.Enum", qnameName = Name "foreign" }, ForeignImport Nothing - ( ModuleName "Data.Enum" ) ".spago/enums/v6.1.1/src/Data/Enum.purs" + ( ModuleName "Data.Enum" ) ".spago/enums/v6.1.2/src/Data/Enum.purs" [ ( Nothing, Name "toCharCode" ), ( Nothing, Name "fromCharCode" ) ] ), Standalone ( QName diff --git a/test/ps/output/Golden.StringCodePoints.Test/golden.lua b/test/ps/output/Golden.StringCodePoints.Test/golden.lua index 09d452d..25716f1 100644 --- a/test/ps/output/Golden.StringCodePoints.Test/golden.lua +++ b/test/ps/output/Golden.StringCodePoints.Test/golden.lua @@ -98,13 +98,21 @@ M.Effect_foreign = { } M.Data_Enum_foreign = { toCharCode = function(c) - -- pslua compiles a PureScript Char as a string of its UTF-8 bytes, so decode - -- the first code point (JS does c.charCodeAt(0)) rather than the first byte. + -- pslua compiles a PureScript Char literal as a string of its UTF-8 bytes, + -- so decode the first code point (JS c.charCodeAt(0)) when the WHOLE + -- sequence is present. But Data.String.CodeUnits hands this single raw bytes + -- (it slices a String byte-wise and lets the CodePoints layer reassemble), + -- so a lone lead/continuation byte must return that byte rather than read a + -- missing c:byte(2) and crash on nil. + local n = #c local b1 = c:byte(1) if b1 < 0x80 then return b1 end - if b1 < 0xE0 then return (b1 - 0xC0) * 0x40 + (c:byte(2) - 0x80) end - if b1 < 0xF0 then return (b1 - 0xE0) * 0x1000 + (c:byte(2) - 0x80) * 0x40 + (c:byte(3) - 0x80) end - return (b1 - 0xF0) * 0x40000 + (c:byte(2) - 0x80) * 0x1000 + (c:byte(3) - 0x80) * 0x40 + (c:byte(4) - 0x80) + if b1 < 0xE0 and n >= 2 then return (b1 - 0xC0) * 0x40 + (c:byte(2) - 0x80) end + if b1 < 0xF0 and n >= 3 then return (b1 - 0xE0) * 0x1000 + (c:byte(2) - 0x80) * 0x40 + (c:byte(3) - 0x80) end + if b1 >= 0xF0 and n >= 4 then + return (b1 - 0xF0) * 0x40000 + (c:byte(2) - 0x80) * 0x1000 + (c:byte(3) - 0x80) * 0x40 + (c:byte(4) - 0x80) + end + return b1 end, fromCharCode = function(n) -- Encode the code point as UTF-8 (JS String.fromCharCode over 0..65535); diff --git a/test/ps/packages.dhall b/test/ps/packages.dhall index 1399e89..a280947 100644 --- a/test/ps/packages.dhall +++ b/test/ps/packages.dhall @@ -3,7 +3,7 @@ let upstream-ps = sha256:e48c9b283ca89ec994453459fb74c4b5b5a9432349f83a2e104f39dd869a0f6e let upstream-lua = - https://github.com/purescript-lua/purescript-lua-package-sets/releases/download/psc-0.15.15-20260615/packages.dhall - sha256:76624f5210200039e6510b8b7666851cfe4d665fab75bf65707474bd53ca5c8a + https://github.com/purescript-lua/purescript-lua-package-sets/releases/download/psc-0.15.15-20260615-2/packages.dhall + sha256:da1998fd6cf7c411b8decb16d2be5a8b1499a0789e1ac5a2790d2ad9868aaf6e in upstream-ps // upstream-lua From c32ae27843159cfc5488dccc894ce24bed7810a9 Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 15 Jun 2026 15:53:11 +0200 Subject: [PATCH 9/9] docs: point template/example links at the purescript-lua org (#103) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8502488..a3778bf 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ Consider configuring [Cachix](https://docs.cachix.org/installation) as a binary ``` cachix use purescript-lua ``` -You can use this [template repository](https://github.com/Unisay/purescript-lua-template) to initialize your project. +You can use this [template repository](https://github.com/purescript-lua/purescript-lua-template) to initialize your project. -Here is an another [example](https://github.com/Unisay/purescript-lua-example) project: Nginx server running Lua code using [OpenResty](https://openresty.org/). +Here is an another [example](https://github.com/purescript-lua/purescript-lua-example) project: Nginx server running Lua code using [OpenResty](https://openresty.org/). If you use [Spago](https://github.com/purescript/spago) to build your PureScript project, then you can configure `pslua` as a custom backend like this: