@@ -63,6 +63,7 @@ import Booster.Pattern.Match (
6363 MatchResult (MatchFailed , MatchIndeterminate , MatchSuccess ),
6464 MatchType (Rewrite ),
6565 SortError ,
66+ Substitution ,
6667 matchTerms ,
6768 )
6869import Booster.Pattern.Pretty
@@ -334,61 +335,12 @@ applyRule pat@Pattern{ceilConditions} rule =
334335 pat
335336 rule. computedAttributes. notPreservesDefinednessReasons
336337
337- -- apply substitution to rule requires constraints and simplify (one by one
338- -- in isolation). Stop if false, abort rewrite if indeterminate.
339- let ruleRequires =
340- concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) rule. requires
341- notAppliedIfBottom = RewriteRuleAppT $ pure NotApplied
342- -- filter out any predicates known to be _syntactically_ present in the known prior
343- let prior = pat. constraints
344- toCheck <- lift $ filterOutKnownConstraints prior ruleRequires
345-
346- unclearRequires <-
347- catMaybes <$> mapM (checkConstraint id notAppliedIfBottom prior) toCheck
348-
349- -- unclear conditions may have been simplified and
350- -- could now be syntactically present in the path constraints, filter again
351- stillUnclear <- lift $ filterOutKnownConstraints prior unclearRequires
352-
353- -- check unclear requires-clauses in the context of known constraints (prior)
354- solver <- lift $ RewriteT $ (. smtSolver) <$> ask
355-
356- let smtUnclear = do
357- withContext CtxConstraint . withContext CtxAbort . logMessage $
358- WithJsonMessage (object [" conditions" .= (externaliseTerm . coerce <$> stillUnclear)]) $
359- renderOneLineText $
360- " Uncertain about condition(s) in a rule:"
361- <+> (hsep . punctuate comma . map (pretty' @ mods ) $ stillUnclear)
362- failRewrite $
363- RuleConditionUnclear rule . coerce . foldl1 AndTerm $
364- map coerce stillUnclear
365-
366- SMT. checkPredicates solver prior mempty (Set. fromList stillUnclear) >>= \ case
367- SMT. IsUnknown {} ->
368- smtUnclear -- abort rewrite if a solver result was Unknown
369- SMT. IsInvalid -> do
370- -- requires is actually false given the prior
371- withContext CtxFailure $ logMessage (" Required clauses evaluated to #Bottom." :: Text )
372- RewriteRuleAppT $ pure NotApplied
373- SMT. IsValid ->
374- pure () -- can proceed
338+ -- check required constraints from lhs: Stop if any is false, abort rewrite if indeterminate.
339+ checkRequires subst
375340
376341 -- check ensures constraints (new) from rhs: stop and return `Trivial` if
377342 -- any are false, remove all that are trivially true, return the rest
378- let ruleEnsures =
379- concatMap (splitBoolPredicates . coerce . substituteInTerm subst . coerce) $
380- Set. toList rule. ensures
381- trivialIfBottom = RewriteRuleAppT $ pure Trivial
382- newConstraints <-
383- catMaybes <$> mapM (checkConstraint id trivialIfBottom prior) ruleEnsures
384-
385- -- check all new constraints together with the known side constraints
386- (lift $ SMT. checkPredicates solver prior mempty (Set. fromList newConstraints)) >>= \ case
387- SMT. IsInvalid -> do
388- withContext CtxSuccess $ logMessage (" New constraints evaluated to #Bottom." :: Text )
389- RewriteRuleAppT $ pure Trivial
390- _other ->
391- pure ()
343+ newConstraints <- checkEnsures subst
392344
393345 -- if a new constraint is going to be added, the equation cache is invalid
394346 unless (null newConstraints) $ do
@@ -438,6 +390,12 @@ applyRule pat@Pattern{ceilConditions} rule =
438390 failRewrite :: RewriteFailed " Rewrite" -> RewriteRuleAppT (RewriteT io ) a
439391 failRewrite = lift . (throw)
440392
393+ notAppliedIfBottom :: RewriteRuleAppT (RewriteT io ) a
394+ notAppliedIfBottom = RewriteRuleAppT $ pure NotApplied
395+
396+ trivialIfBottom :: RewriteRuleAppT (RewriteT io ) a
397+ trivialIfBottom = RewriteRuleAppT $ pure Trivial
398+
441399 checkConstraint ::
442400 (Predicate -> a ) ->
443401 RewriteRuleAppT (RewriteT io ) (Maybe a ) ->
@@ -459,6 +417,72 @@ applyRule pat@Pattern{ceilConditions} rule =
459417 Left UndefinedTerm {} -> onBottom
460418 Left _ -> pure $ Just $ onUnclear p
461419
420+ checkRequires ::
421+ Substitution -> RewriteRuleAppT (RewriteT io ) ()
422+ checkRequires matchingSubst = do
423+ ModifiersRep (_ :: FromModifiersT mods => Proxy mods ) <- getPrettyModifiers
424+ -- apply substitution to rule requires
425+ let ruleRequires =
426+ concatMap (splitBoolPredicates . coerce . substituteInTerm matchingSubst . coerce) rule. requires
427+
428+ -- filter out any predicates known to be _syntactically_ present in the known prior
429+ toCheck <- lift $ filterOutKnownConstraints pat. constraints ruleRequires
430+
431+ -- simplify the constraints (one by one in isolation). Stop if false, abort rewrite if indeterminate.
432+ unclearRequires <-
433+ catMaybes <$> mapM (checkConstraint id notAppliedIfBottom pat. constraints) toCheck
434+
435+ -- unclear conditions may have been simplified and
436+ -- could now be syntactically present in the path constraints, filter again
437+ stillUnclear <- lift $ filterOutKnownConstraints pat. constraints unclearRequires
438+
439+ -- check unclear requires-clauses in the context of known constraints (priorKnowledge)
440+ solver <- lift $ RewriteT $ (. smtSolver) <$> ask
441+ let smtUnclear = do
442+ withContext CtxConstraint . withContext CtxAbort . logMessage $
443+ WithJsonMessage (object [" conditions" .= (externaliseTerm . coerce <$> stillUnclear)]) $
444+ renderOneLineText $
445+ " Uncertain about condition(s) in a rule:"
446+ <+> (hsep . punctuate comma . map (pretty' @ mods ) $ stillUnclear)
447+ failRewrite $
448+ RuleConditionUnclear rule . coerce . foldl1 AndTerm $
449+ map coerce stillUnclear
450+ SMT. checkPredicates solver pat. constraints mempty (Set. fromList stillUnclear) >>= \ case
451+ SMT. IsUnknown {} ->
452+ smtUnclear -- abort rewrite if a solver result was Unknown
453+ SMT. IsInvalid -> do
454+ -- requires is actually false given the prior
455+ withContext CtxFailure $ logMessage (" Required clauses evaluated to #Bottom." :: Text )
456+ RewriteRuleAppT $ pure NotApplied
457+ SMT. IsValid ->
458+ pure () -- can proceed
459+ checkEnsures ::
460+ Substitution -> RewriteRuleAppT (RewriteT io ) [Predicate ]
461+ checkEnsures matchingSubst = do
462+ -- apply substitution to rule requires
463+ let ruleEnsures =
464+ concatMap (splitBoolPredicates . coerce . substituteInTerm matchingSubst . coerce) $
465+ Set. toList rule. ensures
466+ newConstraints <-
467+ catMaybes <$> mapM (checkConstraint id trivialIfBottom pat. constraints) ruleEnsures
468+
469+ -- check all new constraints together with the known side constraints
470+ solver <- lift $ RewriteT $ (. smtSolver) <$> ask
471+ (lift $ SMT. checkPredicates solver pat. constraints mempty (Set. fromList newConstraints)) >>= \ case
472+ SMT. IsInvalid -> do
473+ withContext CtxSuccess $ logMessage (" New constraints evaluated to #Bottom." :: Text )
474+ RewriteRuleAppT $ pure Trivial
475+ _other ->
476+ pure ()
477+
478+ -- if a new constraint is going to be added, the equation cache is invalid
479+ unless (null newConstraints) $ do
480+ withContextFor Equations . logMessage $
481+ (" New path condition ensured, invalidating cache" :: Text )
482+
483+ lift . RewriteT . lift . modify $ \ s -> s{equations = mempty }
484+ pure newConstraints
485+
462486{- | Reason why a rewrite did not produce a result. Contains additional
463487 information for logging what happened during the rewrite.
464488-}
0 commit comments