{-# LANGUAGE FlexibleContexts #-}
module Control.Search.Combinator.For (for, foreach) where
import Control.Search.Language
import Control.Search.GeneratorInfo
import Control.Search.Generator
import Control.Search.Memo
import Control.Search.MemoReader
import Data.Int
import Control.Monatron.Zipper hiding (i,r)
import Control.Monatron.Monatron hiding (Abort, L, state, cont)
forLoop :: (ReaderM Bool m, Evalable m) => Int32 -> Int -> (Eval m) -> Eval m
forLoop n uid (super) = commentEval $
Eval
{
structs = structs super @++@ mystructs
, toString = "for" ++ show uid ++ "(" ++ show n ++ "," ++ toString super ++ ")"
, treeState_ = treeState_ super
, initH = \i -> initE super i @>>>@ return (parent i <== baseTstate i) @>>>@ cachedClone i (cloneBase i)
, evalState_ = ("counter",Int,const $ return 0) : ("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 = \i -> do deref <- dec_ref i
tryE super ((i `withField` ("counter", counter)) `onAbort` deref)
, startTryH = \i -> do deref <- dec_ref i
startTryE super ((i `withField` ("counter", counter)) `onAbort` deref)
, tryLH = \i -> tryE_ super i @>>>@ dec_ref i
, intArraysE = intArraysE super
, boolArraysE = boolArraysE super
, intVarsE = intVarsE super
, deleteH = error "forLoop.deleteE NOT YET IMPLEMENTED"
, canBranch = return True
, complete = complete super
}
where mystructs = ([],[])
fs1 = [(field,init) | (field,ty,init) <- evalState_ super]
parent = \i -> estate i @=> "parent"
counter = \i -> estate i @=> "counter"
dec_ref = \i -> let i' = resetCommit $ i `withBase` ("for_tstate" ++ show uid)
in do flag <- ask
if flag
then local (const False) $ do
stmt1 <- inits super i'
stmt2 <- startTryE super (i' `withField` ("counter", counter))
ini <- inite fs1 i'
cc <- cachedClone (cloneBase i) i'
compl <- complete super i
return (dec (ref_count i)
>>> ifthen (ref_count i @== 0)
( inc (counter i)
>>> comment ("forLoop: bla 1 (baseTstate i' == \"" ++ rp 0 (baseTstate i') ++ "\", ref_count i' == \"" ++ rp 0 (ref_count i') ++ "\")")
>>> ifthen (counter i @< IVal n &&& Not compl)
( SHook ("TreeState for_tstate" ++ show uid ++ ";")
>>> comment "forLoop: bla 2"
>>> (baseTstate i' <== parent i)
>>> comment "forLoop: bla 3"
>>> cc
>>> comment "forLoop: bla 4"
>>> (ref_count i' <== 1)
>>> comment "forLoop: bla 5"
>>> comment "forLoop: bla 6"
>>> ini
>>> comment "forLoop: bla 7"
>>> stmt1
>>> comment "forLoop: bla 8"
>>> stmt2)
))
else return $ dec (ref_count i) >>> ifthen (ref_count i @== 0) (comment "Delete-forLoop-dec_ref" >>> Delete (space $ cloneBase i))
push dir = \i -> dir super (i `onCommit` inc (ref_count i))
for
:: Int32
-> Search
-> Search
for n 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) $ forLoop n uid (mapE runL s')
}
, runsearch = runs . rReaderT True . runL
}
foreach
:: Int32
-> ((Info -> Value) -> Search)
-> Search
foreach n mksearch =
case mksearch (\i -> field i "counter") of
Search { mkeval = eval, runsearch = run } ->
Search { mkeval =
\super ->
do { uid <- get
; put (uid + 1)
; s' <- eval $ mapE (L . L . mmap runL . runL) super
; return $ mapE (L . mmap L . runL) $ forLoop n uid (mapE runL s')
}
, runsearch = run . rReaderT True . runL
}