From 09f8916d53583c2e9fb5b78de84fe23de3788492 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 24 Jun 2024 15:46:34 +0200 Subject: [PATCH 01/54] Add condition to Applied --- booster/library/Booster/Pattern/Rewrite.hs | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index ba37452c53..27cb1ffe14 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -171,10 +171,21 @@ rewriteStep cutLabels terminalLabels pat = do ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc uniqueId = (.uniqueId) . (.attributes) + -- compute remainder condition here. If Bottom, the following code returns the result + -- if it is not Bottom. Let's say we have computed P : Predicate which is the remainder predicate. + -- To construct the "remainder pattern", we add the remainder condition to the predicates of the @pattr@ + + -- let remainder :: Predicate = undefined + -- newPattr = pattr{constraints = pattr.constraints <> Set.singleton remainder} + + -- case (remainder, results) of + -- (PredicateTrue, []) -> processGroups pattr rest -- do not need the Top remainder + -- (PredicateFalse, _) -> + case results of -- no rules in this group were applicable [] -> processGroups pattr rest - _ -> case concatMap (\case Applied x -> [x]; _ -> []) results of + _ -> case concatMap (\case Applied _condition x -> [x]; _ -> []) results of [] -> -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false -- if, all the other groups only generate a not applicable or trivial rewrites, @@ -199,7 +210,7 @@ rewriteStep cutLabels terminalLabels pat = do map (\(r, p) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs data RewriteRuleAppResult a - = Applied a + = Applied Predicate a | NotApplied | Trivial deriving (Show, Eq, Functor) @@ -208,19 +219,20 @@ newtype RewriteRuleAppT m a = RewriteRuleAppT {runRewriteRuleAppT :: m (RewriteR deriving (Functor) instance Monad m => Applicative (RewriteRuleAppT m) where - pure = RewriteRuleAppT . return . Applied + pure = RewriteRuleAppT . return . Applied (Predicate TrueBool) {-# INLINE pure #-} mf <*> mx = RewriteRuleAppT $ do mb_f <- runRewriteRuleAppT mf case mb_f of NotApplied -> return NotApplied Trivial -> return Trivial - Applied f -> do + Applied _condition f -> do mb_x <- runRewriteRuleAppT mx case mb_x of NotApplied -> return NotApplied Trivial -> return Trivial - Applied x -> return (Applied (f x)) + -- FIXME what to do with the top-level condition??? Conjoin? + Applied secondCondition x -> return (Applied secondCondition (f x)) {-# INLINE (<*>) #-} m *> k = m >> k {-# INLINE (*>) #-} @@ -231,14 +243,15 @@ instance Monad m => Monad (RewriteRuleAppT m) where x >>= f = RewriteRuleAppT $ do v <- runRewriteRuleAppT x case v of - Applied y -> runRewriteRuleAppT (f y) + -- FIXME what to do with the condition??? + Applied _condition y -> runRewriteRuleAppT (f y) NotApplied -> return NotApplied Trivial -> return Trivial {-# INLINE (>>=) #-} instance MonadTrans RewriteRuleAppT where lift :: Monad m => m a -> RewriteRuleAppT m a - lift = RewriteRuleAppT . fmap Applied + lift = RewriteRuleAppT . fmap (Applied (Predicate TrueBool)) {-# INLINE lift #-} instance Monad m => MonadFail (RewriteRuleAppT m) where From 254e87792ba4a9e890d6cb390b6770ce66e28b05 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 24 Jun 2024 16:20:37 +0200 Subject: [PATCH 02/54] Allow assuming unclear requires clauses --- booster/library/Booster/Pattern/Bool.hs | 5 ++++ booster/library/Booster/Pattern/Rewrite.hs | 33 +++++++++++++--------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/booster/library/Booster/Pattern/Bool.hs b/booster/library/Booster/Pattern/Bool.hs index 39dd2cacc3..7cef672ce7 100644 --- a/booster/library/Booster/Pattern/Bool.hs +++ b/booster/library/Booster/Pattern/Bool.hs @@ -10,6 +10,7 @@ module Booster.Pattern.Bool ( negateBool, splitBoolPredicates, splitAndBools, + collapseAndBools, -- patterns pattern TrueBool, pattern FalseBool, @@ -206,3 +207,7 @@ splitAndBools :: Predicate -> [Predicate] splitAndBools p@(Predicate t) | AndBool l r <- t = concatMap (splitAndBools . Predicate) [l, r] | otherwise = [p] + +-- | Inverse of splitAndBools +collapseAndBools :: [Predicate] -> Predicate +collapseAndBools = Predicate . foldAndBool . map (\(Predicate p) -> p) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 27cb1ffe14..2cfdbddaa4 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -355,7 +355,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu failRewrite $ RuleConditionUnclear rule . coerce . foldl1 AndTerm $ map coerce unclearRequires - case mbSolver of + assumedUnclearConditions <- case mbSolver of Just solver -> do checkAllRequires <- SMT.checkPredicates solver prior mempty (Set.fromList unclearRequires) @@ -370,17 +370,21 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu withContext CtxFailure $ logMessage ("Required clauses evaluated to #Bottom." :: Text) RewriteRuleAppT $ pure NotApplied Right (Just True) -> - pure () -- can proceed - Right Nothing -> - smtUnclear -- no implication could be determined - Nothing -> - unless (null unclearRequires) $ do - withContext CtxConstraint . withContext CtxAbort $ - logMessage $ - renderOneLineText $ - "Uncertain about a condition(s) in rule, no SMT solver:" <+> pretty unclearRequires - failRewrite $ - RuleConditionUnclear rule (head unclearRequires) + pure [] -- can proceed + Right Nothing -> do + withContext CtxConstraint . withContext CtxAbort . logMessage . renderOneLineText $ + "Uncertain about condition(s) in a rule:" <+> pretty unclearRequires + pure unclearRequires + Nothing -> do + if (not . null $ unclearRequires) + then do + withContext CtxConstraint . withContext CtxAbort $ + logMessage $ + renderOneLineText $ + "Uncertain about a condition(s) in rule, no SMT solver:" <+> pretty unclearRequires + failRewrite $ + RuleConditionUnclear rule (head unclearRequires) + else pure [] -- check ensures constraints (new) from rhs: stop and return `Trivial` if -- any are false, remove all that are trivially true, return the rest @@ -396,6 +400,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu (lift $ SMT.checkPredicates solver prior mempty (Set.fromList newConstraints)) >>= \case Right (Just False) -> do withContext CtxSuccess $ logMessage ("New constraints evaluated to #Bottom." :: Text) + -- it's probably still fine to return trivial here even if we assumed unclear required conditions RewriteRuleAppT $ pure Trivial Right _other -> pure () @@ -428,7 +433,9 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu ceilConditions withContext CtxSuccess $ withPatternContext rewritten $ - return (rule, rewritten) + RewriteRuleAppT $ + pure $ + Applied (collapseAndBools assumedUnclearConditions) (rule, rewritten) where failRewrite = lift . throw From 1ee240d3657d2124fde82ad70d981e476bfa523d Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 24 Jun 2024 17:20:50 +0200 Subject: [PATCH 03/54] Draft remainder predicate computation and check --- booster/library/Booster/Pattern/Rewrite.hs | 118 +++++++++++++-------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 2cfdbddaa4..d0494768da 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -152,7 +152,7 @@ rewriteStep cutLabels terminalLabels pat = do RewriteT io (RewriteResult Pattern) processGroups pattr [] = pure $ RewriteStuck pattr - processGroups pattr (rules : rest) = do + processGroups pattr (rules : lowerPriorityRules) = do -- try all rules of the priority group. This will immediately -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) @@ -167,50 +167,80 @@ rewriteStep cutLabels terminalLabels pat = do -- so unless the original pattern contained bottom, we won't gain anything from -- calling the simplifier on the original conditions which came with the term. - let labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) - ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc - uniqueId = (.uniqueId) . (.attributes) - - -- compute remainder condition here. If Bottom, the following code returns the result - -- if it is not Bottom. Let's say we have computed P : Predicate which is the remainder predicate. - -- To construct the "remainder pattern", we add the remainder condition to the predicates of the @pattr@ - - -- let remainder :: Predicate = undefined - -- newPattr = pattr{constraints = pattr.constraints <> Set.singleton remainder} - - -- case (remainder, results) of - -- (PredicateTrue, []) -> processGroups pattr rest -- do not need the Top remainder - -- (PredicateFalse, _) -> - case results of -- no rules in this group were applicable - [] -> processGroups pattr rest - _ -> case concatMap (\case Applied _condition x -> [x]; _ -> []) results of - [] -> - -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false - -- if, all the other groups only generate a not applicable or trivial rewrites, - -- then we return a `RewriteTrivial`. - processGroups pattr rest >>= \case - RewriteStuck{} -> pure $ RewriteTrivial pat - other -> pure other - -- all branches but one were either not applied or trivial - [(r, x)] - | labelOf r `elem` cutLabels -> - pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x - | labelOf r `elem` terminalLabels -> - pure $ RewriteTerminal (labelOf r) (uniqueId r) x - | otherwise -> - pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x - -- at this point, there were some Applied rules and potentially some Trivial ones. - -- here, we just return all the applied rules in a `RewriteBranch` - rxs -> - pure $ - RewriteBranch pat $ - NE.fromList $ - map (\(r, p) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs + [] -> processGroups pattr lowerPriorityRules + _ -> do + let nonTrivialResults = concatMap (\case Applied conditions x -> [(conditions, x)]; _ -> []) results + + -- compute remainder condition here from @nonTrivialResults@ here. + -- If the remainder is bottom, then the rest + let remainder@(Predicate remainderTerm) :: Predicate = Predicate FalseBool + -- newPattr = pattr{constraints = pattr.constraints <> Set.singleton remainder} + -- check unclear requires-clauses in the context of known constraints (prior) + let mbSolver = undefined + + case mbSolver of + Just solver -> do + checkAllRequires <- + SMT.checkPredicates solver mempty mempty (Set.singleton remainder) + + case checkAllRequires of + Left SMT.SMTSolverUnknown{} -> + -- solver cannot solve the remainder. Descend into the remainder branch anyway? + undefined + Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors + Right (Just False) -> + -- the remainder condition is unsatisfiable: no need to consider the remainder branch + continueNoRemainder pattr lowerPriorityRules nonTrivialResults + Right (Just True) -> + -- the remainder condition is satisfiable. + -- Have to construct the remainder branch and consider it + -- To construct the "remainder pattern", + -- we add the remainder condition to the predicates of the @pattr@ + undefined + Right Nothing -> + -- solver cannot solve the remainder. Descend into the remainder branch anyway? + -- how is this different from the @Left SMT.SMTSolverUnknown@ case? + undefined + Nothing -> undefined + where + continueNoRemainder :: + LoggerMIO io => + Pattern -> + [[RewriteRule "Rewrite"]] -> + [([Predicate], (RewriteRule "Rewrite", Pattern))] -> + RewriteT io (RewriteResult Pattern) + continueNoRemainder pattr rest = \case + [] -> + -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false + -- if, all the other groups only generate a not applicable or trivial rewrites, + -- then we return a `RewriteTrivial`. + processGroups pattr rest >>= \case + RewriteStuck{} -> pure $ RewriteTrivial pat + other -> pure other + -- all branches but one were either not applied or trivial + [(_assumedConditons, (r, x))] + | labelOf r `elem` cutLabels -> + pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x + | labelOf r `elem` terminalLabels -> + pure $ RewriteTerminal (labelOf r) (uniqueId r) x + | otherwise -> + pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x + -- at this point, there were some Applied rules and potentially some Trivial ones. + -- here, we just return all the applied rules in a `RewriteBranch` + rxs -> + pure $ + RewriteBranch pat $ + NE.fromList $ + map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs + + labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) + ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc + uniqueId = (.uniqueId) . (.attributes) data RewriteRuleAppResult a - = Applied Predicate a + = Applied ![Predicate] a | NotApplied | Trivial deriving (Show, Eq, Functor) @@ -219,7 +249,7 @@ newtype RewriteRuleAppT m a = RewriteRuleAppT {runRewriteRuleAppT :: m (RewriteR deriving (Functor) instance Monad m => Applicative (RewriteRuleAppT m) where - pure = RewriteRuleAppT . return . Applied (Predicate TrueBool) + pure = RewriteRuleAppT . return . Applied [] {-# INLINE pure #-} mf <*> mx = RewriteRuleAppT $ do mb_f <- runRewriteRuleAppT mf @@ -251,7 +281,7 @@ instance Monad m => Monad (RewriteRuleAppT m) where instance MonadTrans RewriteRuleAppT where lift :: Monad m => m a -> RewriteRuleAppT m a - lift = RewriteRuleAppT . fmap (Applied (Predicate TrueBool)) + lift = RewriteRuleAppT . fmap (Applied []) {-# INLINE lift #-} instance Monad m => MonadFail (RewriteRuleAppT m) where @@ -435,7 +465,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu withPatternContext rewritten $ RewriteRuleAppT $ pure $ - Applied (collapseAndBools assumedUnclearConditions) (rule, rewritten) + Applied assumedUnclearConditions (rule, rewritten) where failRewrite = lift . throw From b67a97fe8f20850a5250ad3e2160f755c7c0a902 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Wed, 26 Jun 2024 16:51:06 +0100 Subject: [PATCH 04/54] Reorganised doSteps function in performRewrite --- booster/library/Booster/Pattern/Rewrite.hs | 657 ++++++++++----------- booster/library/Booster/SMT/Interface.hs | 45 ++ 2 files changed, 365 insertions(+), 337 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index d0494768da..f2ecf6a454 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -1,6 +1,8 @@ {-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE PatternSynonyms #-} +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} +{-# HLINT ignore "Redundant <$>" #-} {- | Copyright : (c) Runtime Verification, 2022 @@ -34,7 +36,7 @@ import Data.List (intersperse, partition) import Data.List.NonEmpty (NonEmpty (..), toList) import Data.List.NonEmpty qualified as NE import Data.Map qualified as Map -import Data.Maybe (catMaybes, fromMaybe) +import Data.Maybe (catMaybes, fromMaybe, mapMaybe) import Data.Sequence (Seq, (|>)) import Data.Set qualified as Set import Data.Text as Text (Text, pack) @@ -66,10 +68,11 @@ import Booster.Prettyprinter import Booster.SMT.Interface qualified as SMT import Booster.Syntax.Json.Externalise (externaliseTerm) import Booster.Util (Flag (..)) +import Unsafe.Coerce (unsafeCoerce) newtype RewriteT io a = RewriteT { unRewriteT :: - ReaderT RewriteConfig (StateT SimplifierCache (ExceptT (RewriteFailed "Rewrite") io)) a + ReaderT RewriteConfig (StateT (SimplifierCache, Set.Set Predicate) (ExceptT (RewriteFailed "Rewrite") io)) a } deriving newtype (Functor, Applicative, Monad, MonadIO) @@ -98,12 +101,13 @@ runRewriteT :: Maybe LLVM.API -> Maybe SMT.SMTContext -> SimplifierCache -> + Set.Set Predicate -> RewriteT io a -> - io (Either (RewriteFailed "Rewrite") (a, SimplifierCache)) -runRewriteT doTracing definition llvmApi smtSolver cache m = do + io (Either (RewriteFailed "Rewrite") (a, (SimplifierCache, Set.Set Predicate))) +runRewriteT doTracing definition llvmApi smtSolver cache remainders m = do logger <- getLogger runExceptT - . flip runStateT cache + . flip runStateT (cache, remainders) . flip runReaderT RewriteConfig{definition, llvmApi, smtSolver, doTracing, logger} . unRewriteT $ m @@ -111,9 +115,23 @@ runRewriteT doTracing definition llvmApi smtSolver cache m = do throw :: LoggerMIO io => RewriteFailed "Rewrite" -> RewriteT io a throw = RewriteT . lift . lift . throwE -getDefinition :: LoggerMIO io => RewriteT io KoreDefinition + +getConfig :: Monad m => RewriteT m RewriteConfig +getConfig = RewriteT ask + +getDefinition :: Monad m => RewriteT m KoreDefinition getDefinition = RewriteT $ definition <$> ask +getSolver :: Monad m => RewriteT m (Maybe SMT.SMTContext) +getSolver = RewriteT $ (.smtSolver) <$> ask + +getRemainder :: Monad m => RewriteT m (Set.Set Predicate) +getRemainder = RewriteT $ snd <$> lift get + +setRemainder :: Monad m => Set.Set Predicate -> RewriteT m () +setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) + + {- | Performs a rewrite step (using suitable rewrite rules from the definition). @@ -123,11 +141,9 @@ getDefinition = RewriteT $ definition <$> ask -} rewriteStep :: LoggerMIO io => - [Text] -> - [Text] -> Pattern -> - RewriteT io (RewriteResult Pattern) -rewriteStep cutLabels terminalLabels pat = do + RewriteT io [(RewriteRule "Rewrite", Pattern)] +rewriteStep pat = do def <- getDefinition let getIndex = if null def.attributes.indexCells @@ -149,151 +165,134 @@ rewriteStep cutLabels terminalLabels pat = do LoggerMIO io => Pattern -> [[RewriteRule "Rewrite"]] -> - RewriteT io (RewriteResult Pattern) - processGroups pattr [] = - pure $ RewriteStuck pattr + RewriteT io [(RewriteRule "Rewrite", Pattern)] + processGroups _pattr [] = pure mempty processGroups pattr (rules : lowerPriorityRules) = do -- try all rules of the priority group. This will immediately -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) - results <- filter (/= NotApplied) <$> mapM (applyRule pattr) rules - - -- simplify and filter out bottom states - - -- At the moment, there is no point in calling simplify on the conditions of the - -- resulting patterns again, since we already pruned any rule applications - -- which resulted in one of the conditions being bottom. - -- Also, our current simplifier cannot deduce bottom from a combination of conditions, - -- so unless the original pattern contained bottom, we won't gain anything from - -- calling the simplifier on the original conditions which came with the term. - - case results of - -- no rules in this group were applicable - [] -> processGroups pattr lowerPriorityRules - _ -> do - let nonTrivialResults = concatMap (\case Applied conditions x -> [(conditions, x)]; _ -> []) results - - -- compute remainder condition here from @nonTrivialResults@ here. - -- If the remainder is bottom, then the rest - let remainder@(Predicate remainderTerm) :: Predicate = Predicate FalseBool - -- newPattr = pattr{constraints = pattr.constraints <> Set.singleton remainder} - -- check unclear requires-clauses in the context of known constraints (prior) - let mbSolver = undefined - - case mbSolver of - Just solver -> do - checkAllRequires <- - SMT.checkPredicates solver mempty mempty (Set.singleton remainder) - - case checkAllRequires of - Left SMT.SMTSolverUnknown{} -> - -- solver cannot solve the remainder. Descend into the remainder branch anyway? - undefined - Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - Right (Just False) -> - -- the remainder condition is unsatisfiable: no need to consider the remainder branch - continueNoRemainder pattr lowerPriorityRules nonTrivialResults - Right (Just True) -> - -- the remainder condition is satisfiable. - -- Have to construct the remainder branch and consider it - -- To construct the "remainder pattern", - -- we add the remainder condition to the predicates of the @pattr@ - undefined - Right Nothing -> - -- solver cannot solve the remainder. Descend into the remainder branch anyway? - -- how is this different from the @Left SMT.SMTSolverUnknown@ case? - undefined - Nothing -> undefined - where - continueNoRemainder :: - LoggerMIO io => - Pattern -> - [[RewriteRule "Rewrite"]] -> - [([Predicate], (RewriteRule "Rewrite", Pattern))] -> - RewriteT io (RewriteResult Pattern) - continueNoRemainder pattr rest = \case - [] -> - -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false - -- if, all the other groups only generate a not applicable or trivial rewrites, - -- then we return a `RewriteTrivial`. - processGroups pattr rest >>= \case - RewriteStuck{} -> pure $ RewriteTrivial pat - other -> pure other - -- all branches but one were either not applied or trivial - [(_assumedConditons, (r, x))] - | labelOf r `elem` cutLabels -> - pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x - | labelOf r `elem` terminalLabels -> - pure $ RewriteTerminal (labelOf r) (uniqueId r) x - | otherwise -> - pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x - -- at this point, there were some Applied rules and potentially some Trivial ones. - -- here, we just return all the applied rules in a `RewriteBranch` - rxs -> - pure $ - RewriteBranch pat $ - NE.fromList $ - map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs - - labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) - ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc - uniqueId = (.uniqueId) . (.attributes) - -data RewriteRuleAppResult a - = Applied ![Predicate] a - | NotApplied - | Trivial - deriving (Show, Eq, Functor) - -newtype RewriteRuleAppT m a = RewriteRuleAppT {runRewriteRuleAppT :: m (RewriteRuleAppResult a)} - deriving (Functor) - -instance Monad m => Applicative (RewriteRuleAppT m) where - pure = RewriteRuleAppT . return . Applied [] - {-# INLINE pure #-} - mf <*> mx = RewriteRuleAppT $ do - mb_f <- runRewriteRuleAppT mf - case mb_f of - NotApplied -> return NotApplied - Trivial -> return Trivial - Applied _condition f -> do - mb_x <- runRewriteRuleAppT mx - case mb_x of - NotApplied -> return NotApplied - Trivial -> return Trivial - -- FIXME what to do with the top-level condition??? Conjoin? - Applied secondCondition x -> return (Applied secondCondition (f x)) - {-# INLINE (<*>) #-} - m *> k = m >> k - {-# INLINE (*>) #-} - -instance Monad m => Monad (RewriteRuleAppT m) where - return = pure - {-# INLINE return #-} - x >>= f = RewriteRuleAppT $ do - v <- runRewriteRuleAppT x - case v of - -- FIXME what to do with the condition??? - Applied _condition y -> runRewriteRuleAppT (f y) - NotApplied -> return NotApplied - Trivial -> return Trivial - {-# INLINE (>>=) #-} - -instance MonadTrans RewriteRuleAppT where - lift :: Monad m => m a -> RewriteRuleAppT m a - lift = RewriteRuleAppT . fmap (Applied []) - {-# INLINE lift #-} - -instance Monad m => MonadFail (RewriteRuleAppT m) where - fail _ = RewriteRuleAppT (return NotApplied) - {-# INLINE fail #-} - -instance MonadIO m => MonadIO (RewriteRuleAppT m) where - liftIO = lift . liftIO - {-# INLINE liftIO #-} - -instance LoggerMIO m => LoggerMIO (RewriteRuleAppT m) where - withLogger l (RewriteRuleAppT m) = RewriteRuleAppT $ withLogger l m + currentRemainder <- getRemainder + results <- catMaybes <$> mapM (\r -> fmap (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) rules + + + let nonTrivialResultsWithPartialRemainders = catMaybes results + -- compute remainder condition here from @nonTrivialResults@ and the remainder up to now. + -- If the new remainder is bottom, then no lower priority rules apply + newRemainder = currentRemainder <> Set.fromList (mapMaybe (snd . snd) nonTrivialResultsWithPartialRemainders) + nonTrivialResults = map (fmap fst) nonTrivialResultsWithPartialRemainders + + setRemainder newRemainder + + if Set.null newRemainder + then pure nonTrivialResults + else getSolver >>= \case + Just solver -> SMT.checkSat solver (pattr.constraints <> newRemainder) >>= \case + Right False -> do + -- the remainder condition is unsatisfiable: no need to consider the remainder branch. + -- we need to make sure we set the remainder to empty before returning + setRemainder mempty + pure nonTrivialResults + Right True -> do + -- the remainder condition is satisfiable. + -- Have to construct the remainder branch and consider it + -- To construct the "remainder pattern", + -- we add the remainder condition to the predicates of the @pattr@ + (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + Left SMT.SMTSolverUnknown{} -> + -- solver cannot solve the remainder. Descend into the remainder branch anyway? + (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors + + + Nothing -> (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + -- where + -- continueNoRemainder :: + -- LoggerMIO io => + -- Pattern -> + -- [[RewriteRule "Rewrite"]] -> + -- [([Predicate], (RewriteRule "Rewrite", Pattern))] -> + -- RewriteT io (RewriteResult Pattern) + -- continueNoRemainder pattr rest = \case + -- [] -> + -- -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false + -- -- if, all the other groups only generate a not applicable or trivial rewrites, + -- -- then we return a `RewriteTrivial`. + -- processGroups pattr rest >>= \case + -- RewriteStuck{} -> pure $ RewriteTrivial pat + -- other -> pure other + -- -- all branches but one were either not applied or trivial + -- [(_assumedConditons, (r, x))] + -- | labelOf r `elem` cutLabels -> + -- pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x + -- | labelOf r `elem` terminalLabels -> + -- pure $ RewriteTerminal (labelOf r) (uniqueId r) x + -- | otherwise -> + -- pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x + -- -- at this point, there were some Applied rules and potentially some Trivial ones. + -- -- here, we just return all the applied rules in a `RewriteBranch` + -- rxs -> + -- pure $ + -- RewriteBranch pat $ + -- NE.fromList $ + -- map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs + + -- labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) + -- ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc + -- uniqueId = (.uniqueId) . (.attributes) + +-- data RewriteRuleAppResult a +-- = Applied a +-- | NotApplied +-- | Trivial +-- deriving (Show, Eq, Functor) + +-- newtype RewriteRuleAppT m a = RewriteRuleAppT {runRewriteRuleAppT :: m (RewriteRuleAppResult a)} +-- deriving (Functor) + +-- instance Monad m => Applicative (RewriteRuleAppT m) where +-- pure = RewriteRuleAppT . return . Applied [] +-- {-# INLINE pure #-} +-- mf <*> mx = RewriteRuleAppT $ do +-- mb_f <- runRewriteRuleAppT mf +-- case mb_f of +-- NotApplied -> return NotApplied +-- Trivial -> return Trivial +-- Applied f -> do +-- mb_x <- runRewriteRuleAppT mx +-- case mb_x of +-- NotApplied -> return NotApplied +-- Trivial -> return Trivial +-- Applied x -> return (Applied (f x)) +-- {-# INLINE (<*>) #-} +-- m *> k = m >> k +-- {-# INLINE (*>) #-} + +-- instance Monad m => Monad (RewriteRuleAppT m) where +-- return = pure +-- {-# INLINE return #-} +-- x >>= f = RewriteRuleAppT $ do +-- v <- runRewriteRuleAppT x +-- case v of +-- Applied y -> runRewriteRuleAppT (f y) +-- NotApplied -> return NotApplied +-- Trivial -> return Trivial +-- {-# INLINE (>>=) #-} + +-- instance MonadTrans RewriteRuleAppT where +-- lift :: Monad m => m a -> RewriteRuleAppT m a +-- lift = RewriteRuleAppT . fmap (Applied []) +-- {-# INLINE lift #-} + +-- instance Monad m => MonadFail (RewriteRuleAppT m) where +-- fail _ = RewriteRuleAppT (return NotApplied) +-- {-# INLINE fail #-} + +-- instance MonadIO m => MonadIO (RewriteRuleAppT m) where +-- liftIO = lift . liftIO +-- {-# INLINE liftIO #-} + +-- instance LoggerMIO m => LoggerMIO (RewriteRuleAppT m) where +-- withLogger l (RewriteRuleAppT m) = RewriteRuleAppT $ withLogger l m {- | Tries to apply one rewrite rule: @@ -306,12 +305,22 @@ If it cannot be determined whether the rule can be applied or not, an exception is thrown which indicates the exact reason why (this will abort the entire rewrite). -} + +type RewriteRuleAppT m a = ExceptT (Maybe ()) m a + +returnTrivial, returnNotApplied :: Monad m => RewriteRuleAppT m a +returnTrivial = throwE $ Just () +returnNotApplied = throwE Nothing + +runRewriteRuleAppT :: Monad m => RewriteRuleAppT m a -> m (Maybe (Maybe a)) +runRewriteRuleAppT = fmap (either (maybe Nothing (const $ Just Nothing)) (Just . Just)) . runExceptT + applyRule :: forall io. LoggerMIO io => Pattern -> RewriteRule "Rewrite" -> - RewriteT io (RewriteRuleAppResult (RewriteRule "Rewrite", Pattern)) + RewriteT io (Maybe (Maybe (Pattern, Maybe Predicate))) applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRuleAppT $ do def <- lift getDefinition -- unify terms @@ -324,7 +333,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu failRewrite $ InternalMatchError $ renderText $ pretty err MatchFailed reason -> do withContext CtxFailure $ logPretty reason - fail "Rule matching failed" + returnNotApplied MatchIndeterminate remainder -> do withContext CtxIndeterminate $ logMessage $ @@ -364,7 +373,6 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu -- in isolation). Stop if false, abort rewrite if indeterminate. let ruleRequires = concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) rule.requires - notAppliedIfBottom = RewriteRuleAppT $ pure NotApplied -- filter out any predicates known to be _syntactically_ present in the known prior let prior = pat.constraints (knownTrue, toCheck) = partition (`Set.member` prior) ruleRequires @@ -374,36 +382,32 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu "Known true side conditions (won't check):" <+> pretty knownTrue unclearRequires <- - catMaybes <$> mapM (checkConstraint id notAppliedIfBottom) toCheck + catMaybes <$> mapM (checkConstraint returnNotApplied) toCheck -- check unclear requires-clauses in the context of known constraints (prior) - mbSolver <- lift $ RewriteT $ (.smtSolver) <$> ask - - let smtUnclear = do - withContext CtxConstraint . withContext CtxAbort . logMessage . renderOneLineText $ - "Uncertain about condition(s) in a rule:" <+> pretty unclearRequires - failRewrite $ - RuleConditionUnclear rule . coerce . foldl1 AndTerm $ - map coerce unclearRequires - assumedUnclearConditions <- case mbSolver of + mbSolver <- lift getSolver + + unclearRequiresAfterSmt <- case mbSolver of Just solver -> do checkAllRequires <- SMT.checkPredicates solver prior mempty (Set.fromList unclearRequires) case checkAllRequires of - Left SMT.SMTSolverUnknown{} -> - smtUnclear -- abort rewrite if a solver result was Unknown + Left SMT.SMTSolverUnknown{} -> do + withContext CtxConstraint . logMessage . renderOneLineText $ + "Uncertain about condition(s) in a rule, SMT returned unknown, adding as remainder:" <+> pretty unclearRequires + pure unclearRequires Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors Right (Just False) -> do -- requires is actually false given the prior withContext CtxFailure $ logMessage ("Required clauses evaluated to #Bottom." :: Text) - RewriteRuleAppT $ pure NotApplied + returnNotApplied Right (Just True) -> pure [] -- can proceed Right Nothing -> do - withContext CtxConstraint . withContext CtxAbort . logMessage . renderOneLineText $ - "Uncertain about condition(s) in a rule:" <+> pretty unclearRequires + withContext CtxConstraint . logMessage . renderOneLineText $ + "Uncertain about condition(s) in a rule, adding as remainder:" <+> pretty unclearRequires pure unclearRequires Nothing -> do if (not . null $ unclearRequires) @@ -421,9 +425,8 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu let ruleEnsures = concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) $ Set.toList rule.ensures - trivialIfBottom = RewriteRuleAppT $ pure Trivial newConstraints <- - catMaybes <$> mapM (checkConstraint id trivialIfBottom) ruleEnsures + catMaybes <$> mapM (checkConstraint returnTrivial) ruleEnsures -- check all new constraints together with the known side constraints whenJust mbSolver $ \solver -> @@ -431,7 +434,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu Right (Just False) -> do withContext CtxSuccess $ logMessage ("New constraints evaluated to #Bottom." :: Text) -- it's probably still fine to return trivial here even if we assumed unclear required conditions - RewriteRuleAppT $ pure Trivial + returnTrivial Right _other -> pure () Left SMT.SMTSolverUnknown{} -> @@ -462,33 +465,33 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu ) ceilConditions withContext CtxSuccess $ - withPatternContext rewritten $ - RewriteRuleAppT $ - pure $ - Applied assumedUnclearConditions (rule, rewritten) + withPatternContext rewritten $ do + let remainder = case unclearRequiresAfterSmt of + [] -> Nothing + _ -> Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt + pure (rewritten, remainder) where failRewrite = lift . throw checkConstraint :: - (Predicate -> a) -> - RewriteRuleAppT (RewriteT io) (Maybe a) -> + RewriteRuleAppT (RewriteT io) (Maybe Predicate) -> Predicate -> - RewriteRuleAppT (RewriteT io) (Maybe a) - checkConstraint onUnclear onBottom p = do - RewriteConfig{definition, llvmApi, smtSolver} <- lift $ RewriteT ask - oldCache <- lift . RewriteT . lift $ get + RewriteRuleAppT (RewriteT io) (Maybe Predicate) + checkConstraint onBottom p = do + RewriteConfig{definition, llvmApi, smtSolver} <- lift getConfig + (oldCache, _) <- lift . RewriteT . lift $ get (simplified, cache) <- withContext CtxConstraint $ simplifyConstraint definition llvmApi smtSolver oldCache p -- update cache - lift . RewriteT . lift . modify $ const cache + lift . RewriteT . lift . modify $ \(_, rems) -> (cache, rems) -- TODO should we keep the traces? Or only on success? case simplified of Right (Predicate FalseBool) -> onBottom Right (Predicate TrueBool) -> pure Nothing - Right other -> pure $ Just $ onUnclear other + Right other -> pure $ Just other Left UndefinedTerm{} -> onBottom - Left _ -> pure $ Just $ onUnclear p + Left _ -> pure $ Just p {- | Reason why a rewrite did not produce a result. Contains additional information for logging what happened during the rewrite. @@ -644,6 +647,30 @@ mkDiffTerms = \case in (SymbolApplication s1 ss1 xs', SymbolApplication s2 ss2 ys') r -> r +data MaybeSimplified (isSimplified :: Bool) a where + Simplified :: a -> MaybeSimplified 'True a + Unsimplified :: a -> MaybeSimplified 'False a + Bottom :: a -> MaybeSimplified 'True a + + +instance Functor (MaybeSimplified 'True) where + fmap f = \case + Simplified a -> Simplified $ f a + Bottom a -> Bottom $ f a + +extract :: MaybeSimplified isSimplified a -> a +extract = \case + Simplified a -> unsafeCoerce a + Unsimplified a -> unsafeCoerce a + Bottom a -> unsafeCoerce a + +catSimplified :: [MaybeSimplified 'True a] -> [a] +catSimplified = \case + [] -> [] + Bottom{}:xs -> catSimplified xs + (Simplified x):xs -> x : catSimplified xs + + {- | Interface for RPC execute: Rewrite given term as long as there is exactly one result in each step. @@ -729,9 +756,9 @@ performRewrite :: [Text] -> Pattern -> io (Natural, Seq (RewriteTrace ()), RewriteResult Pattern) -performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalLabels pat = do +performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalLabels initialPattern = do (rr, RewriteStepsState{counter, traces}) <- - flip runStateT rewriteStart $ doSteps False pat + flip runStateT rewriteStart $ doSteps (Unsimplified initialPattern) pure (counter, traces, rr) where logDepth = withContext CtxDepth . logMessage @@ -750,73 +777,47 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL updateCache simplifierCache = modify $ \rss -> rss{simplifierCache} - simplifyP :: Pattern -> StateT RewriteStepsState io (Maybe Pattern) - simplifyP p = withContext CtxSimplify $ do - st <- get - let cache = st.simplifierCache - smt = st.smtSolver - evaluatePattern def mLlvmLibrary smt cache p >>= \(res, newCache) -> do - updateCache newCache - case res of - Right newPattern -> do - emitRewriteTrace $ RewriteSimplified Nothing - pure $ Just newPattern - Left r@SideConditionFalse{} -> do - emitRewriteTrace $ RewriteSimplified (Just r) - pure Nothing - Left r@UndefinedTerm{} -> do - emitRewriteTrace $ RewriteSimplified (Just r) - pure Nothing - Left other -> do - emitRewriteTrace $ RewriteSimplified (Just other) - pure $ Just p - - -- Results may change when simplification prunes a false side - -- condition, otherwise this would mainly be fmap simplifyP - simplifyResult :: - Pattern -> - RewriteResult Pattern -> - StateT RewriteStepsState io (RewriteResult Pattern) - simplifyResult orig = \case - RewriteBranch p nexts -> do - simplifyP p >>= \case - Nothing -> pure $ RewriteTrivial orig - Just p' -> do - let simplifyP3rd (a, b, c) = - fmap (a,b,) <$> simplifyP c - nexts' <- catMaybes <$> mapM simplifyP3rd (toList nexts) - pure $ case nexts' of - -- The `[]` case should be `Stuck` not `Trivial`, because `RewriteTrivial p'` - -- means the pattern `p'` is bottom, but we know that is not the case here. - [] -> RewriteStuck p' - [(lbl, uId, n)] -> RewriteFinished (Just lbl) (Just uId) n - ns -> RewriteBranch p' $ NE.fromList ns - r@RewriteStuck{} -> pure r - r@RewriteTrivial{} -> pure r - RewriteCutPoint lbl uId p next -> do - simplifyP p >>= \case - Nothing -> pure $ RewriteTrivial orig - Just p' -> do - next' <- simplifyP next - pure $ case next' of - Nothing -> RewriteTrivial next - Just n -> RewriteCutPoint lbl uId p' n - RewriteTerminal lbl uId p -> - maybe (RewriteTrivial orig) (RewriteTerminal lbl uId) <$> simplifyP p - RewriteFinished lbl uId p -> - maybe (RewriteTrivial orig) (RewriteFinished lbl uId) <$> simplifyP p - RewriteAborted reason p -> - maybe (RewriteTrivial orig) (RewriteAborted reason) <$> simplifyP p + simplifyP :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (MaybeSimplified 'True Pattern) + simplifyP = \case + Simplified p -> pure $ Simplified p + Bottom p -> pure $ Bottom p + Unsimplified p -> withPatternContext p $ withContext CtxSimplify $ do + st <- get + let cache = st.simplifierCache + smt = st.smtSolver + evaluatePattern def mLlvmLibrary smt cache p >>= \(res, newCache) -> do + updateCache newCache + case res of + Right newPattern -> do + emitRewriteTrace $ RewriteSimplified Nothing + pure $ Simplified newPattern + Left r@SideConditionFalse{} -> do + emitRewriteTrace $ RewriteSimplified (Just r) + pure $ Bottom p + Left r@UndefinedTerm{} -> do + emitRewriteTrace $ RewriteSimplified (Just r) + pure $ Bottom p + Left other -> do + emitRewriteTrace $ RewriteSimplified (Just other) + pure $ Simplified p + + + labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) + ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc + uniqueId = (.uniqueId) . (.attributes) doSteps :: - Bool -> Pattern -> StateT RewriteStepsState io (RewriteResult Pattern) - doSteps wasSimplified pat' = do + MaybeSimplified flag Pattern -> StateT RewriteStepsState io (RewriteResult Pattern) + doSteps pat = do RewriteStepsState{counter, simplifierCache} <- get logDepth $ showCounter counter if depthReached counter then do logDepth $ "Reached maximum depth of " <> maybe "?" showCounter mbMaxDepth - (if wasSimplified then pure else simplifyResult pat') $ RewriteFinished Nothing Nothing pat' + simplifyP pat >>= \case + Simplified pat' -> pure $ RewriteFinished Nothing Nothing pat' + Bottom pat' -> pure $ RewriteTrivial pat' + else runRewriteT doTracing @@ -824,98 +825,80 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL mLlvmLibrary mSolver simplifierCache - (withPatternContext pat' $ rewriteStep cutLabels terminalLabels pat') + mempty + (withPatternContext (extract pat) $ rewriteStep (extract pat)) >>= \case - Right (RewriteFinished mlbl mUniqueId single, cache) -> do - whenJust mlbl $ \lbl -> - whenJust mUniqueId $ \uniqueId -> - emitRewriteTrace $ RewriteSingleStep lbl uniqueId pat' single - updateCache cache - incrementCounter - doSteps False single - Right (terminal@(RewriteTerminal lbl uniqueId single), _cache) -> withPatternContext pat' $ do - emitRewriteTrace $ RewriteSingleStep lbl uniqueId pat' single - incrementCounter - simplifyResult pat' terminal - Right (branching@RewriteBranch{}, cache) -> do - logMessage $ "Stopped due to branching after " <> showCounter counter - updateCache cache - simplified <- withPatternContext pat' $ simplifyResult pat' branching - case simplified of - RewriteStuck{} -> withPatternContext pat' $ do - logMessage ("Rewrite stuck after pruning branches" :: Text) - pure simplified - RewriteTrivial{} -> withPatternContext pat' $ do - logMessage $ "Simplified to bottom after " <> showCounter counter - pure simplified - RewriteFinished mlbl mUniqueId single -> do - logMessage ("All but one branch pruned, continuing" :: Text) - whenJust mlbl $ \lbl -> - whenJust mUniqueId $ \uniqueId -> - emitRewriteTrace $ RewriteSingleStep lbl uniqueId pat' single - incrementCounter - doSteps False single - RewriteBranch pat'' branches -> withPatternContext pat' $ do - emitRewriteTrace $ RewriteBranchingStep pat'' $ fmap (\(lbl, uid, _) -> (lbl, uid)) branches - pure simplified - _other -> withPatternContext pat' $ error "simplifyResult: Unexpected return value" - Right (cutPoint@(RewriteCutPoint lbl _ _ _), _) -> withPatternContext pat' $ do - simplified <- simplifyResult pat' cutPoint - case simplified of - RewriteCutPoint{} -> - logMessage $ "Cut point " <> lbl <> " after " <> showCounter counter - RewriteStuck{} -> - logMessage $ "Stuck after " <> showCounter counter - RewriteTrivial{} -> - logMessage $ "Simplified to bottom after " <> showCounter counter - _other -> error "simplifyResult: Unexpected return value" - pure simplified - Right (stuck@RewriteStuck{}, cache) -> do - logMessage $ "Stopped after " <> showCounter counter - updateCache cache - emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules pat' - if wasSimplified - then pure stuck - else withSimplified pat' "Retrying with simplified pattern" (doSteps True) - Right (trivial@RewriteTrivial{}, _) -> withPatternContext pat' $ do - logMessage $ "Simplified to bottom after " <> showCounter counter - pure trivial - Right (aborted@RewriteAborted{}, _) -> withPatternContext pat' $ do - logMessage $ "Aborted after " <> showCounter counter - simplifyResult pat' aborted - -- if unification was unclear and the pattern was - -- unsimplified, simplify and retry rewriting once - Left failure@(RuleApplicationUnclear rule _ remainder) - | not wasSimplified -> do - emitRewriteTrace $ RewriteStepFailed failure - -- simplify remainders, substitute and rerun. - -- If failed, do the pattern-wide simplfication and rerun again - withSimplified pat' "Retrying with simplified pattern" (doSteps True) - | otherwise -> do - -- was already simplified, emit an abort log entry - withRuleContext rule . withContext CtxMatch . withContext CtxAbort . logMessage $ - WithJsonMessage (object ["remainder" .= (bimap externaliseTerm externaliseTerm <$> remainder)]) $ - renderOneLineText $ - "Uncertain about match with rule. Remainder:" <+> pretty remainder - emitRewriteTrace $ RewriteStepFailed failure - logMessage $ "Aborted after " <> showCounter counter - pure (RewriteAborted failure pat') + Left failure@RuleApplicationUnclear{} -> + case pat of + Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + _ -> simplifyP pat >>= \case + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' Left failure -> do emitRewriteTrace $ RewriteStepFailed failure - let msg = "Aborted after " <> showCounter counter - if wasSimplified - then logMessage msg >> pure (RewriteAborted failure pat') - else withSimplified pat' msg (pure . RewriteAborted failure) - where - withSimplified p msg cont = do - (withPatternContext p $ simplifyP p) >>= \case - Nothing -> do - logMessage ("Rewrite stuck after simplification." :: Text) - pure $ RewriteStuck p - Just simplifiedPat -> do - logMessage msg - cont simplifiedPat - + case pat of + Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + _ -> simplifyP pat >>= \case + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + Right (appliedRules, (cache, remainder)) -> updateCache cache >> incrementCounter >> case appliedRules of + [] -> if Set.null remainder + then do + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial $ extract pat + else do + logMessage $ "Stopped after " <> showCounter counter + emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules $ extract pat + case pat of + Simplified pat' -> pure $ RewriteStuck pat' + _ -> simplifyP pat >>= \case + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' + [(rule, nextPat)] + | labelOf rule `elem` cutLabels -> do + simplifyP pat >>= \case + Bottom pat' -> do + logMessage $ "Previous state found to be bottom after " <> showCounter counter + pure $ RewriteTrivial pat' + Simplified pat' -> simplifyP (Unsimplified nextPat) >>= \case + Bottom nextPat' -> do + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial nextPat' + Simplified n -> do + logMessage $ "Cut point " <> (labelOf rule) <> " after " <> showCounter counter + pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' n + | labelOf rule `elem` terminalLabels -> do + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat + simplifyP (Unsimplified nextPat) >>= \case + Bottom pat' -> do + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial pat' + Simplified n -> do + logMessage $ "Terminal " <> (labelOf rule) <> " after " <> showCounter counter + pure $ RewriteTerminal (labelOf rule) (uniqueId rule) n + | otherwise -> do + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat + doSteps (Unsimplified nextPat) + pats -> do + logMessage $ "Stopped due to branching after " <> showCounter counter + simplifyP pat >>= \case + Bottom pat' -> do + logMessage $ "Previous state found to be bottom after " <> showCounter counter + pure $ RewriteTrivial pat' + Simplified p -> + (catSimplified <$> mapM (\(r, n) -> fmap (r,) <$> simplifyP (Unsimplified n)) pats) >>= \case + [] -> withPatternContext p $ do + logMessage ("Rewrite stuck after pruning branches" :: Text) + pure $ RewriteStuck p + [(rule, nextPat)] -> withPatternContext p $ do + logMessage ("All but one branch pruned, continuing" :: Text) + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) p nextPat + doSteps (Unsimplified nextPat) + pats' -> do + emitRewriteTrace $ RewriteBranchingStep p $ NE.fromList $ + map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) pats' + pure $ RewriteBranch p $ NE.fromList $ + map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) pats' data RewriteStepsState = RewriteStepsState { counter :: !Natural , traces :: !(Seq (RewriteTrace ())) diff --git a/booster/library/Booster/SMT/Interface.hs b/booster/library/Booster/SMT/Interface.hs index 5d0fd5b0c1..3dfca61a81 100644 --- a/booster/library/Booster/SMT/Interface.hs +++ b/booster/library/Booster/SMT/Interface.hs @@ -11,6 +11,7 @@ module Booster.SMT.Interface ( finaliseSolver, getModelFor, checkPredicates, + checkSat, hardResetSolver, ) where @@ -448,3 +449,47 @@ checkPredicates ctxt givenPs givenSubst psToCheck <> pack (show (positive, negative)) pure (positive, negative) + + +checkSat :: + forall io. + Log.LoggerMIO io => + SMT.SMTContext -> + Set Predicate -> + io (Either SMTError Bool) +checkSat = undefined + + -- interactWithSolver :: + -- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) + -- interactWithSolver smtGiven sexprsToCheck = do + -- smtRun_ Push + + -- -- assert ground truth + -- mapM_ smtRun smtGiven + + -- consistent <- smtRun CheckSat + -- unless (consistent == Sat) $ do + -- let errMsg = ("Inconsistent ground truth, check returns Nothing" :: Text) + -- Log.logMessage errMsg + -- let ifConsistent check = if (consistent == Sat) then check else pure Unsat + + -- -- save ground truth for 2nd check + -- smtRun_ Push + + -- -- run check for K ∧ P and then for K ∧ !P + -- let allToCheck = SMT.List (Atom "and" : sexprsToCheck) + + -- positive <- ifConsistent $ do + -- smtRun_ $ Assert "P" allToCheck + -- smtRun CheckSat + -- smtRun_ Pop + -- negative <- ifConsistent $ do + -- smtRun_ $ Assert "not P" (SMT.smtnot allToCheck) + -- smtRun CheckSat + -- smtRun_ Pop + + -- Log.logMessage $ + -- "Check of Given ∧ P and Given ∧ !P produced " + -- <> pack (show (positive, negative)) + + -- pure (positive, negative) From 0d6092bbd1bffb55e53686277ae11c3885db6d3e Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 26 Jun 2024 15:52:24 +0000 Subject: [PATCH 05/54] Format with fourmolu --- booster/library/Booster/Pattern/Rewrite.hs | 268 +++++++++++---------- booster/library/Booster/SMT/Interface.hs | 55 +++-- 2 files changed, 168 insertions(+), 155 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index f2ecf6a454..deac4dca3d 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE PatternSynonyms #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} + {-# HLINT ignore "Avoid lambda" #-} {-# HLINT ignore "Redundant <$>" #-} @@ -72,7 +73,10 @@ import Unsafe.Coerce (unsafeCoerce) newtype RewriteT io a = RewriteT { unRewriteT :: - ReaderT RewriteConfig (StateT (SimplifierCache, Set.Set Predicate) (ExceptT (RewriteFailed "Rewrite") io)) a + ReaderT + RewriteConfig + (StateT (SimplifierCache, Set.Set Predicate) (ExceptT (RewriteFailed "Rewrite") io)) + a } deriving newtype (Functor, Applicative, Monad, MonadIO) @@ -115,7 +119,6 @@ runRewriteT doTracing definition llvmApi smtSolver cache remainders m = do throw :: LoggerMIO io => RewriteFailed "Rewrite" -> RewriteT io a throw = RewriteT . lift . lift . throwE - getConfig :: Monad m => RewriteT m RewriteConfig getConfig = RewriteT ask @@ -131,7 +134,6 @@ getRemainder = RewriteT $ snd <$> lift get setRemainder :: Monad m => Set.Set Predicate -> RewriteT m () setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) - {- | Performs a rewrite step (using suitable rewrite rules from the definition). @@ -172,8 +174,11 @@ rewriteStep pat = do -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) currentRemainder <- getRemainder - results <- catMaybes <$> mapM (\r -> fmap (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) rules - + results <- + catMaybes + <$> mapM + (\r -> fmap (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) + rules let nonTrivialResultsWithPartialRemainders = catMaybes results -- compute remainder condition here from @nonTrivialResults@ and the remainder up to now. @@ -185,60 +190,61 @@ rewriteStep pat = do if Set.null newRemainder then pure nonTrivialResults - else getSolver >>= \case - Just solver -> SMT.checkSat solver (pattr.constraints <> newRemainder) >>= \case - Right False -> do - -- the remainder condition is unsatisfiable: no need to consider the remainder branch. - -- we need to make sure we set the remainder to empty before returning - setRemainder mempty - pure nonTrivialResults - Right True -> do - -- the remainder condition is satisfiable. - -- Have to construct the remainder branch and consider it - -- To construct the "remainder pattern", - -- we add the remainder condition to the predicates of the @pattr@ - (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules - Left SMT.SMTSolverUnknown{} -> - -- solver cannot solve the remainder. Descend into the remainder branch anyway? - (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules - Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - - - Nothing -> (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules - -- where - -- continueNoRemainder :: - -- LoggerMIO io => - -- Pattern -> - -- [[RewriteRule "Rewrite"]] -> - -- [([Predicate], (RewriteRule "Rewrite", Pattern))] -> - -- RewriteT io (RewriteResult Pattern) - -- continueNoRemainder pattr rest = \case - -- [] -> - -- -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false - -- -- if, all the other groups only generate a not applicable or trivial rewrites, - -- -- then we return a `RewriteTrivial`. - -- processGroups pattr rest >>= \case - -- RewriteStuck{} -> pure $ RewriteTrivial pat - -- other -> pure other - -- -- all branches but one were either not applied or trivial - -- [(_assumedConditons, (r, x))] - -- | labelOf r `elem` cutLabels -> - -- pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x - -- | labelOf r `elem` terminalLabels -> - -- pure $ RewriteTerminal (labelOf r) (uniqueId r) x - -- | otherwise -> - -- pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x - -- -- at this point, there were some Applied rules and potentially some Trivial ones. - -- -- here, we just return all the applied rules in a `RewriteBranch` - -- rxs -> - -- pure $ - -- RewriteBranch pat $ - -- NE.fromList $ - -- map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs - - -- labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) - -- ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc - -- uniqueId = (.uniqueId) . (.attributes) + else + getSolver >>= \case + Just solver -> + SMT.checkSat solver (pattr.constraints <> newRemainder) >>= \case + Right False -> do + -- the remainder condition is unsatisfiable: no need to consider the remainder branch. + -- we need to make sure we set the remainder to empty before returning + setRemainder mempty + pure nonTrivialResults + Right True -> do + -- the remainder condition is satisfiable. + -- Have to construct the remainder branch and consider it + -- To construct the "remainder pattern", + -- we add the remainder condition to the predicates of the @pattr@ + (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + Left SMT.SMTSolverUnknown{} -> + -- solver cannot solve the remainder. Descend into the remainder branch anyway? + (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors + Nothing -> (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + +-- where +-- continueNoRemainder :: +-- LoggerMIO io => +-- Pattern -> +-- [[RewriteRule "Rewrite"]] -> +-- [([Predicate], (RewriteRule "Rewrite", Pattern))] -> +-- RewriteT io (RewriteResult Pattern) +-- continueNoRemainder pattr rest = \case +-- [] -> +-- -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false +-- -- if, all the other groups only generate a not applicable or trivial rewrites, +-- -- then we return a `RewriteTrivial`. +-- processGroups pattr rest >>= \case +-- RewriteStuck{} -> pure $ RewriteTrivial pat +-- other -> pure other +-- -- all branches but one were either not applied or trivial +-- [(_assumedConditons, (r, x))] +-- | labelOf r `elem` cutLabels -> +-- pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x +-- | labelOf r `elem` terminalLabels -> +-- pure $ RewriteTerminal (labelOf r) (uniqueId r) x +-- | otherwise -> +-- pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x +-- -- at this point, there were some Applied rules and potentially some Trivial ones. +-- -- here, we just return all the applied rules in a `RewriteBranch` +-- rxs -> +-- pure $ +-- RewriteBranch pat $ +-- NE.fromList $ +-- map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs + +-- labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) +-- ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc +-- uniqueId = (.uniqueId) . (.attributes) -- data RewriteRuleAppResult a -- = Applied a @@ -305,7 +311,6 @@ If it cannot be determined whether the rule can be applied or not, an exception is thrown which indicates the exact reason why (this will abort the entire rewrite). -} - type RewriteRuleAppT m a = ExceptT (Maybe ()) m a returnTrivial, returnNotApplied :: Monad m => RewriteRuleAppT m a @@ -395,7 +400,8 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu case checkAllRequires of Left SMT.SMTSolverUnknown{} -> do withContext CtxConstraint . logMessage . renderOneLineText $ - "Uncertain about condition(s) in a rule, SMT returned unknown, adding as remainder:" <+> pretty unclearRequires + "Uncertain about condition(s) in a rule, SMT returned unknown, adding as remainder:" + <+> pretty unclearRequires pure unclearRequires Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors @@ -652,7 +658,6 @@ data MaybeSimplified (isSimplified :: Bool) a where Unsimplified :: a -> MaybeSimplified 'False a Bottom :: a -> MaybeSimplified 'True a - instance Functor (MaybeSimplified 'True) where fmap f = \case Simplified a -> Simplified $ f a @@ -667,9 +672,8 @@ extract = \case catSimplified :: [MaybeSimplified 'True a] -> [a] catSimplified = \case [] -> [] - Bottom{}:xs -> catSimplified xs - (Simplified x):xs -> x : catSimplified xs - + Bottom{} : xs -> catSimplified xs + (Simplified x) : xs -> x : catSimplified xs {- | Interface for RPC execute: Rewrite given term as long as there is exactly one result in each step. @@ -777,7 +781,8 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL updateCache simplifierCache = modify $ \rss -> rss{simplifierCache} - simplifyP :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (MaybeSimplified 'True Pattern) + simplifyP :: + MaybeSimplified flag Pattern -> StateT RewriteStepsState io (MaybeSimplified 'True Pattern) simplifyP = \case Simplified p -> pure $ Simplified p Bottom p -> pure $ Bottom p @@ -801,7 +806,6 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL emitRewriteTrace $ RewriteSimplified (Just other) pure $ Simplified p - labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc uniqueId = (.uniqueId) . (.attributes) @@ -817,7 +821,6 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL simplifyP pat >>= \case Simplified pat' -> pure $ RewriteFinished Nothing Nothing pat' Bottom pat' -> pure $ RewriteTrivial pat' - else runRewriteT doTracing @@ -831,74 +834,85 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Left failure@RuleApplicationUnclear{} -> case pat of Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - _ -> simplifyP pat >>= \case - Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') - pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' + _ -> + simplifyP pat >>= \case + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' Left failure -> do emitRewriteTrace $ RewriteStepFailed failure case pat of Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - _ -> simplifyP pat >>= \case - Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') - Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - Right (appliedRules, (cache, remainder)) -> updateCache cache >> incrementCounter >> case appliedRules of - [] -> if Set.null remainder - then do - logMessage $ "Simplified to bottom after " <> showCounter counter - pure $ RewriteTrivial $ extract pat - else do - logMessage $ "Stopped after " <> showCounter counter - emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules $ extract pat - case pat of - Simplified pat' -> pure $ RewriteStuck pat' - _ -> simplifyP pat >>= \case - Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') - pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' - [(rule, nextPat)] - | labelOf rule `elem` cutLabels -> do + _ -> simplifyP pat >>= \case - Bottom pat' -> do - logMessage $ "Previous state found to be bottom after " <> showCounter counter - pure $ RewriteTrivial pat' - Simplified pat' -> simplifyP (Unsimplified nextPat) >>= \case - Bottom nextPat' -> do + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + Right (appliedRules, (cache, remainder)) -> + updateCache cache >> incrementCounter >> case appliedRules of + [] -> + if Set.null remainder + then do + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial $ extract pat + else do + logMessage $ "Stopped after " <> showCounter counter + emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules $ extract pat + case pat of + Simplified pat' -> pure $ RewriteStuck pat' + _ -> + simplifyP pat >>= \case + Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' + [(rule, nextPat)] + | labelOf rule `elem` cutLabels -> do + simplifyP pat >>= \case + Bottom pat' -> do + logMessage $ "Previous state found to be bottom after " <> showCounter counter + pure $ RewriteTrivial pat' + Simplified pat' -> + simplifyP (Unsimplified nextPat) >>= \case + Bottom nextPat' -> do + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial nextPat' + Simplified n -> do + logMessage $ "Cut point " <> (labelOf rule) <> " after " <> showCounter counter + pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' n + | labelOf rule `elem` terminalLabels -> do + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat + simplifyP (Unsimplified nextPat) >>= \case + Bottom pat' -> do logMessage $ "Simplified to bottom after " <> showCounter counter - pure $ RewriteTrivial nextPat' + pure $ RewriteTrivial pat' Simplified n -> do - logMessage $ "Cut point " <> (labelOf rule) <> " after " <> showCounter counter - pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' n - | labelOf rule `elem` terminalLabels -> do - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat - simplifyP (Unsimplified nextPat) >>= \case + logMessage $ "Terminal " <> (labelOf rule) <> " after " <> showCounter counter + pure $ RewriteTerminal (labelOf rule) (uniqueId rule) n + | otherwise -> do + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat + doSteps (Unsimplified nextPat) + pats -> do + logMessage $ "Stopped due to branching after " <> showCounter counter + simplifyP pat >>= \case Bottom pat' -> do - logMessage $ "Simplified to bottom after " <> showCounter counter + logMessage $ "Previous state found to be bottom after " <> showCounter counter pure $ RewriteTrivial pat' - Simplified n -> do - logMessage $ "Terminal " <> (labelOf rule) <> " after " <> showCounter counter - pure $ RewriteTerminal (labelOf rule) (uniqueId rule) n - | otherwise -> do - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat - doSteps (Unsimplified nextPat) - pats -> do - logMessage $ "Stopped due to branching after " <> showCounter counter - simplifyP pat >>= \case - Bottom pat' -> do - logMessage $ "Previous state found to be bottom after " <> showCounter counter - pure $ RewriteTrivial pat' - Simplified p -> - (catSimplified <$> mapM (\(r, n) -> fmap (r,) <$> simplifyP (Unsimplified n)) pats) >>= \case - [] -> withPatternContext p $ do - logMessage ("Rewrite stuck after pruning branches" :: Text) - pure $ RewriteStuck p - [(rule, nextPat)] -> withPatternContext p $ do - logMessage ("All but one branch pruned, continuing" :: Text) - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) p nextPat - doSteps (Unsimplified nextPat) - pats' -> do - emitRewriteTrace $ RewriteBranchingStep p $ NE.fromList $ - map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) pats' - pure $ RewriteBranch p $ NE.fromList $ - map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) pats' + Simplified p -> + (catSimplified <$> mapM (\(r, n) -> fmap (r,) <$> simplifyP (Unsimplified n)) pats) >>= \case + [] -> withPatternContext p $ do + logMessage ("Rewrite stuck after pruning branches" :: Text) + pure $ RewriteStuck p + [(rule, nextPat)] -> withPatternContext p $ do + logMessage ("All but one branch pruned, continuing" :: Text) + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) p nextPat + doSteps (Unsimplified nextPat) + pats' -> do + emitRewriteTrace $ + RewriteBranchingStep p $ + NE.fromList $ + map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) pats' + pure $ + RewriteBranch p $ + NE.fromList $ + map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) pats' + data RewriteStepsState = RewriteStepsState { counter :: !Natural , traces :: !(Seq (RewriteTrace ())) diff --git a/booster/library/Booster/SMT/Interface.hs b/booster/library/Booster/SMT/Interface.hs index 3dfca61a81..5bd067713a 100644 --- a/booster/library/Booster/SMT/Interface.hs +++ b/booster/library/Booster/SMT/Interface.hs @@ -450,7 +450,6 @@ checkPredicates ctxt givenPs givenSubst psToCheck pure (positive, negative) - checkSat :: forall io. Log.LoggerMIO io => @@ -459,37 +458,37 @@ checkSat :: io (Either SMTError Bool) checkSat = undefined - -- interactWithSolver :: - -- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) - -- interactWithSolver smtGiven sexprsToCheck = do - -- smtRun_ Push +-- interactWithSolver :: +-- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) +-- interactWithSolver smtGiven sexprsToCheck = do +-- smtRun_ Push - -- -- assert ground truth - -- mapM_ smtRun smtGiven +-- -- assert ground truth +-- mapM_ smtRun smtGiven - -- consistent <- smtRun CheckSat - -- unless (consistent == Sat) $ do - -- let errMsg = ("Inconsistent ground truth, check returns Nothing" :: Text) - -- Log.logMessage errMsg - -- let ifConsistent check = if (consistent == Sat) then check else pure Unsat +-- consistent <- smtRun CheckSat +-- unless (consistent == Sat) $ do +-- let errMsg = ("Inconsistent ground truth, check returns Nothing" :: Text) +-- Log.logMessage errMsg +-- let ifConsistent check = if (consistent == Sat) then check else pure Unsat - -- -- save ground truth for 2nd check - -- smtRun_ Push +-- -- save ground truth for 2nd check +-- smtRun_ Push - -- -- run check for K ∧ P and then for K ∧ !P - -- let allToCheck = SMT.List (Atom "and" : sexprsToCheck) +-- -- run check for K ∧ P and then for K ∧ !P +-- let allToCheck = SMT.List (Atom "and" : sexprsToCheck) - -- positive <- ifConsistent $ do - -- smtRun_ $ Assert "P" allToCheck - -- smtRun CheckSat - -- smtRun_ Pop - -- negative <- ifConsistent $ do - -- smtRun_ $ Assert "not P" (SMT.smtnot allToCheck) - -- smtRun CheckSat - -- smtRun_ Pop +-- positive <- ifConsistent $ do +-- smtRun_ $ Assert "P" allToCheck +-- smtRun CheckSat +-- smtRun_ Pop +-- negative <- ifConsistent $ do +-- smtRun_ $ Assert "not P" (SMT.smtnot allToCheck) +-- smtRun CheckSat +-- smtRun_ Pop - -- Log.logMessage $ - -- "Check of Given ∧ P and Given ∧ !P produced " - -- <> pack (show (positive, negative)) +-- Log.logMessage $ +-- "Check of Given ∧ P and Given ∧ !P produced " +-- <> pack (show (positive, negative)) - -- pure (positive, negative) +-- pure (positive, negative) From a5e831894a0dc0f292658577fe8fdcbfc6e66415 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Thu, 27 Jun 2024 11:50:34 +0100 Subject: [PATCH 06/54] further tweaks to performRewrite --- booster/library/Booster/Pattern/Rewrite.hs | 255 ++++++++------------- 1 file changed, 94 insertions(+), 161 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index f2ecf6a454..afb9756e2e 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -1,7 +1,6 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE PatternSynonyms #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} -{-# HLINT ignore "Avoid lambda" #-} {-# HLINT ignore "Redundant <$>" #-} {- | @@ -42,6 +41,7 @@ import Data.Set qualified as Set import Data.Text as Text (Text, pack) import Numeric.Natural import Prettyprinter +import Unsafe.Coerce (unsafeCoerce) import Booster.Definition.Attributes.Base import Booster.Definition.Base @@ -68,7 +68,6 @@ import Booster.Prettyprinter import Booster.SMT.Interface qualified as SMT import Booster.Syntax.Json.Externalise (externaliseTerm) import Booster.Util (Flag (..)) -import Unsafe.Coerce (unsafeCoerce) newtype RewriteT io a = RewriteT { unRewriteT :: @@ -142,7 +141,7 @@ setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) rewriteStep :: LoggerMIO io => Pattern -> - RewriteT io [(RewriteRule "Rewrite", Pattern)] + RewriteT io [(RewriteRule "Rewrite", Maybe Pattern)] rewriteStep pat = do def <- getDefinition let getIndex = @@ -165,134 +164,60 @@ rewriteStep pat = do LoggerMIO io => Pattern -> [[RewriteRule "Rewrite"]] -> - RewriteT io [(RewriteRule "Rewrite", Pattern)] + RewriteT io [(RewriteRule "Rewrite", Maybe Pattern)] processGroups _pattr [] = pure mempty processGroups pattr (rules : lowerPriorityRules) = do -- try all rules of the priority group. This will immediately -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) currentRemainder <- getRemainder - results <- catMaybes <$> mapM (\r -> fmap (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) rules + results <- catMaybes <$> mapM (\r -> (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) rules - let nonTrivialResultsWithPartialRemainders = catMaybes results + let nonTrivialResultsWithPartialRemainders = + foldr + (\(rule, mRes) accRes -> case mRes of + Nothing -> accRes + Just res -> (rule,res): accRes) + mempty results -- compute remainder condition here from @nonTrivialResults@ and the remainder up to now. -- If the new remainder is bottom, then no lower priority rules apply newRemainder = currentRemainder <> Set.fromList (mapMaybe (snd . snd) nonTrivialResultsWithPartialRemainders) - nonTrivialResults = map (fmap fst) nonTrivialResultsWithPartialRemainders + resultsWithoutRemainders = map (fmap (fmap fst)) results setRemainder newRemainder if Set.null newRemainder - then pure nonTrivialResults + then pure resultsWithoutRemainders else getSolver >>= \case Just solver -> SMT.checkSat solver (pattr.constraints <> newRemainder) >>= \case Right False -> do -- the remainder condition is unsatisfiable: no need to consider the remainder branch. -- we need to make sure we set the remainder to empty before returning setRemainder mempty - pure nonTrivialResults + pure resultsWithoutRemainders Right True -> do -- the remainder condition is satisfiable. -- Have to construct the remainder branch and consider it -- To construct the "remainder pattern", -- we add the remainder condition to the predicates of the @pattr@ - (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules Left SMT.SMTSolverUnknown{} -> -- solver cannot solve the remainder. Descend into the remainder branch anyway? - (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules + (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - Nothing -> (nonTrivialResults <>) <$> processGroups pattr lowerPriorityRules - -- where - -- continueNoRemainder :: - -- LoggerMIO io => - -- Pattern -> - -- [[RewriteRule "Rewrite"]] -> - -- [([Predicate], (RewriteRule "Rewrite", Pattern))] -> - -- RewriteT io (RewriteResult Pattern) - -- continueNoRemainder pattr rest = \case - -- [] -> - -- -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false - -- -- if, all the other groups only generate a not applicable or trivial rewrites, - -- -- then we return a `RewriteTrivial`. - -- processGroups pattr rest >>= \case - -- RewriteStuck{} -> pure $ RewriteTrivial pat - -- other -> pure other - -- -- all branches but one were either not applied or trivial - -- [(_assumedConditons, (r, x))] - -- | labelOf r `elem` cutLabels -> - -- pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x - -- | labelOf r `elem` terminalLabels -> - -- pure $ RewriteTerminal (labelOf r) (uniqueId r) x - -- | otherwise -> - -- pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x - -- -- at this point, there were some Applied rules and potentially some Trivial ones. - -- -- here, we just return all the applied rules in a `RewriteBranch` - -- rxs -> - -- pure $ - -- RewriteBranch pat $ - -- NE.fromList $ - -- map (\(_assumedConditons, (r, p)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs - - -- labelOf = fromMaybe "" . (.ruleLabel) . (.attributes) - -- ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc - -- uniqueId = (.uniqueId) . (.attributes) - --- data RewriteRuleAppResult a --- = Applied a --- | NotApplied --- | Trivial --- deriving (Show, Eq, Functor) - --- newtype RewriteRuleAppT m a = RewriteRuleAppT {runRewriteRuleAppT :: m (RewriteRuleAppResult a)} --- deriving (Functor) - --- instance Monad m => Applicative (RewriteRuleAppT m) where --- pure = RewriteRuleAppT . return . Applied [] --- {-# INLINE pure #-} --- mf <*> mx = RewriteRuleAppT $ do --- mb_f <- runRewriteRuleAppT mf --- case mb_f of --- NotApplied -> return NotApplied --- Trivial -> return Trivial --- Applied f -> do --- mb_x <- runRewriteRuleAppT mx --- case mb_x of --- NotApplied -> return NotApplied --- Trivial -> return Trivial --- Applied x -> return (Applied (f x)) --- {-# INLINE (<*>) #-} --- m *> k = m >> k --- {-# INLINE (*>) #-} - --- instance Monad m => Monad (RewriteRuleAppT m) where --- return = pure --- {-# INLINE return #-} --- x >>= f = RewriteRuleAppT $ do --- v <- runRewriteRuleAppT x --- case v of --- Applied y -> runRewriteRuleAppT (f y) --- NotApplied -> return NotApplied --- Trivial -> return Trivial --- {-# INLINE (>>=) #-} - --- instance MonadTrans RewriteRuleAppT where --- lift :: Monad m => m a -> RewriteRuleAppT m a --- lift = RewriteRuleAppT . fmap (Applied []) --- {-# INLINE lift #-} - --- instance Monad m => MonadFail (RewriteRuleAppT m) where --- fail _ = RewriteRuleAppT (return NotApplied) --- {-# INLINE fail #-} - --- instance MonadIO m => MonadIO (RewriteRuleAppT m) where --- liftIO = lift . liftIO --- {-# INLINE liftIO #-} - --- instance LoggerMIO m => LoggerMIO (RewriteRuleAppT m) where --- withLogger l (RewriteRuleAppT m) = RewriteRuleAppT $ withLogger l m + Nothing -> (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules + +type RewriteRuleAppT m a = ExceptT (Maybe ()) m a + +returnTrivial, returnNotApplied :: Monad m => RewriteRuleAppT m a +returnTrivial = throwE $ Just () +returnNotApplied = throwE Nothing + +runRewriteRuleAppT :: Monad m => RewriteRuleAppT m a -> m (Maybe (Maybe a)) +runRewriteRuleAppT = fmap (either (maybe Nothing (const $ Just Nothing)) (Just . Just)) . runExceptT {- | Tries to apply one rewrite rule: @@ -305,16 +230,6 @@ If it cannot be determined whether the rule can be applied or not, an exception is thrown which indicates the exact reason why (this will abort the entire rewrite). -} - -type RewriteRuleAppT m a = ExceptT (Maybe ()) m a - -returnTrivial, returnNotApplied :: Monad m => RewriteRuleAppT m a -returnTrivial = throwE $ Just () -returnNotApplied = throwE Nothing - -runRewriteRuleAppT :: Monad m => RewriteRuleAppT m a -> m (Maybe (Maybe a)) -runRewriteRuleAppT = fmap (either (maybe Nothing (const $ Just Nothing)) (Just . Just)) . runExceptT - applyRule :: forall io. LoggerMIO io => @@ -658,8 +573,8 @@ instance Functor (MaybeSimplified 'True) where Simplified a -> Simplified $ f a Bottom a -> Bottom $ f a -extract :: MaybeSimplified isSimplified a -> a -extract = \case +unMaybeSimplified :: MaybeSimplified isSimplified a -> a +unMaybeSimplified = \case Simplified a -> unsafeCoerce a Unsimplified a -> unsafeCoerce a Bottom a -> unsafeCoerce a @@ -670,7 +585,6 @@ catSimplified = \case Bottom{}:xs -> catSimplified xs (Simplified x):xs -> x : catSimplified xs - {- | Interface for RPC execute: Rewrite given term as long as there is exactly one result in each step. @@ -777,8 +691,8 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL updateCache simplifierCache = modify $ \rss -> rss{simplifierCache} - simplifyP :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (MaybeSimplified 'True Pattern) - simplifyP = \case + simplify :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (MaybeSimplified 'True Pattern) + simplify = \case Simplified p -> pure $ Simplified p Bottom p -> pure $ Bottom p Unsimplified p -> withPatternContext p $ withContext CtxSimplify $ do @@ -806,18 +720,26 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc uniqueId = (.uniqueId) . (.attributes) + -- return `Nothing` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, + -- return a `Just` list of `(r, p)` pairs. + collapseIfOnlyTrivial :: [(RewriteRule "Rewrite", Maybe Pattern)] -> Maybe [(RewriteRule "Rewrite", Pattern)] + collapseIfOnlyTrivial = \case + [] -> Just [] + [(_, Nothing)] -> Nothing + (_, Nothing):xs -> collapseIfOnlyTrivial xs + (rule, Just pat):xs -> ((rule,pat):) <$> collapseIfOnlyTrivial xs + doSteps :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (RewriteResult Pattern) - doSteps pat = do + doSteps pat | unWrappedPat <- unMaybeSimplified pat = do RewriteStepsState{counter, simplifierCache} <- get logDepth $ showCounter counter if depthReached counter then do logDepth $ "Reached maximum depth of " <> maybe "?" showCounter mbMaxDepth - simplifyP pat >>= \case - Simplified pat' -> pure $ RewriteFinished Nothing Nothing pat' + simplify pat >>= \case Bottom pat' -> pure $ RewriteTrivial pat' - + Simplified pat' -> pure $ RewriteFinished Nothing Nothing pat' else runRewriteT doTracing @@ -826,79 +748,90 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL mSolver simplifierCache mempty - (withPatternContext (extract pat) $ rewriteStep (extract pat)) + (withPatternContext unWrappedPat $ rewriteStep unWrappedPat) >>= \case Left failure@RuleApplicationUnclear{} -> case pat of Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - _ -> simplifyP pat >>= \case + _ -> simplify pat >>= \case + -- FIXME: I think this should be trivial, surely? Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' Left failure -> do emitRewriteTrace $ RewriteStepFailed failure case pat of Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - _ -> simplifyP pat >>= \case + _ -> simplify pat >>= \case + -- FIXME: I think this should be trivial, surely? Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') - Right (appliedRules, (cache, remainder)) -> updateCache cache >> incrementCounter >> case appliedRules of - [] -> if Set.null remainder - then do - logMessage $ "Simplified to bottom after " <> showCounter counter - pure $ RewriteTrivial $ extract pat - else do - logMessage $ "Stopped after " <> showCounter counter - emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules $ extract pat - case pat of - Simplified pat' -> pure $ RewriteStuck pat' - _ -> simplifyP pat >>= \case - Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') - pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' - [(rule, nextPat)] + Right (appliedRules, (cache, _remainder)) -> updateCache cache >> incrementCounter >> case collapseIfOnlyTrivial appliedRules of + Nothing -> do + -- all rule applications were trivial + -- by definition that means we couldn't have had any remainders, so we can just return trivial + logMessage $ "Simplified to bottom after " <> showCounter counter + pure $ RewriteTrivial unWrappedPat + Just [] -> do + -- No trivial results, and no other applied rules. + -- We return stuck if the term had already been simplified in a previous step + -- If not, we attempt to + logMessage $ "Stopped after " <> showCounter counter + emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules unWrappedPat + case pat of + Simplified pat' -> pure $ RewriteStuck pat' + _ -> simplify pat >>= \case + Bottom pat' -> + -- FIXME: I think this should be trivial, surely? + logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') + pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' + Just [(rule, nextPat)] | labelOf rule `elem` cutLabels -> do - simplifyP pat >>= \case + simplify pat >>= \case Bottom pat' -> do logMessage $ "Previous state found to be bottom after " <> showCounter counter pure $ RewriteTrivial pat' - Simplified pat' -> simplifyP (Unsimplified nextPat) >>= \case + Simplified pat' -> simplify (Unsimplified nextPat) >>= \case Bottom nextPat' -> do logMessage $ "Simplified to bottom after " <> showCounter counter pure $ RewriteTrivial nextPat' - Simplified n -> do + Simplified nextPat' -> do logMessage $ "Cut point " <> (labelOf rule) <> " after " <> showCounter counter - pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' n + pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' nextPat' | labelOf rule `elem` terminalLabels -> do - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat - simplifyP (Unsimplified nextPat) >>= \case - Bottom pat' -> do + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) unWrappedPat nextPat + simplify (Unsimplified nextPat) >>= \case + Bottom nextPat' -> do logMessage $ "Simplified to bottom after " <> showCounter counter - pure $ RewriteTrivial pat' - Simplified n -> do + pure $ RewriteTrivial nextPat' + Simplified nextPat' -> do logMessage $ "Terminal " <> (labelOf rule) <> " after " <> showCounter counter - pure $ RewriteTerminal (labelOf rule) (uniqueId rule) n + pure $ RewriteTerminal (labelOf rule) (uniqueId rule) nextPat' | otherwise -> do - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) (extract pat) nextPat + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) unWrappedPat nextPat doSteps (Unsimplified nextPat) - pats -> do + Just nextPats -> do logMessage $ "Stopped due to branching after " <> showCounter counter - simplifyP pat >>= \case + simplify pat >>= \case Bottom pat' -> do logMessage $ "Previous state found to be bottom after " <> showCounter counter pure $ RewriteTrivial pat' - Simplified p -> - (catSimplified <$> mapM (\(r, n) -> fmap (r,) <$> simplifyP (Unsimplified n)) pats) >>= \case - [] -> withPatternContext p $ do + Simplified pat' -> + (catSimplified <$> mapM (\(r, nextPat) -> fmap (r,) <$> simplify (Unsimplified nextPat)) nextPats) >>= \case + [] -> withPatternContext pat' $ do logMessage ("Rewrite stuck after pruning branches" :: Text) - pure $ RewriteStuck p - [(rule, nextPat)] -> withPatternContext p $ do + -- FIXME: why is this stuck? Surely we go from some pats to an empty list only if all branches were pruned to bottom + -- in which case we should say that the rewrite is trivial? ... but perhaps this branch should not occur at all? + -- i.e. pat would have been bottom already?? + pure $ RewriteStuck pat' + [(rule, nextPat')] -> withPatternContext pat' $ do logMessage ("All but one branch pruned, continuing" :: Text) - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) p nextPat - doSteps (Unsimplified nextPat) - pats' -> do - emitRewriteTrace $ RewriteBranchingStep p $ NE.fromList $ - map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) pats' - pure $ RewriteBranch p $ NE.fromList $ - map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) pats' + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) pat' nextPat' + doSteps (Simplified nextPat') + nextPats' -> do + emitRewriteTrace $ RewriteBranchingStep pat' $ NE.fromList $ + map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) nextPats' + pure $ RewriteBranch pat' $ NE.fromList $ + map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) nextPats' data RewriteStepsState = RewriteStepsState { counter :: !Natural , traces :: !(Seq (RewriteTrace ())) From 3a47065be420f81776f7d952890d87c56ccf9372 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Thu, 27 Jun 2024 16:46:33 +0100 Subject: [PATCH 07/54] implment isSat --- booster/library/Booster/SMT/Interface.hs | 56 ++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/booster/library/Booster/SMT/Interface.hs b/booster/library/Booster/SMT/Interface.hs index 5bd067713a..61f028d85d 100644 --- a/booster/library/Booster/SMT/Interface.hs +++ b/booster/library/Booster/SMT/Interface.hs @@ -11,7 +11,7 @@ module Booster.SMT.Interface ( finaliseSolver, getModelFor, checkPredicates, - checkSat, + isSat, hardResetSolver, ) where @@ -450,13 +450,63 @@ checkPredicates ctxt givenPs givenSubst psToCheck pure (positive, negative) -checkSat :: +isSat :: forall io. Log.LoggerMIO io => SMT.SMTContext -> Set Predicate -> io (Either SMTError Bool) -checkSat = undefined +isSat ctxt psToCheck + | null psToCheck = pure . Right $ True + | Left errMsg <- translated = Log.withContext Log.CtxSMT $ do + Log.withContext Log.CtxAbort $ Log.logMessage $ "SMT translation error: " <> errMsg + pure . Left . SMTTranslationError $ errMsg + | Right (smtToCheck, transState) <- translated = Log.withContext Log.CtxSMT $ do + evalSMT ctxt . runExceptT $ solve smtToCheck transState + where + translated :: Either Text ([DeclareCommand], TranslationState) + translated = SMT.runTranslator $ + mapM (\(Predicate p) -> Assert (mkComment p) <$> SMT.translateTerm p) $ Set.toList psToCheck + + solve smtToCheck transState = solve' + where + solve' = do + lift $ hardResetSolver ctxt.options + Log.logMessage . Pretty.renderOneLineText $ + hsep ("Predicates to check for SAT:" : map pretty (Set.toList psToCheck)) + lift $ declareVariables transState + mapM_ smtRun smtToCheck + smtRun CheckSat >>= \case + Sat -> pure True + Unsat -> pure False + Unknown -> retry + other -> do + let msg = "Unexpected result while calling 'check-sat': " <> show other + Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg + throwSMT' msg + + retry = do + opts <- lift . SMT $ gets (.options) + case opts.retryLimit of + Just x | x > 0 -> do + let newOpts = opts{timeout = 2 * opts.timeout, retryLimit = Just $ x - 1} + lift $ hardResetSolver newOpts + Log.logMessage ("Retrying with higher timeout" :: Text) + solve' + _ -> failBecauseUnknown + + failBecauseUnknown :: ExceptT SMTError (SMT io) Bool + failBecauseUnknown = + smtRun GetReasonUnknown >>= \case + ReasonUnknown reason -> do + Log.withContext Log.CtxAbort $ + Log.logMessage $ + "Returned Unknown. Reason: " <> reason + throwE $ SMTSolverUnknown reason mempty psToCheck + other -> do + let msg = "Unexpected result while calling ':reason-unknown': " <> show other + Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg + throwSMT' msg -- interactWithSolver :: -- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) From c5dd30b2b5b3d86e67080d9428610d629d1ab1d6 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Thu, 27 Jun 2024 16:47:33 +0100 Subject: [PATCH 08/54] actually return the branching condition as part of the rewritten pattern + fix unit tests --- booster/library/Booster/Pattern/Rewrite.hs | 65 +++++++++---------- .../Test/Booster/Pattern/Rewrite.hs | 30 ++++----- 2 files changed, 43 insertions(+), 52 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 8050fad487..12f641299e 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -12,6 +12,7 @@ module Booster.Pattern.Rewrite ( performRewrite, rewriteStep, RewriteFailed (..), + RewriteStepResult(..), RewriteResult (..), RewriteTrace (..), pattern CollectRewriteTraces, @@ -133,6 +134,9 @@ getRemainder = RewriteT $ snd <$> lift get setRemainder :: Monad m => Set.Set Predicate -> RewriteT m () setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) + +data RewriteStepResult a = OnlyTrivial | AppliedRules a deriving (Eq, Show, Functor) + {- | Performs a rewrite step (using suitable rewrite rules from the definition). @@ -143,7 +147,7 @@ setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) rewriteStep :: LoggerMIO io => Pattern -> - RewriteT io [(RewriteRule "Rewrite", Maybe Pattern)] + RewriteT io (RewriteStepResult [(RewriteRule "Rewrite", Pattern)]) rewriteStep pat = do def <- getDefinition let getIndex = @@ -160,8 +164,18 @@ rewriteStep pat = do -- process one priority group at a time (descending priority), -- until a result is obtained or the entire rewrite fails. - processGroups pat rules + filterOutTrivial <$> processGroups pat rules where + -- return `OnlyTrivial` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, + -- return an `AppliedRules` list of `(r, p)` pairs. + filterOutTrivial :: + [(RewriteRule "Rewrite", Maybe Pattern)] -> RewriteStepResult [(RewriteRule "Rewrite", Pattern)] + filterOutTrivial = \case + [] -> AppliedRules [] + [(_, Nothing)] -> OnlyTrivial + (_, Nothing) : xs -> filterOutTrivial xs + (rule, Just p) : xs -> AppliedRules $ (rule, p) : mapMaybe (\(r, mp) -> (r,) <$> mp) xs + processGroups :: LoggerMIO io => Pattern -> @@ -199,11 +213,9 @@ rewriteStep pat = do else getSolver >>= \case Just solver -> - SMT.checkSat solver (pattr.constraints <> newRemainder) >>= \case + SMT.isSat solver (pattr.constraints <> newRemainder) >>= \case Right False -> do -- the remainder condition is unsatisfiable: no need to consider the remainder branch. - -- we need to make sure we set the remainder to empty before returning - setRemainder mempty pure resultsWithoutRemainders Right True -> do -- the remainder condition is satisfiable. @@ -212,7 +224,7 @@ rewriteStep pat = do -- we add the remainder condition to the predicates of the @pattr@ (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules Left SMT.SMTSolverUnknown{} -> - -- solver cannot solve the remainder. Descend into the remainder branch anyway? + -- solver cannot solve the remainder. Descend into the remainder branch anyway (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors Nothing -> (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules @@ -387,12 +399,11 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu <> (Set.fromList $ map (coerce . substituteInTerm existentialSubst . coerce) newConstraints) ) ceilConditions - withContext CtxSuccess $ - withPatternContext rewritten $ do - let remainder = case unclearRequiresAfterSmt of - [] -> Nothing - _ -> Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt - pure (rewritten, remainder) + withContext CtxSuccess $ do + case unclearRequiresAfterSmt of + [] -> withPatternContext rewritten $ pure (rewritten, Nothing) + _ -> let rewritten' = rewritten{constraints = rewritten.constraints <> Set.fromList unclearRequiresAfterSmt} in + withPatternContext rewritten' $ pure (rewritten', Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt) where failRewrite = lift . throw @@ -727,16 +738,6 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc uniqueId = (.uniqueId) . (.attributes) - -- return `Nothing` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, - -- return a `Just` list of `(r, p)` pairs. - collapseIfOnlyTrivial :: - [(RewriteRule "Rewrite", Maybe Pattern)] -> Maybe [(RewriteRule "Rewrite", Pattern)] - collapseIfOnlyTrivial = \case - [] -> Just [] - [(_, Nothing)] -> Nothing - (_, Nothing) : xs -> collapseIfOnlyTrivial xs - (rule, Just pat) : xs -> ((rule, pat) :) <$> collapseIfOnlyTrivial xs - doSteps :: MaybeSimplified flag Pattern -> StateT RewriteStepsState io (RewriteResult Pattern) doSteps pat | unWrappedPat <- unMaybeSimplified pat = do @@ -776,16 +777,15 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') Right (appliedRules, (cache, _remainder)) -> - updateCache cache >> incrementCounter >> case collapseIfOnlyTrivial appliedRules of - Nothing -> do + updateCache cache >> incrementCounter >> case appliedRules of + OnlyTrivial -> do -- all rule applications were trivial -- by definition that means we couldn't have had any remainders, so we can just return trivial logMessage $ "Simplified to bottom after " <> showCounter counter pure $ RewriteTrivial unWrappedPat - Just [] -> do - -- No trivial results, and no other applied rules. + AppliedRules [] -> do + -- No rules applied. -- We return stuck if the term had already been simplified in a previous step - -- If not, we attempt to logMessage $ "Stopped after " <> showCounter counter emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules unWrappedPat case pat of @@ -796,7 +796,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL -- FIXME: I think this should be trivial, surely? logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' - Just [(rule, nextPat)] + AppliedRules [(rule, nextPat)] | labelOf rule `elem` cutLabels -> do simplify pat >>= \case Bottom pat' -> do @@ -822,7 +822,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL | otherwise -> do emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) unWrappedPat nextPat doSteps (Unsimplified nextPat) - Just nextPats -> do + AppliedRules nextPats -> do logMessage $ "Stopped due to branching after " <> showCounter counter simplify pat >>= \case Bottom pat' -> do @@ -831,11 +831,8 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Simplified pat' -> (catSimplified <$> mapM (\(r, nextPat) -> fmap (r,) <$> simplify (Unsimplified nextPat)) nextPats) >>= \case [] -> withPatternContext pat' $ do - logMessage ("Rewrite stuck after pruning branches" :: Text) - -- FIXME: why is this stuck? Surely we go from some pats to an empty list only if all branches were pruned to bottom - -- in which case we should say that the rewrite is trivial? ... but perhaps this branch should not occur at all? - -- i.e. pat would have been bottom already?? - pure $ RewriteStuck pat' + logMessage ("Rewrite trivial after pruning all branches" :: Text) + pure $ RewriteTrivial pat' [(rule, nextPat')] -> withPatternContext pat' $ do logMessage ("All but one branch pruned, continuing" :: Text) emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) pat' nextPat' diff --git a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs index f5a4c1aa37..c22f663e5d 100644 --- a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs @@ -201,9 +201,7 @@ errorCases = rewriteSuccess = testCase "con1 app rewrites to f1 app" $ [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("thing") ) ), ConfigVar:SortK{}) ) |] - `rewritesTo` ( "con1-f1" - , [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("thing") ) ), ConfigVar:SortK{}) ) |] - ) + `rewritesTo` [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("thing") ) ), ConfigVar:SortK{}) ) |] unifyNotMatch = testCase "Stuck case when subject has variables" $ getsStuck @@ -231,36 +229,32 @@ rulePriority = testCase "con1 rewrites to a branch when higher priority does not apply" $ [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] `branchesTo` [ - ( "con1-f2" - , [trm| kCell{}( kseq{}( inj{AnotherSort{}, SortKItem{}}( con4{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] - ) + [trm| kCell{}( kseq{}( inj{AnotherSort{}, SortKItem{}}( con4{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] , - ( "con1-f1'" - , [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] - ) + [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] ] -runWith :: Term -> Either (RewriteFailed "Rewrite") (RewriteResult Pattern) -runWith t = +runWith :: Term -> Either (RewriteFailed "Rewrite") (RewriteStepResult [Pattern]) +runWith t = second fst $ unsafePerformIO ( runNoLoggingT $ - runRewriteT NoCollectRewriteTraces def Nothing Nothing mempty (rewriteStep [] [] $ Pattern_ t) + runRewriteT NoCollectRewriteTraces def Nothing Nothing mempty mempty (fmap (fmap snd) <$> (rewriteStep $ Pattern_ t)) ) -rewritesTo :: Term -> (Text, Term) -> IO () -t1 `rewritesTo` (lbl, t2) = - runWith t1 @?= Right (RewriteFinished (Just lbl) (Just mockUniqueId) $ Pattern_ t2) +rewritesTo :: Term -> Term -> IO () +t1 `rewritesTo` t2 = + runWith t1 @?= Right (AppliedRules [Pattern_ t2]) getsStuck :: Term -> IO () getsStuck t1 = - runWith t1 @?= Right (RewriteStuck $ Pattern_ t1) + runWith t1 @?= Right (AppliedRules []) -branchesTo :: Term -> [(Text, Term)] -> IO () +branchesTo :: Term -> [Term] -> IO () t `branchesTo` ts = runWith t @?= Right - (RewriteBranch (Pattern_ t) $ NE.fromList $ map (\(lbl, t') -> (lbl, mockUniqueId, Pattern_ t')) ts) + (AppliedRules $ map Pattern_ ts) failsWith :: Term -> RewriteFailed "Rewrite" -> IO () failsWith t err = From 07189d7fbf5213526f491806245cea69c9757fe9 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Thu, 27 Jun 2024 16:49:47 +0100 Subject: [PATCH 09/54] fourmolu --- booster/library/Booster/Pattern/Rewrite.hs | 13 +-- booster/library/Booster/SMT/Interface.hs | 90 ++++++++++--------- .../Test/Booster/Pattern/Rewrite.hs | 17 ++-- 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 12f641299e..de4eca6530 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -12,7 +12,7 @@ module Booster.Pattern.Rewrite ( performRewrite, rewriteStep, RewriteFailed (..), - RewriteStepResult(..), + RewriteStepResult (..), RewriteResult (..), RewriteTrace (..), pattern CollectRewriteTraces, @@ -134,7 +134,6 @@ getRemainder = RewriteT $ snd <$> lift get setRemainder :: Monad m => Set.Set Predicate -> RewriteT m () setRemainder r = RewriteT $ lift $ modify $ \(cache, _) -> (cache, r) - data RewriteStepResult a = OnlyTrivial | AppliedRules a deriving (Eq, Show, Functor) {- | Performs a rewrite step (using suitable rewrite rules from the @@ -400,10 +399,12 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu ) ceilConditions withContext CtxSuccess $ do - case unclearRequiresAfterSmt of - [] -> withPatternContext rewritten $ pure (rewritten, Nothing) - _ -> let rewritten' = rewritten{constraints = rewritten.constraints <> Set.fromList unclearRequiresAfterSmt} in - withPatternContext rewritten' $ pure (rewritten', Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt) + case unclearRequiresAfterSmt of + [] -> withPatternContext rewritten $ pure (rewritten, Nothing) + _ -> + let rewritten' = rewritten{constraints = rewritten.constraints <> Set.fromList unclearRequiresAfterSmt} + in withPatternContext rewritten' $ + pure (rewritten', Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt) where failRewrite = lift . throw diff --git a/booster/library/Booster/SMT/Interface.hs b/booster/library/Booster/SMT/Interface.hs index 61f028d85d..2d5a75c0dd 100644 --- a/booster/library/Booster/SMT/Interface.hs +++ b/booster/library/Booster/SMT/Interface.hs @@ -463,50 +463,52 @@ isSat ctxt psToCheck pure . Left . SMTTranslationError $ errMsg | Right (smtToCheck, transState) <- translated = Log.withContext Log.CtxSMT $ do evalSMT ctxt . runExceptT $ solve smtToCheck transState - where - translated :: Either Text ([DeclareCommand], TranslationState) - translated = SMT.runTranslator $ - mapM (\(Predicate p) -> Assert (mkComment p) <$> SMT.translateTerm p) $ Set.toList psToCheck - - solve smtToCheck transState = solve' - where - solve' = do - lift $ hardResetSolver ctxt.options - Log.logMessage . Pretty.renderOneLineText $ - hsep ("Predicates to check for SAT:" : map pretty (Set.toList psToCheck)) - lift $ declareVariables transState - mapM_ smtRun smtToCheck - smtRun CheckSat >>= \case - Sat -> pure True - Unsat -> pure False - Unknown -> retry - other -> do - let msg = "Unexpected result while calling 'check-sat': " <> show other - Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg - throwSMT' msg - - retry = do - opts <- lift . SMT $ gets (.options) - case opts.retryLimit of - Just x | x > 0 -> do - let newOpts = opts{timeout = 2 * opts.timeout, retryLimit = Just $ x - 1} - lift $ hardResetSolver newOpts - Log.logMessage ("Retrying with higher timeout" :: Text) - solve' - _ -> failBecauseUnknown - - failBecauseUnknown :: ExceptT SMTError (SMT io) Bool - failBecauseUnknown = - smtRun GetReasonUnknown >>= \case - ReasonUnknown reason -> do - Log.withContext Log.CtxAbort $ - Log.logMessage $ - "Returned Unknown. Reason: " <> reason - throwE $ SMTSolverUnknown reason mempty psToCheck - other -> do - let msg = "Unexpected result while calling ':reason-unknown': " <> show other - Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg - throwSMT' msg + where + translated :: Either Text ([DeclareCommand], TranslationState) + translated = + SMT.runTranslator $ + mapM (\(Predicate p) -> Assert (mkComment p) <$> SMT.translateTerm p) $ + Set.toList psToCheck + + solve smtToCheck transState = solve' + where + solve' = do + lift $ hardResetSolver ctxt.options + Log.logMessage . Pretty.renderOneLineText $ + hsep ("Predicates to check for SAT:" : map pretty (Set.toList psToCheck)) + lift $ declareVariables transState + mapM_ smtRun smtToCheck + smtRun CheckSat >>= \case + Sat -> pure True + Unsat -> pure False + Unknown -> retry + other -> do + let msg = "Unexpected result while calling 'check-sat': " <> show other + Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg + throwSMT' msg + + retry = do + opts <- lift . SMT $ gets (.options) + case opts.retryLimit of + Just x | x > 0 -> do + let newOpts = opts{timeout = 2 * opts.timeout, retryLimit = Just $ x - 1} + lift $ hardResetSolver newOpts + Log.logMessage ("Retrying with higher timeout" :: Text) + solve' + _ -> failBecauseUnknown + + failBecauseUnknown :: ExceptT SMTError (SMT io) Bool + failBecauseUnknown = + smtRun GetReasonUnknown >>= \case + ReasonUnknown reason -> do + Log.withContext Log.CtxAbort $ + Log.logMessage $ + "Returned Unknown. Reason: " <> reason + throwE $ SMTSolverUnknown reason mempty psToCheck + other -> do + let msg = "Unexpected result while calling ':reason-unknown': " <> show other + Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg + throwSMT' msg -- interactWithSolver :: -- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) diff --git a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs index c22f663e5d..ba8d2b08e9 100644 --- a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs @@ -228,18 +228,23 @@ rewriteStuck = rulePriority = testCase "con1 rewrites to a branch when higher priority does not apply" $ [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] - `branchesTo` [ - [trm| kCell{}( kseq{}( inj{AnotherSort{}, SortKItem{}}( con4{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] - , - [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] + `branchesTo` [ [trm| kCell{}( kseq{}( inj{AnotherSort{}, SortKItem{}}( con4{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] + , [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] ] runWith :: Term -> Either (RewriteFailed "Rewrite") (RewriteStepResult [Pattern]) -runWith t = +runWith t = second fst $ unsafePerformIO ( runNoLoggingT $ - runRewriteT NoCollectRewriteTraces def Nothing Nothing mempty mempty (fmap (fmap snd) <$> (rewriteStep $ Pattern_ t)) + runRewriteT + NoCollectRewriteTraces + def + Nothing + Nothing + mempty + mempty + (fmap (fmap snd) <$> (rewriteStep $ Pattern_ t)) ) rewritesTo :: Term -> Term -> IO () From cee50e9dba116865b4706ab04777e0c20d448275 Mon Sep 17 00:00:00 2001 From: Sam Balco Date: Fri, 28 Jun 2024 14:16:34 +0100 Subject: [PATCH 10/54] misc --- booster/library/Booster/Pattern/Rewrite.hs | 26 +++++++------- booster/library/Booster/SMT/Interface.hs | 41 +++------------------- booster/tools/booster/Server.hs | 2 +- 3 files changed, 19 insertions(+), 50 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index fe129fbefb..9fa30a0f25 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -170,7 +170,7 @@ rewriteStep pat = do -- process one priority group at a time (descending priority), -- until a result is obtained or the entire rewrite fails. - filterOutTrivial <$> processGroups pat rules + filterOutTrivial <$> processGroups rules where -- return `OnlyTrivial` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, -- return an `AppliedRules` list of `(r, p)` pairs. @@ -184,11 +184,10 @@ rewriteStep pat = do processGroups :: LoggerMIO io => - Pattern -> [[RewriteRule "Rewrite"]] -> RewriteT io [(RewriteRule "Rewrite", Maybe Pattern)] - processGroups _pattr [] = pure mempty - processGroups pattr (rules : lowerPriorityRules) = do + processGroups [] = pure [] + processGroups (rules : lowerPriorityRules) = do -- try all rules of the priority group. This will immediately -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) @@ -196,7 +195,7 @@ rewriteStep pat = do results <- catMaybes <$> mapM - (\r -> (fmap (r,)) <$> applyRule pattr{constraints = pattr.constraints <> currentRemainder} r) + (\r -> (fmap (r,)) <$> applyRule pat{constraints = pat.constraints <> currentRemainder} r) rules let nonTrivialResultsWithPartialRemainders = @@ -219,21 +218,22 @@ rewriteStep pat = do else getSolver >>= \case Just solver -> - SMT.isSat solver (pattr.constraints <> newRemainder) >>= \case + SMT.isSat solver (pat.constraints <> newRemainder) >>= \case Right False -> do -- the remainder condition is unsatisfiable: no need to consider the remainder branch. + setRemainder mempty pure resultsWithoutRemainders Right True -> do -- the remainder condition is satisfiable. -- Have to construct the remainder branch and consider it -- To construct the "remainder pattern", -- we add the remainder condition to the predicates of the @pattr@ - (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules + (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules Left SMT.SMTSolverUnknown{} -> -- solver cannot solve the remainder. Descend into the remainder branch anyway - (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules + (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - Nothing -> (resultsWithoutRemainders <>) <$> processGroups pattr lowerPriorityRules + Nothing -> (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules type RewriteRuleAppT m a = ExceptT (Maybe ()) m a @@ -795,7 +795,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') _ -> simplify pat >>= \case - -- FIXME: I think this should be trivial, surely? + -- We are stuck here not trivial because we didn't apply a single rule Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' Left failure -> do @@ -804,9 +804,11 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') _ -> simplify pat >>= \case - -- FIXME: I think this should be trivial, surely? + -- We are stuck here not trivial because we didn't apply a single rule Bottom pat' -> logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + -- We may want to return the remainder as a new field in the execute response, as the remainder + -- may not be empty, which would indicate a "hole" in the semantics that the user should be aware of. Right (appliedRules, (cache, _remainder)) -> updateCache cache >> incrementCounter >> case appliedRules of OnlyTrivial -> do @@ -824,7 +826,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL _ -> simplify pat >>= \case Bottom pat' -> - -- FIXME: I think this should be trivial, surely? + -- We are stuck here not trivial because we didn't apply a single rule logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' AppliedRules [(rule, nextPat)] diff --git a/booster/library/Booster/SMT/Interface.hs b/booster/library/Booster/SMT/Interface.hs index 2f85652632..70d0f0618a 100644 --- a/booster/library/Booster/SMT/Interface.hs +++ b/booster/library/Booster/SMT/Interface.hs @@ -483,8 +483,10 @@ isSat ctxt psToCheck where solve' = do lift $ hardResetSolver ctxt.options - Log.logMessage . Pretty.renderOneLineText $ - hsep ("Predicates to check for SAT:" : map pretty (Set.toList psToCheck)) + Log.getPrettyModifiers >>= \case + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) -> + Log.logMessage . Pretty.renderOneLineText $ + hsep ("Predicates to check for SAT:" : map (pretty' @mods) (Set.toList psToCheck)) lift $ declareVariables transState mapM_ smtRun smtToCheck smtRun CheckSat >>= \case @@ -518,38 +520,3 @@ isSat ctxt psToCheck let msg = "Unexpected result while calling ':reason-unknown': " <> show other Log.withContext Log.CtxAbort $ Log.logMessage $ Text.pack msg throwSMT' msg - --- interactWithSolver :: --- [DeclareCommand] -> [SExpr] -> ExceptT SMTError (SMT io) (Response, Response) --- interactWithSolver smtGiven sexprsToCheck = do --- smtRun_ Push - --- -- assert ground truth --- mapM_ smtRun smtGiven - --- consistent <- smtRun CheckSat --- unless (consistent == Sat) $ do --- let errMsg = ("Inconsistent ground truth, check returns Nothing" :: Text) --- Log.logMessage errMsg --- let ifConsistent check = if (consistent == Sat) then check else pure Unsat - --- -- save ground truth for 2nd check --- smtRun_ Push - --- -- run check for K ∧ P and then for K ∧ !P --- let allToCheck = SMT.List (Atom "and" : sexprsToCheck) - --- positive <- ifConsistent $ do --- smtRun_ $ Assert "P" allToCheck --- smtRun CheckSat --- smtRun_ Pop --- negative <- ifConsistent $ do --- smtRun_ $ Assert "not P" (SMT.smtnot allToCheck) --- smtRun CheckSat --- smtRun_ Pop - --- Log.logMessage $ --- "Check of Given ∧ P and Given ∧ !P produced " --- <> pack (show (positive, negative)) - --- pure (positive, negative) diff --git a/booster/tools/booster/Server.hs b/booster/tools/booster/Server.hs index 8f1cdadbe7..08742c2fba 100644 --- a/booster/tools/booster/Server.hs +++ b/booster/tools/booster/Server.hs @@ -455,7 +455,7 @@ clProxyOptionsParser = (eitherReader $ mapM reasonReader . splitOn ",") ( long "fallback-on" <> metavar "REASON1,REASON2..." - <> value [Branching, Stuck, Aborted] + <> value [Stuck, Aborted] <> help "Halt reasons for which requests should be re-executed with kore-rpc" <> showDefaultWith (intercalate "," . map show) ) From e384a971e017fc5c4d6ada6fbce15140868f2f65 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 1 Jul 2024 08:14:14 +0200 Subject: [PATCH 11/54] Log rule remainder predicates --- booster/library/Booster/Pattern/Rewrite.hs | 8 ++++++-- kore-rpc-types/src/Kore/JsonRpc/Types/ContextLog.hs | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 9fa30a0f25..a3963b18c0 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -210,8 +210,9 @@ rewriteStep pat = do -- If the new remainder is bottom, then no lower priority rules apply newRemainder = currentRemainder <> Set.fromList (mapMaybe (snd . snd) nonTrivialResultsWithPartialRemainders) resultsWithoutRemainders = map (fmap (fmap fst)) results - setRemainder newRemainder + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers + withContext CtxRemainder $ logPretty' @mods (collapseAndBools . Set.toList $ newRemainder) if Set.null newRemainder then pure resultsWithoutRemainders @@ -222,14 +223,17 @@ rewriteStep pat = do Right False -> do -- the remainder condition is unsatisfiable: no need to consider the remainder branch. setRemainder mempty + withContext CtxRemainder $ logMessage ("remainder is UNSAT" :: Text) pure resultsWithoutRemainders Right True -> do + withContext CtxRemainder $ logMessage ("remainder is SAT" :: Text) -- the remainder condition is satisfiable. -- Have to construct the remainder branch and consider it -- To construct the "remainder pattern", -- we add the remainder condition to the predicates of the @pattr@ (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules - Left SMT.SMTSolverUnknown{} -> + Left SMT.SMTSolverUnknown{} -> do + withContext CtxRemainder $ logMessage ("remainder is UNKNWON" :: Text) -- solver cannot solve the remainder. Descend into the remainder branch anyway (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors diff --git a/kore-rpc-types/src/Kore/JsonRpc/Types/ContextLog.hs b/kore-rpc-types/src/Kore/JsonRpc/Types/ContextLog.hs index 86a76839f5..f7d4b24090 100644 --- a/kore-rpc-types/src/Kore/JsonRpc/Types/ContextLog.hs +++ b/kore-rpc-types/src/Kore/JsonRpc/Types/ContextLog.hs @@ -45,6 +45,7 @@ data SimpleContext CtxKoreTerm | CtxDetail | CtxSubstitution + | CtxRemainder | CtxDepth | CtxTiming | -- standard log levels From e70bdca7f92d7e967e06de2889b875eb216816c2 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 1 Jul 2024 08:14:31 +0200 Subject: [PATCH 12/54] Continue with lower-priority rules if no rules applied group --- booster/library/Booster/Pattern/Rewrite.hs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index a3963b18c0..40deb95ce3 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -215,7 +215,14 @@ rewriteStep pat = do withContext CtxRemainder $ logPretty' @mods (collapseAndBools . Set.toList $ newRemainder) if Set.null newRemainder - then pure resultsWithoutRemainders + then case resultsWithoutRemainders of + [] -> + -- proceed to lower priority rules if we have not applied any rules at this priority level + processGroups lowerPriorityRules + xs -> + -- if we applied at least one rule and the remainder was empty, return the results. + -- TODO: I think we have to apply lower priority rules here still! + pure xs else getSolver >>= \case Just solver -> From ac350fd7460f9cd951bab8bba37b19f27a889b8c Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 1 Jul 2024 10:31:00 +0200 Subject: [PATCH 13/54] Fix KEVM script by calling the new Makefile target --- scripts/performance-tests-kevm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/performance-tests-kevm.sh b/scripts/performance-tests-kevm.sh index aaae52f6c8..afe3f96d97 100755 --- a/scripts/performance-tests-kevm.sh +++ b/scripts/performance-tests-kevm.sh @@ -106,13 +106,13 @@ feature_shell "cd kevm-pyk && poetry run pytest src/tests/integration/test_prove mkdir -p $SCRIPT_DIR/logs -feature_shell "make test-prove-pyk PYTEST_PARALLEL=$PYTEST_PARALLEL PYTEST_ARGS='--maxfail=0 --timeout 7200 -vv $BUG_REPORT --kompiled-targets-dir $PREKOMPILED_DIR' | tee $SCRIPT_DIR/logs/kevm-$KEVM_VERSION-$FEATURE_BRANCH_NAME.log" +feature_shell "make test-prove-rules PYTEST_PARALLEL=$PYTEST_PARALLEL PYTEST_ARGS='--maxfail=0 --timeout 7200 -vv $BUG_REPORT --kompiled-targets-dir $PREKOMPILED_DIR' | tee $SCRIPT_DIR/logs/kevm-$KEVM_VERSION-$FEATURE_BRANCH_NAME.log" killall kore-rpc-booster || echo "No zombie processes found" if [ -z "$BUG_REPORT" ]; then if [ ! -e "$SCRIPT_DIR/logs/kevm-$KEVM_VERSION-master-$MASTER_COMMIT_SHORT.log" ]; then - master_shell "make test-prove-pyk PYTEST_PARALLEL=$PYTEST_PARALLEL PYTEST_ARGS='--maxfail=0 --timeout 7200 -vv --kompiled-targets-dir $PREKOMPILED_DIR' | tee $SCRIPT_DIR/logs/kevm-$KEVM_VERSION-master-$MASTER_COMMIT_SHORT.log" + master_shell "make test-prove-rules PYTEST_PARALLEL=$PYTEST_PARALLEL PYTEST_ARGS='--maxfail=0 --timeout 7200 -vv --kompiled-targets-dir $PREKOMPILED_DIR' | tee $SCRIPT_DIR/logs/kevm-$KEVM_VERSION-master-$MASTER_COMMIT_SHORT.log" killall kore-rpc-booster || echo "No zombie processes found" fi From cab49d7165c9824ef007097060b888864d418226 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 2 Jul 2024 11:31:34 +0200 Subject: [PATCH 14/54] Increment rewrite depth counter in the same way as before, add comments --- booster/library/Booster/Pattern/Rewrite.hs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 40deb95ce3..fa980068a7 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -821,14 +821,14 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL -- We may want to return the remainder as a new field in the execute response, as the remainder -- may not be empty, which would indicate a "hole" in the semantics that the user should be aware of. Right (appliedRules, (cache, _remainder)) -> - updateCache cache >> incrementCounter >> case appliedRules of + updateCache cache >> case appliedRules of OnlyTrivial -> do -- all rule applications were trivial -- by definition that means we couldn't have had any remainders, so we can just return trivial logMessage $ "Simplified to bottom after " <> showCounter counter pure $ RewriteTrivial unWrappedPat AppliedRules [] -> do - -- No rules applied. + -- no rules applied. -- We return stuck if the term had already been simplified in a previous step logMessage $ "Stopped after " <> showCounter counter emitRewriteTrace $ RewriteStepFailed $ NoApplicableRules unWrappedPat @@ -840,7 +840,8 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL -- We are stuck here not trivial because we didn't apply a single rule logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' - AppliedRules [(rule, nextPat)] + AppliedRules [(rule, nextPat)] -- applied single rule + -- cut-point rule, stop | labelOf rule `elem` cutLabels -> do simplify pat >>= \case Bottom pat' -> do @@ -855,6 +856,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL logMessage $ "Cut point " <> (labelOf rule) <> " after " <> showCounter counter pure $ RewriteCutPoint (labelOf rule) (uniqueId rule) pat' nextPat' | labelOf rule `elem` terminalLabels -> do + -- terminal rule, stop emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) unWrappedPat nextPat simplify (Unsimplified nextPat) >>= \case Bottom nextPat' -> do @@ -862,11 +864,15 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL pure $ RewriteTrivial nextPat' Simplified nextPat' -> do logMessage $ "Terminal " <> (labelOf rule) <> " after " <> showCounter counter + incrementCounter pure $ RewriteTerminal (labelOf rule) (uniqueId rule) nextPat' | otherwise -> do + -- any other rule, go on emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) unWrappedPat nextPat + incrementCounter doSteps (Unsimplified nextPat) AppliedRules nextPats -> do + -- applied multiple rules logMessage $ "Stopped due to branching after " <> showCounter counter simplify pat >>= \case Bottom pat' -> do @@ -880,6 +886,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL [(rule, nextPat')] -> withPatternContext pat' $ do logMessage ("All but one branch pruned, continuing" :: Text) emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) pat' nextPat' + incrementCounter doSteps (Simplified nextPat') nextPats' -> do emitRewriteTrace $ From b4d3a99c6a6db60e4982cb713b46271e1695331c Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 2 Jul 2024 13:39:52 +0200 Subject: [PATCH 15/54] Log uncovered remainder --- booster/library/Booster/Pattern/Rewrite.hs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index fa980068a7..0dafb462cc 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -42,7 +42,7 @@ import Data.Map qualified as Map import Data.Maybe (catMaybes, fromMaybe, mapMaybe) import Data.Sequence (Seq, (|>)) import Data.Set qualified as Set -import Data.Text as Text (Text, pack) +import Data.Text as Text (Text, intercalate, pack) import Numeric.Natural import Prettyprinter import Unsafe.Coerce (unsafeCoerce) @@ -820,7 +820,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') -- We may want to return the remainder as a new field in the execute response, as the remainder -- may not be empty, which would indicate a "hole" in the semantics that the user should be aware of. - Right (appliedRules, (cache, _remainder)) -> + Right (appliedRules, (cache, remainderPredicates)) -> updateCache cache >> case appliedRules of OnlyTrivial -> do -- all rule applications were trivial @@ -893,6 +893,14 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL RewriteBranchingStep pat' $ NE.fromList $ map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) nextPats' + unless (Set.null remainderPredicates) $ do + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers + withContext CtxRemainder . withContext CtxDetail $ + logMessage + ( ("Uncovered remainder branch after rewriting with rules " :: Text) + <> ( Text.intercalate ", " $ map (\(r, _) -> getUniqueId $ uniqueId r) nextPats' + ) + ) pure $ RewriteBranch pat' $ NE.fromList $ From fafaf13f213d571720b0ae0fdd62438c1d153dc0 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 12:30:18 +0200 Subject: [PATCH 16/54] Increment depth counter when pruning branch in post-simpl --- booster/tools/booster/Proxy.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 93ef9b513c..98e948d544 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -500,11 +500,14 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of postExecResult <- simplifyExecResult logSettings r._module def boosterResult case postExecResult of - Left (nextState, newLogs) -> + Left (nextState, newLogs) -> do + let prunedBoosterBranchStep + | boosterResult.reason == Branching = 1 + | otherwise = 0 executionLoop logSettings def - ( currentDepth + boosterResult.depth + ( currentDepth + boosterResult.depth + prunedBoosterBranchStep , time + bTime , koreTime , postProcessLogs <$> combineLogs (rpcLogs : boosterResult.logs : newLogs) From 5e03d4174ecfb707ae3dc01e6d4c0106e379f9b8 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 15:31:43 +0200 Subject: [PATCH 17/54] Add rule predicates --- booster/library/Booster/JsonRpc.hs | 33 +++++++++++++--------- booster/library/Booster/Pattern/Rewrite.hs | 9 ++++-- booster/tools/booster/Proxy.hs | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/booster/library/Booster/JsonRpc.hs b/booster/library/Booster/JsonRpc.hs index 13f038eef3..723d58bca8 100644 --- a/booster/library/Booster/JsonRpc.hs +++ b/booster/library/Booster/JsonRpc.hs @@ -48,7 +48,7 @@ import Booster.Definition.Base qualified as Definition (RewriteRule (..)) import Booster.LLVM as LLVM (API) import Booster.Log import Booster.Pattern.ApplyEquations qualified as ApplyEquations -import Booster.Pattern.Base (Pattern (..), Sort (SortApp), Term, Variable) +import Booster.Pattern.Base (Pattern (..), Predicate (..), Sort (SortApp), Term, Variable) import Booster.Pattern.Base qualified as Pattern import Booster.Pattern.Bool (pattern TrueBool) import Booster.Pattern.Match (FailReason (..), MatchResult (..), MatchType (..), matchTerms) @@ -604,10 +604,11 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Branching , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Just $ - map (\(_, muid, p') -> toExecState p' originalSubstitution unsupported (Just muid)) $ + map + (\(_, muid, p', mrulePred) -> toExecState p' originalSubstitution unsupported (Just muid) mrulePred) $ toList nexts , rule = Nothing , unknownPredicate = Nothing @@ -619,7 +620,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Stuck , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -631,7 +632,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Vacuous , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -643,8 +644,8 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.CutPointRule , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing - , nextStates = Just [toExecState next originalSubstitution unsupported Nothing] + , state = toExecState p originalSubstitution unsupported Nothing Nothing + , nextStates = Just [toExecState next originalSubstitution unsupported Nothing Nothing] , rule = Just lbl , unknownPredicate = Nothing } @@ -655,7 +656,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.TerminalRule , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Nothing , rule = Just lbl , unknownPredicate = Nothing @@ -667,7 +668,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.DepthBound , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -684,7 +685,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c (logSuccessfulRewrites, logFailedRewrites) (RewriteStepFailed failure) in logs <|> abortRewriteLog - , state = toExecState p originalSubstitution unsupported Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -710,17 +711,23 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c (Just t, xs) -> Just (t : xs) toExecState :: - Pattern -> Map Variable Term -> [Syntax.KorePattern] -> Maybe UniqueId -> RpcTypes.ExecuteState -toExecState pat sub unsupported muid = + Pattern -> + Map Variable Term -> + [Syntax.KorePattern] -> + Maybe UniqueId -> + Maybe Predicate -> + RpcTypes.ExecuteState +toExecState pat sub unsupported muid mrulePredicate = RpcTypes.ExecuteState { term = addHeader t , predicate = addHeader <$> addUnsupported p , substitution = addHeader <$> s , ruleSubstitution = Nothing - , rulePredicate = Nothing + , rulePredicate = addHeader <$> mrulePredExt , ruleId = getUniqueId <$> muid } where + mrulePredExt = externalisePredicate (externaliseSort Pattern.SortBool) <$> mrulePredicate (t, p, s) = externalisePattern pat sub termSort = externaliseSort $ sortOfPattern pat allUnsupported = Syntax.KJAnd termSort unsupported diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 0dafb462cc..56bdc0c778 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -175,7 +175,8 @@ rewriteStep pat = do -- return `OnlyTrivial` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, -- return an `AppliedRules` list of `(r, p)` pairs. filterOutTrivial :: - [(RewriteRule "Rewrite", Maybe Pattern)] -> RewriteStepResult [(RewriteRule "Rewrite", Pattern)] + [(RewriteRule "Rewrite", Maybe Pattern)] -> + RewriteStepResult [(RewriteRule "Rewrite", Pattern)] filterOutTrivial = \case [] -> AppliedRules [] [(_, Nothing)] -> OnlyTrivial @@ -536,7 +537,7 @@ ruleLabelOrLoc rule = -- | Different rewrite results (returned from RPC execute endpoint) data RewriteResult pat = -- | branch point - RewriteBranch pat (NonEmpty (Text, UniqueId, pat)) + RewriteBranch pat (NonEmpty (Text, UniqueId, pat, Maybe Predicate)) | -- | no rules could be applied, config is stuck RewriteStuck pat | -- | cut point rule, return current (lhs) and single next state @@ -904,7 +905,9 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL pure $ RewriteBranch pat' $ NE.fromList $ - map (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n)) nextPats' + map + (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n, Just (collapseAndBools . Set.toList $ r.requires))) + nextPats' data RewriteStepsState = RewriteStepsState { counter :: !Natural diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 98e948d544..39ab5594eb 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -567,7 +567,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of -- this ensures the information from next states in a branch reponse doesn't get lost pure $ Right - ( (Booster.toExecState p sub unsup Nothing) + ( (Booster.toExecState p sub unsup Nothing Nothing) { ruleId = s.ruleId , ruleSubstitution = s.ruleSubstitution , rulePredicate = s.rulePredicate From 391b47ccf938a54b5ecc817b501aaacc1a9fd409 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 16:32:55 +0200 Subject: [PATCH 18/54] Apply substitution to the rule predicate --- booster/library/Booster/Pattern/Rewrite.hs | 94 +++++++++++++--------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 56bdc0c778..45c55db166 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -65,6 +65,7 @@ import Booster.Pattern.Match ( MatchResult (MatchFailed, MatchIndeterminate, MatchSuccess), MatchType (Rewrite), SortError, + Substitution, matchTerms, ) import Booster.Pattern.Pretty @@ -153,7 +154,7 @@ data RewriteStepResult a = OnlyTrivial | AppliedRules a deriving (Eq, Show, Func rewriteStep :: LoggerMIO io => Pattern -> - RewriteT io (RewriteStepResult [(RewriteRule "Rewrite", Pattern)]) + RewriteT io (RewriteStepResult [(RewriteRule "Rewrite", Pattern, Substitution)]) rewriteStep pat = do def <- getDefinition let getIndex = @@ -175,18 +176,18 @@ rewriteStep pat = do -- return `OnlyTrivial` if all elements of a list are `(r, Nothing)`. If the list is empty or contains at least one `(r, Just p)`, -- return an `AppliedRules` list of `(r, p)` pairs. filterOutTrivial :: - [(RewriteRule "Rewrite", Maybe Pattern)] -> - RewriteStepResult [(RewriteRule "Rewrite", Pattern)] + [(RewriteRule "Rewrite", Maybe (Pattern, Substitution))] -> + RewriteStepResult [(RewriteRule "Rewrite", Pattern, Substitution)] filterOutTrivial = \case [] -> AppliedRules [] [(_, Nothing)] -> OnlyTrivial (_, Nothing) : xs -> filterOutTrivial xs - (rule, Just p) : xs -> AppliedRules $ (rule, p) : mapMaybe (\(r, mp) -> (r,) <$> mp) xs + (rule, Just (p, subst)) : xs -> AppliedRules $ (rule, p, subst) : mapMaybe (\(r, mp) -> (\(x, y) -> (r, x, y)) <$> mp) xs processGroups :: LoggerMIO io => [[RewriteRule "Rewrite"]] -> - RewriteT io [(RewriteRule "Rewrite", Maybe Pattern)] + RewriteT io [(RewriteRule "Rewrite", Maybe (Pattern, Substitution))] processGroups [] = pure [] processGroups (rules : lowerPriorityRules) = do -- try all rules of the priority group. This will immediately @@ -209,8 +210,10 @@ rewriteStep pat = do results -- compute remainder condition here from @nonTrivialResults@ and the remainder up to now. -- If the new remainder is bottom, then no lower priority rules apply - newRemainder = currentRemainder <> Set.fromList (mapMaybe (snd . snd) nonTrivialResultsWithPartialRemainders) - resultsWithoutRemainders = map (fmap (fmap fst)) results + newRemainder = + currentRemainder + <> Set.fromList (mapMaybe ((\(_, r, _) -> r) . snd) nonTrivialResultsWithPartialRemainders) + resultsWithoutRemainders = map (fmap (fmap (\(p, _, s) -> (p, s)))) results setRemainder newRemainder ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers withContext CtxRemainder $ logPretty' @mods (collapseAndBools . Set.toList $ newRemainder) @@ -272,7 +275,7 @@ applyRule :: LoggerMIO io => Pattern -> RewriteRule "Rewrite" -> - RewriteT io (Maybe (Maybe (Pattern, Maybe Predicate))) + RewriteT io (Maybe (Maybe (Pattern, Maybe Predicate, Substitution))) applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRuleAppT $ @@ -436,11 +439,12 @@ applyRule pat@Pattern{ceilConditions} rule = ceilConditions withContext CtxSuccess $ do case unclearRequiresAfterSmt of - [] -> withPatternContext rewritten $ pure (rewritten, Nothing) + [] -> withPatternContext rewritten $ pure (rewritten, Nothing, subst) _ -> let rewritten' = rewritten{constraints = rewritten.constraints <> Set.fromList unclearRequiresAfterSmt} in withPatternContext rewritten' $ - pure (rewritten', Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt) + pure + (rewritten', Just $ Predicate $ NotBool $ coerce $ collapseAndBools unclearRequiresAfterSmt, subst) where failRewrite :: RewriteFailed "Rewrite" -> RewriteRuleAppT (RewriteT io) a failRewrite = lift . (throw) @@ -841,7 +845,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL -- We are stuck here not trivial because we didn't apply a single rule logMessage ("Rewrite stuck after simplification." :: Text) >> pure (RewriteStuck pat') pat'@Simplified{} -> logMessage ("Retrying with simplified pattern" :: Text) >> doSteps pat' - AppliedRules [(rule, nextPat)] -- applied single rule + AppliedRules [(rule, nextPat, _subst)] -- applied single rule -- cut-point rule, stop | labelOf rule `elem` cutLabels -> do simplify pat >>= \case @@ -880,34 +884,46 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL logMessage $ "Previous state found to be bottom after " <> showCounter counter pure $ RewriteTrivial pat' Simplified pat' -> - (catSimplified <$> mapM (\(r, nextPat) -> fmap (r,) <$> simplify (Unsimplified nextPat)) nextPats) >>= \case - [] -> withPatternContext pat' $ do - logMessage ("Rewrite trivial after pruning all branches" :: Text) - pure $ RewriteTrivial pat' - [(rule, nextPat')] -> withPatternContext pat' $ do - logMessage ("All but one branch pruned, continuing" :: Text) - emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) pat' nextPat' - incrementCounter - doSteps (Simplified nextPat') - nextPats' -> do - emitRewriteTrace $ - RewriteBranchingStep pat' $ - NE.fromList $ - map (\(rule, _) -> (ruleLabelOrLocT rule, uniqueId rule)) nextPats' - unless (Set.null remainderPredicates) $ do - ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers - withContext CtxRemainder . withContext CtxDetail $ - logMessage - ( ("Uncovered remainder branch after rewriting with rules " :: Text) - <> ( Text.intercalate ", " $ map (\(r, _) -> getUniqueId $ uniqueId r) nextPats' - ) - ) - pure $ - RewriteBranch pat' $ - NE.fromList $ - map - (\(r, n) -> (ruleLabelOrLocT r, uniqueId r, n, Just (collapseAndBools . Set.toList $ r.requires))) - nextPats' + ( catSimplified + <$> mapM (\(r, nextPat, subst) -> fmap (r,,subst) <$> simplify (Unsimplified nextPat)) nextPats + ) + >>= \case + [] -> withPatternContext pat' $ do + logMessage ("Rewrite trivial after pruning all branches" :: Text) + pure $ RewriteTrivial pat' + [(rule, nextPat', _subst)] -> withPatternContext pat' $ do + logMessage ("All but one branch pruned, continuing" :: Text) + emitRewriteTrace $ RewriteSingleStep (labelOf rule) (uniqueId rule) pat' nextPat' + incrementCounter + doSteps (Simplified nextPat') + nextPats' -> do + emitRewriteTrace $ + RewriteBranchingStep pat' $ + NE.fromList $ + map (\(rule, _, _subst) -> (ruleLabelOrLocT rule, uniqueId rule)) nextPats' + unless (Set.null remainderPredicates) $ do + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers + withContext CtxRemainder . withContext CtxDetail $ + logMessage + ( ("Uncovered remainder branch after rewriting with rules " :: Text) + <> ( Text.intercalate ", " $ map (\(r, _, _subst) -> getUniqueId $ uniqueId r) nextPats' + ) + ) + pure $ + RewriteBranch pat' $ + NE.fromList $ + map + ( \(r, n, subst) -> + ( ruleLabelOrLocT r + , uniqueId r + , n + , Just + ( collapseAndBools $ + concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) r.requires + ) + ) + ) + nextPats' data RewriteStepsState = RewriteStepsState { counter :: !Natural From ad42fbda7e9aafbafdc0c6bfca950f244c392706 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 16:54:58 +0200 Subject: [PATCH 19/54] Return rule substitution --- booster/library/Booster/JsonRpc.hs | 38 +++++++++++++--------- booster/library/Booster/Pattern/Rewrite.hs | 3 +- booster/tools/booster/Proxy.hs | 2 +- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/booster/library/Booster/JsonRpc.hs b/booster/library/Booster/JsonRpc.hs index 723d58bca8..48ccf495ce 100644 --- a/booster/library/Booster/JsonRpc.hs +++ b/booster/library/Booster/JsonRpc.hs @@ -604,12 +604,13 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Branching , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = - Just $ - map - (\(_, muid, p', mrulePred) -> toExecState p' originalSubstitution unsupported (Just muid) mrulePred) $ - toList nexts + Just + $ map + ( \(_, muid, p', mrulePred, ruleSubst) -> toExecState p' originalSubstitution unsupported (Just muid) mrulePred (Just ruleSubst) + ) + $ toList nexts , rule = Nothing , unknownPredicate = Nothing } @@ -620,7 +621,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Stuck , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -632,7 +633,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.Vacuous , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -644,8 +645,8 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.CutPointRule , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing - , nextStates = Just [toExecState next originalSubstitution unsupported Nothing Nothing] + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing + , nextStates = Just [toExecState next originalSubstitution unsupported Nothing Nothing Nothing] , rule = Just lbl , unknownPredicate = Nothing } @@ -656,7 +657,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.TerminalRule , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = Nothing , rule = Just lbl , unknownPredicate = Nothing @@ -668,7 +669,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c { reason = RpcTypes.DepthBound , depth , logs - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -685,7 +686,7 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c (logSuccessfulRewrites, logFailedRewrites) (RewriteStepFailed failure) in logs <|> abortRewriteLog - , state = toExecState p originalSubstitution unsupported Nothing Nothing + , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = Nothing , rule = Nothing , unknownPredicate = Nothing @@ -716,20 +717,27 @@ toExecState :: [Syntax.KorePattern] -> Maybe UniqueId -> Maybe Predicate -> + Maybe (Map Variable Term) -> RpcTypes.ExecuteState -toExecState pat sub unsupported muid mrulePredicate = +toExecState pat sub unsupported muid mrulePredicate mruleSubst = RpcTypes.ExecuteState { term = addHeader t , predicate = addHeader <$> addUnsupported p , substitution = addHeader <$> s - , ruleSubstitution = Nothing + , ruleSubstitution = addHeader <$> mruleSubstExt , rulePredicate = addHeader <$> mrulePredExt , ruleId = getUniqueId <$> muid } where - mrulePredExt = externalisePredicate (externaliseSort Pattern.SortBool) <$> mrulePredicate + mrulePredExt = externalisePredicate predicateSort <$> mrulePredicate + mruleSubstExt = + Syntax.KJAnd predicateSort + . map (uncurry $ externaliseSubstitution predicateSort) + . Map.toList + <$> mruleSubst (t, p, s) = externalisePattern pat sub termSort = externaliseSort $ sortOfPattern pat + predicateSort = externaliseSort Pattern.SortBool allUnsupported = Syntax.KJAnd termSort unsupported addUnsupported | null unsupported = id diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 45c55db166..2eeef0884b 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -541,7 +541,7 @@ ruleLabelOrLoc rule = -- | Different rewrite results (returned from RPC execute endpoint) data RewriteResult pat = -- | branch point - RewriteBranch pat (NonEmpty (Text, UniqueId, pat, Maybe Predicate)) + RewriteBranch pat (NonEmpty (Text, UniqueId, pat, Maybe Predicate, Substitution)) | -- | no rules could be applied, config is stuck RewriteStuck pat | -- | cut point rule, return current (lhs) and single next state @@ -921,6 +921,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL ( collapseAndBools $ concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) r.requires ) + , subst ) ) nextPats' diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 39ab5594eb..c3f6249960 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -567,7 +567,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of -- this ensures the information from next states in a branch reponse doesn't get lost pure $ Right - ( (Booster.toExecState p sub unsup Nothing Nothing) + ( (Booster.toExecState p sub unsup Nothing Nothing Nothing) { ruleId = s.ruleId , ruleSubstitution = s.ruleSubstitution , rulePredicate = s.rulePredicate From 7ee244d3be8d904229620914c5fabb1dd88679d6 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 21:40:56 +0200 Subject: [PATCH 20/54] Make rule predicate construction more explicit --- booster/library/Booster/Pattern/Rewrite.hs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 2eeef0884b..59daad40f0 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -909,6 +909,11 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL <> ( Text.intercalate ", " $ map (\(r, _, _subst) -> getUniqueId $ uniqueId r) nextPats' ) ) + let mkRulePredicate :: RewriteRule "Rewrite" -> Substitution -> Predicate + mkRulePredicate rule subst = + collapseAndBools $ + concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) rule.requires + pure $ RewriteBranch pat' $ NE.fromList $ @@ -917,10 +922,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL ( ruleLabelOrLocT r , uniqueId r , n - , Just - ( collapseAndBools $ - concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) r.requires - ) + , Just (mkRulePredicate r subst) , subst ) ) From 6b7bb6ac113652b66000e48bbf4f8135b3a8f357 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 21:42:26 +0200 Subject: [PATCH 21/54] Do not return rule substitution for now --- booster/library/Booster/JsonRpc.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/booster/library/Booster/JsonRpc.hs b/booster/library/Booster/JsonRpc.hs index 48ccf495ce..97d1ae4458 100644 --- a/booster/library/Booster/JsonRpc.hs +++ b/booster/library/Booster/JsonRpc.hs @@ -606,9 +606,10 @@ execResponse mbDuration req (d, traces, rr) originalSubstitution unsupported = c , logs , state = toExecState p originalSubstitution unsupported Nothing Nothing Nothing , nextStates = + -- FIXME return _ruleSubst in the response, removing '#'s from the variable names to make pyk happy Just $ map - ( \(_, muid, p', mrulePred, ruleSubst) -> toExecState p' originalSubstitution unsupported (Just muid) mrulePred (Just ruleSubst) + ( \(_, muid, p', mrulePred, _ruleSubst) -> toExecState p' originalSubstitution unsupported (Just muid) mrulePred Nothing ) $ toList nexts , rule = Nothing From bf200c38b1610c740f1e6bf299860cd19e2d7c6d Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Sun, 7 Jul 2024 21:47:44 +0200 Subject: [PATCH 22/54] Use termSort when externalising rule predicate --- booster/library/Booster/JsonRpc.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/booster/library/Booster/JsonRpc.hs b/booster/library/Booster/JsonRpc.hs index 97d1ae4458..482c25eb9d 100644 --- a/booster/library/Booster/JsonRpc.hs +++ b/booster/library/Booster/JsonRpc.hs @@ -730,7 +730,7 @@ toExecState pat sub unsupported muid mrulePredicate mruleSubst = , ruleId = getUniqueId <$> muid } where - mrulePredExt = externalisePredicate predicateSort <$> mrulePredicate + mrulePredExt = externalisePredicate termSort <$> mrulePredicate mruleSubstExt = Syntax.KJAnd predicateSort . map (uncurry $ externaliseSubstitution predicateSort) From d6e2043444b23be1a246083c717e6606b0368b50 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 08:34:40 +0200 Subject: [PATCH 23/54] Ignore rule predicate and substitution in unit tests --- .../Test/Booster/Pattern/Rewrite.hs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs index ba8d2b08e9..3bd36f2dda 100644 --- a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs @@ -244,7 +244,7 @@ runWith t = Nothing mempty mempty - (fmap (fmap snd) <$> (rewriteStep $ Pattern_ t)) + (fmap (fmap (\(_, p, _) -> p)) <$> (rewriteStep $ Pattern_ t)) ) rewritesTo :: Term -> Term -> IO () @@ -280,8 +280,22 @@ aborts failure t = runRewrite t >>= (@?= (0, RewriteAborted failure t)) newtype Steps = Steps Natural rewrites :: Steps -> Term -> t -> (t -> RewriteResult Term) -> IO () -rewrites (Steps n) t t' f = - runRewrite t >>= (@?= (n, f t')) +rewrites (Steps n) t t' f = do + let expected = (n, f t') + actual <- runRewrite t + second withoutRulePredAndSubst actual @?= expected + +mkRewriteBranch :: a -> NE.NonEmpty (Text, UniqueId, a) -> RewriteResult a +mkRewriteBranch pre branches = RewriteBranch pre (fmap withEmptyPredandSubst branches) + where + withEmptyPredandSubst (l, uid, post) = (l, uid, post, Nothing, Map.empty) + +withoutRulePredAndSubst :: RewriteResult a -> RewriteResult a +withoutRulePredAndSubst = \case + RewriteBranch pre branches -> RewriteBranch pre (fmap ignorePredandSubst branches) + other -> other + where + ignorePredandSubst (l, uid, post, _, _) = (l, uid, post, Nothing, Map.empty) canRewrite :: TestTree canRewrite = @@ -313,7 +327,7 @@ canRewrite = (Steps 1) [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con3{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("thing") ) ), C:SortK{}) ) |] [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("somethingElse") ) ), C:SortK{}) ) |] - (`RewriteBranch` NE.fromList [branch1, branch2]) + (`mkRewriteBranch` NE.fromList [branch1, branch2]) , testCase "Returns stuck when no rules could be applied" $ do rewrites (Steps 0) @@ -407,7 +421,7 @@ supportsDepthControl = (Steps 1) [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con3{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("thing") ) ), C:SortK{}) ) |] [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("somethingElse") ) ), C:SortK{}) ) |] - (`RewriteBranch` NE.fromList [branch1, branch2]) + (`mkRewriteBranch` NE.fromList [branch1, branch2]) ] where rewritesToDepth :: MaxDepth -> Steps -> Term -> t -> (t -> RewriteResult Term) -> IO () @@ -416,7 +430,7 @@ supportsDepthControl = runNoLoggingT $ performRewrite NoCollectRewriteTraces def Nothing Nothing (Just depth) [] [] $ Pattern_ t - (counter, fmap (.term) res) @?= (n, f t') + (counter, withoutRulePredAndSubst $ fmap (.term) res) @?= (n, f t') supportsCutPoints :: TestTree supportsCutPoints = @@ -461,7 +475,7 @@ supportsCutPoints = (Steps 1) [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con3{}( \dv{SomeSort{}}("otherThing"), \dv{SomeSort{}}("thing") ) ), C:SortK{}) ) |] [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con1{}( \dv{SomeSort{}}("somethingElse") ) ), C:SortK{}) ) |] - (`RewriteBranch` NE.fromList [branch1, branch2]) + (`mkRewriteBranch` NE.fromList [branch1, branch2]) ] where rewritesToCutPoint :: Text -> Steps -> Term -> t -> (t -> RewriteResult Term) -> IO () @@ -470,7 +484,7 @@ supportsCutPoints = runNoLoggingT $ performRewrite NoCollectRewriteTraces def Nothing Nothing Nothing [lbl] [] $ Pattern_ t - (counter, fmap (.term) res) @?= (n, f t') + (counter, withoutRulePredAndSubst $ fmap (.term) res) @?= (n, f t') supportsTerminalRules :: TestTree supportsTerminalRules = From f65cd3417fffaf7d39f328efb5fd8fca60d670ed Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 11:16:36 +0200 Subject: [PATCH 24/54] Log rule priorities when processing groups --- booster/library/Booster/Pattern/Rewrite.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 59daad40f0..c3afd95836 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -190,6 +190,7 @@ rewriteStep pat = do RewriteT io [(RewriteRule "Rewrite", Maybe (Pattern, Substitution))] processGroups [] = pure [] processGroups (rules : lowerPriorityRules) = do + withContext CtxDetail $ logMessage ("Trying rules at priority " <> show (ruleGroupPriority rules)) -- try all rules of the priority group. This will immediately -- fail the rewrite if anything is uncertain (unification, -- definedness, rule conditions) @@ -250,6 +251,11 @@ rewriteStep pat = do Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors Nothing -> (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules +ruleGroupPriority :: [RewriteRule a] -> Maybe Priority +ruleGroupPriority = \case + [] -> Nothing + (rule : _) -> Just rule.attributes.priority + type RewriteRuleAppT m a = ExceptT (Maybe ()) m a returnTrivial, returnNotApplied :: Monad m => RewriteRuleAppT m a From 2ae36935e08dd38013b8212c4907b71771b3b24d Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 14:28:47 +0200 Subject: [PATCH 25/54] Remove directory name assumption in `kore-rpc-client` --- booster/tools/rpc-client/RpcClient.hs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/booster/tools/rpc-client/RpcClient.hs b/booster/tools/rpc-client/RpcClient.hs index 8754b783e7..c126183d2d 100644 --- a/booster/tools/rpc-client/RpcClient.hs +++ b/booster/tools/rpc-client/RpcClient.hs @@ -483,7 +483,7 @@ parseMode = maybeReader $ \s -> case split (== '=') s of [k, v] -> Just (k, v); _ -> Nothing ---------------------------------------- --- Running all requests contained in the `rpc_*` directory of a tarball +-- Running all requests contained in the subdirectories of the tarball runTarball :: CommonOptions -> @@ -548,15 +548,13 @@ runTarball common (Just sock) tarFile keepGoing runOnly compareDetails = do case splitFileName (Tar.entryPath entry) of -- unpack all directories "rpc_" containing "*.json" files (dir, "") -- directory - | Tar.Directory <- Tar.entryContent entry - , "rpc_" `isPrefixOf` dir -> do + | Tar.Directory <- Tar.entryContent entry -> do createDirectoryIfMissing False dir -- create rpc dir so we can unpack files there acc -- no additional file to return | otherwise -> acc -- skip other directories and top-level files (dir, file) - | "rpc_" `isPrefixOf` dir - , ".json" `isSuffixOf` file + | ".json" `isSuffixOf` file , not ("." `isPrefixOf` file) , Tar.NormalFile bs _size <- Tar.entryContent entry -> do -- unpack json files into tmp directory From 119476a7b7b8a368afee9e3ec6c67b2f77d1839c Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 14:42:49 +0200 Subject: [PATCH 26/54] Return False when the remainder is trivial --- booster/library/Booster/Pattern/Rewrite.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index c3afd95836..502bb5205e 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -445,7 +445,7 @@ applyRule pat@Pattern{ceilConditions} rule = ceilConditions withContext CtxSuccess $ do case unclearRequiresAfterSmt of - [] -> withPatternContext rewritten $ pure (rewritten, Nothing, subst) + [] -> withPatternContext rewritten $ pure (rewritten, Just $ Predicate FalseBool, subst) _ -> let rewritten' = rewritten{constraints = rewritten.constraints <> Set.fromList unclearRequiresAfterSmt} in withPatternContext rewritten' $ From 221083eb8b7cf1878a374e62d4568f0424114aff Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 16:14:25 +0200 Subject: [PATCH 27/54] Check remainder for literal false when there's not SMT solver --- booster/library/Booster/Pattern/Bool.hs | 6 ++++++ booster/library/Booster/Pattern/Rewrite.hs | 24 ++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/booster/library/Booster/Pattern/Bool.hs b/booster/library/Booster/Pattern/Bool.hs index 7cef672ce7..c1672f3671 100644 --- a/booster/library/Booster/Pattern/Bool.hs +++ b/booster/library/Booster/Pattern/Bool.hs @@ -7,6 +7,7 @@ License : BSD-3-Clause module Booster.Pattern.Bool ( foldAndBool, isBottom, + isFalse, negateBool, splitBoolPredicates, splitAndBools, @@ -190,6 +191,11 @@ foldAndBool (x : xs) = AndBool x $ foldAndBool xs isBottom :: Pattern -> Bool isBottom = (Predicate FalseBool `elem`) . constraints +isFalse :: Predicate -> Bool +isFalse = \case + (Predicate FalseBool) -> True + _ -> False + {- | We want to break apart predicates of type `Y1 andBool ... Yn` apart, in case some of the `Y`s are abstract which prevents the original expression from being fed to the LLVM simplifyBool function -} diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 502bb5205e..b5b3f051ea 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -219,16 +219,12 @@ rewriteStep pat = do ModifiersRep (_ :: FromModifiersT mods => Proxy mods) <- getPrettyModifiers withContext CtxRemainder $ logPretty' @mods (collapseAndBools . Set.toList $ newRemainder) - if Set.null newRemainder - then case resultsWithoutRemainders of - [] -> - -- proceed to lower priority rules if we have not applied any rules at this priority level - processGroups lowerPriorityRules - xs -> - -- if we applied at least one rule and the remainder was empty, return the results. - -- TODO: I think we have to apply lower priority rules here still! - pure xs - else + case resultsWithoutRemainders of + [] -> do + -- proceed to lower priority rules if we have not applied any rules at this priority level + processGroups lowerPriorityRules + _xs -> do + liftIO . putStrLn $ "YES RESULTS WITH REMAINDER" getSolver >>= \case Just solver -> SMT.isSat solver (pat.constraints <> newRemainder) >>= \case @@ -249,7 +245,13 @@ rewriteStep pat = do -- solver cannot solve the remainder. Descend into the remainder branch anyway (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - Nothing -> (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules + Nothing -> + -- using poor-man's SMT solver, for unit-tests + if any isFalse (pat.constraints <> newRemainder) + then do + setRemainder mempty + pure resultsWithoutRemainders + else (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules ruleGroupPriority :: [RewriteRule a] -> Maybe Priority ruleGroupPriority = \case From 00898f461e1627616d617caa71f5bb71689bc728 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 17:10:48 +0200 Subject: [PATCH 28/54] Add test-remainder-predicates integration test --- .../resources/remainder-predicates.k | 169 +++ .../resources/remainder-predicates.kompile | 4 + .../test-remainder-predicates/README.md | 3 + .../response-test1.json | 483 +++++++++ .../response-test2.json | 483 +++++++++ .../response-test3.json | 483 +++++++++ .../response-test4.json | 23 + .../response-test5.json | 730 +++++++++++++ .../response-test6.json | 977 ++++++++++++++++++ .../state-test1.execute | 87 ++ .../state-test2.execute | 87 ++ .../state-test3.execute | 87 ++ .../state-test4.execute | 87 ++ .../state-test5.execute | 87 ++ .../state-test6.execute | 87 ++ scripts/booster-integration-tests.sh | 2 +- 16 files changed, 3878 insertions(+), 1 deletion(-) create mode 100644 booster/test/rpc-integration/resources/remainder-predicates.k create mode 100755 booster/test/rpc-integration/resources/remainder-predicates.kompile create mode 100644 booster/test/rpc-integration/test-remainder-predicates/README.md create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test1.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test2.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test3.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test4.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test5.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/response-test6.json create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test1.execute create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test2.execute create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test3.execute create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test4.execute create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test5.execute create mode 100644 booster/test/rpc-integration/test-remainder-predicates/state-test6.execute diff --git a/booster/test/rpc-integration/resources/remainder-predicates.k b/booster/test/rpc-integration/resources/remainder-predicates.k new file mode 100644 index 0000000000..c3ccd20256 --- /dev/null +++ b/booster/test/rpc-integration/resources/remainder-predicates.k @@ -0,0 +1,169 @@ +module REMAINDER-PREDICATES + imports INT + imports BOOL + + syntax State ::= test1Init() + | test1State1() + | test1State2() + | test1State3() + + | test2Init() + | test2State1() + | test2State2() + | test2State3() + + | test3Init() + | test3State1() + | test3State2() + | test3State3() + + | test4Init() + | test4State1() + | test4State2() + | test4State3() + | test4State4() + + | test5Init() + | test5State1() + | test5State2() + | test5State3() + | test5State4() + | test5State5() + + | test6Init() + | test6State1() + | test6State2() + | test6State3() + | test6State4() + | test6State5() + + configuration $PGM:State ~> .K + 0:Int + + //////////////////////////////////////////////////////////////////////////////// + /// two rules apply with UNSAT remainder predicate, no further rules apply. // + /// Results in 2 branches. // + //////////////////////////////////////////////////////////////////////////////// + rule [test1-init]: test1Init() => test1State1() ... + _ => ?_X + + rule [test1-1-2]: test1State1() => test1State2() ... + X + requires X >Int 0 + + rule [test1-1-3]: test1State1() => test1State3() ... + X + requires X <=Int 0 + + //////////////////////////////////////////////////////////////////////////////// + /// two rules apply with SAT remainder predicate, // + /// have to consider the remainder branch where X ==Int 0, // + /// no further rules apply. // + /// Results in 2 branches. // + //////////////////////////////////////////////////////////////////////////////// + rule [test2-init]: test2Init() => test2State1() ... + _ => ?_X + + rule [test2-1-2]: test2State1() => test2State2() ... + X + requires X >Int 0 + + rule [test2-1-3]: test2State1() => test2State3() ... + X + requires X test3Init() => test3State1() ... + _ => ?_X + + rule [test3-1-2]: test3State1() => test3State2() ... + X + requires X >Int 0 + + rule [test3-1-3]: test3State1() => test3State3() ... + X + requires X test4Init() => test4State1() ... + _ => ?_X + + rule [test4-1-2]: test4State1() => test4State2() ... + X + requires X >Int 0 + [priority(49)] + + rule [test4-1-3]: test4State1() => test4State3() ... + X + requires X test4State1() => test4State4() ... + X + requires X ==Int 0 + + + //////////////////////////////////////////////////////////////////////////////// + /// two hight-priorty rules apply with SAT remainder predicate, // + /// have to consider the remainder branch where X ==Int 0, // + /// one rule at a lower priority applies unconditionally, which means that // + /// that the remainder is False. Rule test5-1-5 is unreachable. // + /// Results in 3 branches. // + //////////////////////////////////////////////////////////////////////////////// + rule [test5-init]: test5Init() => test5State1() ... + _ => ?_X + + rule [test5-1-2]: test5State1() => test5State2() ... + X + requires X >Int 0 [priority(48)] + + rule [test5-1-3]: test5State1() => test5State3() ... + X + requires X test5State1() => test5State4() ... + [priority(49)] + + rule [test5-1-5]: test5State1() => test5State5() ... + X + requires X ==Int 0 + + //////////////////////////////////////////////////////////////////////////////// + /// two hight-priorty rules apply with SAT remainder predicate, // + /// have to consider the remainder branch where X ==Int 0, // + /// two rule at a lower priority applies unconditionally. // + /// Results in 4 branches. // + //////////////////////////////////////////////////////////////////////////////// + rule [test6-init]: test6Init() => test6State1() ... + _ => ?_X + + rule [test6-1-2]: test6State1() => test6State2() ... + X + requires X >Int 0 [priority(48)] + + rule [test6-1-3]: test6State1() => test6State3() ... + X + requires X test6State1() => test6State4() ... + [priority(49)] + + rule [test6-1-5]: test6State1() => test6State5() ... + [priority(49)] + +// to produce input state: +// krun --output kore --depth 1 -cPGM='test1Init()' | kore-parser test-kompiled/definition.kore --module TEST --pattern /dev/stdin --print-pattern-json > state-test1Init.json +// then edit state-test1Init.json to substitute test1State1() for test1Init() + +endmodule diff --git a/booster/test/rpc-integration/resources/remainder-predicates.kompile b/booster/test/rpc-integration/resources/remainder-predicates.kompile new file mode 100755 index 0000000000..9caac778f2 --- /dev/null +++ b/booster/test/rpc-integration/resources/remainder-predicates.kompile @@ -0,0 +1,4 @@ +echo "kompiling remainder-predicates.k" +kompile --backend haskell remainder-predicates.k +cp remainder-predicates-kompiled/definition.kore remainder-predicates.kore +rm -r remainder-predicates-kompiled \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/README.md b/booster/test/rpc-integration/test-remainder-predicates/README.md new file mode 100644 index 0000000000..1ece831d61 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/README.md @@ -0,0 +1,3 @@ +# Tests for rewrite rule remainders in `kore-rpc-booster` and `kore-rpc-booster` + +See `../predicate-remainders.k`. diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test1.json b/booster/test/rpc-integration/test-remainder-predicates/response-test1.json new file mode 100644 index 0000000000..7c4d2cb026 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test1.json @@ -0,0 +1,483 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest1State1'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest1State2'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "5d4eb64f156b1bcc36c3693a2d76b43d1a7f0c6e23c00bec3335dce24ae97e5b", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest1State3'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "6d3f26eddd9a067dcda74a6754144328aaf60fc9c925896e6f464fb58061d30f", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test2.json b/booster/test/rpc-integration/test-remainder-predicates/response-test2.json new file mode 100644 index 0000000000..18d96ec73d --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test2.json @@ -0,0 +1,483 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest2State1'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest2State2'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "f1062b57b8ba73d1fa8fa0a1b5cb828ee0c750f42a3ff3227b6ddb5c260b8c03", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest2State3'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "54a5fca77be17b0d99e953eded75809e0ed9046f73cab5027603a82df1f4c4b2", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test3.json b/booster/test/rpc-integration/test-remainder-predicates/response-test3.json new file mode 100644 index 0000000000..808502a865 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test3.json @@ -0,0 +1,483 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3State1'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3State2'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "8ce63de629513dde00ad2347ce4ed0cc6908aac917f9f30598f0cd82463d6843", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3State3'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "7ccf8fa0f75a19b966b5c54445785eedacb29b223c4242f3163dc5231189471d", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test4.json b/booster/test/rpc-integration/test-remainder-predicates/response-test4.json new file mode 100644 index 0000000000..de34e0913b --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test4.json @@ -0,0 +1,23 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": 2, + "data": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbltest4Init'LParRParUnds'TEST'REMAINDER-PREDICATES'State", + "sorts": [], + "args": [] + } + }, + "error": "Unknown symbol 'Lbltest4Init'LParRParUnds'TEST'REMAINDER-PREDICATES'State'" + } + ], + "message": "Could not verify pattern" + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test5.json b/booster/test/rpc-integration/test-remainder-predicates/response-test5.json new file mode 100644 index 0000000000..f844b91d37 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test5.json @@ -0,0 +1,730 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest5State1'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest5State2'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "59e616c490a66f3fa06473b5721174f3876994dff3489b9738725e3b6ec8c6a3", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest5State3'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "f1e80e82c4f2cba9988a4f279c75b452f3c19d2a78250fd749f25d5e135c6af8", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest5State4'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + ] + } + }, + "rule-id": "62ea7f9228e3bae8eb12055ebf3fae372d764d720959f832e268e97421ad571c", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test6.json b/booster/test/rpc-integration/test-remainder-predicates/response-test6.json new file mode 100644 index 0000000000..01f35be3d8 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test6.json @@ -0,0 +1,977 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6State1'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6State2'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "a914809698e743ff52b59f5935de27c8df97b0add7bfaaa94585f3c11bd26296", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6State3'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + }, + "rule-id": "9271f5eaee75e5b348b4c75f016c224ba0cf71c770b07d74bd736798f5e4454e", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6State4'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + ] + } + }, + "rule-id": "504e09adcc37676f83ab4a060a25f81775e4ecb3f407f87305e81f2d9a95012f", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6State5'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "LblnotBool'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X0", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + } + ] + } + }, + "rule-id": "7c1b1b9736f7e2a1d4204aaf8895daf491f8651bfd394ab5f532239629d81ca9", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test1.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test1.execute new file mode 100644 index 0000000000..a64860c808 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test1.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest1Init'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test2.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test2.execute new file mode 100644 index 0000000000..e4b596da6b --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test2.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest2Init'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test3.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test3.execute new file mode 100644 index 0000000000..3c0a604d43 --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test3.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3Init'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test4.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test4.execute new file mode 100644 index 0000000000..f921ccce3c --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test4.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4Init'LParRParUnds'TEST'REMAINDER-PREDICATES'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test5.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test5.execute new file mode 100644 index 0000000000..5263fddf8c --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test5.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest5Init'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-remainder-predicates/state-test6.execute b/booster/test/rpc-integration/test-remainder-predicates/state-test6.execute new file mode 100644 index 0000000000..5da178209e --- /dev/null +++ b/booster/test/rpc-integration/test-remainder-predicates/state-test6.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest6Init'LParRParUnds'REMAINDER-PREDICATES'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'QuesUnds'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/scripts/booster-integration-tests.sh b/scripts/booster-integration-tests.sh index bd6db4ac4f..c61a53e7c8 100755 --- a/scripts/booster-integration-tests.sh +++ b/scripts/booster-integration-tests.sh @@ -49,7 +49,7 @@ for dir in $(ls -d test-*); do SERVER=$BOOSTER_DEV ./runDirectoryTest.sh test-$name $@ SERVER=$KORE_RPC_DEV ./runDirectoryTest.sh test-$name $@ ;; - "compute-ceil" | "no-evaluator" | "non-linear-int-requires" | "get-model-subsorts" | "simplify") + "remainder-predicates" | "compute-ceil" | "no-evaluator" | "non-linear-int-requires" | "get-model-subsorts" | "simplify") SERVER=$BOOSTER_DEV ./runDirectoryTest.sh test-$name $@ ;; "log-simplify-json") From df0047f86f14180f882b3f1023e3c5c668810221 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 17:15:14 +0200 Subject: [PATCH 29/54] Oops, remove awkward print --- booster/library/Booster/Pattern/Rewrite.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index b5b3f051ea..9c4a337067 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -224,7 +224,6 @@ rewriteStep pat = do -- proceed to lower priority rules if we have not applied any rules at this priority level processGroups lowerPriorityRules _xs -> do - liftIO . putStrLn $ "YES RESULTS WITH REMAINDER" getSolver >>= \case Just solver -> SMT.isSat solver (pat.constraints <> newRemainder) >>= \case From 555728dfc8e7a04d30d8146fce7a9b3dcc282098 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Mon, 8 Jul 2024 17:17:02 +0200 Subject: [PATCH 30/54] Add comment --- booster/library/Booster/Pattern/Rewrite.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 9c4a337067..2f67f815e0 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -245,7 +245,8 @@ rewriteStep pat = do (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors Nothing -> - -- using poor-man's SMT solver, for unit-tests + -- using poor-man's SMT solver, for unit-tests, as otherwise the branch due to False + -- remainders produces by unconditional rules if any isFalse (pat.constraints <> newRemainder) then do setRemainder mempty From 2d0b0fd79dad0189abe4bc62392a18b94eb3c6eb Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 9 Jul 2024 19:41:54 +0200 Subject: [PATCH 31/54] Bring back the abort message on unclear rewrite rule match --- booster/library/Booster/Pattern/Rewrite.hs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 2f67f815e0..9545558fca 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -814,9 +814,25 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL mempty (withPatternContext unWrappedPat $ rewriteStep unWrappedPat) >>= \case - Left failure@RuleApplicationUnclear{} -> + Left failure@(RuleApplicationUnclear rule _ remainder) -> case pat of - Simplified pat' -> logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') + Simplified pat' -> do + -- was already simplified, emit an abort log entry + -- TODO factor-out common code with the non-abort message + -- search for "Uncertain about match with rule. Remainder:" + withRuleContext rule . withContext CtxMatch . withContext CtxAbort $ + getPrettyModifiers >>= \case + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) -> + logMessage $ + WithJsonMessage (object ["remainder" .= (bimap externaliseTerm externaliseTerm <$> remainder)]) $ + renderOneLineText $ + "Uncertain about match with rule. Remainder:" + <+> ( hsep $ + punctuate comma $ + map (\(t1, t2) -> pretty' @mods t1 <+> "==" <+> pretty' @mods t2) $ + NE.toList remainder + ) + logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') _ -> simplify pat >>= \case -- We are stuck here not trivial because we didn't apply a single rule From 554d70160789ad71803dff653ebf7c072d2a9ef6 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 09:47:19 +0200 Subject: [PATCH 32/54] Refactor match remainder into a function to deduplicate code --- booster/library/Booster/Pattern/Rewrite.hs | 40 +++++++++------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 9545558fca..e0f89381df 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -302,16 +302,7 @@ applyRule pat@Pattern{ceilConditions} rule = withContext CtxFailure $ logPretty' @mods reason returnNotApplied MatchIndeterminate remainder -> do - withContext CtxIndeterminate $ - logMessage $ - WithJsonMessage (object ["remainder" .= (bimap externaliseTerm externaliseTerm <$> remainder)]) $ - renderOneLineText $ - "Uncertain about match with rule. Remainder:" - <+> ( hsep $ - punctuate comma $ - map (\(t1, t2) -> pretty' @mods t1 <+> "==" <+> pretty' @mods t2) $ - NE.toList remainder - ) + withContext CtxIndeterminate $ logIndeterminateMatch remainder failRewrite $ RuleApplicationUnclear rule pat.term remainder MatchSuccess substitution -> do withContext CtxSuccess $ do @@ -818,20 +809,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL case pat of Simplified pat' -> do -- was already simplified, emit an abort log entry - -- TODO factor-out common code with the non-abort message - -- search for "Uncertain about match with rule. Remainder:" - withRuleContext rule . withContext CtxMatch . withContext CtxAbort $ - getPrettyModifiers >>= \case - ModifiersRep (_ :: FromModifiersT mods => Proxy mods) -> - logMessage $ - WithJsonMessage (object ["remainder" .= (bimap externaliseTerm externaliseTerm <$> remainder)]) $ - renderOneLineText $ - "Uncertain about match with rule. Remainder:" - <+> ( hsep $ - punctuate comma $ - map (\(t1, t2) -> pretty' @mods t1 <+> "==" <+> pretty' @mods t2) $ - NE.toList remainder - ) + withRuleContext rule . withContext CtxMatch . withContext CtxAbort $ logIndeterminateMatch remainder logMessage ("Aborted after " <> showCounter counter) >> pure (RewriteAborted failure pat') _ -> simplify pat >>= \case @@ -967,3 +945,17 @@ rewriteStart = , simplifierCache = mempty , smtSolver = Nothing } + +logIndeterminateMatch :: forall io. LoggerMIO io => NonEmpty (Term, Term) -> io () +logIndeterminateMatch remainder = + getPrettyModifiers >>= \case + ModifiersRep (_ :: FromModifiersT mods => Proxy mods) -> + logMessage $ + WithJsonMessage (object ["remainder" .= (bimap externaliseTerm externaliseTerm <$> remainder)]) $ + renderOneLineText $ + "Uncertain about match with rule. Remainder:" + <+> ( hsep $ + punctuate comma $ + map (\(t1, t2) -> pretty' @mods t1 <+> "==" <+> pretty' @mods t2) $ + NE.toList remainder + ) From d8e712fecfa0df9c8b1cc11ef68264cb2ab9ba53 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 10:30:05 +0200 Subject: [PATCH 33/54] Factor-out `mkRulePredicate` --- booster/library/Booster/Pattern/Rewrite.hs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index e0f89381df..73436861fa 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -911,11 +911,6 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL <> ( Text.intercalate ", " $ map (\(r, _, _subst) -> getUniqueId $ uniqueId r) nextPats' ) ) - let mkRulePredicate :: RewriteRule "Rewrite" -> Substitution -> Predicate - mkRulePredicate rule subst = - collapseAndBools $ - concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) rule.requires - pure $ RewriteBranch pat' $ NE.fromList $ @@ -924,7 +919,7 @@ performRewrite doTracing def mLlvmLibrary mSolver mbMaxDepth cutLabels terminalL ( ruleLabelOrLocT r , uniqueId r , n - , Just (mkRulePredicate r subst) + , mkRulePredicate r subst , subst ) ) @@ -946,6 +941,17 @@ rewriteStart = , smtSolver = Nothing } +{- | Instantiate a rewrite rule's requires clause with a substitution. + Returns Nothing is the resulting @Predicate@ is trivially @True@. +-} +mkRulePredicate :: RewriteRule a -> Substitution -> Maybe Predicate +mkRulePredicate rule subst = + case concatMap + (splitBoolPredicates . coerce . substituteInTerm subst . coerce) + rule.requires of + [] -> Nothing + xs -> Just $ collapseAndBools xs + logIndeterminateMatch :: forall io. LoggerMIO io => NonEmpty (Term, Term) -> io () logIndeterminateMatch remainder = getPrettyModifiers >>= \case From b709fb8d300a88ec548f908ef71b3910c108d72c Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 10:48:50 +0200 Subject: [PATCH 34/54] Ignore rule substitution when comparing branching responses --- booster/library/Booster/JsonRpc/Utils.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/booster/library/Booster/JsonRpc/Utils.hs b/booster/library/Booster/JsonRpc/Utils.hs index 16dc8bb660..4061f78d25 100644 --- a/booster/library/Booster/JsonRpc/Utils.hs +++ b/booster/library/Booster/JsonRpc/Utils.hs @@ -70,15 +70,19 @@ diffJson file1 file2 = -- \| Branching execution results are considered equivalent if -- \* they both have two branches -- \* branches are syntactically the same, but may be in different order + -- \* the "rule-substitution" field is ignored sameModuloBranchOrder :: ExecuteResult -> ExecuteResult -> Bool sameModuloBranchOrder res1 res2 | res1.reason == Branching && res1.reason == res2.reason = - case (res1.nextStates, res2.nextStates) of + case (map ignoreRuleSubstituiton <$> res1.nextStates, map ignoreRuleSubstituiton <$> res2.nextStates) of (Just xs, Just ys) -> length xs == 2 && length ys == 2 && (xs == ys || xs == reverse ys) _ -> False | otherwise = False + ignoreRuleSubstituiton :: ExecuteState -> ExecuteState + ignoreRuleSubstituiton state = state{ruleSubstitution = Nothing} + data DiffResult = Identical KoreRpcType | DifferentType KoreRpcType KoreRpcType From 55c9dcf4799746f388cf1fbda49ae89989550a19 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 11:39:42 +0200 Subject: [PATCH 35/54] Do not send trivial remainders to SMT --- booster/library/Booster/Pattern/Rewrite.hs | 54 +++++++++++----------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 462432e36b..f5fb7adaa9 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -224,34 +224,32 @@ rewriteStep pat = do -- proceed to lower priority rules if we have not applied any rules at this priority level processGroups lowerPriorityRules _xs -> do - getSolver >>= \case - Just solver -> - SMT.isSat solver (pat.constraints <> newRemainder) >>= \case - Right False -> do - -- the remainder condition is unsatisfiable: no need to consider the remainder branch. - setRemainder mempty - withContext CtxRemainder $ logMessage ("remainder is UNSAT" :: Text) - pure resultsWithoutRemainders - Right True -> do - withContext CtxRemainder $ logMessage ("remainder is SAT" :: Text) - -- the remainder condition is satisfiable. - -- Have to construct the remainder branch and consider it - -- To construct the "remainder pattern", - -- we add the remainder condition to the predicates of the @pattr@ - (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules - Left SMT.SMTSolverUnknown{} -> do - withContext CtxRemainder $ logMessage ("remainder is UNKNWON" :: Text) - -- solver cannot solve the remainder. Descend into the remainder branch anyway - (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules - Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors - Nothing -> - -- using poor-man's SMT solver, for unit-tests, as otherwise the branch due to False - -- remainders produces by unconditional rules - if any isFalse (pat.constraints <> newRemainder) - then do - setRemainder mempty - pure resultsWithoutRemainders - else (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules + if any isFalse newRemainder -- no need to call SMT if any of the conditions is trivially false + then do + setRemainder mempty + pure resultsWithoutRemainders + else + getSolver >>= \case + Just solver -> + SMT.isSat solver (pat.constraints <> newRemainder) >>= \case + Right False -> do + -- the remainder condition is unsatisfiable: no need to consider the remainder branch. + setRemainder mempty + withContext CtxRemainder $ logMessage ("remainder is UNSAT" :: Text) + pure resultsWithoutRemainders + Right True -> do + withContext CtxRemainder $ logMessage ("remainder is SAT" :: Text) + -- the remainder condition is satisfiable. + -- Have to construct the remainder branch and consider it + -- To construct the "remainder pattern", + -- we add the remainder condition to the predicates of the @pattr@ + (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules + Left SMT.SMTSolverUnknown{} -> do + withContext CtxRemainder $ logMessage ("remainder is UNKNWON" :: Text) + -- solver cannot solve the remainder. Descend into the remainder branch anyway + (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules + Left other -> liftIO $ Exception.throw other -- fail hard on other SMT errors + Nothing -> (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules ruleGroupPriority :: [RewriteRule a] -> Maybe Priority ruleGroupPriority = \case From e5f674c6db886553be4ebe5caefe284a69155758 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 12:36:15 +0200 Subject: [PATCH 36/54] Remove trivial rule predicates from tests --- .../response-test5.json | 37 +--------- .../response-test6.json | 74 +------------------ 2 files changed, 3 insertions(+), 108 deletions(-) diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test5.json b/booster/test/rpc-integration/test-remainder-predicates/response-test5.json index f844b91d37..e9f44e147a 100644 --- a/booster/test/rpc-integration/test-remainder-predicates/response-test5.json +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test5.json @@ -688,42 +688,7 @@ ] } }, - "rule-id": "62ea7f9228e3bae8eb12055ebf3fae372d764d720959f832e268e97421ad571c", - "rule-predicate": { - "format": "KORE", - "version": 1, - "term": { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - }, - "second": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - } - } - } + "rule-id": "62ea7f9228e3bae8eb12055ebf3fae372d764d720959f832e268e97421ad571c" } ] } diff --git a/booster/test/rpc-integration/test-remainder-predicates/response-test6.json b/booster/test/rpc-integration/test-remainder-predicates/response-test6.json index 01f35be3d8..e10550d376 100644 --- a/booster/test/rpc-integration/test-remainder-predicates/response-test6.json +++ b/booster/test/rpc-integration/test-remainder-predicates/response-test6.json @@ -688,42 +688,7 @@ ] } }, - "rule-id": "504e09adcc37676f83ab4a060a25f81775e4ecb3f407f87305e81f2d9a95012f", - "rule-predicate": { - "format": "KORE", - "version": 1, - "term": { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - }, - "second": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - } - } - } + "rule-id": "504e09adcc37676f83ab4a060a25f81775e4ecb3f407f87305e81f2d9a95012f" }, { "term": { @@ -935,42 +900,7 @@ ] } }, - "rule-id": "7c1b1b9736f7e2a1d4204aaf8895daf491f8651bfd394ab5f532239629d81ca9", - "rule-predicate": { - "format": "KORE", - "version": 1, - "term": { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - }, - "second": { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBool", - "args": [] - }, - "value": "true" - } - } - } + "rule-id": "7c1b1b9736f7e2a1d4204aaf8895daf491f8651bfd394ab5f532239629d81ca9" } ] } From f227ad79999297db14ce6673a356e583e44168b1 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 19:25:38 +0200 Subject: [PATCH 37/54] Rework test-use-path-condition-in-equations --- .../use-path-condition-in-equations.k | 85 ++- .../response-test1.booster-dev | 148 ++++ .../response-test1.json | 48 +- .../response-test2.booster-dev | 212 ++++++ .../response-test2.json | 54 +- .../response-test3.booster-dev | 212 ++++++ .../response-test3.json | 212 ++++++ .../response-test4.booster-dev | 676 ++++++++++++++++++ .../response-test4.json | 132 ++++ .../state-test3.execute | 87 +++ .../state-test4.execute | 87 +++ 11 files changed, 1879 insertions(+), 74 deletions(-) create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.booster-dev create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.booster-dev create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.booster-dev create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.json create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.booster-dev create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.json create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/state-test3.execute create mode 100644 booster/test/rpc-integration/test-use-path-condition-in-equations/state-test4.execute diff --git a/booster/test/rpc-integration/resources/use-path-condition-in-equations.k b/booster/test/rpc-integration/resources/use-path-condition-in-equations.k index 7324877bbd..8ce59e8f0b 100644 --- a/booster/test/rpc-integration/resources/use-path-condition-in-equations.k +++ b/booster/test/rpc-integration/resources/use-path-condition-in-equations.k @@ -10,17 +10,29 @@ module USE-PATH-CONDITION-IN-EQUATIONS | test2State1() | test2State2() + | test3Init() + | test3State1() + | test3State2() + + | test4Init() + | test4State1() + | test4State2() + | test4State3() + syntax Int ::= test1F ( Int ) [function, total, no-evaluators] | test2F ( Int ) [function, total, no-evaluators] + | test3F ( Int ) [function, total] + | test4F ( Int ) [function, total] configuration $PGM:State ~> .K 0:Int //////////////////////////////////////////////////////////////////////////////// // Here the simplification's side condition is syntactically present // - // in the path condition and is not checked. // - // Result: Stuck at depth 2 in state test1State2() // - // after applying rules test1-init,test1-1-2 // + // in the path condition and is not checked. // + // Result booster-dev, kore-rpc-booster // + // Stuck at depth 2 in state test1State2() // + // after applying rules test1-init,test1-1-2 // //////////////////////////////////////////////////////////////////////////////// rule [test1-init]: test1Init() => test1State1() ... _ => ?X @@ -32,11 +44,20 @@ module USE-PATH-CONDITION-IN-EQUATIONS rule [test1F-simplify]: test1F(X:Int) => X requires X ==Int 42 [simplification] - //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////// // Here the simplification's side condition is implied by the path condition, // - // but we need an SMT solver to establish that. // - // Result: Aborted at depth 1 due to indeterminate condition of rule test2-1-2 // - //////////////////////////////////////////////////////////////////////////////// + // but we need an SMT solver to establish that. Booster proceeds by assuming // + // the condition without applying test2F-simplify. // + // In Kore, the simplification is applied. // + // Result booster-dev: // + // Stuck at depth 2 in state test2State2() // + // after applying rules test2-init,test1-2-2. // + // The constraints contain test2F, unevaluated. // + // Result kore-rpc-booster: // + // Stuck at depth 2 in state test2State2() // + // after applying rules test2-init,test1-2-2. // + // No mention of test2F. // + ///////////////////////////////////////////////////////////////////////////////// rule [test2-init]: test2Init() => test2State1() ... _ => ?X ensures ?X ==Int 42 @@ -47,6 +68,56 @@ module USE-PATH-CONDITION-IN-EQUATIONS rule [test2F-simplify]: test2F(X:Int) => X requires X >Int 0 [simplification] + ///////////////////////////////////////////////////////////////////////////////// + // Exactly like test2, but the function now has actual evaluators, rather than // + // a simplification-based semantics. Booster over-approximates and rewrites, // + // as it cannot determine the condition of rule test3-1-2. // + // Simplification in Kore detects a vacuous result. // + // Result booster-dev: // + // Stuck at depth 2 in state test3State2() // + // after applying rules test3-init,test3-1-2. // + // The constraints contain test2F, unevaluated. // + // Result kore-rpc-booster: // + // Vacuous at depth 2 in state test2State2() // + // after applying rules test3-init,test3-1-2. // + ///////////////////////////////////////////////////////////////////////////////// + rule [test3-init]: test3Init() => test3State1() ... + _ => ?X + ensures ?X ==Int 42 + + rule [test3-1-2]: test3State1() => test3State2() ... + X + requires test3F(X) >Int 0 + + rule [test3F-zero-if-x-positive]: test3F(X:Int) => 0 requires X >Int 0 + rule [test3F-one-if-not-x-nonpositive]: test3F(X:Int) => 1 requires X <=Int 0 + + ///////////////////////////////////////////////////////////////////////////////// + // Similar to test3, but now there are two rules. Booster rewrites with both, // + // and Kore then prunes the vacuous branch. // + // Result booster-dev: // + // Branching at depth 1 // + // The constraints contain test4F, unevaluated. // + // Result kore-rpc-booster: // + // Stuck at depth 2 in state test2State3() // + // The vacuous branch leading to state test2State3() is pruned // + ///////////////////////////////////////////////////////////////////////////////// + rule [test4-init]: test4Init() => test4State1() ... + _ => ?X + ensures ?X ==Int 42 + + rule [test4-1-2]: test4State1() => test4State2() ... + X + requires test4F(X) >Int 0 + + rule [test4-1-3]: test4State1() => test4State3() ... + X + requires test4F(X) <=Int 0 + + + rule [test4F-zero-if-x-positive]: test4F(X:Int) => 0 requires X >Int 0 + rule [test4F-one-if-not-x-nonpositive]: test4F(X:Int) => 1 requires X <=Int 0 + // to produce input state: // krun --output kore --depth 1 -cPGM='test1Init()' | kore-parser test-kompiled/definition.kore --module TEST --pattern /dev/stdin --print-pattern-json > state-test1Init.json // then edit state-test1Init.json to substitute test1State1() for test1Init() diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.booster-dev b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.booster-dev new file mode 100644 index 0000000000..caf1cf3ac9 --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.booster-dev @@ -0,0 +1,148 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "stuck", + "depth": 2, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest1State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.json b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.json index caf1cf3ac9..f0938023a3 100644 --- a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.json +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test1.json @@ -63,13 +63,13 @@ "sorts": [], "args": [ { - "tag": "EVar", - "name": "Var'Ques'X", + "tag": "DV", "sort": { "tag": "SortApp", "name": "SortInt", "args": [] - } + }, + "value": "42" } ] }, @@ -92,14 +92,14 @@ ] } }, - "predicate": { + "substitution": { "format": "KORE", "version": 1, "term": { "tag": "Equals", "argSort": { "tag": "SortApp", - "name": "SortBool", + "name": "SortInt", "args": [] }, "sort": { @@ -108,38 +108,22 @@ "args": [] }, "first": { - "tag": "DV", + "tag": "EVar", + "name": "Var'Ques'X", "sort": { "tag": "SortApp", - "name": "SortBool", + "name": "SortInt", "args": [] - }, - "value": "true" + } }, "second": { - "tag": "App", - "name": "Lbl'UndsEqlsEqls'Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "Var'Ques'X", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "42" - } - ] + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" } } } diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.booster-dev b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.booster-dev new file mode 100644 index 0000000000..9186cfc683 --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.booster-dev @@ -0,0 +1,212 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "stuck", + "depth": 2, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest2State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest2F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.json b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.json index f4ccffbb2a..8b9792046d 100644 --- a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.json +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test2.json @@ -2,8 +2,8 @@ "jsonrpc": "2.0", "id": 1, "result": { - "reason": "aborted", - "depth": 1, + "reason": "stuck", + "depth": 2, "state": { "term": { "format": "KORE", @@ -41,7 +41,7 @@ "args": [ { "tag": "App", - "name": "Lbltest2State1'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "name": "Lbltest2State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", "sorts": [], "args": [] } @@ -63,13 +63,13 @@ "sorts": [], "args": [ { - "tag": "EVar", - "name": "Var'Ques'X", + "tag": "DV", "sort": { "tag": "SortApp", "name": "SortInt", "args": [] - } + }, + "value": "42" } ] }, @@ -92,14 +92,14 @@ ] } }, - "predicate": { + "substitution": { "format": "KORE", "version": 1, "term": { "tag": "Equals", "argSort": { "tag": "SortApp", - "name": "SortBool", + "name": "SortInt", "args": [] }, "sort": { @@ -108,38 +108,22 @@ "args": [] }, "first": { - "tag": "DV", + "tag": "EVar", + "name": "Var'Ques'X", "sort": { "tag": "SortApp", - "name": "SortBool", + "name": "SortInt", "args": [] - }, - "value": "true" + } }, "second": { - "tag": "App", - "name": "Lbl'UndsEqlsEqls'Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "Var'Ques'X", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "42" - } - ] + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" } } } diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.booster-dev b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.booster-dev new file mode 100644 index 0000000000..0dc51c405c --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.booster-dev @@ -0,0 +1,212 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "stuck", + "depth": 2, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest3F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.json b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.json new file mode 100644 index 0000000000..e2c366b41f --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test3.json @@ -0,0 +1,212 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "vacuous", + "depth": 2, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest3F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + } + ] + } + } + } + } +} diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.booster-dev b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.booster-dev new file mode 100644 index 0000000000..18ab0480c6 --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.booster-dev @@ -0,0 +1,676 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "branching", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4State1'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + } + } + }, + "next-states": [ + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4State2'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest4F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + } + ] + } + }, + "rule-id": "9b2d5b22b810aec01e7d91889b1256b7c44e087257750e1ec270fc9b03fa6c78", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-GT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest4F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + }, + { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4State3'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "And", + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "patterns": [ + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'UndsEqlsEqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + } + }, + { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest4F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + ] + } + }, + "rule-id": "3333b5923bfd6ad3bfb7767a54386c6ecb99db4d3f5ffcbfc7500e2eb46bdf24", + "rule-predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "value": "true" + }, + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbltest4F'LParUndsRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'Int'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.json b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.json new file mode 100644 index 0000000000..a982ba27e2 --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/response-test4.json @@ -0,0 +1,132 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "stuck", + "depth": 2, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4State3'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "substitution": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "EVar", + "name": "Var'Ques'X", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + "second": { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + } + } + } + } +} \ No newline at end of file diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test3.execute b/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test3.execute new file mode 100644 index 0000000000..f12afc276c --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test3.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest3Init'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} diff --git a/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test4.execute b/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test4.execute new file mode 100644 index 0000000000..118e0b36a2 --- /dev/null +++ b/booster/test/rpc-integration/test-use-path-condition-in-equations/state-test4.execute @@ -0,0 +1,87 @@ +{ + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbltest4Init'LParRParUnds'USE-PATH-CONDITION-IN-EQUATIONS'Unds'State", + "sorts": [], + "args": [] + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "42" + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } +} From 3a2b13f59c00b04cdbbdc7aa90b946c2c09153a0 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 10 Jul 2024 19:35:48 +0200 Subject: [PATCH 38/54] Update test-non-linear-int-requires --- .../test-non-linear-int-requires/README.md | 2 + .../response-init.json | 322 ++++++++++++------ 2 files changed, 220 insertions(+), 104 deletions(-) diff --git a/booster/test/rpc-integration/test-non-linear-int-requires/README.md b/booster/test/rpc-integration/test-non-linear-int-requires/README.md index 85201ecffc..dec8220870 100644 --- a/booster/test/rpc-integration/test-non-linear-int-requires/README.md +++ b/booster/test/rpc-integration/test-non-linear-int-requires/README.md @@ -1 +1,3 @@ This test is useful for debugging the SMT solver retry logic. To force the solver to return unknown and retry, run the server with a very short SMT timeout, e.g. `booster-dev --smt-timeout 1`. + +Note that with the changes [PR#3960](https://github.com/runtimeverification/haskell-backend/pull/3960) is merged, Booster starts assuming indeterminate rewrite rule conditions and going on rewriting, hence this test will always make a rewrite step. diff --git a/booster/test/rpc-integration/test-non-linear-int-requires/response-init.json b/booster/test/rpc-integration/test-non-linear-int-requires/response-init.json index ab82565480..4b9a9d3be0 100644 --- a/booster/test/rpc-integration/test-non-linear-int-requires/response-init.json +++ b/booster/test/rpc-integration/test-non-linear-int-requires/response-init.json @@ -1,117 +1,231 @@ { - "jsonrpc": "2.0", - "id": 1, - "result": { - "reason": "aborted", - "depth": 0, - "state": { - "term": { - "format": "KORE", - "version": 1, - "term": { - "tag": "App", - "name": "Lbl'-LT-'generatedTop'-GT-'", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "Lbl'-LT-'k'-GT-'", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ + "jsonrpc": "2.0", + "id": 1, + "result": { + "reason": "stuck", + "depth": 1, + "state": { + "term": { + "format": "KORE", + "version": 1, + "term": { + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ { - "tag": "SortApp", - "name": "SortState", - "args": [] + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortState", + "args": [] + }, + "value": "target" + } + ] + }, + { + "tag": "App", + "name": "dotk", + "sorts": [], + "args": [] + } + ] + } + ] }, { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], - "args": [ + "tag": "App", + "name": "Lbl'-LT-'x-int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarX", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, { - "tag": "DV", - "sort": { + "tag": "App", + "name": "Lbl'-LT-'y-int'-GT-'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarY", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'-LT-'generatedCounter'-GT-'", + "sorts": [], + "args": [ + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "0" + } + ] + } + ] + } + }, + "predicate": { + "format": "KORE", + "version": 1, + "term": { + "tag": "Equals", + "argSort": { + "tag": "SortApp", + "name": "SortBool", + "args": [] + }, + "sort": { + "tag": "SortApp", + "name": "SortGeneratedTopCell", + "args": [] + }, + "first": { + "tag": "DV", + "sort": { "tag": "SortApp", - "name": "SortState", + "name": "SortBool", "args": [] - }, - "value": "init" - } - ] + }, + "value": "true" }, - { - "tag": "App", - "name": "dotk", - "sorts": [], - "args": [] + "second": { + "tag": "App", + "name": "Lbl'Unds-LT-'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarX", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "App", + "name": "Lbl'UndsSlsh'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'UndsPlus'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lbl'UndsStar'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarX", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "EVar", + "name": "VarY", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "EVar", + "name": "VarY", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + }, + { + "tag": "App", + "name": "Lbl'UndsSlsh'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarY", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "EVar", + "name": "VarX", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + } + ] + } + ] } - ] - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'x-int'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarX", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'y-int'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarY", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'generatedCounter'-GT-'", - "sorts": [], - "args": [ - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "0" } - ] } - ] } - } } - } -} - +} \ No newline at end of file From 6d730a50e5da705a68fb0d10df3e48785e137e18 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Fri, 12 Jul 2024 08:41:12 +0200 Subject: [PATCH 39/54] Only emit proxy branch-eliminating rewrite trace when asked for --- booster/tools/booster/Proxy.hs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 4d9b2b78b5..4acfb88dfc 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -645,22 +645,25 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of -- extract the rule-id information from the result we proceed with let onlyNext = head filteredNexts rewriteRuleId = fromMaybe "UNKNOWN" onlyNext.ruleId - proxyRewriteStepLog = - RPCLog.Rewrite - { result = - RPCLog.Success - { rewrittenTerm = Nothing - , substitution = Nothing - , ruleId = rewriteRuleId + proxyRewriteStepLogs + | Just True <- logSettings.logSuccessfulRewrites = + Just . (: []) $ + RPCLog.Rewrite + { result = + RPCLog.Success + { rewrittenTerm = Nothing + , substitution = Nothing + , ruleId = rewriteRuleId + } + , origin = RPCLog.Proxy } - , origin = RPCLog.Proxy - } + | otherwise = Nothing Booster.Log.withContext CtxProxy $ Booster.Log.logMessage' ("Continuing after rewriting with rule " <> rewriteRuleId) pure $ Left ( execStateToKoreJson onlyNext - , logsOnly <> filteredNextLogs <> [Just [proxyRewriteStepLog]] + , logsOnly <> filteredNextLogs <> [proxyRewriteStepLogs] ) -- otherwise falling through to _otherReason CutPointRule From 4e1524ef105a3eb99fef7a2dab02fcfa68b8dcbf Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Fri, 12 Jul 2024 12:30:56 +0200 Subject: [PATCH 40/54] Update output of test-3934-smt: slight change in rule predicate --- .../test-3934-smt/response-008.json | 8310 ++++------------- 1 file changed, 1880 insertions(+), 6430 deletions(-) diff --git a/booster/test/rpc-integration/test-3934-smt/response-008.json b/booster/test/rpc-integration/test-3934-smt/response-008.json index 98e9dca69e..1487dcd8ac 100644 --- a/booster/test/rpc-integration/test-3934-smt/response-008.json +++ b/booster/test/rpc-integration/test-3934-smt/response-008.json @@ -1910,64 +1910,30 @@ "args": [ { "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], + "name": "Lblend", + "sorts": [], "args": [ { "tag": "App", - "name": "Lbl'Hash'gas'LSqBUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode", - "sorts": [], + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortExceptionalStatusCode", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortStatusCode", + "args": [] + } + ], "args": [ { "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - } - ] - } - ] + "name": "LblEVMC'Unds'OUT'Unds'OF'Unds'GAS'Unds'NETWORK'Unds'ExceptionalStatusCode", + "sorts": [], + "args": [] } ] } @@ -1996,33 +1962,9 @@ "args": [ { "tag": "App", - "name": "Lbl'Hash'access'LSqBUndsCommUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode'Unds'OpCode", + "name": "Lbl'Hash'gas'LSqBUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode", "sorts": [], "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortUnStackOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - } - ] - }, { "tag": "App", "name": "inj", @@ -2090,23 +2032,72 @@ "args": [ { "tag": "App", - "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", + "name": "Lbl'Hash'access'LSqBUndsCommUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode'Unds'OpCode", "sorts": [], "args": [ { "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortUnStackOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortOpCode", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + } + ] }, { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortInternalOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortOpCode", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "64" + } + ] + } + ] } ] } @@ -2135,32 +2126,23 @@ "args": [ { "tag": "App", - "name": "Lblpc", + "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", "sorts": [], "args": [ { "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortUnStackOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - } - ] + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "64" } ] } @@ -2173,18 +2155,74 @@ "args": [ { "tag": "App", - "name": "Lblexecute", - "sorts": [], - "args": [] + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortInternalOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lblpc", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortUnStackOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortOpCode", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + } + ] + } + ] + } + ] }, { - "tag": "EVar", - "name": "VarK'Unds'CELL'Unds'de090c3b", - "sort": { - "tag": "SortApp", - "name": "SortK", - "args": [] - } + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "Lblexecute", + "sorts": [], + "args": [] + }, + { + "tag": "EVar", + "name": "VarK'Unds'CELL'Unds'de090c3b", + "sort": { + "tag": "SortApp", + "name": "SortK", + "args": [] + } + } + ] } ] } @@ -2551,96 +2589,13 @@ "sorts": [], "args": [ { - "tag": "App", - "name": "Lbl'Unds'-Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarGAS'Unds'AMT", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "App", - "name": "Lbl'Unds'-Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblLONDON'Unds'EVM", - "sorts": [], - "args": [] - }, - { - "tag": "App", - "name": "Lbl'Hash'memoryUsageUpdate'LParUndsCommUndsCommUndsRParUnds'EVM'Unds'Int'Unds'Int'Unds'Int'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarMEMORYUSED'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "32" - } - ] - } - ] - }, - { - "tag": "App", - "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblLONDON'Unds'EVM", - "sorts": [], - "args": [] - }, - { - "tag": "EVar", - "name": "VarMEMORYUSED'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - } - ] - } - ] - } - ] + "tag": "EVar", + "name": "VarGAS'Unds'AMT", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } }, { "tag": "DV", @@ -3324,9 +3279,34 @@ }, "second": { "tag": "App", - "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "name": "Lbl'Unds-LT-'Int'Unds'", "sorts": [], "args": [ + { + "tag": "App", + "name": "Lbl'UndsPlus'Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "EVar", + "name": "VarGAS'Unds'AMT", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "-23" + } + ] + }, { "tag": "App", "name": "Lbl'Unds'-Int'Unds'", @@ -3402,31 +3382,6 @@ ] } ] - }, - { - "tag": "App", - "name": "Lbl'UndsPlus'Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarGAS'Unds'AMT", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "-23" - } - ] } ] } @@ -3843,7 +3798,7 @@ ] } }, - "rule-id": "e80dae2349dc4cf016147f969cff262399d625e3e979474e412b3c14914c4e77", + "rule-id": "a0a224658695b9eeae4eecf43289c46f78c5b34020e5e6ef966eaaf80525eccf", "rule-predicate": { "format": "KORE", "version": 1, @@ -3870,80 +3825,47 @@ }, "second": { "tag": "App", - "name": "Lbl'Unds-LT-Eqls'Int'Unds'", + "name": "Lbl'Unds-LT-'Gas'UndsUnds'GAS-SYNTAX'Unds'Bool'Unds'Gas'Unds'Gas", "sorts": [], "args": [ { "tag": "App", - "name": "Lbl'Unds'-Int'Unds'", - "sorts": [], - "args": [ + "name": "inj", + "sorts": [ { - "tag": "App", - "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblLONDON'Unds'EVM", - "sorts": [], - "args": [] - }, - { - "tag": "App", - "name": "Lbl'Hash'memoryUsageUpdate'LParUndsCommUndsCommUndsRParUnds'EVM'Unds'Int'Unds'Int'Unds'Int'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarMEMORYUSED'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "32" - } - ] - } - ] + "tag": "SortApp", + "name": "SortInt", + "args": [] }, + { + "tag": "SortApp", + "name": "SortGas", + "args": [] + } + ], + "args": [ { "tag": "App", - "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", + "name": "Lbl'UndsPlus'Int'Unds'", "sorts": [], "args": [ - { - "tag": "App", - "name": "LblLONDON'Unds'EVM", - "sorts": [], - "args": [] - }, { "tag": "EVar", - "name": "VarMEMORYUSED'Unds'CELL", + "name": "VarGAS'Unds'AMT", "sort": { "tag": "SortApp", "name": "SortInt", "args": [] } + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "-23" } ] } @@ -3951,2678 +3873,876 @@ }, { "tag": "App", - "name": "Lbl'UndsPlus'Int'Unds'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarGAS'Unds'AMT", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - }, + "name": "inj", + "sorts": [ { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "-23" + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortGas", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbl'Unds'-Int'Unds'", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblLONDON'Unds'EVM", + "sorts": [], + "args": [] + }, + { + "tag": "App", + "name": "Lbl'Hash'memory'LParUndsCommUndsRParUnds'EVM'Unds'Int'Unds'OpCode'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "inj", + "sorts": [ + { + "tag": "SortApp", + "name": "SortInternalOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortOpCode", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + }, + { + "tag": "DV", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + }, + "value": "64" + } + ] + } + ] + }, + { + "tag": "EVar", + "name": "VarMEMORYUSED'Unds'CELL", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + } + ] + }, + { + "tag": "App", + "name": "LblCmem'LParUndsCommUndsRParUnds'GAS-FEES'Unds'Int'Unds'Schedule'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblLONDON'Unds'EVM", + "sorts": [], + "args": [] + }, + { + "tag": "EVar", + "name": "VarMEMORYUSED'Unds'CELL", + "sort": { + "tag": "SortApp", + "name": "SortInt", + "args": [] + } + } + ] + } + ] } ] } ] } } - }, - "rule-substitution": { + } + }, + { + "term": { "format": "KORE", "version": 1, "term": { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "Lbl'-LT-'generatedTop'-GT-'", + "sorts": [], + "args": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "Lbl'-LT-'kevm'-GT-'", + "sorts": [], + "args": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "Lbl'-LT-'k'-GT-'", + "sorts": [], + "args": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "kseq", + "sorts": [], + "args": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "inj", + "sorts": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "SortApp", + "name": "SortInternalOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortKItem", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbl'Hash'gas'LSqBUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode", + "sorts": [], + "args": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "App", + "name": "inj", + "sorts": [ { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ + "tag": "SortApp", + "name": "SortInternalOp", + "args": [] + }, + { + "tag": "SortApp", + "name": "SortOpCode", + "args": [] + } + ], + "args": [ + { + "tag": "App", + "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", + "sorts": [], + "args": [ + { + "tag": "App", + "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", + "sorts": [], + "args": [] + }, { - "tag": "And", + "tag": "DV", "sort": { "tag": "SortApp", - "name": "SortGeneratedTopCell", + "name": "SortInt", "args": [] }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "And", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "patterns": [ - { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortGeneratedCounterCell", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "EVar", - "name": "RuleVar'Unds'DotVar0", - "sort": { - "tag": "SortApp", - "name": "SortGeneratedCounterCell", - "args": [] - } - }, - "second": { - "tag": "App", - "name": "Lbl'-LT-'generatedCounter'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarGENERATEDCOUNTER'Unds'CELL'Unds'c84b0b5f", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - } - ] - } - }, - { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortK", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "EVar", - "name": "RuleVar'Unds'DotVar2", - "sort": { - "tag": "SortApp", - "name": "SortK", - "args": [] - } - }, - "second": { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'Hash'gas'LSqBUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - } - ] - } - ] - } - ] - } - ] - }, - { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'Hash'access'LSqBUndsCommUndsRSqBUnds'EVM'Unds'InternalOp'Unds'OpCode'Unds'OpCode", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortUnStackOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - } - ] - }, - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - } - ] - } - ] - } - ] - } - ] - }, - { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lbl'UndsUndsUnds'EVM'Unds'InternalOp'Unds'UnStackOp'Unds'Int", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - }, - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - }, - "value": "64" - } - ] - } - ] - }, - { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortInternalOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortKItem", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "Lblpc", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "inj", - "sorts": [ - { - "tag": "SortApp", - "name": "SortUnStackOp", - "args": [] - }, - { - "tag": "SortApp", - "name": "SortOpCode", - "args": [] - } - ], - "args": [ - { - "tag": "App", - "name": "LblMLOAD'Unds'EVM'Unds'UnStackOp", - "sorts": [], - "args": [] - } - ] - } - ] - } - ] - }, - { - "tag": "App", - "name": "kseq", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "Lblexecute", - "sorts": [], - "args": [] - }, - { - "tag": "EVar", - "name": "VarK'Unds'CELL'Unds'de090c3b", - "sort": { - "tag": "SortApp", - "name": "SortK", - "args": [] - } - } - ] - } - ] - } - ] - } - ] - } - ] - } - } - ] - }, - { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortNetworkCell", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "EVar", - "name": "RuleVar'Unds'DotVar3", - "sort": { - "tag": "SortApp", - "name": "SortNetworkCell", - "args": [] - } - }, - "second": { - "tag": "App", - "name": "Lbl'-LT-'network'-GT-'", - "sorts": [], - "args": [ - { - "tag": "App", - "name": "Lbl'-LT-'chainID'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarCHAINID'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortInt", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'accounts'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarACCOUNTS'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortAccountCellMap", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'txOrder'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarTXORDER'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortList", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'txPending'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarTXPENDING'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortList", - "args": [] - } - } - ] - }, - { - "tag": "App", - "name": "Lbl'-LT-'messages'-GT-'", - "sorts": [], - "args": [ - { - "tag": "EVar", - "name": "VarMESSAGES'Unds'CELL", - "sort": { - "tag": "SortApp", - "name": "SortMessageCellMap", - "args": [] - } - } - ] - } - ] - } - } - ] - }, - { - "tag": "Equals", - "argSort": { - "tag": "SortApp", - "name": "SortProgramCell", - "args": [] - }, - "sort": { - "tag": "SortApp", - "name": "SortGeneratedTopCell", - "args": [] - }, - "first": { - "tag": "EVar", - "name": "RuleVar'Unds'Gen0", - "sort": { - "tag": "SortApp", - "name": "SortProgramCell", - "args": [] - } - }, - "second": { - "tag": "App", - "name": "Lbl'-LT-'program'-GT-'", - "sorts": [], - "args": [ - { - "tag": "DV", - "sort": { - "tag": "SortApp", - "name": "SortBytes", - "args": [] - }, - "value": "`€`@R4€\u0015a\u0000\u0010W`\u0000€ý[P`\u00046\u0010a\u0001,W`\u00005`à\u001c€c]â/\u0007\u0011a\u0000­W€c¡\u0018á\u0002\u0011a\u0000qW€c¡\u0018á\u0002\u0014a\u0002bW€cºAO¦\u0014a\u0002uW€cÓ\u0013”\r\u0014a\u0002W€cøÌ¿G\u0014a\u0002 W€cúv&Ô\u0014a\u0002³W`\u0000€ý[€c]â/\u0007\u0014a\u0002\u0003W€cm]9ß\u0014a\u0002\u0016W€c~Ž#Ð\u0014a\u0002)W€cˆ~OÛ\u0014a\u0002=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0004‘a\u0013eV[a\u0004™„a\u0013}V[a\u0004£‘a\u00138V[P`\u0000a\u0004°ƒa\u000c`V[Pa\u0003\u0014‚‚a\u000c’V[`\u0000a\u0004ǂa\rqV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0004ÛWP[\u0015a\u0005\u0012WƒQ\u0010a\u0004òWa\u0004òa\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005\na\u0013LV[‘PPa\u0004ÎV[Pa\u0003\u0014a\t›V[`\u0000a\u0003&`da\u0005‰V[`\u0000a\u00053‚a\rÐV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0005GWP[\u0015a\u0005\u0012WƒQ\u0010a\u0005^Wa\u0005^a\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005va\u0013LV[‘PPa\u0005:V[`\u0000a\u0002˃a\u000e.V[`@Qc&1ò±`á\u001bRf¸\u0017\u0002à\\\u000bo‚\u0011\u0015`\u0004‚\u0001R`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0005âW`\u0000€ý[PZñ\u0015€\u0015a\u0005öW=`\u0000€>=`\u0000ý[PPPP`\u0000[‚\u0015a\u0006!Wa\u0006\rƒ‚a\u0013eV[Pa\u0006\u001a`\u0001„a\u0013!V[’Pa\u0005ýV[’‘PPV[`@Qc&1ò±`á\u001bR`d‚\u0011\u0015`\u0004‚\u0001Rsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0006wW`\u0000€ý[PZñ\u0015€\u0015a\u0006‹W=`\u0000€>=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0006 ‘a\u0013eV[a\u0006ª„a\u0013}V[a\u0006´‘a\u00138V[P`\u0000a\u0004°ƒa\u000eeV[`\u0000a\u0006̂a\u000eV[P`\u0001€[‚Q\u0010€\u0015a\u0006ßWP[\u0015a\u0005\u0012WƒQ\u0010a\u0006öWa\u0006öa\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\u0007\u000c‘a\u0013!V[Q\u0010a\u0007\u001cWa\u0007\u001ca\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\u00073a\u0013LV[‘PPa\u0006ÒV[`\u0000a\u0007Fƒa\u000e»V[P‚`\u0000\u0003a\u0007[Wa\u0003\u0014`\u0000a\u000c’V[a\u0007ga\u0002݂a\tJV[`\u0000a\u0007|a\u0007w`\u0001†a\u0013!V[a\u000e»V[Pa\u0003ƒ„\u0011\u0015€a\u0007WP‚„\u0010\u0015[€a\u0002ÝWPa\u0007Ÿ„a\tJV[\u0015a\t›V[`\u0000€Ta\u0001\u0000\u0004`ÿ\u0016\u0015a\u0007ÅWP`\u0000Ta\u0001\u0000\u0004`ÿ\u0016V[`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0008ËW`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b‚„\u0001R‚Q€ƒ\u0003„\u0001R``ƒ\u0001“R`\u0000’‘a\u0008S‘fpÊA\u001dpêÕ\r\\\"\u0007\r¯Ãj×_=Ï^r7²*ޚìđ`€\u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u0008m‘a\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0008ªW`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0008¯V[``‘P[P‘PP€€` \u0001Q\u0001a\u0008Ǒa\u0014+V[‘PP[‘PV[`\u0000a\u0008ۂa\u000eõV[P`\u0001€[‚Q\u0010€\u0015a\u0008îWP[\u0015a\u0005\u0012WƒQ\u0010a\t\u0005Wa\t\u0005a\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\t\u001b‘a\u0013!V[Q\u0010a\t+Wa\t+a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\tBa\u0013LV[‘PPa\u0008áV[`\u0000`\u0002‚\u0010\u0015a\t]WP`\u0000‘PV[`\u0002[‚\u0010\u0015a\t’Wa\tr„a\u0012÷V[\u0015a\t€WP`\u0000’‘PPV[€a\tŠa\u0013LV[‘PPa\t`V[P`\u0001’‘PPV[€a\u0003£WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\tÿ` €‚R`\u0017‚\u0001RError: Assertion Failed\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`@‚\u0001R``\u0001V[`@Q€‘\u0003¡a\u0003£a\u000f\u0017V[`\u0000`\u0000\u0003a\n!WP`\u0000‘PV[[€‘P`\u0002a\n3…„a\u0010#V[a\n=‘a\u0013eV[a\nG‘a\u00138V[P\u0003a\n#W[P‘PV[`\u0000g\rඳ§d\u0000\u0000a\nm`\u0002‚a\u00138V[a\nw„†a\u0013}V[a\n‘a\u0013eV[a\n‹‘a\u00138V[“’PPPV[`\u0000`\u0002‚\u0010\u0015a\n¥WP`\u0000‘PV[`\u0002[a\n³`\u0002„a\u00138V[\u0011a\t’Wa\nÁ„a\u0012÷V[\u0015a\nÑWP`\u0000’‘PPV[€a\nہa\u0013LV[‘PPa\n¨V[€\u0015\u0015‚\u0015\u0015\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\u000bX` €‚R`\"‚\u0001RError: a == b not satisfied [boo`@‚\u0001Ral]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒa\u000b©W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000bÇV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000bԑa\u0014yV[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒ‚a\u000c%W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000cCV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000cP‘a\u0014½V[`@Q€‘\u0003¡a\u0004\u0006a\u000f\u0017V[`\u0000€€[ƒ\u0010\u0015a\u000c‹Wa\u000cwƒa\u0013eV[‘P€a\u000cƒa\u0013LV[‘PPa\u000ceV[P’‘PPV[€‚\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\r\u0003` €‚R`\"‚\u0001RError: a == b not satisfied [uin`@‚\u0001Rat]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨`@Qa\r:‘a\u0014çV[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨‚`@Qa\u000cP‘a\u0015\u001fV[`\u0000€`\u0001[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\r“Wa\r“a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\r¾WƒQ\u0010a\r³Wa\r³a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\rȁa\u0013LV[‘PPa\rwV[`\u0000€€[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\rñWa\rña\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\u000e\u001cWƒQ\u0010a\u000e\u0011Wa\u000e\u0011a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\u000e&a\u0013LV[‘PPa\rÕV[`\u0000`\u0002[‚\u0010\u0015a\t’Wa\u000eE„a\u0012÷V[\u0015a\u000eSWP`\u0000’‘PPV[€a\u000e]a\u0013LV[‘PPa\u000e3V[`\u0000€€[ƒ\u0011a\u000c‹Wa\u000e{ƒa\u0013eV[‘P€a\u000e‡a\u0013LV[‘PPa\u000ejV[```\u0001‚Q\u0011a\u000ežWPV[a\u000e·‚`\u0000`\u0001…Qa\u000e²‘a\u0013!V[a\u0010CV[PV[`\u0000€[‚\u0010\u0015a\nQWa\u000eсa\u0013LV[’PPa\u000e݂a\tJV[\u0015a\u000eðW€a\u000eìa\u0013LV[‘PP[a\u000e¿V[```\u0001‚Q\u0011a\u000f\u0004WPV[a\u000e·‚`\u0001€…Qa\u000e²‘a\u0013!V[sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0010\u0012W`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b’‚\u0001’’R`\u0001``‚\u0001R`\u0000‘pÊ\u0010»ÐÛý ©ô±4\u0002Ál± p^\r\u001c\nê±\u000f£S®XoĐ`€\u0001`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000f±’‘` \u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000fˑa\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0010\u0008W`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0010\rV[``‘P[PPPP[`\u0000€Taÿ\u0000\u0019\u0016a\u0001\u0000\u0017UV[`\u0000a\u00101`\u0002‚a\u00138V[a\nwg\rඳ§d\u0000\u0000†a\u0013}V[€‚\u0010a\u0010OWPPPV[`\u0000…`\u0002a\u0010`……a\u0013!V[a\u0010j‘a\u00138V[a\u0010t‡a\u0013eV[Q\u0010a\u0010„Wa\u0010„a\u0013œV[` \u0002` \u0001\u0001QP[ƒ\u0011a\u0011¤W[€†„Q\u0010a\u0010ªWa\u0010ªa\u0013œV[` \u0002` \u0001\u0001Q\u0010\u0015a\u0010ÊW‚a\u0010a\u0013LV[“PPa\u0010—V[…‚Q\u0010a\u0010ÜWa\u0010Üa\u0013œV[` \u0002` \u0001\u0001Q\u0010€\u0015a\u0010òWP`\u0000‚\u0011[\u0015a\u0011\tWa\u0011\u0001a\u0015IV[’PPa\u0010ÊV[ƒ\u0011a\u0011ŸW…‚Q\u0010a\u0011\"Wa\u0011\"a\u0013œV[` \u0002` \u0001\u0001Q†„Q\u0010a\u0011=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0004‘a\u0013eV[a\u0004™„a\u0013}V[a\u0004£‘a\u00138V[P`\u0000a\u0004°ƒa\u000c`V[Pa\u0003\u0014‚‚a\u000c’V[`\u0000a\u0004ǂa\rqV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0004ÛWP[\u0015a\u0005\u0012WƒQ\u0010a\u0004òWa\u0004òa\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005\na\u0013LV[‘PPa\u0004ÎV[Pa\u0003\u0014a\t›V[`\u0000a\u0003&`da\u0005‰V[`\u0000a\u00053‚a\rÐV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0005GWP[\u0015a\u0005\u0012WƒQ\u0010a\u0005^Wa\u0005^a\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005va\u0013LV[‘PPa\u0005:V[`\u0000a\u0002˃a\u000e.V[`@Qc&1ò±`á\u001bRf¸\u0017\u0002à\\\u000bo‚\u0011\u0015`\u0004‚\u0001R`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0005âW`\u0000€ý[PZñ\u0015€\u0015a\u0005öW=`\u0000€>=`\u0000ý[PPPP`\u0000[‚\u0015a\u0006!Wa\u0006\rƒ‚a\u0013eV[Pa\u0006\u001a`\u0001„a\u0013!V[’Pa\u0005ýV[’‘PPV[`@Qc&1ò±`á\u001bR`d‚\u0011\u0015`\u0004‚\u0001Rsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0006wW`\u0000€ý[PZñ\u0015€\u0015a\u0006‹W=`\u0000€>=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0006 ‘a\u0013eV[a\u0006ª„a\u0013}V[a\u0006´‘a\u00138V[P`\u0000a\u0004°ƒa\u000eeV[`\u0000a\u0006̂a\u000eV[P`\u0001€[‚Q\u0010€\u0015a\u0006ßWP[\u0015a\u0005\u0012WƒQ\u0010a\u0006öWa\u0006öa\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\u0007\u000c‘a\u0013!V[Q\u0010a\u0007\u001cWa\u0007\u001ca\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\u00073a\u0013LV[‘PPa\u0006ÒV[`\u0000a\u0007Fƒa\u000e»V[P‚`\u0000\u0003a\u0007[Wa\u0003\u0014`\u0000a\u000c’V[a\u0007ga\u0002݂a\tJV[`\u0000a\u0007|a\u0007w`\u0001†a\u0013!V[a\u000e»V[Pa\u0003ƒ„\u0011\u0015€a\u0007WP‚„\u0010\u0015[€a\u0002ÝWPa\u0007Ÿ„a\tJV[\u0015a\t›V[`\u0000€Ta\u0001\u0000\u0004`ÿ\u0016\u0015a\u0007ÅWP`\u0000Ta\u0001\u0000\u0004`ÿ\u0016V[`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0008ËW`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b‚„\u0001R‚Q€ƒ\u0003„\u0001R``ƒ\u0001“R`\u0000’‘a\u0008S‘fpÊA\u001dpêÕ\r\\\"\u0007\r¯Ãj×_=Ï^r7²*ޚìđ`€\u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u0008m‘a\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0008ªW`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0008¯V[``‘P[P‘PP€€` \u0001Q\u0001a\u0008Ǒa\u0014+V[‘PP[‘PV[`\u0000a\u0008ۂa\u000eõV[P`\u0001€[‚Q\u0010€\u0015a\u0008îWP[\u0015a\u0005\u0012WƒQ\u0010a\t\u0005Wa\t\u0005a\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\t\u001b‘a\u0013!V[Q\u0010a\t+Wa\t+a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\tBa\u0013LV[‘PPa\u0008áV[`\u0000`\u0002‚\u0010\u0015a\t]WP`\u0000‘PV[`\u0002[‚\u0010\u0015a\t’Wa\tr„a\u0012÷V[\u0015a\t€WP`\u0000’‘PPV[€a\tŠa\u0013LV[‘PPa\t`V[P`\u0001’‘PPV[€a\u0003£WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\tÿ` €‚R`\u0017‚\u0001RError: Assertion Failed\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`@‚\u0001R``\u0001V[`@Q€‘\u0003¡a\u0003£a\u000f\u0017V[`\u0000`\u0000\u0003a\n!WP`\u0000‘PV[[€‘P`\u0002a\n3…„a\u0010#V[a\n=‘a\u0013eV[a\nG‘a\u00138V[P\u0003a\n#W[P‘PV[`\u0000g\rඳ§d\u0000\u0000a\nm`\u0002‚a\u00138V[a\nw„†a\u0013}V[a\n‘a\u0013eV[a\n‹‘a\u00138V[“’PPPV[`\u0000`\u0002‚\u0010\u0015a\n¥WP`\u0000‘PV[`\u0002[a\n³`\u0002„a\u00138V[\u0011a\t’Wa\nÁ„a\u0012÷V[\u0015a\nÑWP`\u0000’‘PPV[€a\nہa\u0013LV[‘PPa\n¨V[€\u0015\u0015‚\u0015\u0015\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\u000bX` €‚R`\"‚\u0001RError: a == b not satisfied [boo`@‚\u0001Ral]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒa\u000b©W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000bÇV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000bԑa\u0014yV[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒ‚a\u000c%W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000cCV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000cP‘a\u0014½V[`@Q€‘\u0003¡a\u0004\u0006a\u000f\u0017V[`\u0000€€[ƒ\u0010\u0015a\u000c‹Wa\u000cwƒa\u0013eV[‘P€a\u000cƒa\u0013LV[‘PPa\u000ceV[P’‘PPV[€‚\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\r\u0003` €‚R`\"‚\u0001RError: a == b not satisfied [uin`@‚\u0001Rat]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨`@Qa\r:‘a\u0014çV[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨‚`@Qa\u000cP‘a\u0015\u001fV[`\u0000€`\u0001[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\r“Wa\r“a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\r¾WƒQ\u0010a\r³Wa\r³a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\rȁa\u0013LV[‘PPa\rwV[`\u0000€€[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\rñWa\rña\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\u000e\u001cWƒQ\u0010a\u000e\u0011Wa\u000e\u0011a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\u000e&a\u0013LV[‘PPa\rÕV[`\u0000`\u0002[‚\u0010\u0015a\t’Wa\u000eE„a\u0012÷V[\u0015a\u000eSWP`\u0000’‘PPV[€a\u000e]a\u0013LV[‘PPa\u000e3V[`\u0000€€[ƒ\u0011a\u000c‹Wa\u000e{ƒa\u0013eV[‘P€a\u000e‡a\u0013LV[‘PPa\u000ejV[```\u0001‚Q\u0011a\u000ežWPV[a\u000e·‚`\u0000`\u0001…Qa\u000e²‘a\u0013!V[a\u0010CV[PV[`\u0000€[‚\u0010\u0015a\nQWa\u000eсa\u0013LV[’PPa\u000e݂a\tJV[\u0015a\u000eðW€a\u000eìa\u0013LV[‘PP[a\u000e¿V[```\u0001‚Q\u0011a\u000f\u0004WPV[a\u000e·‚`\u0001€…Qa\u000e²‘a\u0013!V[sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0010\u0012W`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b’‚\u0001’’R`\u0001``‚\u0001R`\u0000‘pÊ\u0010»ÐÛý ©ô±4\u0002Ál± p^\r\u001c\nê±\u000f£S®XoĐ`€\u0001`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000f±’‘` \u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000fˑa\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0010\u0008W`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0010\rV[``‘P[PPPP[`\u0000€Taÿ\u0000\u0019\u0016a\u0001\u0000\u0017UV[`\u0000a\u00101`\u0002‚a\u00138V[a\nwg\rඳ§d\u0000\u0000†a\u0013}V[€‚\u0010a\u0010OWPPPV[`\u0000…`\u0002a\u0010`……a\u0013!V[a\u0010j‘a\u00138V[a\u0010t‡a\u0013eV[Q\u0010a\u0010„Wa\u0010„a\u0013œV[` \u0002` \u0001\u0001QP[ƒ\u0011a\u0011¤W[€†„Q\u0010a\u0010ªWa\u0010ªa\u0013œV[` \u0002` \u0001\u0001Q\u0010\u0015a\u0010ÊW‚a\u0010a\u0013LV[“PPa\u0010—V[…‚Q\u0010a\u0010ÜWa\u0010Üa\u0013œV[` \u0002` \u0001\u0001Q\u0010€\u0015a\u0010òWP`\u0000‚\u0011[\u0015a\u0011\tWa\u0011\u0001a\u0015IV[’PPa\u0010ÊV[ƒ\u0011a\u0011ŸW…‚Q\u0010a\u0011\"Wa\u0011\"a\u0013œV[` \u0002` \u0001\u0001Q†„Q\u0010a\u0011=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0004‘a\u0013eV[a\u0004™„a\u0013}V[a\u0004£‘a\u00138V[P`\u0000a\u0004°ƒa\u000c`V[Pa\u0003\u0014‚‚a\u000c’V[`\u0000a\u0004ǂa\rqV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0004ÛWP[\u0015a\u0005\u0012WƒQ\u0010a\u0004òWa\u0004òa\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005\na\u0013LV[‘PPa\u0004ÎV[Pa\u0003\u0014a\t›V[`\u0000a\u0003&`da\u0005‰V[`\u0000a\u00053‚a\rÐV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0005GWP[\u0015a\u0005\u0012WƒQ\u0010a\u0005^Wa\u0005^a\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005va\u0013LV[‘PPa\u0005:V[`\u0000a\u0002˃a\u000e.V[`@Qc&1ò±`á\u001bRf¸\u0017\u0002à\\\u000bo‚\u0011\u0015`\u0004‚\u0001R`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0005âW`\u0000€ý[PZñ\u0015€\u0015a\u0005öW=`\u0000€>=`\u0000ý[PPPP`\u0000[‚\u0015a\u0006!Wa\u0006\rƒ‚a\u0013eV[Pa\u0006\u001a`\u0001„a\u0013!V[’Pa\u0005ýV[’‘PPV[`@Qc&1ò±`á\u001bR`d‚\u0011\u0015`\u0004‚\u0001Rsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0006wW`\u0000€ý[PZñ\u0015€\u0015a\u0006‹W=`\u0000€>=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0006 ‘a\u0013eV[a\u0006ª„a\u0013}V[a\u0006´‘a\u00138V[P`\u0000a\u0004°ƒa\u000eeV[`\u0000a\u0006̂a\u000eV[P`\u0001€[‚Q\u0010€\u0015a\u0006ßWP[\u0015a\u0005\u0012WƒQ\u0010a\u0006öWa\u0006öa\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\u0007\u000c‘a\u0013!V[Q\u0010a\u0007\u001cWa\u0007\u001ca\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\u00073a\u0013LV[‘PPa\u0006ÒV[`\u0000a\u0007Fƒa\u000e»V[P‚`\u0000\u0003a\u0007[Wa\u0003\u0014`\u0000a\u000c’V[a\u0007ga\u0002݂a\tJV[`\u0000a\u0007|a\u0007w`\u0001†a\u0013!V[a\u000e»V[Pa\u0003ƒ„\u0011\u0015€a\u0007WP‚„\u0010\u0015[€a\u0002ÝWPa\u0007Ÿ„a\tJV[\u0015a\t›V[`\u0000€Ta\u0001\u0000\u0004`ÿ\u0016\u0015a\u0007ÅWP`\u0000Ta\u0001\u0000\u0004`ÿ\u0016V[`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0008ËW`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b‚„\u0001R‚Q€ƒ\u0003„\u0001R``ƒ\u0001“R`\u0000’‘a\u0008S‘fpÊA\u001dpêÕ\r\\\"\u0007\r¯Ãj×_=Ï^r7²*ޚìđ`€\u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u0008m‘a\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0008ªW`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0008¯V[``‘P[P‘PP€€` \u0001Q\u0001a\u0008Ǒa\u0014+V[‘PP[‘PV[`\u0000a\u0008ۂa\u000eõV[P`\u0001€[‚Q\u0010€\u0015a\u0008îWP[\u0015a\u0005\u0012WƒQ\u0010a\t\u0005Wa\t\u0005a\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\t\u001b‘a\u0013!V[Q\u0010a\t+Wa\t+a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\tBa\u0013LV[‘PPa\u0008áV[`\u0000`\u0002‚\u0010\u0015a\t]WP`\u0000‘PV[`\u0002[‚\u0010\u0015a\t’Wa\tr„a\u0012÷V[\u0015a\t€WP`\u0000’‘PPV[€a\tŠa\u0013LV[‘PPa\t`V[P`\u0001’‘PPV[€a\u0003£WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\tÿ` €‚R`\u0017‚\u0001RError: Assertion Failed\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`@‚\u0001R``\u0001V[`@Q€‘\u0003¡a\u0003£a\u000f\u0017V[`\u0000`\u0000\u0003a\n!WP`\u0000‘PV[[€‘P`\u0002a\n3…„a\u0010#V[a\n=‘a\u0013eV[a\nG‘a\u00138V[P\u0003a\n#W[P‘PV[`\u0000g\rඳ§d\u0000\u0000a\nm`\u0002‚a\u00138V[a\nw„†a\u0013}V[a\n‘a\u0013eV[a\n‹‘a\u00138V[“’PPPV[`\u0000`\u0002‚\u0010\u0015a\n¥WP`\u0000‘PV[`\u0002[a\n³`\u0002„a\u00138V[\u0011a\t’Wa\nÁ„a\u0012÷V[\u0015a\nÑWP`\u0000’‘PPV[€a\nہa\u0013LV[‘PPa\n¨V[€\u0015\u0015‚\u0015\u0015\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\u000bX` €‚R`\"‚\u0001RError: a == b not satisfied [boo`@‚\u0001Ral]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒa\u000b©W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000bÇV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000bԑa\u0014yV[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒ‚a\u000c%W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000cCV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000cP‘a\u0014½V[`@Q€‘\u0003¡a\u0004\u0006a\u000f\u0017V[`\u0000€€[ƒ\u0010\u0015a\u000c‹Wa\u000cwƒa\u0013eV[‘P€a\u000cƒa\u0013LV[‘PPa\u000ceV[P’‘PPV[€‚\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\r\u0003` €‚R`\"‚\u0001RError: a == b not satisfied [uin`@‚\u0001Rat]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨`@Qa\r:‘a\u0014çV[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨‚`@Qa\u000cP‘a\u0015\u001fV[`\u0000€`\u0001[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\r“Wa\r“a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\r¾WƒQ\u0010a\r³Wa\r³a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\rȁa\u0013LV[‘PPa\rwV[`\u0000€€[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\rñWa\rña\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\u000e\u001cWƒQ\u0010a\u000e\u0011Wa\u000e\u0011a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\u000e&a\u0013LV[‘PPa\rÕV[`\u0000`\u0002[‚\u0010\u0015a\t’Wa\u000eE„a\u0012÷V[\u0015a\u000eSWP`\u0000’‘PPV[€a\u000e]a\u0013LV[‘PPa\u000e3V[`\u0000€€[ƒ\u0011a\u000c‹Wa\u000e{ƒa\u0013eV[‘P€a\u000e‡a\u0013LV[‘PPa\u000ejV[```\u0001‚Q\u0011a\u000ežWPV[a\u000e·‚`\u0000`\u0001…Qa\u000e²‘a\u0013!V[a\u0010CV[PV[`\u0000€[‚\u0010\u0015a\nQWa\u000eсa\u0013LV[’PPa\u000e݂a\tJV[\u0015a\u000eðW€a\u000eìa\u0013LV[‘PP[a\u000e¿V[```\u0001‚Q\u0011a\u000f\u0004WPV[a\u000e·‚`\u0001€…Qa\u000e²‘a\u0013!V[sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0010\u0012W`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b’‚\u0001’’R`\u0001``‚\u0001R`\u0000‘pÊ\u0010»ÐÛý ©ô±4\u0002Ál± p^\r\u001c\nê±\u000f£S®XoĐ`€\u0001`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000f±’‘` \u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000fˑa\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0010\u0008W`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0010\rV[``‘P[PPPP[`\u0000€Taÿ\u0000\u0019\u0016a\u0001\u0000\u0017UV[`\u0000a\u00101`\u0002‚a\u00138V[a\nwg\rඳ§d\u0000\u0000†a\u0013}V[€‚\u0010a\u0010OWPPPV[`\u0000…`\u0002a\u0010`……a\u0013!V[a\u0010j‘a\u00138V[a\u0010t‡a\u0013eV[Q\u0010a\u0010„Wa\u0010„a\u0013œV[` \u0002` \u0001\u0001QP[ƒ\u0011a\u0011¤W[€†„Q\u0010a\u0010ªWa\u0010ªa\u0013œV[` \u0002` \u0001\u0001Q\u0010\u0015a\u0010ÊW‚a\u0010a\u0013LV[“PPa\u0010—V[…‚Q\u0010a\u0010ÜWa\u0010Üa\u0013œV[` \u0002` \u0001\u0001Q\u0010€\u0015a\u0010òWP`\u0000‚\u0011[\u0015a\u0011\tWa\u0011\u0001a\u0015IV[’PPa\u0010ÊV[ƒ\u0011a\u0011ŸW…‚Q\u0010a\u0011\"Wa\u0011\"a\u0013œV[` \u0002` \u0001\u0001Q†„Q\u0010a\u0011=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0004‘a\u0013eV[a\u0004™„a\u0013}V[a\u0004£‘a\u00138V[P`\u0000a\u0004°ƒa\u000c`V[Pa\u0003\u0014‚‚a\u000c’V[`\u0000a\u0004ǂa\rqV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0004ÛWP[\u0015a\u0005\u0012WƒQ\u0010a\u0004òWa\u0004òa\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005\na\u0013LV[‘PPa\u0004ÎV[Pa\u0003\u0014a\t›V[`\u0000a\u0003&`da\u0005‰V[`\u0000a\u00053‚a\rÐV[P`\u0001`\u0000[ƒQ\u0010€\u0015a\u0005GWP[\u0015a\u0005\u0012WƒQ\u0010a\u0005^Wa\u0005^a\u0013œV[` \u0002` \u0001\u0001Qƒ\u0010\u0015‘P€€a\u0005va\u0013LV[‘PPa\u0005:V[`\u0000a\u0002˃a\u000e.V[`@Qc&1ò±`á\u001bRf¸\u0017\u0002à\\\u000bo‚\u0011\u0015`\u0004‚\u0001R`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0005âW`\u0000€ý[PZñ\u0015€\u0015a\u0005öW=`\u0000€>=`\u0000ý[PPPP`\u0000[‚\u0015a\u0006!Wa\u0006\rƒ‚a\u0013eV[Pa\u0006\u001a`\u0001„a\u0013!V[’Pa\u0005ýV[’‘PPV[`@Qc&1ò±`á\u001bR`d‚\u0011\u0015`\u0004‚\u0001Rsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-cLcåb`$\u0001`\u0000`@Q€ƒ\u0003`\u0000‡€;\u0015€\u0015a\u0006wW`\u0000€ý[PZñ\u0015€\u0015a\u0006‹W=`\u0000€>=`\u0000ý[PPPP`\u0000`\u0002‚`\u0001a\u0006 ‘a\u0013eV[a\u0006ª„a\u0013}V[a\u0006´‘a\u00138V[P`\u0000a\u0004°ƒa\u000eeV[`\u0000a\u0006̂a\u000eV[P`\u0001€[‚Q\u0010€\u0015a\u0006ßWP[\u0015a\u0005\u0012WƒQ\u0010a\u0006öWa\u0006öa\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\u0007\u000c‘a\u0013!V[Q\u0010a\u0007\u001cWa\u0007\u001ca\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\u00073a\u0013LV[‘PPa\u0006ÒV[`\u0000a\u0007Fƒa\u000e»V[P‚`\u0000\u0003a\u0007[Wa\u0003\u0014`\u0000a\u000c’V[a\u0007ga\u0002݂a\tJV[`\u0000a\u0007|a\u0007w`\u0001†a\u0013!V[a\u000e»V[Pa\u0003ƒ„\u0011\u0015€a\u0007WP‚„\u0010\u0015[€a\u0002ÝWPa\u0007Ÿ„a\tJV[\u0015a\t›V[`\u0000€Ta\u0001\u0000\u0004`ÿ\u0016\u0015a\u0007ÅWP`\u0000Ta\u0001\u0000\u0004`ÿ\u0016V[`\u0000sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0008ËW`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b‚„\u0001R‚Q€ƒ\u0003„\u0001R``ƒ\u0001“R`\u0000’‘a\u0008S‘fpÊA\u001dpêÕ\r\\\"\u0007\r¯Ãj×_=Ï^r7²*ޚìđ`€\u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u0008m‘a\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0008ªW`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0008¯V[``‘P[P‘PP€€` \u0001Q\u0001a\u0008Ǒa\u0014+V[‘PP[‘PV[`\u0000a\u0008ۂa\u000eõV[P`\u0001€[‚Q\u0010€\u0015a\u0008îWP[\u0015a\u0005\u0012WƒQ\u0010a\t\u0005Wa\t\u0005a\u0013œV[` \u0002` \u0001\u0001Q„`\u0001ƒa\t\u001b‘a\u0013!V[Q\u0010a\t+Wa\t+a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015‘P€€a\tBa\u0013LV[‘PPa\u0008áV[`\u0000`\u0002‚\u0010\u0015a\t]WP`\u0000‘PV[`\u0002[‚\u0010\u0015a\t’Wa\tr„a\u0012÷V[\u0015a\t€WP`\u0000’‘PPV[€a\tŠa\u0013LV[‘PPa\t`V[P`\u0001’‘PPV[€a\u0003£WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\tÿ` €‚R`\u0017‚\u0001RError: Assertion Failed\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`@‚\u0001R``\u0001V[`@Q€‘\u0003¡a\u0003£a\u000f\u0017V[`\u0000`\u0000\u0003a\n!WP`\u0000‘PV[[€‘P`\u0002a\n3…„a\u0010#V[a\n=‘a\u0013eV[a\nG‘a\u00138V[P\u0003a\n#W[P‘PV[`\u0000g\rඳ§d\u0000\u0000a\nm`\u0002‚a\u00138V[a\nw„†a\u0013}V[a\n‘a\u0013eV[a\n‹‘a\u00138V[“’PPPV[`\u0000`\u0002‚\u0010\u0015a\n¥WP`\u0000‘PV[`\u0002[a\n³`\u0002„a\u00138V[\u0011a\t’Wa\nÁ„a\u0012÷V[\u0015a\nÑWP`\u0000’‘PPV[€a\nہa\u0013LV[‘PPa\n¨V[€\u0015\u0015‚\u0015\u0015\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\u000bX` €‚R`\"‚\u0001RError: a == b not satisfied [boo`@‚\u0001Ral]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒa\u000b©W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000bÇV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000bԑa\u0014yV[`@Q€‘\u0003¡(\u000fDF²Š\u0013rA}Úe0¹[)’±*ÉÇóxS_)©zÏ5ƒ‚a\u000c%W`@Q€`@\u0001`@R€`\u0005R` \u0001dfalse`Ø\u001bRPa\u000cCV[`@Q€`@\u0001`@R€`\u0004R` \u0001ctrue`à\u001bRP[`@Qa\u000cP‘a\u0014½V[`@Q€‘\u0003¡a\u0004\u0006a\u000f\u0017V[`\u0000€€[ƒ\u0010\u0015a\u000c‹Wa\u000cwƒa\u0013eV[‘P€a\u000cƒa\u0013LV[‘PPa\u000ceV[P’‘PPV[€‚\u0014a\u0004\u0006WA0O¬Ù2=u±\u001bÍÖ\tË8ïÿý°W\u0010÷Êðé±lmpŸP`@Qa\r\u0003` €‚R`\"‚\u0001RError: a == b not satisfied [uin`@‚\u0001Rat]`ð\u001b``‚\u0001R`€\u0001V[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨`@Qa\r:‘a\u0014çV[`@Q€‘\u0003¡²Þ/¾€\u001a\röÀËÝýD‹£Ä\u001dH @Ê5Ål–ï\u000fÊç!¨‚`@Qa\u000cP‘a\u0015\u001fV[`\u0000€`\u0001[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\r“Wa\r“a\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\r¾WƒQ\u0010a\r³Wa\r³a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\rȁa\u0013LV[‘PPa\rwV[`\u0000€€[ƒQ\u0010\u0015a\u000c‹W„‚Q\u0010a\rñWa\rña\u0013œV[` \u0002` \u0001\u0001Q\u0011\u0015a\u000e\u001cWƒQ\u0010a\u000e\u0011Wa\u000e\u0011a\u0013œV[` \u0002` \u0001\u0001Q‘P[€a\u000e&a\u0013LV[‘PPa\rÕV[`\u0000`\u0002[‚\u0010\u0015a\t’Wa\u000eE„a\u0012÷V[\u0015a\u000eSWP`\u0000’‘PPV[€a\u000e]a\u0013LV[‘PPa\u000e3V[`\u0000€€[ƒ\u0011a\u000c‹Wa\u000e{ƒa\u0013eV[‘P€a\u000e‡a\u0013LV[‘PPa\u000ejV[```\u0001‚Q\u0011a\u000ežWPV[a\u000e·‚`\u0000`\u0001…Qa\u000e²‘a\u0013!V[a\u0010CV[PV[`\u0000€[‚\u0010\u0015a\nQWa\u000eсa\u0013LV[’PPa\u000e݂a\tJV[\u0015a\u000eðW€a\u000eìa\u0013LV[‘PP[a\u000e¿V[```\u0001‚Q\u0011a\u000f\u0004WPV[a\u000e·‚`\u0001€…Qa\u000e²‘a\u0013!V[sq\tpžÏ©\u001a€boó˜hö[\u001dÑ-;\u0015a\u0010\u0012W`@€Qsq\tpžÏ©\u001a€boó˜hö[\u001dÑ-` ‚\u0001Re\u0019˜Z[\u0019Y`Ò\u001b’‚\u0001’’R`\u0001``‚\u0001R`\u0000‘pÊ\u0010»ÐÛý ©ô±4\u0002Ál± p^\r\u001c\nê±\u000f£S®XoĐ`€\u0001`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000f±’‘` \u0001a\u0013ÞV[`@€Q`\u001f\u0019„\u0003\u0001R‚Ra\u000fˑa\u0014\u000fV[`\u0000`@Q€ƒ\u0003`\u0000†Zñ‘PP=€`\u0000\u0014a\u0010\u0008W`@Q‘P`\u001f\u0019`?=\u0001\u0016‚\u0001`@R=‚R=`\u0000` „\u0001>a\u0010\rV[``‘P[PPPP[`\u0000€Taÿ\u0000\u0019\u0016a\u0001\u0000\u0017UV[`\u0000a\u00101`\u0002‚a\u00138V[a\nwg\rඳ§d\u0000\u0000†a\u0013}V[€‚\u0010a\u0010OWPPPV[`\u0000…`\u0002a\u0010`……a\u0013!V[a\u0010j‘a\u00138V[a\u0010t‡a\u0013eV[Q\u0010a\u0010„Wa\u0010„a\u0013œV[` \u0002` \u0001\u0001QP[ƒ\u0011a\u0011¤W[€†„Q\u0010a\u0010ªWa\u0010ªa\u0013œV[` \u0002` \u0001\u0001Q\u0010\u0015a\u0010ÊW‚a\u0010a\u0013LV[“PPa\u0010—V[…‚Q\u0010a\u0010ÜWa\u0010Üa\u0013œV[` \u0002` \u0001\u0001Q\u0010€\u0015a\u0010òWP`\u0000‚\u0011[\u0015a\u0011\tWa\u0011\u0001a\u0015IV[’PPa\u0010ÊV[ƒ\u0011a\u0011ŸW…‚Q\u0010a\u0011\"Wa\u0011\"a\u0013œV[` \u0002` \u0001\u0001Q†„Q\u0010a\u0011 Date: Fri, 12 Jul 2024 14:13:15 +0200 Subject: [PATCH 41/54] Do not ignore rule predicates in unit-tests, only rule subst --- booster/unit-tests/Test/Booster/Pattern/Rewrite.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs index 3bd36f2dda..e22bf27681 100644 --- a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs @@ -283,19 +283,19 @@ rewrites :: Steps -> Term -> t -> (t -> RewriteResult Term) -> IO () rewrites (Steps n) t t' f = do let expected = (n, f t') actual <- runRewrite t - second withoutRulePredAndSubst actual @?= expected + second withoutRuleSubst actual @?= expected mkRewriteBranch :: a -> NE.NonEmpty (Text, UniqueId, a) -> RewriteResult a mkRewriteBranch pre branches = RewriteBranch pre (fmap withEmptyPredandSubst branches) where withEmptyPredandSubst (l, uid, post) = (l, uid, post, Nothing, Map.empty) -withoutRulePredAndSubst :: RewriteResult a -> RewriteResult a -withoutRulePredAndSubst = \case - RewriteBranch pre branches -> RewriteBranch pre (fmap ignorePredandSubst branches) +withoutRuleSubst :: RewriteResult a -> RewriteResult a +withoutRuleSubst = \case + RewriteBranch pre branches -> RewriteBranch pre (fmap ignoreRuleSubst branches) other -> other where - ignorePredandSubst (l, uid, post, _, _) = (l, uid, post, Nothing, Map.empty) + ignoreRuleSubst (l, uid, post, rulePred, _) = (l, uid, post, rulePred, Map.empty) canRewrite :: TestTree canRewrite = @@ -430,7 +430,7 @@ supportsDepthControl = runNoLoggingT $ performRewrite NoCollectRewriteTraces def Nothing Nothing (Just depth) [] [] $ Pattern_ t - (counter, withoutRulePredAndSubst $ fmap (.term) res) @?= (n, f t') + (counter, withoutRuleSubst $ fmap (.term) res) @?= (n, f t') supportsCutPoints :: TestTree supportsCutPoints = @@ -484,7 +484,7 @@ supportsCutPoints = runNoLoggingT $ performRewrite NoCollectRewriteTraces def Nothing Nothing Nothing [lbl] [] $ Pattern_ t - (counter, withoutRulePredAndSubst $ fmap (.term) res) @?= (n, f t') + (counter, withoutRuleSubst $ fmap (.term) res) @?= (n, f t') supportsTerminalRules :: TestTree supportsTerminalRules = From 8c943d346edf2965ed78b5ed65a2d8e13a1c2683 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 24 Jul 2024 09:39:28 +0200 Subject: [PATCH 42/54] Make default fallback reasons more explicit, fix comment --- booster/tools/booster/Proxy.hs | 2 +- booster/tools/booster/Server.hs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 4acfb88dfc..f20477c1ff 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -351,7 +351,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of <$> accumulatedLogs ) r{ExecuteRequest.state = execStateToKoreJson simplifiedBoosterState} - -- if we stop for a reason in fallbackReasons (default [Aborted, Stuck, Branching], + -- if we stop for a reason in fallbackReasons (default [Aborted, Stuck], -- revert to the old backend to re-confirm and possibly proceed | boosterResult.reason `elem` cfg.fallbackReasons -> do Booster.Log.withContext CtxProxy $ diff --git a/booster/tools/booster/Server.hs b/booster/tools/booster/Server.hs index 8b158eccbf..2806fd0c0d 100644 --- a/booster/tools/booster/Server.hs +++ b/booster/tools/booster/Server.hs @@ -450,7 +450,7 @@ clProxyOptionsParser = (eitherReader $ mapM reasonReader . splitOn ",") ( long "fallback-on" <> metavar "REASON1,REASON2..." - <> value [Stuck, Aborted] + <> value defaultFallbackReasons <> help "Halt reasons for which requests should be re-executed with kore-rpc" <> showDefaultWith (intercalate "," . map show) ) @@ -466,6 +466,8 @@ clProxyOptionsParser = ( long "no-fallback-simplify" <> help "disable simplification before fallback requests" ) + defaultFallbackReasons :: [HaltReason] + defaultFallbackReasons = [Stuck, Aborted] reasonReader :: String -> Either String HaltReason reasonReader = \case From 13b4b9e18140749e94e2a705a70961b7d787a1f4 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 24 Jul 2024 09:52:31 +0200 Subject: [PATCH 43/54] Refactor result printing messages --- booster/tools/booster/Proxy.hs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index f20477c1ff..b2a114de9d 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -356,8 +356,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of | boosterResult.reason `elem` cfg.fallbackReasons -> do Booster.Log.withContext CtxProxy $ Booster.Log.logMessage $ - Text.pack $ - "Booster " <> show boosterResult.reason <> " at " <> show boosterResult.depth + "Booster " <> displayExecuteResultVerbose boosterResult -- simplify Booster's state with Kore's simplifier Booster.Log.withContext CtxProxy $ Booster.Log.logMessage ("Simplifying booster state and falling back to Kore" :: Text) @@ -494,8 +493,8 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of -- we were successful with the booster, thus we -- return the booster result with the updated -- depth, in case we previously looped - Booster.Log.withContext CtxProxy . Booster.Log.logMessage . Text.pack $ - "Booster " <> show boosterResult.reason <> " at " <> show boosterResult.depth + Booster.Log.withContext CtxProxy . Booster.Log.logMessage $ + "Booster " <> displayExecuteResultVerbose boosterResult -- perform post-exec simplification postExecResult <- simplifyExecResult logSettings r._module def boosterResult @@ -753,3 +752,13 @@ mkFallbackLogEntry boosterResult koreResult = getRewriteSuccessRuleId = \case RPCLog.Rewrite{result = RPCLog.Success{ruleId}} -> Just ruleId _ -> Nothing + +displayExecuteResultVerbose :: ExecuteResult -> Text +displayExecuteResultVerbose result = + Text.pack $ + show result.reason + <> " at " + <> show result.depth + <> " with " + <> show (length <$> result.nextStates) + <> " next states" From 3b179b296ddedd94c4bf464dbfc27775a4bed816 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 24 Jul 2024 10:22:00 +0200 Subject: [PATCH 44/54] Add a new handler for Booster Branching in Proxy.hs --- booster/tools/booster/Proxy.hs | 67 +++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index b2a114de9d..33ce980663 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -351,7 +351,72 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of <$> accumulatedLogs ) r{ExecuteRequest.state = execStateToKoreJson simplifiedBoosterState} - -- if we stop for a reason in fallbackReasons (default [Aborted, Stuck], + -- TODO this is an experimental code path. It needs to be guarded with an CLI option before merging + -- if we stop because of branching, simplify the next states to prune them and optionally + -- execute a fallback rewrite step from the pre-state in Kore con confirm the branch + | boosterResult.reason == Branching -> do + Booster.Log.withContext CtxProxy $ + Booster.Log.logMessage $ + "Booster " <> displayExecuteResultVerbose boosterResult + prunedBoosterResult <- simplifyExecResult logSettings r._module def boosterResult + case prunedBoosterResult of + Left (_prunedToOneNext, _logs) -> do + Booster.Log.withContext CtxProxy $ + Booster.Log.logMessage $ + "After simplification: Booster " + <> displayExecuteResultVerbose boosterResult{nextStates = take 1 <$> boosterResult.nextStates} + Right stillBranching -> + Booster.Log.withContext CtxProxy $ + Booster.Log.logMessage $ + "After simplification: Booster " <> displayExecuteResultVerbose stillBranching + + -- attempt to do one step in the old backend + Booster.Log.withContext CtxProxy $ + Booster.Log.logMessage ("Executing fall-back request" :: Text) + (koreResult, _kTime) <- + Stats.timed $ + kore + ( Execute + r + { state = execStateToKoreJson boosterResult.state + , maxDepth = Just $ Depth 1 + , assumeStateDefined = Just True + } + ) + case koreResult of + Right (Execute result) -> + Booster.Log.withContext CtxProxy $ + Booster.Log.logMessage $ + "Kore " <> displayExecuteResultVerbose result + _err -> + Booster.Log.withContext CtxProxy $ + Booster.Log.withContext CtxWarn $ + Booster.Log.logMessage ("Kore returned error" :: Text) + -- continue with the pruned Booster's result + case prunedBoosterResult of + Left (nextState, newLogs) -> do + let prunedBoosterBranchStep + | boosterResult.reason == Branching = 1 + | otherwise = 0 + executionLoop + logSettings + def + ( currentDepth + boosterResult.depth + prunedBoosterBranchStep + , time + bTime + , koreTime + , postProcessLogs <$> combineLogs (rpcLogs : boosterResult.logs : newLogs) + ) + r{ExecuteRequest.state = nextState} + Right result -> do + logStats ExecuteM (time + bTime, koreTime) + pure . Right $ + Execute + result + { depth = currentDepth + boosterResult.depth + , logs = postProcessLogs <$> combineLogs [rpcLogs, result.logs] + } + + -- if we stop for a reason in fallbackReasons (default [Aborted, Stuck]), -- revert to the old backend to re-confirm and possibly proceed | boosterResult.reason `elem` cfg.fallbackReasons -> do Booster.Log.withContext CtxProxy $ From cbfa7740f59b717634b66ea4a68b799bc6c691b9 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Thu, 25 Jul 2024 08:43:22 +0200 Subject: [PATCH 45/54] Update `kore-rpc-client` to use `tar-0.6.3` (#3996) With https://github.com/runtimeverification/k/pull/4548, the bug reports will be generated in GNU format of tar files instead of the default POSIX.1-2001 pax format. This is necessary because: - the filenames in the bug reports are often longer than the format-portable restriction of 256 characters - the Haskell [library](https://hackage.haskell.org/package/tar-0.6.3.0) we use to work with tar does not support the pax format. However, it does support the GNU format which also allows long names. With this change, we get to process bug reports with long names. --- booster/tools/rpc-client/RpcClient.hs | 24 +- cabal.project.freeze | 12 +- dev-tools/package.yaml | 27 --- dev-tools/tarball-compare/Main.hs | 318 -------------------------- flake.nix | 4 +- stack.yaml | 1 + stack.yaml.lock | 7 + 7 files changed, 31 insertions(+), 362 deletions(-) delete mode 100644 dev-tools/tarball-compare/Main.hs diff --git a/booster/tools/rpc-client/RpcClient.hs b/booster/tools/rpc-client/RpcClient.hs index 83a48ddd2c..80544c2d45 100644 --- a/booster/tools/rpc-client/RpcClient.hs +++ b/booster/tools/rpc-client/RpcClient.hs @@ -15,7 +15,7 @@ module RpcClient ( ) where import Codec.Archive.Tar qualified as Tar -import Codec.Archive.Tar.Check qualified as Tar +import Codec.Archive.Tar.Entry qualified as Tar import Codec.Compression.BZip qualified as BZ2 import Codec.Compression.GZip qualified as GZip import Control.Exception @@ -505,20 +505,24 @@ runTarball common (Just sock) tarFile keepGoing runOnly compareDetails = do | ".tar.bz2" `isSuffixOf` takeExtensions tarFile = Tar.read . BZ2.decompress | otherwise = Tar.read - containedFiles <- unpackTar <$> BS.readFile tarFile - let checked = Tar.checkSecurity containedFiles + entries <- Tar.decodeLongNames . unpackTar <$> BS.readFile tarFile -- probe server connection before doing anything, display -- instructions unless server was found. - runAllRequests checked sock + runAllRequests entries sock where runAllRequests :: - Tar.Entries (Either Tar.FormatError Tar.FileNameError) -> Socket -> IO () + Tar.GenEntries + FilePath + a + (Either Tar.FormatError Tar.DecodeLongNamesError) -> + Socket -> + IO () runAllRequests checked skt = cancelIfInterrupted skt $ do withTempDir $ \tmp -> withLogLevel common.logLevel $ do -- unpack relevant tar files (rpc_* directories only) logInfo_ $ unwords ["unpacking json files from tarball", tarFile, "into", tmp] (jsonFiles, sequenceMap) <- - liftIO $ Tar.foldEntries (unpackIfRpc tmp) (pure mempty) throwAnyError checked + liftIO $ Tar.foldEntries (unpackIfRpc tmp) (pure mempty) (error . show) checked logInfo_ $ "RPC data:" <> show jsonFiles logInfo_ $ "Sequence data:" <> show sequenceMap @@ -543,10 +547,6 @@ runTarball common (Just sock) tarFile keepGoing runOnly compareDetails = do liftIO $ shutdown skt ShutdownReceive liftIO $ exitWith (if all isNothing results then ExitSuccess else ExitFailure 2) - -- complain on any errors in the tarball - throwAnyError :: Either Tar.FormatError Tar.FileNameError -> IO a - throwAnyError = either throwIO throwIO - compareSequence :: Ord a => Ord b => Map.Map a b -> a -> a -> Ordering compareSequence seqMap a b = case (Map.lookup a seqMap, Map.lookup b seqMap) of (Nothing, Nothing) -> compare a b @@ -557,11 +557,11 @@ runTarball common (Just sock) tarFile keepGoing runOnly compareDetails = do -- unpack all */*.json files into dir and return their names unpackIfRpc :: FilePath -> - Tar.Entry -> + Tar.GenEntry FilePath a -> IO ([FilePath], Map.Map FilePath Int) -> IO ([FilePath], Map.Map FilePath Int) unpackIfRpc tmpDir entry acc = do - case splitFileName (Tar.entryPath entry) of + case splitFileName (Tar.entryTarPath entry) of -- unpack all directories "" containing "*.json" files (dir, "") -- directory | Tar.Directory <- Tar.entryContent entry -> do diff --git a/cabal.project.freeze b/cabal.project.freeze index 880df446e0..2c1bf4233f 100644 --- a/cabal.project.freeze +++ b/cabal.project.freeze @@ -37,7 +37,7 @@ constraints: any.Cabal ==3.10.3.0, any.bytesmith ==0.3.11.1, any.bytestring ==0.11.5.3, any.bz2 ==1.0.1.2, - any.cabal-doctest ==1.0.9, + any.cabal-doctest ==1.0.10, any.call-stack ==0.4.0, any.case-insensitive ==1.2.1.0, any.casing ==0.1.4.1, @@ -81,6 +81,7 @@ constraints: any.Cabal ==3.10.3.0, any.extra ==1.7.16, any.fast-logger ==3.2.3, any.fgl ==5.8.2.0, + any.file-embed ==0.0.11.2, any.filepath ==1.4.300.1, any.free ==5.2, any.generic-lens ==2.2.2.0, @@ -91,6 +92,7 @@ constraints: any.Cabal ==3.10.3.0, any.ghc-compact ==0.1.0.0, any.ghc-events ==0.19.0.1, any.ghc-prim ==0.10.0, + any.ghc-prof ==1.4.1.12, any.ghc-trace-events ==0.1.2.9, any.gitrev ==1.3.1, any.graphviz ==2999.20.2.0, @@ -117,6 +119,7 @@ constraints: any.Cabal ==3.10.3.0, any.integer-logarithms ==1.0.3.1, any.intern ==0.9.5, any.invariant ==0.6.3, + any.js-jquery ==3.3.1, any.json-rpc ==1.0.4, any.junit-xml ==0.1.0.3, any.kan-extensions ==5.2.6, @@ -148,6 +151,7 @@ constraints: any.Cabal ==3.10.3.0, any.old-locale ==1.0.0.7, any.old-time ==1.1.0.4, any.optparse-applicative ==0.18.1.0, + any.os-string ==2.0.2.2, any.parallel ==3.2.2.0, any.parsec ==3.1.16.1, any.parser-combinators ==1.3.0, @@ -162,6 +166,8 @@ constraints: any.Cabal ==3.10.3.0, any.primitive-offset ==0.2.0.1, any.primitive-unlifted ==2.1.0.0, any.process ==1.6.19.0, + any.profiteur ==0.4.7.0, + profiteur +embed-data-files, any.profunctors ==5.6.2, any.quickcheck-instances ==0.3.30, quickcheck-instances -bytestring-builder, @@ -198,7 +204,7 @@ constraints: any.Cabal ==3.10.3.0, any.string-conversions ==0.4.0.1, any.syb ==0.7.2.4, any.tagged ==0.8.8, - any.tar ==0.5.1.1, + any.tar ==0.6.3.0, any.tasty ==1.4.3, tasty +unix, any.tasty-discover ==5.0.0, @@ -254,4 +260,4 @@ constraints: any.Cabal ==3.10.3.0, any.yaml ==0.11.11.2, any.zigzag ==0.0.1.0, any.zlib ==0.6.3.0 -index-state: hackage.haskell.org 2024-05-24T09:11:31Z +index-state: hackage.haskell.org 2024-07-22T06:21:59Z diff --git a/dev-tools/package.yaml b/dev-tools/package.yaml index ce458bdab7..3ab1e66bc3 100644 --- a/dev-tools/package.yaml +++ b/dev-tools/package.yaml @@ -173,33 +173,6 @@ executables: - hs-backend-booster ghc-options: - -rtsopts - tarball-compare: - source-dirs: tarball-compare - main: Main - dependencies: - - aeson - - aeson-pretty - - base - - bytestring - - bz2 - - clock - - containers - - directory - - extra - - filepath - - hs-backend-booster - - kore-rpc-types - - monad-logger - - optparse-applicative - - prettyprinter - - recursion-schemes - - tar - - text - - transformers - - vector - - zlib - ghc-options: - - -rtsopts kore-rpc-dev: source-dirs: kore-rpc-dev main: Server.hs diff --git a/dev-tools/tarball-compare/Main.hs b/dev-tools/tarball-compare/Main.hs deleted file mode 100644 index 2565407090..0000000000 --- a/dev-tools/tarball-compare/Main.hs +++ /dev/null @@ -1,318 +0,0 @@ -{- | -Copyright : (c) Runtime Verification, 2022 -License : BSD-3-Clause - -Tool to compare two bug report tarballs (or directories containing an -unpacked bug report) for correspondence. The following comparisons are -performed: - -. compare number of request/response files in the tarball -. compare definition.kore file in the tarball (top-level) -Then, for each pair of requests or responses in the rpc_* directories: - . compare file contents and file size of json files - . compare the number of steps (depth) in responses to execute requests - . internalise states in response data (based on the definition.kore - file) and compare internal data (displaying diff if not equal) - -The tool can work on: - -. a single gzipped tarball containing other tarballs for many tests - (when given a single argument) -. two tarballs or directories of unpacked bug report data, assumed to - contain the same rpc_* directory names (two files as arguments) . - (when given two arguments, each one either a tar file or a directory) --} -module Main ( - module Main, -) where - -import Codec.Archive.Tar qualified as Tar -import Codec.Archive.Tar.Check qualified as Tar -import Codec.Compression.BZip qualified as BZ2 -import Codec.Compression.GZip qualified as GZip -import Control.Monad (forM, forM_, unless, when) -import Control.Monad.Trans.Writer -import Data.ByteString.Lazy.Char8 qualified as BS -import Data.List.Extra as List -import Data.Map (Map) -import Data.Map qualified as Map -import Data.Maybe (catMaybes, fromMaybe) -import Data.Text.Encoding qualified as Text -import System.Directory -import System.Directory.Extra -import System.Environment (getArgs) -import System.FilePath - -import Booster.JsonRpc.Utils -import Booster.Syntax.Json (sortOfJson) -import Booster.Syntax.ParsedKore (internalise, parseKoreDefinition) -import Kore.JsonRpc.Types -import Kore.Syntax.Json.Types hiding (Left, Right) - -data BugReportData = BugReportData - { requests :: Map FilePath BS.ByteString - , responses :: Map FilePath BS.ByteString - , definition :: BS.ByteString - } - deriving (Show) - -emptyBugReport :: BugReportData -emptyBugReport = BugReportData mempty mempty "INVALID" - -data BugReportDiff = BugReportDiff - { booster :: BugReportData - , koreRpc :: BugReportData - } - deriving (Show) - -emptyDiff :: BugReportDiff -emptyDiff = BugReportDiff emptyBugReport emptyBugReport - -main :: IO () -main = - getArgs >>= \case - [tarFile] -> do - contents <- readToTar tarFile - case unpackBugReports contents of - Left err -> either print print err - Right bugReports -> - forM_ (Map.toList bugReports) $ - mapM_ BS.putStrLn . uncurry checkDiff - [tar1, tar2] -> do - let dataFrom = - fmap (either (error . either show show) id . unpackBugReportDataFrom) - . readToTar - bugReportDiff <- - BugReportDiff - <$> dataFrom tar1 - <*> dataFrom tar2 - mapM_ BS.putStrLn $ checkDiff (tar1 <> "<->" <> tar2) bugReportDiff - _ -> putStrLn "incorrect args" - where - readToTar :: FilePath -> IO (Tar.Entries (Either Tar.FormatError Tar.FileNameError)) - readToTar file - | ".tar" == takeExtension file = - Tar.checkSecurity . Tar.read <$> BS.readFile file - | ".tgz" == takeExtension file || ".tar.gz" `isSuffixOf` takeExtensions file = - Tar.checkSecurity . Tar.read . GZip.decompress <$> BS.readFile file - | ".tar.bz2" `isSuffixOf` takeExtensions file = - Tar.checkSecurity . Tar.read . BZ2.decompress <$> BS.readFile file - | otherwise = do - isDir <- doesDirectoryExist file - if isDir - then withCurrentDirectory file $ do - -- create a Tar.Entries structure from the rpc_* - -- directories within the directory (ignore all other - -- files and subdirectories) - subdirs <- - filter (dirPrefix `isPrefixOf`) . map takeFileName <$> listDirectories "." - let hasCorrectSuffix f = - requestSuffix `isSuffixOf` f || responseSuffix `isSuffixOf` f - files <- - filter hasCorrectSuffix . concat <$> mapM listFiles subdirs - defFile <- - fromMaybe (error $ "No definition found in " <> file) - . find (== "./definition.kore") - <$> listFiles "." - - entries <- Tar.pack "." $ defFile : files - -- need to force the tar entries, withCurrentDirectory is not retained - mapM_ (`seq` pure ()) entries - pure $ foldr Tar.Next Tar.Done entries - else -- if a differently-named file was given. try to read a tarball - Tar.checkSecurity . Tar.read <$> BS.readFile file - -unpackBugReports :: - Tar.Entries (Either Tar.FormatError Tar.FileNameError) -> - Either (Either Tar.FormatError Tar.FileNameError) (Map FilePath BugReportDiff) -unpackBugReports = Tar.foldEntries unpackBugReportData (Right mempty) Left - where - unpackBugReportData :: - Tar.Entry -> - Either (Either Tar.FormatError Tar.FileNameError) (Map FilePath BugReportDiff) -> - Either (Either Tar.FormatError Tar.FileNameError) (Map FilePath BugReportDiff) - unpackBugReportData _ err@(Left _) = err - unpackBugReportData entry acc@(Right m) - | Tar.NormalFile bs _size <- Tar.entryContent entry - , ".tar" `isSuffixOf` file - , contents <- Tar.read bs = - case unpackBugReportDataFrom contents of - Left err -> Left $ Left err - Right bugReport -> Right $ Map.alter (insertBugReport bugReport) file m - | otherwise = acc - where - (dir, file) = splitFileName (Tar.entryPath entry) - insertBugReport b bDiff = - Just - $ ( \bugReportDiff -> - if "booster" `isInfixOf` dir - then bugReportDiff{booster = b} - else bugReportDiff{koreRpc = b} - ) - $ fromMaybe emptyDiff bDiff - -{- Unpack all files inside rpc_* directories in a tarball, into maps - of file prefixes (dir.name and number) to requests and resp. responses. - - There may be multiple rpc_* directories in a single tarball, therefore - the map keys have to contain the directory name. --} -unpackBugReportDataFrom :: - Tar.Entries err -> - Either err BugReportData -unpackBugReportDataFrom = Tar.foldEntries unpackRpc (Right emptyBugReport) Left - where - unpackRpc :: - Tar.Entry -> - Either err BugReportData -> - Either err BugReportData - unpackRpc _ err@(Left _) = err - unpackRpc entry acc@(Right bugReportData) - | Tar.NormalFile bs _size <- Tar.entryContent entry - , Just dir <- stripPrefix dirPrefix rpcDir - , ".json" `isSuffixOf` file = - let (isRequest, number, json) - | Just num <- stripSuffix requestSuffix file = - (True, num, bs) - | Just num <- stripSuffix responseSuffix file = - (False, num, bs) - | otherwise = error $ "Bad file in tarball: " <> show (rpcDir file) - in Right $ - if isRequest - then bugReportData{requests = Map.insert (dir <> number) json bugReportData.requests} - else bugReportData{responses = Map.insert (dir <> number) json bugReportData.responses} - | Tar.NormalFile bs _size <- Tar.entryContent entry - , rpcDir == "./" -- dir output of splitFileName for names without path - , file == "definition.kore" = - Right bugReportData{definition = bs} - | otherwise = acc - where - (rpcDir, file) = splitFileName (Tar.entryPath entry) - -dirPrefix, requestSuffix, responseSuffix :: FilePath -dirPrefix = "rpc_" -requestSuffix = "_request.json" -responseSuffix = "_response.json" - -checkDiff :: FilePath -> BugReportDiff -> [BS.ByteString] -checkDiff name BugReportDiff{booster, koreRpc} = - "------------- " <> BS.pack name <> " -------------" - : if null $ Map.keys booster.requests - then ["No Booster data... skipping..."] - else execWriter $ do - when (booster.definition /= koreRpc.definition) $ do - msg $ - "Definitions in bug reports differ " - <> compareSizes booster.definition koreRpc.definition - when - ( Map.keys koreRpc.requests /= Map.keys booster.requests - || Map.keys koreRpc.responses /= Map.keys booster.responses - ) - $ msg "Booster and kore-rpc have different requests/responses" - forM (Map.toList koreRpc.requests) $ \(koreRpcReqKey, koreRpcReqJson) -> do - let keyBS = BS.pack koreRpcReqKey - case Map.lookup koreRpcReqKey booster.requests of - Nothing -> - msg $ "Request " <> keyBS <> " does not exist in booster" - Just boosterReqJson -> do - let koreTp = requestType koreRpcReqJson - boosTp = requestType boosterReqJson - when (koreTp /= boosTp) $ - strMsg $ - "Requests have different type: " <> show (boosTp, koreTp) - compareJson - "Requests" - keyBS - koreRpcReqJson - boosterReqJson - comparePatternsIn "requests" keyBS boosterReqJson koreRpcReqJson - case (Map.lookup koreRpcReqKey koreRpc.responses, Map.lookup koreRpcReqKey booster.responses) of - (Just koreResp, Just boosterResp) -> do - compareJson - "Responses" - keyBS - koreResp - boosterResp - let koreDepth = responseDepth koreResp - boosDepth = responseDepth boosterResp - when (koreDepth /= boosDepth) $ - strMsg $ - "Execution depth differs: " - <> show boosDepth - <> " vs " - <> show koreDepth - comparePatternsIn "responses" keyBS boosterResp koreResp - (Just _, Nothing) -> - msg $ "Response " <> keyBS <> " missing in booster" - (Nothing, Just _) -> - msg $ "Response " <> keyBS <> " missing in kore-rpc" - (Nothing, Nothing) -> - msg $ "Response " <> keyBS <> " missing" - where - msg = tell . (: []) - strMsg = msg . BS.pack - - compareJson :: - BS.ByteString -> - BS.ByteString -> - BS.ByteString -> - BS.ByteString -> - Writer [BS.ByteString] () - compareJson prefix key koreJson boosterJson = - when (koreJson /= boosterJson) $ - msg $ - BS.unwords - [prefix, "for", key, "are different", compareSizes boosterJson koreJson] - - compareSizes bsBooster bsKore = - case compare (BS.length bsBooster) (BS.length bsKore) of - LT -> "(kore bigger)" - EQ -> "(same size)" - GT -> "(booster bigger)" - - requestType :: BS.ByteString -> KoreRpcType - requestType = rpcTypeOf . decodeKoreRpc - - responseDepth :: BS.ByteString -> Maybe Depth - responseDepth json = - case decodeKoreRpc json of - RpcResponse (Execute r) -> Just r.depth - _other -> Nothing - - bDef = - -- HACK: compare contents using the default module and booster def - either (error . show) id - . internalise Nothing - . either error id - . parseKoreDefinition (name <> "/definition.kore") - . Text.decodeUtf8 - $ BS.toStrict booster.definition - - patternsIn :: KoreRpcJson -> [KorePattern] - patternsIn (RpcRequest (Execute r)) = [r.state.term] - -- no need for patternsIn (RpcRequest (Implies r)) = map internalised [r.antecedent.term, r.consequent.term] - patternsIn (RpcRequest (Simplify r)) = [r.state.term] - patternsIn (RpcResponse (Execute r)) = fromState r.state : maybe [] (List.sortOn show . map fromState) r.nextStates - patternsIn (RpcResponse (Simplify r)) = [r.state.term] - -- no need for patternsIn (RpcResponse (Implies r)) = [internalised r.implication.term] - patternsIn (RpcKoreJson state) = [state.term] - patternsIn _other = [] - - fromState :: ExecuteState -> KorePattern - fromState exState = - case catMaybes [exState.substitution, exState.predicate] of - [] -> exState.term.term - ps@(p : _) -> - KJAnd - (fromMaybe (error "no sort") $ sortOfJson p.term) - (exState.term.term : map (.term) ps) - - comparePatternsIn tipe key bsBooster bsKore = do - let bPats = patternsIn $ decodeKoreRpc bsBooster - kPats = patternsIn $ decodeKoreRpc bsKore - diffs = catMaybes $ zipWith (diffBy bDef) bPats kPats - if length bPats /= length kPats - then msg "Different amount of patterns" - else unless (null diffs) $ do - msg ("Patterns in " <> tipe <> " " <> key <> " differ.") - mapM_ (msg . BS.pack) diffs diff --git a/flake.nix b/flake.nix index 6dd77b878e..9e9ba3440b 100644 --- a/flake.nix +++ b/flake.nix @@ -104,8 +104,8 @@ # this need to be bumped if changing the stack resolver all-cabal-hashes = final.fetchurl { url = - "https://github.com/commercialhaskell/all-cabal-hashes/archive/8b0d7c881466c603de7975596cb203e3fd4890ad.tar.gz"; - sha256 = "sha256-jTNSwG37bHY5vLMo5yqtk93sTUzlsp/jeYCfXJGaivU="; + "https://github.com/commercialhaskell/all-cabal-hashes/archive/ce857734d7d4c0fad3f6dda3a4db052836ed4619.tar.gz"; + sha256 = "sha256-Q7Zg32v5ubjVJMQXGiyyMmeFg08jTzVRKC18laiHCPE="; }; }; }; diff --git a/stack.yaml b/stack.yaml index b3b31ad2f1..b42775a83b 100644 --- a/stack.yaml +++ b/stack.yaml @@ -14,6 +14,7 @@ packages: # Dependency packages to be pulled from upstream that are not in the resolver extra-deps: + - tar-0.6.3.0 - hashable-1.4.2.0 - decision-diagrams-0.2.0.0 - smtlib-backends-0.3 diff --git a/stack.yaml.lock b/stack.yaml.lock index 73b1ba46c4..098f216431 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -4,6 +4,13 @@ # https://docs.haskellstack.org/en/stable/lock_files packages: +- completed: + hackage: tar-0.6.3.0@sha256:e9f151d9999be8953443e730524b2792e9c0a4fb5b1463097fa1a8230870fd8a,4634 + pantry-tree: + sha256: e59e0d0224352033c32356d517f90d4c6a41cee4fa0d386885df146302d1ba3b + size: 2241 + original: + hackage: tar-0.6.3.0 - completed: hackage: hashable-1.4.2.0@sha256:585792335d5541dba78fa8dfcb291a89cd5812a281825ff7a44afa296ab5d58a,4520 pantry-tree: From 01c344c8bcaf6b10bd651dd43dfbd2f4e57e7757 Mon Sep 17 00:00:00 2001 From: Jost Berthold Date: Thu, 25 Jul 2024 17:42:04 +1000 Subject: [PATCH 46/54] Fixes to simplification diff, request statistics, process-logs (#3992) * Add some context lines to simplification diff * compute request statistics in seconds (and output in seconds in the json format) * Make `process-logs` fail immediately on parse errors, and process lines incrementally (less heap) --- booster/library/Booster/JsonRpc/Utils.hs | 9 ++-- booster/tools/booster/Proxy.hs | 4 +- booster/tools/booster/Stats.hs | 64 ++++++++++++------------ dev-tools/process-logs/Main.hs | 17 +++---- 4 files changed, 46 insertions(+), 48 deletions(-) diff --git a/booster/library/Booster/JsonRpc/Utils.hs b/booster/library/Booster/JsonRpc/Utils.hs index 4061f78d25..a14d36c5b1 100644 --- a/booster/library/Booster/JsonRpc/Utils.hs +++ b/booster/library/Booster/JsonRpc/Utils.hs @@ -228,12 +228,15 @@ methodOfRpcCall = \case renderDiff :: BS.ByteString -> BS.ByteString -> Maybe String renderDiff first second | first == second = Nothing -renderDiff first second = unsafePerformIO . withTempDir $ \dir -> do + | otherwise = renderDiff' ["-w"] first second + +renderDiff' :: [String] -> BS.ByteString -> BS.ByteString -> Maybe String +renderDiff' diffOptions first second = unsafePerformIO . withTempDir $ \dir -> do let path1 = dir "diff_file1.txt" path2 = dir "diff_file2.txt" BS.writeFile path1 first BS.writeFile path2 second - (result, str, _) <- readProcessWithExitCode "diff" ["-w", path1, path2] "" + (result, str, _) <- readProcessWithExitCode "diff" (diffOptions <> [path1, path2]) "" case result of ExitSuccess -> pure Nothing ExitFailure 1 -> pure $ Just str @@ -244,7 +247,7 @@ renderDiff first second = unsafePerformIO . withTempDir $ \dir -> do -- This uses the `pretty` instance for a textual diff. diffBy :: Internal.KoreDefinition -> KorePattern -> KorePattern -> Maybe String diffBy def pat1 pat2 = - renderDiff (internalise pat1) (internalise pat2) + renderDiff' ["-c", "-w"] (internalise pat1) (internalise pat2) where renderBS :: TermOrPredicates -> BS.ByteString renderBS (Predicates ps) = diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 33ce980663..964323cd16 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -49,7 +49,7 @@ import Kore.Log qualified import Kore.Syntax.Definition (SentenceAxiom) import Kore.Syntax.Json.Types qualified as KoreJson import SMT qualified -import Stats (MethodTiming (..), StatsVar, addStats, microsWithUnit, timed) +import Stats (MethodTiming (..), StatsVar, addStats, secWithUnit, timed) data KoreServer = KoreServer { serverState :: MVar.MVar Kore.ServerState @@ -460,7 +460,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of , koreTime = kTime } ) - ("Kore fall-back in " <> microsWithUnit kTime) + ("Kore fall-back in " <> secWithUnit kTime) case kResult of Right (Execute koreResult) -> do let diff --git a/booster/tools/booster/Stats.hs b/booster/tools/booster/Stats.hs index 6ee058cce7..d1d014e015 100644 --- a/booster/tools/booster/Stats.hs +++ b/booster/tools/booster/Stats.hs @@ -3,7 +3,7 @@ module Stats ( addStats, finaliseStats, timed, - microsWithUnit, + secWithUnit, RequestStats (..), StatsVar, MethodTiming (..), @@ -25,7 +25,7 @@ import Booster.Log import Booster.Prettyprinter import Kore.JsonRpc.Types (APIMethod) --- server statistics +-- | Statistics for duration measurement time series (in seconds) data RequestStats a = RequestStats { count :: Int , average :: a @@ -60,31 +60,30 @@ instance (Floating a, PrintfArg a, Ord a) => Pretty (RequestStats a) where <+> withUnit stats.koreMax ] where - withUnit = pretty . microsWithUnit + withUnit = pretty . secWithUnit -microsWithUnit :: (Floating a, Ord a, PrintfArg a) => a -> String -microsWithUnit x - | x > 10 ** 5 = printf "%.2fs" $ x / 10 ** 6 - | x > 10 ** 2 = printf "%.3fms" $ x / 10 ** 3 - | otherwise = printf "%.1fμs" x +secWithUnit :: (Floating a, Ord a, PrintfArg a) => a -> String +secWithUnit x + | x > 0.1 = printf "%.2fs" x + | x > 0.0001 = printf "%.3fms" $ x * 10 ** 3 + | otherwise = printf "%.1fμs" $ x * 10 ** 6 -- internal helper type --- all values are in microseconds -data Stats' a = Stats' +-- all values are in seconds +data Stats' = Stats' { count :: Int - , total :: a - , squares :: a - , maxVal :: a - , minVal :: a - , koreTotal :: a - , koreMax :: a + , total :: Double + , squares :: Double + , maxVal :: Double + , minVal :: Double + , koreTotal :: Double + , koreMax :: Double } -instance (Ord a, Num a) => Semigroup (Stats' a) where +instance Semigroup Stats' where (<>) = addStats' -{-# SPECIALIZE addStats' :: Stats' Double -> Stats' Double -> Stats' Double #-} -addStats' :: (Ord a, Num a) => Stats' a -> Stats' a -> Stats' a +addStats' :: Stats' -> Stats' -> Stats' addStats' stats1 stats2 = Stats' { count = stats1.count + stats2.count @@ -96,7 +95,7 @@ addStats' stats1 stats2 = , koreMax = max stats1.koreMax stats2.koreMax } -singleStats' :: Num a => a -> a -> Stats' a +singleStats' :: Double -> Double -> Stats' singleStats' x korePart = Stats' { count = 1 @@ -108,43 +107,44 @@ singleStats' x korePart = , koreMax = korePart } -type StatsVar = MVar (Map APIMethod (Stats' Double)) +type StatsVar = MVar (Map APIMethod Stats') -- helper type mainly for json logging -data MethodTiming a = MethodTiming {method :: APIMethod, time :: a, koreTime :: a} +data MethodTiming = MethodTiming {method :: APIMethod, time :: Double, koreTime :: Double} deriving stock (Eq, Show, Generic) deriving (ToJSON, FromJSON) - via CustomJSON '[FieldLabelModifier '[CamelToKebab]] (MethodTiming a) + via CustomJSON '[FieldLabelModifier '[CamelToKebab]] MethodTiming -instance ToLogFormat (MethodTiming Double) where +instance ToLogFormat MethodTiming where toTextualLog mt = pack $ printf "Performed %s in %s (%s kore time)" (show mt.method) - (microsWithUnit mt.time) - (microsWithUnit mt.koreTime) + (secWithUnit mt.time) + (secWithUnit mt.koreTime) toJSONLog = toJSON addStats :: MonadIO m => - MVar (Map APIMethod (Stats' Double)) -> - MethodTiming Double -> + MVar (Map APIMethod Stats') -> + MethodTiming -> m () addStats statVar MethodTiming{method, time, koreTime} = liftIO . modifyMVar_ statVar $ pure . Map.insertWith (<>) method (singleStats' time koreTime) -newStats :: MonadIO m => m (MVar (Map APIMethod (Stats' Double))) +newStats :: MonadIO m => m (MVar (Map APIMethod Stats')) newStats = liftIO $ newMVar Map.empty +-- returns time taken by the given action (in seconds) timed :: MonadIO m => m a -> m (a, Double) timed action = do start <- liftIO $ getTime Monotonic result <- action stop <- liftIO $ getTime Monotonic - let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 1000.0 + let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 10 ** 9 pure (result, time) newtype FinalStats = FinalStats (Map APIMethod (RequestStats Double)) @@ -164,10 +164,10 @@ instance ToLogFormat FinalStats where toTextualLog = renderText . pretty toJSONLog = toJSON -finaliseStats :: MVar (Map APIMethod (Stats' Double)) -> IO FinalStats +finaliseStats :: MVar (Map APIMethod Stats') -> IO FinalStats finaliseStats var = FinalStats . Map.map finalise <$> readMVar var where - finalise :: Floating a => Stats' a -> RequestStats a + finalise :: Stats' -> RequestStats Double finalise Stats'{count, total, squares, maxVal, minVal, koreTotal, koreMax} = let average = total / fromIntegral count stddev = sqrt $ squares / fromIntegral count - average * average diff --git a/dev-tools/process-logs/Main.hs b/dev-tools/process-logs/Main.hs index 03c89b5c50..c20151a0ff 100644 --- a/dev-tools/process-logs/Main.hs +++ b/dev-tools/process-logs/Main.hs @@ -7,12 +7,10 @@ module Main ( main, ) where -import Control.Monad (unless) import Data.Aeson qualified as JSON import Data.Aeson.Encode.Pretty qualified as JSON import Data.ByteString.Char8 qualified as BSS import Data.ByteString.Lazy.Char8 qualified as BS -import Data.Either (partitionEithers) import Data.Foldable (toList) import Data.List (foldl', maximumBy, sortBy) import Data.Map (Map) @@ -24,7 +22,6 @@ import Data.Sequence qualified as Seq import Data.Time.Clock import Data.Time.Clock.System (systemToUTCTime) import Options.Applicative -import System.Exit import Text.Printf import Booster.Log.Context (ContextFilter, mustMatch, readContextFilter) @@ -37,17 +34,15 @@ import Kore.JsonRpc.Types.ContextLog main :: IO () main = do Options{cmd, input, output} <- execParser parse - (errors, inputJson) <- - partitionEithers - . map JSON.eitherDecode + inputData <- + map JSON.eitherDecode . BS.lines <$> maybe BS.getContents BS.readFile input - unless (null errors) $ do - putStrLn "JSON parse errors in log file:" - mapM_ putStrLn errors - exitWith (ExitFailure 1) let writeOut = maybe BS.putStrLn BS.writeFile output . BS.unlines - writeOut $ process cmd inputJson + writeOut $ process cmd $ stopOnErrors inputData + where + stopOnErrors :: [Either String LogLine] -> [LogLine] + stopOnErrors = map (either (error . ("JSON parse error: " <>)) id) data Options = Options { cmd :: Command From b7590bc6937186f166703f351464ed742d0f5eb5 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Fri, 26 Jul 2024 12:01:00 +0200 Subject: [PATCH 47/54] TEMP comment-out Kore fallback --- booster/tools/booster/Proxy.hs | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 964323cd16..5769797340 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -370,28 +370,28 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of Booster.Log.logMessage $ "After simplification: Booster " <> displayExecuteResultVerbose stillBranching - -- attempt to do one step in the old backend - Booster.Log.withContext CtxProxy $ - Booster.Log.logMessage ("Executing fall-back request" :: Text) - (koreResult, _kTime) <- - Stats.timed $ - kore - ( Execute - r - { state = execStateToKoreJson boosterResult.state - , maxDepth = Just $ Depth 1 - , assumeStateDefined = Just True - } - ) - case koreResult of - Right (Execute result) -> - Booster.Log.withContext CtxProxy $ - Booster.Log.logMessage $ - "Kore " <> displayExecuteResultVerbose result - _err -> - Booster.Log.withContext CtxProxy $ - Booster.Log.withContext CtxWarn $ - Booster.Log.logMessage ("Kore returned error" :: Text) + -- -- attempt to do one step in the old backend + -- Booster.Log.withContext CtxProxy $ + -- Booster.Log.logMessage ("Executing fall-back request" :: Text) + -- (koreResult, _kTime) <- + -- Stats.timed $ + -- kore + -- ( Execute + -- r + -- { state = execStateToKoreJson boosterResult.state + -- , maxDepth = Just $ Depth 1 + -- , assumeStateDefined = Just True + -- } + -- ) + -- case koreResult of + -- Right (Execute result) -> + -- Booster.Log.withContext CtxProxy $ + -- Booster.Log.logMessage $ + -- "Kore " <> displayExecuteResultVerbose result + -- _err -> + -- Booster.Log.withContext CtxProxy $ + -- Booster.Log.withContext CtxWarn $ + -- Booster.Log.logMessage ("Kore returned error" :: Text) -- continue with the pruned Booster's result case prunedBoosterResult of Left (nextState, newLogs) -> do From 7bdf0a7bd1a24164c3982ad0b64e20932c210a65 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 30 Jul 2024 10:19:47 +0200 Subject: [PATCH 48/54] Allow matching functions when rewriting --- booster/library/Booster/Pattern/Match.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/booster/library/Booster/Pattern/Match.hs b/booster/library/Booster/Pattern/Match.hs index 2e7d3e43ee..8f10d5f60d 100644 --- a/booster/library/Booster/Pattern/Match.hs +++ b/booster/library/Booster/Pattern/Match.hs @@ -294,6 +294,7 @@ match1 _ t1@FunctionApplication{} t2@KSet{} match1 Eval (FunctionApplication symbol1 sorts1 args1) (ConsApplication symbol2 sorts2 args2) = matchSymbolAplications Eval symbol1 sorts1 args1 symbol2 sorts2 args2 match1 _ t1@FunctionApplication{} t2@ConsApplication{} = addIndeterminate t1 t2 match1 Eval (FunctionApplication symbol1 sorts1 args1) (FunctionApplication symbol2 sorts2 args2) = matchSymbolAplications Eval symbol1 sorts1 args1 symbol2 sorts2 args2 +match1 Rewrite (FunctionApplication symbol1 sorts1 args1) (FunctionApplication symbol2 sorts2 args2) = matchSymbolAplications Rewrite symbol1 sorts1 args1 symbol2 sorts2 args2 match1 _ t1@FunctionApplication{} t2@FunctionApplication{} = addIndeterminate t1 t2 match1 Rewrite t1@FunctionApplication{} (Var t2) = failWith $ SubjectVariableMatch t1 t2 match1 _ t1@FunctionApplication{} t2@Var{} = addIndeterminate t1 t2 From bf05ef248c70b5cfae47fb9c8c88edc851cb2bd9 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 30 Jul 2024 14:11:29 +0200 Subject: [PATCH 49/54] Allow matching empty sets --- booster/library/Booster/Pattern/Match.hs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/booster/library/Booster/Pattern/Match.hs b/booster/library/Booster/Pattern/Match.hs index 8f10d5f60d..eba6170e42 100644 --- a/booster/library/Booster/Pattern/Match.hs +++ b/booster/library/Booster/Pattern/Match.hs @@ -25,6 +25,7 @@ import Data.List (partition) import Data.List.NonEmpty as NE (NonEmpty, fromList) import Data.Map (Map) import Data.Map qualified as Map +import Data.Maybe (isNothing) import Data.Sequence (Seq, (><), pattern (:<|), pattern (:|>)) import Data.Sequence qualified as Seq @@ -32,7 +33,7 @@ import Data.Set (Set) import Data.Set qualified as Set import Prettyprinter -import Booster.Definition.Attributes.Base (KListDefinition, KMapDefinition) +import Booster.Definition.Attributes.Base (KListDefinition, KMapDefinition, KSetDefinition) import Booster.Definition.Base import Booster.Pattern.Base import Booster.Pattern.Pretty @@ -262,7 +263,7 @@ match1 Eval t1@KSet{} t2@Injection{} match1 _ t1@KSet{} t2@Injection{} = failWith $ DifferentSymbols t1 t2 match1 _ t1@KSet{} t2@KMap{} = failWith $ DifferentSymbols t1 t2 match1 _ t1@KSet{} t2@KList{} = failWith $ DifferentSymbols t1 t2 -match1 _ t1@KSet{} t2@KSet{} = addIndeterminate t1 t2 +match1 _ t1@(KSet def1 patElements patRest) t2@(KSet def2 subjElements subjRest) = if def1 == def2 then matchSets def1 patElements patRest subjElements subjRest else failWith $ DifferentSorts t1 t2 match1 _ t1@KSet{} t2@ConsApplication{} = failWith $ DifferentSymbols t1 t2 match1 _ t1@KSet{} t2@FunctionApplication{} = addIndeterminate t1 t2 match1 Rewrite t1@KSet{} (Var t2) = failWith $ SubjectVariableMatch t1 t2 @@ -627,6 +628,25 @@ containsOtherKeys = \case Rest OtherKey{} -> True Rest _ -> False +------ Internalised Sets +matchSets :: + KSetDefinition -> + [Term] -> + Maybe Term -> + [Term] -> + Maybe Term -> + StateT MatchState (Except MatchResult) () +matchSets + def + patElements + patRest + subjElements + subjRest = do + -- match only empty sets, indeterminate otherwise + if null patElements && null subjElements && isNothing patRest && isNothing subjRest + then pure () + else addIndeterminate (KSet def patElements patRest) (KSet def subjElements subjRest) + ------ Internalised Maps matchMaps :: KMapDefinition -> From 70817d4797bd6b7772de183d6bb0cb5761857457 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 30 Jul 2024 16:59:12 +0200 Subject: [PATCH 50/54] Add dummy unit test for set matching --- .../unit-tests/Test/Booster/Pattern/MatchRewrite.hs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/booster/unit-tests/Test/Booster/Pattern/MatchRewrite.hs b/booster/unit-tests/Test/Booster/Pattern/MatchRewrite.hs index 4b15123eb9..d56fe5294a 100644 --- a/booster/unit-tests/Test/Booster/Pattern/MatchRewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/MatchRewrite.hs @@ -32,6 +32,7 @@ test_match_rewrite = , sorts , injections , internalLists + , internalSets , internalMaps ] @@ -376,6 +377,17 @@ internalLists = klist = KList testKListDef +internalSets :: TestTree +internalSets = + testGroup + "Internal sets" + [ test + "Can match an empty set with itself" + emptySet + emptySet + (success []) + ] + internalMaps :: TestTree internalMaps = testGroup From 4f955f20373370dfadf1e648eb7fec41eca931e1 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Tue, 6 Aug 2024 18:19:31 +0200 Subject: [PATCH 51/54] Make unit-tests typecheck --- booster/unit-tests/Test/Booster/Pattern/Rewrite.hs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs index 969608f17d..f3950287c2 100644 --- a/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs +++ b/booster/unit-tests/Test/Booster/Pattern/Rewrite.hs @@ -254,24 +254,25 @@ rulePriority = , [trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( f1{}( \dv{SomeSort{}}("otherThing") ) ), ConfigVar:SortK{}) ) |] ] -runWith :: Term -> IO Either (RewriteFailed "Rewrite") (RewriteStepResult [Pattern]) +runWith :: Term -> IO (Either (RewriteFailed "Rewrite") (RewriteStepResult [Pattern])) runWith t = - second fst <$> do + second (fmap (fmap (\(_, p, _) -> p)) . fst) <$> do conf <- testConf - runNoLoggingT $ runRewriteT conf mempty (rewriteStep [] [] $ Pattern_ t) + runNoLoggingT $ + runRewriteT conf mempty mempty (rewriteStep $ Pattern_ t) rewritesTo :: Term -> Term -> IO () t1 `rewritesTo` t2 = - runWith t1 @?= Right (AppliedRules [Pattern_ t2]) + runWith t1 @?>>= Right (AppliedRules [Pattern_ t2]) getsStuck :: Term -> IO () getsStuck t1 = - runWith t1 @?= Right (AppliedRules []) + runWith t1 @?>>= Right (AppliedRules []) branchesTo :: Term -> [Term] -> IO () t `branchesTo` ts = runWith t - @?= Right + @?>>= Right (AppliedRules $ map Pattern_ ts) failsWith :: Term -> RewriteFailed "Rewrite" -> IO () From 342ddd962f87ea24df73ee50b4ab88954fada02e Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 7 Aug 2024 09:01:55 +0200 Subject: [PATCH 52/54] Revert "Allow matching functions when rewriting" This reverts commit 7bdf0a7bd1a24164c3982ad0b64e20932c210a65. --- booster/library/Booster/Pattern/Match.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/booster/library/Booster/Pattern/Match.hs b/booster/library/Booster/Pattern/Match.hs index eba6170e42..06dab386ed 100644 --- a/booster/library/Booster/Pattern/Match.hs +++ b/booster/library/Booster/Pattern/Match.hs @@ -295,7 +295,6 @@ match1 _ t1@FunctionApplication{} t2@KSet{} match1 Eval (FunctionApplication symbol1 sorts1 args1) (ConsApplication symbol2 sorts2 args2) = matchSymbolAplications Eval symbol1 sorts1 args1 symbol2 sorts2 args2 match1 _ t1@FunctionApplication{} t2@ConsApplication{} = addIndeterminate t1 t2 match1 Eval (FunctionApplication symbol1 sorts1 args1) (FunctionApplication symbol2 sorts2 args2) = matchSymbolAplications Eval symbol1 sorts1 args1 symbol2 sorts2 args2 -match1 Rewrite (FunctionApplication symbol1 sorts1 args1) (FunctionApplication symbol2 sorts2 args2) = matchSymbolAplications Rewrite symbol1 sorts1 args1 symbol2 sorts2 args2 match1 _ t1@FunctionApplication{} t2@FunctionApplication{} = addIndeterminate t1 t2 match1 Rewrite t1@FunctionApplication{} (Var t2) = failWith $ SubjectVariableMatch t1 t2 match1 _ t1@FunctionApplication{} t2@Var{} = addIndeterminate t1 t2 From 3d56118252c1643f891992e19652167b1667ec82 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 7 Aug 2024 09:24:15 +0200 Subject: [PATCH 53/54] Eliminate redundant pattern matches --- booster/tools/booster/Proxy.hs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/booster/tools/booster/Proxy.hs b/booster/tools/booster/Proxy.hs index 969b09ccbc..ee4463eb36 100644 --- a/booster/tools/booster/Proxy.hs +++ b/booster/tools/booster/Proxy.hs @@ -361,9 +361,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of -- continue with the pruned Booster's result case prunedBoosterResult of Left (nextState, newLogs) -> do - let prunedBoosterBranchStep - | boosterResult.reason == Branching = 1 - | otherwise = 0 + let prunedBoosterBranchStep = 1 executionLoop logSettings def @@ -525,9 +523,7 @@ respondEither cfg@ProxyConfig{boosterState} booster kore req = case req of simplifyExecResult logSettings r._module def boosterResult case postExecResult of Left (nextState, newLogs) -> do - let prunedBoosterBranchStep - | boosterResult.reason == Branching = 1 - | otherwise = 0 + let prunedBoosterBranchStep = 0 executionLoop logSettings def From 188075d03f728fbb553d4f9eff7b2abd67139db5 Mon Sep 17 00:00:00 2001 From: Georgy Lukyanov Date: Wed, 7 Aug 2024 09:55:17 +0200 Subject: [PATCH 54/54] hlint --- booster/library/Booster/Pattern/Rewrite.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/booster/library/Booster/Pattern/Rewrite.hs b/booster/library/Booster/Pattern/Rewrite.hs index 3d4f05aecf..cadf33fe52 100644 --- a/booster/library/Booster/Pattern/Rewrite.hs +++ b/booster/library/Booster/Pattern/Rewrite.hs @@ -1,5 +1,4 @@ {-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} @@ -27,7 +26,6 @@ module Booster.Pattern.Rewrite ( import Control.Applicative ((<|>)) import Control.Exception qualified as Exception (throw) import Control.Monad -import Control.Monad.Extra (whenJust) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.Class import Control.Monad.Trans.Except