module Text.Ginger.Run.VM where import Text.Ginger.Run.Type import Text.Ginger.Run.FuncUtils import Text.Ginger.AST import Text.Ginger.GVal import Data.Monoid ( (<>) ) import Control.Monad.State (MonadState (..), get, gets, modify) import Control.Monad.Reader (asks, local) import qualified Data.HashMap.Strict as HashMap import Data.HashMap.Strict (HashMap) -- | Helper function to run a State action with a temporary state, reverting -- to the old state after the action has finished. withLocalState :: (Monad m, MonadState s m) => m a -> m a withLocalState a = do s <- get r <- a put s return r -- | Helper function to run a Scope action with a temporary scope, reverting -- to the old scope after the action has finished. withLocalScope :: (Monad m) => Run p m h a -> Run p m h a withLocalScope a = do scope <- gets rsScope r <- a modify (\s -> s { rsScope = scope }) return r -- | Override the encoder used for converting 'GVal's to the output type. -- This can be used for things like temporarily disabling HTML encoding. withEncoder :: (ContextEncodable h, Monad m) => (GVal (Run p m h) -> h) -> Run p m h a -> Run p m h a withEncoder encoder = local (\context -> context { contextEncode = encode }) setVar :: Monad m => VarName -> GVal (Run p m h) -> Run p m h () setVar name val = do vars <- gets rsScope let vars' = HashMap.insert name val vars modify (\s -> s { rsScope = vars' }) getVar :: Monad m => VarName -> Run p m h (GVal (Run p m h)) getVar key = do vars <- gets rsScope case HashMap.lookup key vars of Just val -> return val Nothing -> do l <- asks contextLookup l key clearCapture :: (Monoid h, Monad m) => Run p m h () clearCapture = modify (\s -> s { rsCapture = mempty }) appendCapture :: (Monoid h, Monad m) => h -> Run p m h () appendCapture h = modify (\s -> s { rsCapture = rsCapture s <> h }) fetchCapture :: Monad m => Run p m h h fetchCapture = gets rsCapture