module Ideas.Common.Strategy.Abstract
( Strategy, IsStrategy(..)
, LabeledStrategy, label, unlabel
, derivationList
, emptyPrefix, replayPath, replayPaths, replayStrategy
, rulesInStrategy
, mapRules, mapRulesS
, cleanUpStrategy, cleanUpStrategyAfter
, toCore, fromCore, liftCore, liftCore2
, noInterleaving
) where
import Data.Function
import Ideas.Common.Classes
import Ideas.Common.Derivation
import Ideas.Common.Environment
import Ideas.Common.Id
import Ideas.Common.Rewriting (RewriteRule)
import Ideas.Common.Rule
import Ideas.Common.Strategy.Core
import Ideas.Common.Strategy.Parsing
import Ideas.Common.Strategy.Sequence (Firsts(..), firstsOrdered)
import Ideas.Common.Utils.Uniplate hiding (rewriteM)
import Ideas.Common.View
newtype Strategy a = S (Core a)
instance Show (Strategy a) where
show = show . toCore
instance Apply Strategy where
applyAll = runCore . toCore
class IsStrategy f where
toStrategy :: f a -> Strategy a
instance IsStrategy Strategy where
toStrategy = id
instance IsStrategy (LabeledStrategy) where
toStrategy (LS info (S core)) = S (Label info core)
instance IsStrategy Rule where
toStrategy = S . Rule
instance IsStrategy RewriteRule where
toStrategy = toStrategy . ruleRewrite
data LabeledStrategy a = LS Id (Strategy a)
instance Show (LabeledStrategy a) where
show s = showId s ++ ": " ++ show (unlabel s)
instance Apply LabeledStrategy where
applyAll = applyAll . toStrategy
instance HasId (LabeledStrategy a) where
getId (LS l _) = l
changeId f (LS l s) = LS (changeId f l) s
label :: (IsId l, IsStrategy f) => l -> f a -> LabeledStrategy a
label l = LS (newId l) . toStrategy
unlabel :: LabeledStrategy a -> Strategy a
unlabel (LS _ s) = s
emptyPrefix :: IsStrategy f => f a -> a -> Prefix a
emptyPrefix = makePrefix . toCore
replayPath :: IsStrategy f => Path -> f a -> a -> ([Step a], Prefix a)
replayPath path s a =
let (xs, f) = replayCore path (toCore s)
in (xs, f a)
replayPaths :: IsStrategy f => [Path] -> f a -> a -> Prefix a
replayPaths paths s a = mconcat
[ snd (replayPath path s a) | path <- paths ]
replayStrategy :: (Monad m, IsStrategy f) => Path -> f a -> a -> m (a, Prefix a)
replayStrategy path s a =
let (xs, f) = replayCore path (toCore s)
in case applyList xs a of
Just b -> return (b, f b)
Nothing -> fail "Cannot replay strategy"
derivationList :: IsStrategy f => (Rule a -> Rule a -> Ordering) -> f a -> a -> [Derivation (Rule a, Environment) a]
derivationList cmpRule s a0 = rec a0 (toPrefix s)
where
toPrefix = majorPrefix . flip makePrefix a0 . toCore
rec a prfx = (if ready prfx then (emptyDerivation a:) else id)
[ prepend (a, rEnv) d | (rEnv, b, new) <- firstsOrd prfx, d <- rec b new ]
firstsOrd = map f . firstsOrdered cmp
where
cmp = cmpRule `on` (fst . g . fst)
f ((stp, b), new) = (g stp, b, new)
g stp = (stepRule stp, stepEnvironment stp)
rulesInStrategy :: IsStrategy f => f a -> [Rule a]
rulesInStrategy s = [ r | Rule r <- universe (toCore s), isMajor r ]
instance LiftView LabeledStrategy where
liftViewIn = mapRules . liftViewIn
instance LiftView Strategy where
liftViewIn = mapRulesS . liftViewIn
mapRules :: (Rule a -> Rule b) -> LabeledStrategy a -> LabeledStrategy b
mapRules f (LS n s) = LS n (mapRulesS f s)
mapRulesS :: (Rule a -> Rule b) -> Strategy a -> Strategy b
mapRulesS f = S . fmap f . toCore
cleanUpStrategy :: (a -> a) -> LabeledStrategy a -> LabeledStrategy a
cleanUpStrategy f (LS n s) = cleanUpStrategyAfter f (LS n (make s))
where
make = liftCore2 (:*:) (doAfter f (idRule ()))
cleanUpStrategyAfter :: (a -> a) -> LabeledStrategy a -> LabeledStrategy a
cleanUpStrategyAfter f = mapRules $ \r ->
if isMajor r then doAfter f r else r
noInterleaving :: IsStrategy f => f a -> Strategy a
noInterleaving = liftCore $ transform f
where
f (a :%: b) = a :*: b
f (Atomic a) = a
f s = s
toCore :: IsStrategy f => f a -> Core a
toCore s = let S core = toStrategy s in core
fromCore :: Core a -> Strategy a
fromCore = S
liftCore :: IsStrategy f => (Core a -> Core a) -> f a -> Strategy a
liftCore f = fromCore . f . toCore
liftCore2 :: (IsStrategy f, IsStrategy g) => (Core a -> Core a -> Core a) -> f a -> g a -> Strategy a
liftCore2 f = liftCore . f . toCore