{-# LANGUAGE FlexibleContexts #-}
module Control.Search.Combinator.OrRepeat (orRepeat) where
import Control.Search.Language
import Control.Search.GeneratorInfo
import Control.Search.Generator
import Control.Search.MemoReader
import Control.Search.Memo
import Control.Search.Stat
import Control.Monatron.Monatron hiding (Abort, L, state, cont)
import Control.Monatron.Zipper hiding (i,r)
orRepeatLoop :: (Evalable m, ReaderM Bool m) => Stat -> Int -> Eval m -> Eval m
orRepeatLoop cond uid super' = commentEval $
Eval
{
structs = structs super @++@ mystructs
, treeState_ = treeState_ super
, toString = "orRepeat" ++ show uid ++ "(" ++ toString super' ++ ")"
, initH = \i -> initE super i @>>>@ return (parent i <== baseTstate i) @>>>@ cachedClone i (cloneBase i)
, evalState_ = ("ref_count_orr" ++ show uid,Int,const $ return 1) : ("parent",THook "TreeState",const $ return Null) : evalState_ super
, pushLeftH = push pushLeft
, pushRightH = push pushRight
, nextSameH = nextSame super
, nextDiffH = nextDiff super
, bodyH = \i -> dec_ref i >>= \deref -> bodyE super (i `onAbort` deref)
, addH = addE super
, failH = \i -> failE super i @>>>@ dec_ref i
, returnH = \i -> let j deref = i `onCommit` deref
in dec_ref i >>= returnE super . j
, tryH = \i -> do deref <- dec_ref i
tryE super (i `onAbort` deref)
, startTryH = \i -> do deref <- dec_ref i
startTryE super (i `onAbort` deref)
, tryLH = \i -> tryE_ super i @>>>@ dec_ref i
, intArraysE = intArraysE super
, boolArraysE = boolArraysE super
, intVarsE = intVarsE super
, deleteH = error "orRepeatLoop.deleteE NOT YET IMPLEMENTED"
, canBranch = return True
, complete = complete super
}
where mystructs = ([],[])
super = evalStat cond super'
fs1 = [(field,init) | (field,ty,init) <- evalState_ super]
parent = \i -> estate i @=> "parent"
dec_ref = \i -> let i' = resetAbort $ resetCommit $ i `withBase` ("orr_tstate" ++ show uid)
ii = resetAbort $ resetCommit $ i
in do flag <- ask
if flag
then local (const False) $ do
stmt1 <- inits super i'
stmt2 <- startTryE super i'
r <- readStat cond
ini <- inite fs1 i'
cc1 <- cachedClone (i { baseTstate = parent ii} ) i'
compl <- complete super ii
return (dec (ref_countx ii $ "orr" ++ show uid)
>>> ifthen (ref_countx ii ("orr" ++ show uid) @== 0)
(ifthen (r i' &&& Not compl)
( SHook ("TreeState orr_tstate" ++ show uid ++ ";")
>>> (baseTstate i' <== parent ii)
>>> cc1
>>> (ref_countx i' ("orr" ++ show uid) <== 1)
>>> ini >>> stmt1 >>> stmt2)
))
else return $ dec (ref_countx ii ("orr" ++ show uid)) >>> ifthen (ref_countx ii ("orr" ++ show uid) @== 0) (comment "orRepeatLoop-dec_ref-Delete" >>> Delete (space $ cloneBase ii))
push dir = \i -> dir super (i `onCommit'` inc (ref_countx i $ "orr" ++ show uid))
orRepeat
:: Stat
-> Search
-> Search
orRepeat cond s =
case s of
Search { mkeval = evals, runsearch = runs } ->
Search { mkeval =
\super ->
do { uid <- get
; put (uid + 1)
; s' <- evals $ mapE (L . L . mmap runL . runL) super
; return $ mapE (L . mmap L . runL) $ orRepeatLoop cond uid (mapE runL s')
}
, runsearch = runs . rReaderT True . runL
}