module Data.Generics.Strafunski.StrategyLib.ContainerTheme (
module Data.Generics.Strafunski.StrategyLib.ContainerTheme,
) where
import Data.Generics.Strafunski.StrategyLib.StrategyPrelude
import Control.Monad
import Data.Monoid
modify :: Eq x => (x -> y) -> x -> y -> (x -> y)
modify f x y = \x' -> if x == x' then y else f x'
modifyTP :: (MonadPlus m, Eq t, Term t) => TP m -> t -> m t -> TP m
modifyTP f t = adhocTP f . modify (applyTP f) t
modifyTU :: (MonadPlus m, Eq t, Term t) => TU a m -> t -> m a -> TU a m
modifyTU f t = adhocTU f . modify (applyTU f) t
type GSet = TU () Maybe
emptyGSet :: GSet
emptyGSet = failTU
fullGSet :: GSet
fullGSet = constTU mempty
addGSet :: (Eq t, Term t) => t -> GSet -> GSet
addGSet t s = modifyTU s t (return mempty)
removeGSet :: (Eq t, Term t) => t -> GSet -> GSet
removeGSet t s = modifyTU s t mzero
containsGSet :: (Eq t, Term t) => t -> GSet -> Bool
containsGSet t s= maybe False (const True) (applyTU s t)
type GMap value = TU value Maybe
emptyGMap :: GMap v
emptyGMap = failTU
removeGMap :: (Eq t, Term t) => t -> GMap v -> GMap v
removeGMap t s = modifyTU s t mzero
containsGMap :: (Eq t, Term t) => t -> GMap v -> Bool
containsGMap t s= maybe False (const True) (applyTU s t)
putGMap :: (Eq t, Term t) => t -> v -> GMap v -> GMap v
putGMap t v s = modifyTU s t (return v)
getGMap :: (Eq t, Term t) => t -> GMap v -> Maybe v
getGMap t s = applyTU s t
type GList = (Integer -> TP Maybe,Integer)
sizeGList (_,i) = i
indxGList (f,_) = f
emptyGList :: GList
emptyGList = (const failTP,0)
addGList :: Term t => t -> GList -> GList
addGList t l = (modify f s e,s+1)
where s = sizeGList l
f = indxGList l
e = monoTP (const (return t))
putGList :: Term t => Integer -> t -> GList -> GList
putGList i t l = if i < s then (modify f i e,s)
else l
where s = sizeGList l
f = indxGList l
e = monoTP (const (return t))
getGList :: Term t => Integer -> GList -> Maybe t
getGList i l = if i < s then applyTP (f i) undefined
else Nothing
where f = indxGList l
s = sizeGList l
mapGListTP :: TP Maybe -> GList -> GList
mapGListTP s l = (nth (map forElem [0..size1]),size)
where forElem :: Integer -> TP Maybe
forElem i = (indxGList l i) `seqTP` s
size = sizeGList l
mapGListTU :: Term t => (t -> ()) -> TU a Maybe -> GList -> [Maybe a]
mapGListTU g s l= map forElem [0..size1]
where forElem i
= applyTU ((indxGList l i) `seqTU` s) t
size = sizeGList l
(t,()) = (undefined,g t)
elemsGList :: Term t => (t -> ()) -> GList -> [t]
elemsGList g l = filterJust (map forElem [0..size1])
where forElem i
= applyTP (indxGList l i) t
size = sizeGList l
(t,()) = (error "NOTERM",g t)
filterJust as = map unJust (filter isJust as)
unJust (Just t) = t
isJust (Just _) = True
isJust Nothing = False
nth :: [a] -> Integer -> a
nth (x:_) 0 = x
nth (_:xs) n | n>0 = nth xs (n1)
nth (_:_) _ = error "ContainterTheme.nth: negative index"
nth [] _ = error "ContainerTheme.nth: index too large"
type Coder = (Int,TU Int Maybe)
noCode :: Coder
noCode = (0,failTU)
getCode :: Term x => Coder -> x -> Maybe Int
getCode (_,s) = applyTU s
setCode :: (Term x, Eq x) => Coder -> x -> Int -> Coder
setCode (i,s) x i' = (i,modifyTU s x (return i'))
nextCode :: Coder -> (Int,Coder)
nextCode (i,s) = (i,(i+1,s))
enCode :: (Term x, Eq x) => Coder -> x -> Coder
enCode c x = maybe gen found (getCode c x)
where
gen = let (i,c') = nextCode c
in setCode c' x i
found = const c