@@ -63,6 +63,7 @@ import Booster.Pattern.Match (
63
63
MatchResult (MatchFailed , MatchIndeterminate , MatchSuccess ),
64
64
MatchType (Rewrite ),
65
65
SortError ,
66
+ Substitution ,
66
67
matchTerms ,
67
68
)
68
69
import Booster.Pattern.Pretty
@@ -334,61 +335,12 @@ applyRule pat@Pattern{ceilConditions} rule =
334
335
pat
335
336
rule. computedAttributes. notPreservesDefinednessReasons
336
337
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
375
340
376
341
-- check ensures constraints (new) from rhs: stop and return `Trivial` if
377
342
-- 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
392
344
393
345
-- if a new constraint is going to be added, the equation cache is invalid
394
346
unless (null newConstraints) $ do
@@ -438,6 +390,12 @@ applyRule pat@Pattern{ceilConditions} rule =
438
390
failRewrite :: RewriteFailed " Rewrite" -> RewriteRuleAppT (RewriteT io ) a
439
391
failRewrite = lift . (throw)
440
392
393
+ notAppliedIfBottom :: RewriteRuleAppT (RewriteT io ) a
394
+ notAppliedIfBottom = RewriteRuleAppT $ pure NotApplied
395
+
396
+ trivialIfBottom :: RewriteRuleAppT (RewriteT io ) a
397
+ trivialIfBottom = RewriteRuleAppT $ pure Trivial
398
+
441
399
checkConstraint ::
442
400
(Predicate -> a ) ->
443
401
RewriteRuleAppT (RewriteT io ) (Maybe a ) ->
@@ -459,6 +417,72 @@ applyRule pat@Pattern{ceilConditions} rule =
459
417
Left UndefinedTerm {} -> onBottom
460
418
Left _ -> pure $ Just $ onUnclear p
461
419
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
+
462
486
{- | Reason why a rewrite did not produce a result. Contains additional
463
487
information for logging what happened during the rewrite.
464
488
-}
0 commit comments