{-# LANGUAGE FlexibleContexts #-}
module Control.Search.Combinator.Repeat (repeat) where
import Prelude hiding (lex, until, init, repeat)
import Control.Search.Language
import Control.Search.GeneratorInfo
import Control.Search.Generator
import Control.Search.MemoReader
import Control.Search.Memo
import Control.Monatron.Monatron hiding (Abort, L, state, cont)
import Control.Monatron.Zipper hiding (i,r)
repeatLoop :: (ReaderM Bool m, Evalable m) => Int -> Eval m -> Eval m
repeatLoop uid super = commentEval $
Eval
{
structs = structs super @++@ mystructs
, toString = "repeat" ++ show uid ++ "(" ++ toString super ++ ")"
, treeState_ = ("dummy", Int,
\i -> do cc <- cachedClone i (cloneBase i)
return ((parent i <== baseTstate i)
>>> cc
)
) : treeState_ super
, initH = \i -> initE super i
, evalState_ = ("ref_count",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 = tryE super
, startTryH = startTryE super
, tryLH = \i -> tryE_ super i @>>>@ dec_ref i
, boolArraysE = boolArraysE super
, intArraysE = intArraysE super
, intVarsE = intVarsE super
, deleteH = error "repeatLoop.deleteE NOT YET IMPLEMENTED"
, canBranch = canBranch super
, complete = const $ return true
}
where mystructs = ([],[])
fs1 = [(field,init) | (field,ty,init) <- evalState_ super]
parent = \i -> estate i @=> "parent"
dec_ref = \i -> let i' = resetCommit $ i `withBase` ("repeat_tstate" ++ show uid)
in do flag <- ask
if flag
then local (const False) $ do
stmt1 <- inits super i'
stmt2 <- startTryE super i'
ini <- inite fs1 i'
return (dec (ref_count i)
>>> ifthen (ref_count i @== 0)
( SHook ("TreeState repeat_tstate" ++ show uid ++ ";")
>>> (baseTstate i' <== parent i)
>>> clone (cloneBase i) i'
>>> (ref_count i' <== 1)
>>> ini >>> stmt1 >>> stmt2))
else return $dec (ref_count i) >>> ifthen (ref_count i @== 0) (comment "Delete-repeatLoop-dec_ref" >>> Delete (space $ cloneBase i))
push dir = \i -> dir super (i `onCommit` inc (ref_count i))
repeat
:: Search
-> Search
repeat 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) $ repeatLoop uid $ mapE runL s'
}
, runsearch = runs . rReaderT True . runL
}