ideas-0.6: src/Common/Strategy/Location.hs
-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-- Locations in a strategy
--
-----------------------------------------------------------------------------
module Common.Strategy.Location
( StrategyLocation, topLocation, nextLocation, downLocation
, locationDepth
, subTaskLocation, nextTaskLocation, parseStrategyLocation
, StrategyOrRule, strategyLocations, subStrategy, addLocation
) where
import Common.Strategy.Abstract
import Common.Strategy.Core
import Common.Transformation
import Common.Uniplate
import Common.Utils (readM)
import Data.Foldable (toList)
import Data.Sequence hiding (take)
import Control.Monad.State
-----------------------------------------------------------
--- Strategy locations
-- | A strategy location corresponds to a substrategy or a rule
newtype StrategyLocation = SL (Seq Int)
deriving Eq
instance Show StrategyLocation where
show (SL xs) = show (toList xs)
type StrategyOrRule a = Either (LabeledStrategy a) (Rule a)
topLocation :: StrategyLocation
topLocation = SL empty
nextLocation :: StrategyLocation -> StrategyLocation
nextLocation (SL xs) =
case viewr xs of
EmptyR -> topLocation -- invalid
ys :> a -> SL (ys |> (a+1))
downLocation :: StrategyLocation -> StrategyLocation
downLocation (SL xs) = SL (xs |> 0)
locationDepth :: StrategyLocation -> Int
locationDepth (SL xs) = Data.Sequence.length xs
-- old (current) and actual (next major rule) location
subTaskLocation :: StrategyLocation -> StrategyLocation -> StrategyLocation
subTaskLocation (SL xs) (SL ys) = SL (rec xs ys)
where
rec xs ys =
case (viewl xs, viewl ys) of
(i :< is, j :< js)
| i == j -> i <| rec is js
| otherwise -> empty
(_, j :< _) -> singleton j
_ -> empty
-- old (current) and actual (next major rule) location
nextTaskLocation :: StrategyLocation -> StrategyLocation -> StrategyLocation
nextTaskLocation (SL xs) (SL ys) = SL (rec xs ys)
where
rec xs ys =
case (viewl xs, viewl ys) of
(i :< is, j :< js)
| i == j -> i <| rec is js
| otherwise -> singleton j
_ -> empty
parseStrategyLocation :: String -> Maybe StrategyLocation
parseStrategyLocation = fmap (SL . fromList) . readM
-- | Returns a list of all strategy locations, paired with the labeled
-- substrategy or rule at that location
strategyLocations :: LabeledStrategy a -> [(StrategyLocation, StrategyOrRule a)]
strategyLocations = collect . addLocation . toCore . toStrategy
where
collect core =
case core of
Label (loc, info) s ->
let this = makeLabeledStrategy info (mapLabel snd s)
in (loc, Left this) : collect s
Rule (Just (loc, _)) r ->
[(loc, Right r)]
_ ->
concatMap collect (children core)
-- | Returns the substrategy or rule at a strategy location. Nothing
-- indicates that the location is invalid
subStrategy :: StrategyLocation -> LabeledStrategy a -> Maybe (StrategyOrRule a)
subStrategy loc = lookup loc . strategyLocations
-- local helper functions that decorates interesting places with a
-- strategy lcations (major rules, and labels)
addLocation :: Core l a -> Core (StrategyLocation, l) a
addLocation = flip evalState topLocation . mapCoreM forLabel forRule
where
forLabel l ma = do
loc <- get
put (downLocation loc)
rest <- ma
put (nextLocation loc)
return (Label (loc, l) rest)
forRule (Just l) r = do
loc <- get
put (nextLocation loc)
return (Rule (Just (loc, l)) r)
forRule Nothing r =
return (Rule Nothing r)