module HJScript.Monad
(
HJScript, HJScript',
IsHJScript(..),
evalHJScript,
runHJScript,
outputBlock,
outputStmt,
newVarName,
newVarNum,
hjsInside,
) where
import Language.HJavaScript.Syntax
import Control.Monad.Writer
import Control.Monad.State
import HSP (XMLGenT, unXMLGenT)
type HJScript'= StateT HJState (Writer (Block ()))
type HJScript = XMLGenT HJScript'
type HJState = Int
initState :: HJState
initState = 0
instance Show (HJScript ()) where
show script = show . snd $ evalHJScript script
instance Monoid (Block ()) where
mempty = EmptyBlock
mappend EmptyBlock b = b
mappend b EmptyBlock = b
mappend b1 (Sequence b2 s) = Sequence (mappend b1 b2) s
evalHJScript :: HJScript t -> (t, Block ())
evalHJScript m = runWriter $ evalStateT (unXMLGenT m) initState
runHJScript :: HJScript t -> HJState -> (t, HJState, Block ())
runHJScript m state =
let ((v,state'),block) = runWriter $ runStateT (unXMLGenT m) state
in (v,state',block)
getHJState :: HJScript HJState
getHJState = lift get
putHJState :: HJState -> HJScript ()
putHJState = lift . put
outputStmt :: Stmt () -> HJScript ()
outputStmt = outputBlock . toBlock
outputBlock :: Block () -> HJScript ()
outputBlock = lift . lift . tell
newVarNum :: HJScript Int
newVarNum = lift $ do
n <- get
put $ n + 1
return n
newVarName :: HJScript String
newVarName = do
n <- newVarNum
return $ "var" ++ "_" ++ (show n)
hjsInside :: HJScript t -> HJScript (t, Block ())
hjsInside script = do
state <- getHJState
let (v,state',block) = runHJScript script state
putHJState state'
return (v,block)
class IsHJScript a where
toHJScript :: a -> HJScript ()
instance IsHJScript (HJScript t) where
toHJScript s = s >> return ()
instance IsHJScript (Block ()) where
toHJScript = outputBlock
instance IsHJScript (Stmt ()) where
toHJScript = outputStmt
instance IsHJScript (Exp t) where
toHJScript = toHJScript . ExpStmt