LslPlus-0.1.1: Language/Lsl/Internal/SystemTester.hs
{-# OPTIONS_GHC -XFlexibleContexts #-}
module Language.Lsl.Internal.SystemTester where
import Control.Monad(MonadPlus(..))
import Control.Monad.Error(MonadError(..),ErrorT(..))
import Control.Monad.State(evalState)
import qualified Data.Map as M
import IO
import Language.Lsl.Internal.BreakpointsDeserialize(breakpointsElement)
import Language.Lsl.Internal.Compiler(compile)
import Language.Lsl.Internal.DOMProcessing(Content(..),Document(..),Element(..),ElemAcceptor(..),
elementList,simple,findElement,findOptionalElement,match,xmlParse)
import Language.Lsl.Internal.DOMSourceDescriptor(sourceFilesElement)
import Language.Lsl.Internal.ExecInfo(emitExecutionInfo)
import Language.Lsl.Internal.Log(LogMessage(..),logLevelToName)
import Language.Lsl.Syntax(libFromAugLib)
import Language.Lsl.Internal.Util(unescape,processLinesS)
import Language.Lsl.Sim(SimCommand(..),SimEvent(..),SimEventArg(..),SimStatus(..),SimStateInfo(..),simStep)
import Language.Lsl.WorldDef(worldElement)
import Language.Lsl.Internal.XmlCreate(emit,emitList,emitSimple)
initializationFromXML xml = let doc = xmlParse "" xml in parseInitialization doc
parseInitialization (Document _ _ root _) = match initSimElement root
--initSimElement :: MonadError String m => ElemAcceptor m (([(String,String)],[(String,String)]),FullWorldDef)
initSimElement =
let f (Elem _ _ contents) =
do (sources,contents1) <- findElement sourceFilesElement [ e | e@(CElem _ _) <- contents]
(worldDef,[]) <- findElement worldElement contents1
return (sources,worldDef)
in ElemAcceptor "sim-descriptor" f
commandFromXML xml =
let (Document _ _ root _) = xmlParse "" xml in
case simCommand root of
Left s -> error s
Right command -> command
--simCommand e = match (ElemAcceptor "sim-continue" simple) e >> return (SimContinue [] [])
simCommand e = --execCmd "sim-continue" SimContinue e
(matchSimContinue e) `mplus` (matchSimStep e) `mplus` (matchSimStepOver e) `mplus` (matchSimStepOut e)
matchSimContinue e = execCmd "sim-continue" SimContinue e
matchSimStep e = execCmd "sim-step" SimStep e
matchSimStepOver e = execCmd "sim-step-over" SimStepOver e
matchSimStepOut e = execCmd "sim-step-out" SimStepOut e
execCmd s f e = do
(bp,events) <- match (ElemAcceptor s commandContent) e
return (f bp events)
commandContent (Elem _ _ contents) = do
(breakpoints,contents1) <- findOptionalElement breakpointsElement [ e | e@(CElem _ _) <- contents]
(events,[]) <- findOptionalElement (elementList "events" simEventElement) contents1
return $ (maybe [] id breakpoints, maybe [] id events)
simEventElement :: MonadError String m => ElemAcceptor m SimEvent
simEventElement =
let f (Elem _ _ contents) =
do (name,contents1) <- findElement (ElemAcceptor "name" simple) [ e | e@(CElem _ _) <- contents]
(delay,contents2) <- findElement (ElemAcceptor "delay" simple) contents1
(args,[]) <- findOptionalElement (elementList "args" simArgElement) contents2
case reads delay of
[] -> fail "invalid delay: expected integer"
((i,_):_) -> return $ SimEvent name (maybe [] id args) i
in ElemAcceptor "event" f
simArgElement :: MonadError String m => ElemAcceptor m SimEventArg
simArgElement =
let f (Elem _ _ contents) =
do (name,contents1) <- findElement (ElemAcceptor "name" simple) [ e | e@(CElem _ _) <- contents]
(value,[]) <- findElement (ElemAcceptor "value" simple) contents1
return $ SimEventArg name value
in ElemAcceptor "arg" f
outputToXML (SimInfo _ log state) = (emit "sim-info" [] [emitLog log,emitState state]) ""
outputToXML (SimEnded _ log state) = (emit "sim-ended" [] [emitLog log,emitState state]) ""
outputToXML (SimSuspended _ suspendInfo log state) = (emit "sim-suspended" [] [emitExecutionInfo suspendInfo,
emitLog log,
emitState state]) ""
emitLog log =
emit "messages" [] $ map emitMessage (log)
emitMessage logMessage =
emit "message" [] [ emitSimple "time" [] (show $ logMessageTime logMessage),
emitSimple "level" [] (logLevelToName $ logMessageLevel logMessage),
emitSimple "source" [] (logMessageSource logMessage),
emitSimple "text" [] (logMessageText logMessage)]
emitState state =
emit "state" [] [ emitSimple "time" [] (show $ simStateInfoTime state),
emitPrims (simStateInfoPrims state),
emitAvatars (simStateInfoAvatars state),
emitScripts (simStateInfoScripts state) ]
emitPrims prims = emitList "prims" emitPrim prims
emitAvatars avatars = emitList "avatars" emitAvatar avatars
emitScripts scripts = emitList "scripts" emitScript scripts
emitPrim (key,name) = emit "prim" [] [emitSimple "key" [] key, emitSimple "name" [] name]
emitAvatar (key,name) = emit "avatar" [] [emitSimple "key" [] key, emitSimple "name" [] name]
emitScript (pk,sname) = emit "script" [] [emitSimple "primKey" [] pk, emitSimple "scriptName" [] sname]
testSystem :: IO ()
testSystem =
do input <- getLine
--hPutStrLn stderr input
let result = (evalState . runErrorT) (initializationFromXML (unescape input)) (M.empty,1)
case result of
Left s -> fail s
Right (src,worldDef) -> do
(augLib,scripts) <- compile src
let runStep state s =
let command = commandFromXML s
(e,state') = simStep state command
in (state',outputToXML e)
processLinesS (Left (worldDef,scripts,libFromAugLib augLib)) "quit" runStep