diff --git a/.hlint.yaml b/.hlint.yaml index a41958d886d..d9532dcc200 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -27,3 +27,4 @@ - ignore: {name: Use first, within: [UntypedPlutusCore.Evaluation.Machine.Cek]} - ignore: {name: Redundant if, within: [PlutusLedgerApi.V1.Value, PlutusLedgerApi.V1.Data.Value]} - ignore: {name: Replace case with maybe, within: [PlutusLedgerApi.V1.Value, PlutusLedgerApi.V1.Data.Value]} +- ignore: {name: Use bimap, within: [PlutusTx.Builtins.HasOpaque]} diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.budget.expected new file mode 100644 index 00000000000..1f875e2ed21 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 76521974 +| mem: 618}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.expected new file mode 100644 index 00000000000..c53839615ce --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/bls12_381_G1_scalarMul/mul-neg-one/mul-neg-one.uplc.expected @@ -0,0 +1,7 @@ +(program + 1.0.0 + (con + bls12_381_G1_element + 0x8bd61864f519748032551e42e0ac417fd828f079454e3e3c9891c5c29ed7f10bdecc046854e3931cb7002779bd76d71f + ) +) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-07/case-07.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-07/case-07.uplc.budget.expected index c87df86098c..efb388a633c 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-07/case-07.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-07/case-07.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 260294 -| mem: 601}) \ No newline at end of file +({cpu: 260453 +| mem: 602}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-09/case-09.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-09/case-09.uplc.budget.expected index cf9145bf677..efb388a633c 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-09/case-09.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/replicateByte/case-09/case-09.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 423110 -| mem: 1625}) \ No newline at end of file +({cpu: 260453 +| mem: 602}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-11/case-11.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-11/case-11.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-11/case-11.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-11/case-11.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-12/case-12.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-12/case-12.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-12/case-12.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-12/case-12.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-13/case-13.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-13/case-13.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-13/case-13.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-13/case-13.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-14/case-14.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-14/case-14.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-14/case-14.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-14/case-14.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-15/case-15.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-15/case-15.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-15/case-15.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-15/case-15.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-16/case-16.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-16/case-16.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-16/case-16.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-16/case-16.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-17/case-17.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-17/case-17.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-17/case-17.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-17/case-17.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-18/case-18.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-18/case-18.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-18/case-18.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-18/case-18.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-20/case-20.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-20/case-20.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-20/case-20.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-20/case-20.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-21/case-21.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-21/case-21.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-21/case-21.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-21/case-21.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-22/case-22.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-22/case-22.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-22/case-22.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-22/case-22.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-23/case-23.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-23/case-23.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-23/case-23.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-23/case-23.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-24/case-24.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-24/case-24.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-24/case-24.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-24/case-24.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-25/case-25.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-25/case-25.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-25/case-25.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-25/case-25.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-26/case-26.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-26/case-26.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-26/case-26.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-26/case-26.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-27/case-27.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-27/case-27.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-27/case-27.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-27/case-27.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-29/case-29.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-29/case-29.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-29/case-29.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-29/case-29.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-30/case-30.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-30/case-30.uplc.budget.expected index 30dac2d1008..a1c5da50f2b 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-30/case-30.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-30/case-30.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 430941 +({cpu: 562877 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-31/case-31.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-31/case-31.uplc.budget.expected index 30dac2d1008..a1c5da50f2b 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-31/case-31.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-31/case-31.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 430941 +({cpu: 562877 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-32/case-32.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-32/case-32.uplc.budget.expected index 1abc268e00a..859038aac2b 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-32/case-32.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-32/case-32.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 732509 +({cpu: 1769149 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-33/case-33.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-33/case-33.uplc.budget.expected index 1abc268e00a..859038aac2b 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-33/case-33.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-33/case-33.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 732509 +({cpu: 1769149 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-34/case-34.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-34/case-34.uplc.budget.expected index d51c314bbff..dc3bad8c412 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-34/case-34.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-34/case-34.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 808086 +({cpu: 958870 | mem: 1402}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-35/case-35.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-35/case-35.uplc.budget.expected index d51c314bbff..dc3bad8c412 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-35/case-35.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-35/case-35.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 808086 +({cpu: 958870 | mem: 1402}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-36/case-36.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-36/case-36.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-36/case-36.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-36/case-36.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-37/case-37.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-37/case-37.uplc.budget.expected index 927839980d3..4ef433525a7 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-37/case-37.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-37/case-37.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 412093 +({cpu: 487485 | mem: 801}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-38/case-38.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-38/case-38.uplc.budget.expected index c6aac0b723f..d454b574d76 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-38/case-38.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-38/case-38.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 449789 +({cpu: 638269 | mem: 806}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-39/case-39.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-39/case-39.uplc.budget.expected index 07b22130740..244947ff0d0 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-39/case-39.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-39/case-39.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 940022 +({cpu: 1486614 | mem: 1412}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-40/case-40.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-40/case-40.uplc.budget.expected index c6aac0b723f..d454b574d76 100644 --- a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-40/case-40.uplc.budget.expected +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/writeBits/case-40/case-40.uplc.budget.expected @@ -1,2 +1,2 @@ -({cpu: 449789 +({cpu: 638269 | mem: 806}) \ No newline at end of file diff --git a/plutus-core/cost-model/test/TH.hs b/plutus-core/cost-model/test/TH.hs index ea849584b16..e193400d399 100644 --- a/plutus-core/cost-model/test/TH.hs +++ b/plutus-core/cost-model/test/TH.hs @@ -3,17 +3,14 @@ restrictions. -} -{-# LANGUAGE TemplateHaskell #-} - -module TH (genTest) -where +module TH (genTest) where import Data.Char (toUpper) import Language.Haskell.TH toUpper1 :: String -> String toUpper1 [] = error "empty string in toUpper1" -toUpper1 (c:cs) = (toUpper c):cs +toUpper1 (c:cs) = toUpper c : cs mkIterApp :: Exp -> [Exp] -> Exp mkIterApp = foldl AppE diff --git a/plutus-tx-plugin/plutus-tx-plugin.cabal b/plutus-tx-plugin/plutus-tx-plugin.cabal index b5d191b589c..f36056070ef 100644 --- a/plutus-tx-plugin/plutus-tx-plugin.cabal +++ b/plutus-tx-plugin/plutus-tx-plugin.cabal @@ -124,6 +124,7 @@ test-suite plutus-tx-plugin-tests Budget.Spec Budget.WithGHCOptimisations Budget.WithoutGHCOptimisations + ByteStringLiterals.Spec IntegerLiterals.NoStrict.NegativeLiterals.Spec IntegerLiterals.NoStrict.NoNegativeLiterals.Spec IntegerLiterals.Strict.NegativeLiterals.Spec diff --git a/plutus-tx-plugin/src/PlutusTx/Compiler/Expr.hs b/plutus-tx-plugin/src/PlutusTx/Compiler/Expr.hs index 86f64e3a6b6..d9430093b8b 100644 --- a/plutus-tx-plugin/src/PlutusTx/Compiler/Expr.hs +++ b/plutus-tx-plugin/src/PlutusTx/Compiler/Expr.hs @@ -1,8 +1,10 @@ -- editorconfig-checker-disable-file +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PartialTypeSignatures #-} @@ -12,6 +14,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ViewPatterns #-} + {-# OPTIONS_GHC -Wno-partial-type-signatures #-} -- | Functions for compiling GHC Core expressions into Plutus Core terms. @@ -24,6 +27,7 @@ import GHC.Core qualified as GHC import GHC.Core.Class qualified as GHC import GHC.Core.Multiplicity qualified as GHC import GHC.Core.TyCo.Rep qualified as GHC +import GHC.Num.Integer qualified import GHC.Plugins qualified as GHC import GHC.Types.CostCentre qualified as GHC import GHC.Types.Id.Make qualified as GHC @@ -76,12 +80,13 @@ import Data.ByteString qualified as BS import Data.Generics.Uniplate.Data (transform, universeBi) import Data.List (elemIndex, isPrefixOf, isSuffixOf) import Data.Map qualified as Map -import Data.Maybe +import Data.Maybe (mapMaybe) import Data.Set qualified as Set import Data.Text qualified as T import Data.Text.Encoding qualified as TE -import Data.Traversable -import GHC.Num.Integer qualified +import Data.Traversable (for) +import Data.Word (Word8) + {- Note [System FC and System FW] Haskell uses system FC, which includes type equalities and coercions. @@ -136,23 +141,51 @@ compileLiteral = \case -- do different things to the inner expression. This one assumes it's a literal, the other one keeps compiling -- through it. --- | Get the bytestring content of a string expression, if possible. Follows (Haskell) variable references! -stringExprContent :: GHC.CoreExpr -> Maybe BS.ByteString -stringExprContent = \case - GHC.Lit (GHC.LitString bs) -> Just bs - -- unpackCString# / unpackCStringUtf8# are just wrappers around a literal - GHC.Var n `GHC.App` expr - | let name = GHC.getName n - , name == GHC.unpackCStringName || name == GHC.unpackCStringUtf8Name -> - stringExprContent expr +data StringExprContentAs = AsBytes | AsText + +-- | Get the bytestring content of a string expression, if possible. +-- Follows (Haskell) variable references! +stringExprContent :: StringExprContentAs -> GHC.CoreExpr -> Maybe BS.ByteString +stringExprContent contentAs coreExpr = case coreExpr of + GHC.Lit (GHC.LitString bytes) -> + Just bytes + GHC.Var isUnpackCString `GHC.App` GHC.Lit (GHC.LitString bytes) + | GHC.getName isUnpackCString == GHC.unpackCStringName -> + Just bytes + GHC.Var isUnpackCStringUtf8 `GHC.App` GHC.Lit (GHC.LitString bytes) + | GHC.getName isUnpackCStringUtf8 == GHC.unpackCStringUtf8Name -> + case contentAs of + AsText -> Just bytes + AsBytes -> + -- GHC stores bytestring literals UTF-8 encoded, decoding them at runtime. + -- In Plinth we decode such bytestrings in compile-time. + BS.pack <$> fromUtf8 (BS.unpack bytes) -- See Note [unpackFoldrCString#] GHC.Var build `GHC.App` _ `GHC.App` GHC.Lam _ (GHC.Var unpack `GHC.App` _ `GHC.App` expr) - | GHC.getName build == GHC.buildName && GHC.getName unpack == GHC.unpackCStringFoldrName -> stringExprContent expr + | GHC.getName build == GHC.buildName && GHC.getName unpack == GHC.unpackCStringFoldrName -> + stringExprContent contentAs expr -- GHC helpfully generates an empty list for the empty string literal instead of a 'LitString' GHC.Var nil `GHC.App` GHC.Type (GHC.tyConAppTyCon_maybe -> Just tc) - | nil == GHC.dataConWorkId GHC.nilDataCon, GHC.getName tc == GHC.charTyConName -> Just mempty - -- Chase variable references! GHC likes to lift string constants to variables, that is not good for us! - GHC.Var (GHC.maybeUnfoldingTemplate . GHC.realIdUnfolding -> Just unfolding) -> stringExprContent unfolding + | nil == GHC.dataConWorkId GHC.nilDataCon, GHC.getName tc == GHC.charTyConName -> + Just mempty + -- Chase variable references! GHC likes to lift string constants to variables, + -- that is not good for us! + GHC.Var (GHC.maybeUnfoldingTemplate . GHC.realIdUnfolding -> Just unfolding) -> + stringExprContent contentAs unfolding + _ -> Nothing + +{- | Decoding that undoes GHC's UTF-8 encoding of bytestring literals: + +This isn't a full UTF-8 decoder: it only decodes the subset of UTF-8 that +is expected to be found in bytestring literals: 0x00 - 0xFF +-} +fromUtf8 :: [Word8] -> Maybe [Word8] +fromUtf8 = \case + [] -> Just [] + 192 : 128 : rest -> (0x00 :) <$> fromUtf8 rest + 194 : b : rest | b > 127 && b < 192 -> (b :) <$> fromUtf8 rest + 195 : b : rest | b > 127 && b < 192 -> ((b + 64) :) <$> fromUtf8 rest + b : rest | b > 0 && b < 128 -> (b :) <$> fromUtf8 rest _ -> Nothing {- | Strip off irrelevant things when we're trying to match a particular pattern in the code. Mostly ticks. @@ -699,13 +732,21 @@ compileExpr e = traceCompilation 2 ("Compiling expr:" GHC.<+> GHC.ppr e) $ do _ -> throwPlain $ CompilationError "No info for Pair builtin" -- TODO: Maybe share this to avoid repeated lookups. Probably cheap, though. - (stringTyName, sbsName) <- case (Map.lookup ''Builtins.BuiltinString nameInfo, Map.lookup 'Builtins.stringToBuiltinString nameInfo) of + (stringTyName, sbsName) <- + case + ( Map.lookup ''Builtins.BuiltinString nameInfo + , Map.lookup 'Builtins.stringToBuiltinString nameInfo + ) of (Just t1, Just t2) -> pure (GHC.getName t1, GHC.getName t2) _ -> throwPlain $ CompilationError "No info for String builtin" - (bsTyName, sbbsName) <- case (Map.lookup ''Builtins.BuiltinByteString nameInfo, Map.lookup 'Builtins.stringToBuiltinByteString nameInfo) of - (Just t1, Just t2) -> pure (GHC.getName t1, GHC.getName t2) - _ -> throwPlain $ CompilationError "No info for ByteString builtin" + (builtinByteStringTyName, sbbsName) <- + case + ( Map.lookup ''Builtins.BuiltinByteString nameInfo + , Map.lookup 'Builtins.stringToBuiltinByteString nameInfo + ) of + (Just t1, Just t2) -> pure (GHC.getName t1, GHC.getName t2) + _ -> throwPlain $ CompilationError "No info for ByteString builtin" useToOpaqueName <- GHC.getName <$> getThing 'Builtins.useToOpaque useFromOpaqueName <- GHC.getName <$> getThing 'Builtins.useFromOpaque @@ -730,39 +771,54 @@ compileExpr e = traceCompilation 2 ("Compiling expr:" GHC.<+> GHC.ppr e) $ do -- to know we're looking at fromString. -- We can safely commit to this match as soon as we've seen fromString - we won't accept -- any applications of fromString that aren't creating literals of our builtin types. - (strip -> GHC.Var (GHC.idDetails -> GHC.ClassOpId cls)) `GHC.App` GHC.Type ty `GHC.App` _ `GHC.App` content + (strip -> GHC.Var (GHC.idDetails -> GHC.ClassOpId cls)) + `GHC.App` GHC.Type ty `GHC.App` _dict `GHC.App` content | GHC.getName cls == GHC.isStringClassName -> - case GHC.tyConAppTyCon_maybe ty of - Just tc -> case stringExprContent (strip content) of - Just bs -> - if - | GHC.getName tc == bsTyName -> pure $ PIR.Constant annMayInline $ PLC.someValue bs - | GHC.getName tc == stringTyName -> case TE.decodeUtf8' bs of - Right t -> pure $ PIR.Constant annMayInline $ PLC.someValue t - Left err -> - throwPlain . CompilationError $ - "Text literal with invalid UTF-8 content: " <> (T.pack $ show err) - | otherwise -> - throwSd UnsupportedError $ - "Use of fromString on type other than builtin strings or bytestrings:" GHC.<+> GHC.ppr ty - Nothing -> - throwSd CompilationError $ - "Use of fromString with inscrutable content:" GHC.<+> GHC.ppr content + case GHC.tyConAppTyCon_maybe ty of -- extract Type constructor without arguments + Just tc -> + if + | GHC.getName tc == builtinByteStringTyName -> + case stringExprContent AsBytes (strip content) of + Nothing -> + throwSd CompilationError $ + "Use of fromString @BuiltinByteString with inscrutable content:" + GHC.<+> GHC.ppr content + Just bs -> + pure $ PIR.Constant annMayInline $ PLC.someValue bs + | GHC.getName tc == stringTyName -> + case stringExprContent AsText (strip content) of + Nothing -> + throwSd CompilationError $ + "Use of fromString @BuiltinString with inscrutable content:" + GHC.<+> GHC.ppr content + Just bs -> + case TE.decodeUtf8' bs of + Right t -> pure $ PIR.Constant annMayInline $ PLC.someValue t + Left err -> + throwPlain . CompilationError $ + "Text literal with invalid UTF-8 content: " <> T.pack (show err) + | otherwise -> + throwSd UnsupportedError $ + "Use of fromString on type other than builtin strings or bytestrings:" + GHC.<+> GHC.ppr ty Nothing -> throwSd UnsupportedError $ - "Use of fromString on type other than builtin strings or bytestrings:" GHC.<+> GHC.ppr ty + "Use of fromString on type other than builtin strings or bytestrings:" + GHC.<+> GHC.ppr ty + -- 'stringToBuiltinByteString' invocation - (strip -> GHC.Var n) `GHC.App` (strip -> stringExprContent -> Just bs) + (strip -> GHC.Var n) `GHC.App` (strip -> stringExprContent AsBytes -> Just bs) | GHC.getName n == sbbsName -> pure $ PIR.Constant annMayInline $ PLC.someValue bs -- 'stringToBuiltinString' invocation - (strip -> GHC.Var n) `GHC.App` (strip -> stringExprContent -> Just bs) | GHC.getName n == sbsName -> - case TE.decodeUtf8' bs of - Right t -> pure $ PIR.Constant annMayInline $ PLC.someValue t - Left err -> - throwPlain $ - CompilationError $ - "Text literal with invalid UTF-8 content: " <> (T.pack $ show err) + (strip -> GHC.Var n) `GHC.App` (strip -> stringExprContent AsText -> Just bs) + | GHC.getName n == sbsName -> + case TE.decodeUtf8' bs of + Right t -> pure $ PIR.Constant annMayInline $ PLC.someValue t + Left err -> + throwPlain $ + CompilationError $ + "Text literal with invalid UTF-8 content: " <> (T.pack $ show err) -- See Note [Literals] GHC.Lit lit -> compileLiteral lit -- These are all wrappers around string and char literals, but keeping them allows us to give better errors diff --git a/plutus-tx-plugin/test/AssocMap/Spec.hs b/plutus-tx-plugin/test/AssocMap/Spec.hs index 04e4f2604c2..228b18bae87 100644 --- a/plutus-tx-plugin/test/AssocMap/Spec.hs +++ b/plutus-tx-plugin/test/AssocMap/Spec.hs @@ -91,21 +91,23 @@ map2 = \n -> let m1 = Data.AssocMap.unsafeFromList - [ (n PlutusTx.+ 1, "one") - , (n PlutusTx.+ 2, "two") - , (n PlutusTx.+ 3, "three") - , (n PlutusTx.+ 4, "four") - , (n PlutusTx.+ 5, "five") + [ (n PlutusTx.+ 1, "\1") + , (n PlutusTx.+ 2, "\2") + , (n PlutusTx.+ 3, "\3") + , (n PlutusTx.+ 4, "\4") + , (n PlutusTx.+ 5, "\5") ] m2 = Data.AssocMap.unsafeFromList - [ (n PlutusTx.+ 3, "THREE") - , (n PlutusTx.+ 4, "FOUR") - , (n PlutusTx.+ 6, "SIX") - , (n PlutusTx.+ 7, "SEVEN") + [ (n PlutusTx.+ 3, "\33") + , (n PlutusTx.+ 4, "\44") + , (n PlutusTx.+ 6, "\66") + , (n PlutusTx.+ 7, "\77") ] m = Data.AssocMap.unionWith PlutusTx.appendByteString m1 m2 - in PlutusTx.fmap (\(k, v) -> (k, PlutusTx.decodeUtf8 v)) (Data.AssocMap.toList m) + in PlutusTx.fmap + (\(k, v) -> (k, PlutusTx.decodeUtf8 v)) + (Data.AssocMap.toList m) ||] ) diff --git a/plutus-tx-plugin/test/Budget/9.6/map2-budget.budget.golden b/plutus-tx-plugin/test/Budget/9.6/map2-budget.budget.golden index 432791a44b6..99d8f785118 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map2-budget.budget.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map2-budget.budget.golden @@ -1,2 +1,2 @@ -({cpu: 138097368 -| mem: 465626}) \ No newline at end of file +({cpu: 138096599 +| mem: 465624}) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Budget/9.6/map2.eval.golden b/plutus-tx-plugin/test/Budget/9.6/map2.eval.golden index e8e3b12565c..ca61111946b 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map2.eval.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map2.eval.golden @@ -1,24 +1,22 @@ (constr 1 - (constr 0 (con integer 105) (con string "five")) + (constr 0 (con integer 105) (con string "\ENQ")) (constr 1 - (constr 0 (con integer 104) (con string "fourFOUR")) + (constr 0 (con integer 104) (con string "\EOT,")) (constr 1 - (constr 0 (con integer 103) (con string "threeTHREE")) + (constr 0 (con integer 103) (con string "\ETX!")) (constr 1 - (constr 0 (con integer 102) (con string "two")) + (constr 0 (con integer 102) (con string "\STX")) (constr 1 - (constr 0 (con integer 101) (con string "one")) + (constr 0 (con integer 101) (con string "\SOH")) (constr 1 - (constr 0 (con integer 106) (con string "SIX")) - (constr - 1 (constr 0 (con integer 107) (con string "SEVEN")) (constr 0) - ) + (constr 0 (con integer 106) (con string "B")) + (constr 1 (constr 0 (con integer 107) (con string "M")) (constr 0)) ) ) ) diff --git a/plutus-tx-plugin/test/Budget/9.6/map2.pir.golden b/plutus-tx-plugin/test/Budget/9.6/map2.pir.golden index 2a8e73cb7e8..42c57b4efc6 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map2.pir.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map2.pir.golden @@ -123,25 +123,17 @@ in (/\a -> \(c : Tuple2 integer bytestring -> a -> a) (n : a) -> c - (Tuple2 {integer} {bytestring} (addInteger 3 n) #5448524545) + (Tuple2 {integer} {bytestring} (addInteger 3 n) #21) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 4 n) - #464f5552) + (Tuple2 {integer} {bytestring} (addInteger 4 n) #2c) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 6 n) - #534958) + (Tuple2 {integer} {bytestring} (addInteger 6 n) #42) (c (Tuple2 {integer} {bytestring} (addInteger 7 n) - #534556454e) + #4d) n))))) in letrec @@ -205,27 +197,23 @@ in (/\a -> \(c : Tuple2 integer bytestring -> a -> a) (n : a) -> c - (Tuple2 {integer} {bytestring} (addInteger 1 n) #6f6e65) + (Tuple2 {integer} {bytestring} (addInteger 1 n) #01) (c - (Tuple2 {integer} {bytestring} (addInteger 2 n) #74776f) + (Tuple2 {integer} {bytestring} (addInteger 2 n) #02) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 3 n) - #7468726565) + (Tuple2 {integer} {bytestring} (addInteger 3 n) #03) (c (Tuple2 {integer} {bytestring} (addInteger 4 n) - #666f7572) + #04) (c (Tuple2 {integer} {bytestring} (addInteger 5 n) - #66697665) + #05) n)))))) in letrec diff --git a/plutus-tx-plugin/test/Budget/9.6/map2.uplc.golden b/plutus-tx-plugin/test/Budget/9.6/map2.uplc.golden index 140bc4e7dae..77b4753ceea 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map2.uplc.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map2.uplc.golden @@ -97,22 +97,19 @@ (\i -> iData i) bData (constr 1 - [ (constr 0 [(addInteger 1 n), #6f6e65]) + [ (constr 0 [(addInteger 1 n), #01]) , (constr 1 - [ (constr 0 - [(addInteger 2 n), #74776f]) + [ (constr 0 [(addInteger 2 n), #02]) , (constr 1 [ (constr 0 - [ (addInteger 3 n) - , #7468726565 ]) + [(addInteger 3 n), #03]) , (constr 1 [ (constr 0 - [ (addInteger 4 n) - , #666f7572 ]) + [(addInteger 4 n), #04]) , (constr 1 [ (constr 0 [ (addInteger 5 n) - , #66697665 ]) + , #05 ]) , (constr 0 [ ]) ]) ]) ]) ]) ]))) (fix1 @@ -195,15 +192,14 @@ (\i -> iData i) bData (constr 1 - [ (constr 0 [(addInteger 3 n), #5448524545]) + [ (constr 0 [(addInteger 3 n), #21]) , (constr 1 - [ (constr 0 [(addInteger 4 n), #464f5552]) + [ (constr 0 [(addInteger 4 n), #2c]) , (constr 1 - [ (constr 0 [(addInteger 6 n), #534958]) + [ (constr 0 [(addInteger 6 n), #42]) , (constr 1 [ (constr 0 - [ (addInteger 7 n) - , #534556454e ]) + [(addInteger 7 n), #4d]) , (constr 0 []) ]) ]) ]) ]))) (\`$dToData` `$dToData` -> (\go eta -> goList (go eta)) diff --git a/plutus-tx-plugin/test/Budget/9.6/map3-budget.budget.golden b/plutus-tx-plugin/test/Budget/9.6/map3-budget.budget.golden index 432791a44b6..99d8f785118 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map3-budget.budget.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map3-budget.budget.golden @@ -1,2 +1,2 @@ -({cpu: 138097368 -| mem: 465626}) \ No newline at end of file +({cpu: 138096599 +| mem: 465624}) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Budget/9.6/map3.eval.golden b/plutus-tx-plugin/test/Budget/9.6/map3.eval.golden index e8e3b12565c..ca61111946b 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map3.eval.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map3.eval.golden @@ -1,24 +1,22 @@ (constr 1 - (constr 0 (con integer 105) (con string "five")) + (constr 0 (con integer 105) (con string "\ENQ")) (constr 1 - (constr 0 (con integer 104) (con string "fourFOUR")) + (constr 0 (con integer 104) (con string "\EOT,")) (constr 1 - (constr 0 (con integer 103) (con string "threeTHREE")) + (constr 0 (con integer 103) (con string "\ETX!")) (constr 1 - (constr 0 (con integer 102) (con string "two")) + (constr 0 (con integer 102) (con string "\STX")) (constr 1 - (constr 0 (con integer 101) (con string "one")) + (constr 0 (con integer 101) (con string "\SOH")) (constr 1 - (constr 0 (con integer 106) (con string "SIX")) - (constr - 1 (constr 0 (con integer 107) (con string "SEVEN")) (constr 0) - ) + (constr 0 (con integer 106) (con string "B")) + (constr 1 (constr 0 (con integer 107) (con string "M")) (constr 0)) ) ) ) diff --git a/plutus-tx-plugin/test/Budget/9.6/map3.pir.golden b/plutus-tx-plugin/test/Budget/9.6/map3.pir.golden index 2a8e73cb7e8..42c57b4efc6 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map3.pir.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map3.pir.golden @@ -123,25 +123,17 @@ in (/\a -> \(c : Tuple2 integer bytestring -> a -> a) (n : a) -> c - (Tuple2 {integer} {bytestring} (addInteger 3 n) #5448524545) + (Tuple2 {integer} {bytestring} (addInteger 3 n) #21) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 4 n) - #464f5552) + (Tuple2 {integer} {bytestring} (addInteger 4 n) #2c) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 6 n) - #534958) + (Tuple2 {integer} {bytestring} (addInteger 6 n) #42) (c (Tuple2 {integer} {bytestring} (addInteger 7 n) - #534556454e) + #4d) n))))) in letrec @@ -205,27 +197,23 @@ in (/\a -> \(c : Tuple2 integer bytestring -> a -> a) (n : a) -> c - (Tuple2 {integer} {bytestring} (addInteger 1 n) #6f6e65) + (Tuple2 {integer} {bytestring} (addInteger 1 n) #01) (c - (Tuple2 {integer} {bytestring} (addInteger 2 n) #74776f) + (Tuple2 {integer} {bytestring} (addInteger 2 n) #02) (c - (Tuple2 - {integer} - {bytestring} - (addInteger 3 n) - #7468726565) + (Tuple2 {integer} {bytestring} (addInteger 3 n) #03) (c (Tuple2 {integer} {bytestring} (addInteger 4 n) - #666f7572) + #04) (c (Tuple2 {integer} {bytestring} (addInteger 5 n) - #66697665) + #05) n)))))) in letrec diff --git a/plutus-tx-plugin/test/Budget/9.6/map3.uplc.golden b/plutus-tx-plugin/test/Budget/9.6/map3.uplc.golden index 140bc4e7dae..77b4753ceea 100644 --- a/plutus-tx-plugin/test/Budget/9.6/map3.uplc.golden +++ b/plutus-tx-plugin/test/Budget/9.6/map3.uplc.golden @@ -97,22 +97,19 @@ (\i -> iData i) bData (constr 1 - [ (constr 0 [(addInteger 1 n), #6f6e65]) + [ (constr 0 [(addInteger 1 n), #01]) , (constr 1 - [ (constr 0 - [(addInteger 2 n), #74776f]) + [ (constr 0 [(addInteger 2 n), #02]) , (constr 1 [ (constr 0 - [ (addInteger 3 n) - , #7468726565 ]) + [(addInteger 3 n), #03]) , (constr 1 [ (constr 0 - [ (addInteger 4 n) - , #666f7572 ]) + [(addInteger 4 n), #04]) , (constr 1 [ (constr 0 [ (addInteger 5 n) - , #66697665 ]) + , #05 ]) , (constr 0 [ ]) ]) ]) ]) ]) ]))) (fix1 @@ -195,15 +192,14 @@ (\i -> iData i) bData (constr 1 - [ (constr 0 [(addInteger 3 n), #5448524545]) + [ (constr 0 [(addInteger 3 n), #21]) , (constr 1 - [ (constr 0 [(addInteger 4 n), #464f5552]) + [ (constr 0 [(addInteger 4 n), #2c]) , (constr 1 - [ (constr 0 [(addInteger 6 n), #534958]) + [ (constr 0 [(addInteger 6 n), #42]) , (constr 1 [ (constr 0 - [ (addInteger 7 n) - , #534556454e ]) + [(addInteger 7 n), #4d]) , (constr 0 []) ]) ]) ]) ]))) (\`$dToData` `$dToData` -> (\go eta -> goList (go eta)) diff --git a/plutus-tx-plugin/test/ByteStringLiterals/Spec.hs b/plutus-tx-plugin/test/ByteStringLiterals/Spec.hs new file mode 100644 index 00000000000..dbf9197d07d --- /dev/null +++ b/plutus-tx-plugin/test/ByteStringLiterals/Spec.hs @@ -0,0 +1,114 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} + +module ByteStringLiterals.Spec (tests) where + +import Data.ByteString (ByteString) +import Data.Char (chr) +import Data.Foldable (for_) +import Data.String (fromString) +import PlutusPrelude (display) +import PlutusTx (CompiledCode, getPlcNoAnn) +import PlutusTx.Builtins (BuiltinByteString, fromBuiltin) +import PlutusTx.Builtins.HasOpaque (stringToBuiltinByteString) +import PlutusTx.TH (compile) +import Test.Tasty (TestTree, testGroup) +import Test.Tasty.HUnit (testCase, (@?=)) +import UntypedPlutusCore (Program (_progTerm)) + +tests :: TestTree +tests = + testGroup + "ByteStringLiterals" + [ test_FromString + , testGroup + "Compile BuiltinByteString Literal" + [ test_CompileBuiltinByteStringLiteral_IsString + , test_CompileBuiltinByteStringLiteral_StringToBuiltinByteString + ] + ] + +test_FromString :: TestTree +test_FromString = testCase "fromString" do + for_ [0x00 .. 0xFF] \(i :: Int) -> do + let s :: String = [chr i] + fromBuiltin (fromString @BuiltinByteString s) @?= fromString @ByteString s + +test_CompileBuiltinByteStringLiteral_IsString :: TestTree +test_CompileBuiltinByteStringLiteral_IsString = + testCase "OverloadedStrings" do + display (_progTerm (getPlcNoAnn compiledLiteral)) @?= expectedUplc + where + compiledLiteral :: CompiledCode BuiltinByteString = + $$( compile + [|| + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ + \\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ + \\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ + \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ + \\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ + \\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ + \\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ + \\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ + \\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ + \\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ + \\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ + \\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ + \\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\ + \\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\ + \\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\ + \\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF" + ||] + ) + +test_CompileBuiltinByteStringLiteral_StringToBuiltinByteString :: TestTree +test_CompileBuiltinByteStringLiteral_StringToBuiltinByteString = + testCase "stringToBuiltinByteString" do + display (_progTerm (getPlcNoAnn compiledLiteral)) @?= expectedUplc + where + compiledLiteral :: CompiledCode BuiltinByteString = + $$( compile + [|| + stringToBuiltinByteString + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ + \\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ + \\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ + \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ + \\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ + \\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ + \\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ + \\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ + \\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ + \\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ + \\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ + \\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ + \\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\ + \\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\ + \\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\ + \\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF" + ||] + ) + +expectedUplc :: String +expectedUplc = + "(con\n bytestring\n #\ + \000102030405060708090a0b0c0d0e0f\ + \101112131415161718191a1b1c1d1e1f\ + \202122232425262728292a2b2c2d2e2f\ + \303132333435363738393a3b3c3d3e3f\ + \404142434445464748494a4b4c4d4e4f\ + \505152535455565758595a5b5c5d5e5f\ + \606162636465666768696a6b6c6d6e6f\ + \707172737475767778797a7b7c7d7e7f\ + \808182838485868788898a8b8c8d8e8f\ + \909192939495969798999a9b9c9d9e9f\ + \a0a1a2a3a4a5a6a7a8a9aaabacadaeaf\ + \b0b1b2b3b4b5b6b7b8b9babbbcbdbebf\ + \c0c1c2c3c4c5c6c7c8c9cacbcccdcecf\ + \d0d1d2d3d4d5d6d7d8d9dadbdcdddedf\ + \e0e1e2e3e4e5e6e7e8e9eaebecedeeef\ + \f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff\ + \\n)" diff --git a/plutus-tx-plugin/test/Spec.hs b/plutus-tx-plugin/test/Spec.hs index 6e7e74d74b6..9a9b63dd44b 100644 --- a/plutus-tx-plugin/test/Spec.hs +++ b/plutus-tx-plugin/test/Spec.hs @@ -4,6 +4,7 @@ import AsData.Budget.Spec qualified as AsData.Budget import AssocMap.Spec qualified as AssocMap import Blueprint.Tests qualified import Budget.Spec qualified as Budget +import ByteStringLiterals.Spec qualified as ByteStringLiterals import IntegerLiterals.NoStrict.NegativeLiterals.Spec qualified import IntegerLiterals.NoStrict.NoNegativeLiterals.Spec qualified import IntegerLiterals.Strict.NegativeLiterals.Spec qualified @@ -25,12 +26,14 @@ main = defaultMain tests tests :: TestTree tests = - runTestNested ["test"] + runTestNested + ["test"] [ Plugin.tests , IntegerLiterals.NoStrict.NegativeLiterals.Spec.tests , IntegerLiterals.NoStrict.NoNegativeLiterals.Spec.tests , IntegerLiterals.Strict.NegativeLiterals.Spec.tests , IntegerLiterals.Strict.NoNegativeLiterals.Spec.tests + , embed ByteStringLiterals.tests , IsData.tests , Lift.tests , TH.tests diff --git a/plutus-tx/src/PlutusTx/Builtins/HasOpaque.hs b/plutus-tx/src/PlutusTx/Builtins/HasOpaque.hs index ed784740a52..3ce21e91bad 100644 --- a/plutus-tx/src/PlutusTx/Builtins/HasOpaque.hs +++ b/plutus-tx/src/PlutusTx/Builtins/HasOpaque.hs @@ -13,7 +13,7 @@ module PlutusTx.Builtins.HasOpaque where -import PlutusTx.Base (id, ($)) +import PlutusTx.Base (id) import PlutusTx.Bool (Bool (..)) import PlutusTx.Builtins.Internal @@ -43,7 +43,7 @@ an unfolding. -} stringToBuiltinByteString :: Haskell.String -> BuiltinByteString -stringToBuiltinByteString str = encodeUtf8 $ stringToBuiltinString str +stringToBuiltinByteString str = BuiltinByteString (fromString str) {-# OPAQUE stringToBuiltinByteString #-} stringToBuiltinString :: Haskell.String -> BuiltinString @@ -226,7 +226,7 @@ instance HasToOpaque (BuiltinData, BuiltinData) (BuiltinPair BuiltinData Builtin {-# INLINABLE toOpaque #-} instance (HasFromOpaque arep a, HasFromOpaque brep b) => HasFromOpaque (BuiltinPair arep brep) (a, b) where - fromOpaque p = (fromOpaque $ fst p, fromOpaque $ snd p) + fromOpaque p = (fromOpaque (fst p), fromOpaque (snd p)) {-# INLINABLE fromOpaque #-} instance HasToOpaque BuiltinData BuiltinData