From ca0b1efefd6db1e0932f243592f1320a8ecf7951 Mon Sep 17 00:00:00 2001 From: Chase Date: Mon, 10 Jan 2022 19:52:10 +0530 Subject: [PATCH 1/3] Fix boolean functions not short circuiting --- Plutarch/Bool.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plutarch/Bool.hs b/Plutarch/Bool.hs index 8e071aa0e..64fd46d8b 100644 --- a/Plutarch/Bool.hs +++ b/Plutarch/Bool.hs @@ -74,7 +74,7 @@ x #|| y = por # pdelay x # pdelay y pand :: Term s (PDelayed PBool :--> PDelayed PBool :--> PBool) pand = phoistAcyclic $ plam $ - \x y -> pif' # pforce x # (pif' # pforce y # pcon PTrue # pcon PFalse) # pcon PFalse + \x y -> pif (pforce x) (pif' # pforce y # pcon PTrue # pcon PFalse) (pcon PFalse) -- | Hoisted, Plutarch level, strictly evaluated boolean and function. pand' :: Term s (PBool :--> PBool :--> PBool) @@ -86,7 +86,7 @@ pand' = phoistAcyclic $ por :: Term s (PDelayed PBool :--> PDelayed PBool :--> PBool) por = phoistAcyclic $ plam $ - \x y -> pif' # pforce x # pcon PTrue #$ pif' # pforce y # pcon PTrue # pcon PFalse + \x y -> pif (pforce x) (pcon PTrue) (pif' # pforce y # pcon PTrue # pcon PFalse) -- | Hoisted, Plutarch level, strictly evaluated boolean or function. por' :: Term s (PBool :--> PBool :--> PBool) From a54e018858d07185dfd01f222ef72af293d94dcb Mon Sep 17 00:00:00 2001 From: Las Safin Date: Mon, 10 Jan 2022 17:01:00 +0000 Subject: [PATCH 2/3] [breaking] optimise p{and,or}{,'} --- Plutarch/Bool.hs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Plutarch/Bool.hs b/Plutarch/Bool.hs index 64fd46d8b..f58c48df2 100644 --- a/Plutarch/Bool.hs +++ b/Plutarch/Bool.hs @@ -62,34 +62,26 @@ pnot = phoistAcyclic $ plam $ \x -> pif x (pcon PFalse) $ pcon PTrue infixr 3 #&& (#&&) :: Term s PBool -> Term s PBool -> Term s PBool -x #&& y = pand # pdelay x # pdelay y +x #&& y = pforce $ pand # x # pdelay y -- | Lazily evaluated boolean or for 'PBool' terms. infixr 2 #|| (#||) :: Term s PBool -> Term s PBool -> Term s PBool -x #|| y = por # pdelay x # pdelay y +x #|| y = pforce $ por # x # pdelay y -- | Hoisted, Plutarch level, lazily evaluated boolean and function. -pand :: Term s (PDelayed PBool :--> PDelayed PBool :--> PBool) -pand = phoistAcyclic $ - plam $ - \x y -> pif (pforce x) (pif' # pforce y # pcon PTrue # pcon PFalse) (pcon PFalse) +pand :: Term s (PBool :--> PDelayed PBool :--> PDelayed PBool) +pand = phoistAcyclic $ plam $ \x y -> pif' # x # y # (phoistAcyclic $ pdelay $ pcon PFalse) -- | Hoisted, Plutarch level, strictly evaluated boolean and function. pand' :: Term s (PBool :--> PBool :--> PBool) -pand' = phoistAcyclic $ - plam $ - \x y -> pif' # x # (pif' # y # pcon PTrue # pcon PFalse) # pcon PFalse +pand' = phoistAcyclic $ plam $ \x y -> pif' # x # y # (pcon PFalse) -- | Hoisted, Plutarch level, lazily evaluated boolean or function. -por :: Term s (PDelayed PBool :--> PDelayed PBool :--> PBool) -por = phoistAcyclic $ - plam $ - \x y -> pif (pforce x) (pcon PTrue) (pif' # pforce y # pcon PTrue # pcon PFalse) +por :: Term s (PBool :--> PDelayed PBool :--> PDelayed PBool) +por = phoistAcyclic $ plam $ \x y -> pif' # x # (phoistAcyclic $ pdelay $ pcon PTrue) # y -- | Hoisted, Plutarch level, strictly evaluated boolean or function. por' :: Term s (PBool :--> PBool :--> PBool) -por' = phoistAcyclic $ - plam $ - \x y -> pif' # x # pcon PTrue #$ pif' # y # pcon PTrue # pcon PFalse +por' = phoistAcyclic $ plam $ \x y -> pif' # x # (pcon PTrue) # y From acc1b0a3be62c847aade9cf331aec6a6ac281592 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Mon, 10 Jan 2022 17:11:55 +0000 Subject: [PATCH 3/3] Add some tests for booleans --- examples/Main.hs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/examples/Main.hs b/examples/Main.hs index d793b3943..24132ce3f 100644 --- a/examples/Main.hs +++ b/examples/Main.hs @@ -12,7 +12,7 @@ import Data.Maybe (fromJust) import qualified Examples.List as List import Examples.Tracing (traceTests) import Plutarch (POpaque, pconstant, plift', popaque, printTerm, punsafeBuiltin) -import Plutarch.Bool (PBool (PFalse, PTrue), pif, pnot, (#&&), (#<), (#<=), (#==), (#||)) +import Plutarch.Bool (PBool (PFalse, PTrue), pand, pif, pnot, por, (#&&), (#<), (#<=), (#==), (#||)) import Plutarch.Builtin (PAsData, PBuiltinList (..), PBuiltinPair, PData, pdata) import Plutarch.ByteString (PByteString, pconsBS, phexByteStr, pindexBS, plengthBS, psliceBS) import Plutarch.Either (PEither (PLeft, PRight)) @@ -250,6 +250,19 @@ plutarchTests = let v2 = [("IOHK", [1, 2, 3]), ("Plutus", [9, 8, 7])] plift' (pconstant @(PBuiltinList (PBuiltinPair PString (PBuiltinList PInteger))) v2) @?= Right v2 ] + , testGroup + "Boolean operations" + [ testCase "True && False ≡ False" $ equal (pcon PTrue #&& pcon PFalse) (pcon PFalse) + , testCase "False && True ≡ False" $ equal (pcon PFalse #&& pcon PTrue) (pcon PFalse) + , testCase "False && perror ≡ False" $ equal (pcon PFalse #&& perror) (pcon PFalse) + , testCase "fails: pand False perror" $ fails $ pand # pcon PFalse # perror + , testCase "pand False (pdelay perror) ≡ False" $ equal (pand # pcon PFalse # pdelay perror) (pdelay $ pcon PFalse) + , testCase "True || False ≡ True" $ equal (pcon PTrue #|| pcon PFalse) (pcon PTrue) + , testCase "False || True ≡ True" $ equal (pcon PFalse #|| pcon PTrue) (pcon PTrue) + , testCase "True || perror ≡ True" $ equal (pcon PTrue #|| perror) (pcon PTrue) + , testCase "fails: por True perror" $ fails $ por # pcon PFalse # perror + , testCase "por True (pdelay perror) ≡ True" $ equal (por # pcon PTrue # pdelay perror) (pdelay $ pcon PTrue) + ] ] -- | Tests for the behaviour of UPLC itself.