@@ -198,14 +198,15 @@ rewriteStep cutLabels terminalLabels pat = do
198
198
processGroups rest >>= \ case
199
199
RewriteStuck {} -> pure $ RewriteTrivial pat
200
200
other -> pure other
201
- AppliedRules ([] , _remainder) -> processGroups rest
201
+ AppliedRules ([] , _remainder) ->
202
+ -- TODO check that remainder is trivial, abort otherwise
203
+ processGroups rest
202
204
AppliedRules ([(rule, newPat, _subst)], remainder)
203
205
| not (Set. null remainder) && not (any isFalse remainder) -> do
204
206
-- a non-trivial remainder with a single applicable rule is
205
207
-- an indication if semantics incompleteness: abort
206
208
-- TODO refactor remainder check into a function and reuse below
207
209
solver <- getSolver
208
- logMessage (show (SMT. options solver))
209
210
satRes <- SMT. isSat solver (Set. toList $ pat. constraints <> remainder)
210
211
throw $
211
212
RewriteRemainderPredicate [rule] satRes . coerce . foldl1 AndTerm $
@@ -219,114 +220,70 @@ rewriteStep cutLabels terminalLabels pat = do
219
220
| otherwise ->
220
221
pure $ RewriteFinished (Just $ ruleLabelOrLocT rule) (Just $ uniqueId rule) newPat
221
222
AppliedRules (xs, remainder) -> do
222
- ModifiersRep (_ :: FromModifiersT mods => Proxy mods ) <- getPrettyModifiers
223
- let remainderForLogging = coerce . foldl1 AndTerm $ map coerce . Set. toList $ remainder
224
223
-- multiple rules apply, analyse brunching and remainders
225
224
if any isFalse remainder
226
225
then do
227
- withContext CtxRemainder . withContext CtxContinue
228
- $ logMessage
229
- $ WithJsonMessage
230
- ( object
231
- [ " remainder"
232
- .= externalisePredicate (externaliseSort $ sortOfPattern pat) remainderForLogging
233
- ]
234
- )
235
- $ renderOneLineText
236
- $ pretty' @ mods (RewriteRemainderPredicate (map (\ (r, _, _) -> r) xs) SMT. IsUnsat remainderForLogging)
226
+ logRemainder (map (\ (r, _, _) -> r) xs) SMT. IsUnsat remainder
237
227
-- the remainder predicate is trivially false, return the branching result
238
- pure $
239
- RewriteBranch pat $
240
- NE. fromList $
241
- map (\ (r, p, subst) -> (ruleLabelOrLocT r, uniqueId r, p, mkRulePredicate r subst, subst)) xs
228
+ pure $ mkBranch pat xs
242
229
else do
243
230
-- otherwise, we need to check the remainder predicate with the SMT solver
244
231
-- and construct an additional remainder branch if needed
245
232
solver <- getSolver
246
233
SMT. isSat solver (Set. toList $ pat. constraints <> remainder) >>= \ case
247
234
SMT. IsUnsat -> do
248
235
-- the remainder condition is unsatisfiable: no need to consider the remainder branch.
249
- withContext CtxRemainder . withContext CtxContinue
250
- $ logMessage
251
- $ WithJsonMessage
252
- ( object
253
- [ " remainder"
254
- .= externalisePredicate (externaliseSort $ sortOfPattern pat) (coerce remainderForLogging)
255
- ]
256
- )
257
- $ renderOneLineText
258
- $ pretty' @ mods (RewriteRemainderPredicate (map (\ (r, _, _) -> r) xs) SMT. IsUnsat remainderForLogging)
259
- pure $
260
- RewriteBranch pat $
261
- NE. fromList $
262
- map (\ (r, p, subst) -> (ruleLabelOrLocT r, uniqueId r, p, mkRulePredicate r subst, subst)) xs
236
+ logRemainder (map (\ (r, _, _) -> r) xs) SMT. IsUnsat remainder
237
+ pure $ mkBranch pat xs
263
238
satRes@ (SMT. IsSat {}) -> do
264
239
-- the remainder condition is satisfiable.
265
- -- Have to construct the remainder branch and consider it
240
+ -- TODO construct the remainder branch and consider it
266
241
-- To construct the "remainder pattern",
267
242
-- we add the remainder condition to the predicates of the @pattr@
268
- -- (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules
269
- let rs = map (\ (r, _p, _subst) -> r) xs
270
- throw $
271
- RewriteRemainderPredicate rs satRes . coerce . foldl1 AndTerm $
272
- map coerce . Set. toList $
273
- remainder
243
+ throwRemainder (map (\ (r, _p, _subst) -> r) xs) satRes remainder
274
244
satRes@ SMT. IsUnknown {} -> do
275
- -- solver cannot solve the remainder. Descend into the remainder branch anyway
276
- -- (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules
277
- let rs = map (\ (r, _p, _subst) -> r) xs
278
- throw $
279
- RewriteRemainderPredicate rs satRes . coerce . foldl1 AndTerm $
280
- map coerce . Set. toList $
281
- remainder
282
-
283
- -- if any isFalse remainder -- no need to call SMT if any of the conditions is trivially false
284
- -- then do
285
- -- -- setRemainder mempty
286
- -- pure xs
287
- -- else do
288
- -- solver <- getSolver
289
- -- SMT.isSat solver (pat.constraints <> remainder) >>= \case
290
- -- SMT.IsUnsat -> do
291
- -- -- the remainder condition is unsatisfiable: no need to consider the remainder branch.
292
- -- setRemainder mempty
293
- -- withContext CtxRemainder $ logMessage ("remainder is UNSAT" :: Text)
294
- -- pure resultsWithoutRemainders
295
- -- SMT.IsSat _ -> do
296
- -- withContext CtxRemainder $ logMessage ("remainder is SAT" :: Text)
297
- -- -- the remainder condition is satisfiable.
298
- -- -- Have to construct the remainder branch and consider it
299
- -- -- To construct the "remainder pattern",
300
- -- -- we add the remainder condition to the predicates of the @pattr@
301
- -- (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules
302
- -- SMT.IsUnknown{} -> do
303
- -- withContext CtxRemainder $ logMessage ("remainder is UNKNWON" :: Text)
304
- -- -- solver cannot solve the remainder. Descend into the remainder branch anyway
305
- -- (resultsWithoutRemainders <>) <$> processGroups lowerPriorityRules
306
-
307
- -- _ -> case concatMap (\case Applied x -> [x]; _ -> []) results of
308
- -- [] ->
309
- -- -- all remaining branches are trivial, i.e. rules which did apply had an ensures condition which evaluated to false
310
- -- -- if, all the other groups only generate a not applicable or trivial rewrites,
311
- -- -- then we return a `RewriteTrivial`.
312
- -- processGroups rest >>= \case
313
- -- RewriteStuck{} -> pure $ RewriteTrivial pat
314
- -- other -> pure other
315
- -- -- all branches but one were either not applied or trivial
316
- -- [(r, (x, _remainder, _subst))]
317
- -- | labelOf r `elem` cutLabels ->
318
- -- pure $ RewriteCutPoint (labelOf r) (uniqueId r) pat x
319
- -- | labelOf r `elem` terminalLabels ->
320
- -- pure $ RewriteTerminal (labelOf r) (uniqueId r) x
321
- -- | otherwise ->
322
- -- pure $ RewriteFinished (Just $ ruleLabelOrLocT r) (Just $ uniqueId r) x
323
- -- -- at this point, there were some Applied rules and potentially some Trivial ones.
324
- -- -- here, we just return all the applied rules in a `RewriteBranch`
325
- -- rxs ->
326
- -- pure $
327
- -- RewriteBranch pat $
328
- -- NE.fromList $
329
- -- map (\(r, (p, _remainder, _subst)) -> (ruleLabelOrLocT r, uniqueId r, p)) rxs
245
+ -- solver cannot solve the remainder
246
+ -- TODO descend into the remainder branch anyway
247
+ throwRemainder (map (\ (r, _p, _subst) -> r) xs) satRes remainder
248
+
249
+ mkBranch :: Pattern -> [(RewriteRule " Rewrite" , Pattern , Substitution )] -> RewriteResult Pattern
250
+ mkBranch base leafs =
251
+ let ruleLabelOrLocT = renderOneLineText . ruleLabelOrLoc
252
+ uniqueId = (. uniqueId) . (. attributes)
253
+ in RewriteBranch base $
254
+ NE. fromList $
255
+ map (\ (r, p, subst) -> (ruleLabelOrLocT r, uniqueId r, p, mkRulePredicate r subst, subst)) leafs
256
+
257
+ -- abort rewriting by throwing a remainder predicate as an exception, to be caught and processed in @performRewrite@
258
+ throwRemainder ::
259
+ LoggerMIO io => [RewriteRule " Rewrite" ] -> SMT. IsSatResult () -> Set. Set Predicate -> RewriteT io a
260
+ throwRemainder rules satResult remainderPredicate =
261
+ throw $
262
+ RewriteRemainderPredicate rules satResult . coerce . foldl1 AndTerm $
263
+ map coerce . Set. toList $
264
+ remainderPredicate
265
+
266
+ -- log a remainder predicate as an exception without aborting rewriting
267
+ logRemainder ::
268
+ LoggerMIO io => [RewriteRule " Rewrite" ] -> SMT. IsSatResult () -> Set. Set Predicate -> RewriteT io ()
269
+ logRemainder rules satResult remainderPredicate = do
270
+ ModifiersRep (_ :: FromModifiersT mods => Proxy mods ) <- getPrettyModifiers
271
+ let remainderForLogging = coerce . foldl1 AndTerm $ map coerce . Set. toList $ remainderPredicate
272
+ withContext CtxRemainder . withContext CtxContinue
273
+ $ logMessage
274
+ $ WithJsonMessage
275
+ ( object
276
+ [ " remainder"
277
+ .= externalisePredicate (externaliseSort $ sortOfPattern pat) (coerce remainderForLogging)
278
+ ]
279
+ )
280
+ $ renderOneLineText
281
+ $ pretty' @ mods
282
+ ( RewriteRemainderPredicate
283
+ rules
284
+ satResult
285
+ remainderForLogging
286
+ )
330
287
331
288
-- | Rewrite rule application transformer: may throw exceptions on non-applicable or trivial rule applications
332
289
type RewriteRuleAppT m a = ExceptT RewriteRuleAppException m a
0 commit comments