module Control.Search.Combinator.Let (let', set') where



import Control.Search.Language

import Control.Search.GeneratorInfo

import Control.Search.Generator

import Control.Search.Stat



stmPrefixLoop stm super = super { tryH = \i -> (stm i) @>>>@ (tryE super) i, startTryH = \i -> (stm i) @>>>@ (startTryH super) i, toString = "prefix(" ++ toString super ++ ")" }



letLoop :: Evalable m => VarId -> Stat -> Eval m -> Eval m

letLoop v@(VarId i) val super'' = 

  let super' = evalStat val super''

      super = super' { evalState_ = ("var" ++ (show i), Int, \i -> setVarInfo v i >> readStat val >>= \x -> return (x i)) : evalState_ super', 

                       toString = "let(" ++ show v ++ "," ++ show val ++ "," ++ toString super'' ++ ")" }

      in commentEval super



let'

  :: VarId

  -> Stat

  -> Search

  -> Search



let' var val s = 

  case s of

    Search { mkeval = evals, runsearch = runs } ->

      Search { mkeval = \super -> do { ss <- evals super

                                     ; return $ letLoop var val ss

                                     }

             , runsearch = runs

             }



set' :: VarId -> Stat -> Search -> Search

set' var val s = case s of

   Search { mkeval = evals, runsearch = runs } ->

     Search { mkeval = \super -> do { ss <- evals super

                                    ; let ss1 = evalStat (varStat var) ss

                                    ; let ss2 = evalStat val ss1

                                    ; return $ stmPrefixLoop (\i -> readStat (varStat var) >>= \rvar -> readStat val >>= \rval -> return $ Assign (rvar i) (rval i)) ss2

                                    }

            , runsearch = runs

            }