-- module Console where
import Term
import Program ( Program (..), chase )
import qualified Event
import qualified Rewrite
import qualified Exception
import qualified Option
import qualified ALSA
import qualified Sound.ALSA.Sequencer as SndSeq
import Control.Concurrent ( forkIO )
import Control.Concurrent.Chan
import qualified Control.Monad.Trans.Writer as MW
import qualified Control.Monad.Trans.State as MS
import Control.Monad.Exception.Synchronous
( mapExceptionalT, resolveT, throwT )
import Control.Monad.IO.Class ( liftIO )
import Control.Monad.Trans.Class ( lift )
import Control.Monad ( forM_, (>=>) )
import Control.Functor.HT ( void )
import qualified System.IO as IO
import qualified System.Exit as Exit
import Prelude hiding ( log )
-- | read rules files, start expansion of "main"
main :: IO ()
main = do
opt <- Option.get
p <-
resolveT (\e ->
IO.hPutStrLn IO.stderr (Exception.statusFromMessage e) >>
Exit.exitFailure) $
Program.chase (Option.importPaths opt) $ Option.moduleName opt
ALSA.withSequencer "Rewrite-Sequencer" $ \sq -> do
waitChan <- newChan
void $ forkIO $ Event.listen sq print waitChan
ALSA.parseAndConnect sq
( Option.connectFrom opt ) ( Option.connectTo opt )
ALSA.startQueue sq
flip MS.evalStateT (Event.RealTime, 0) $
execute p sq waitChan ( read "main" )
writeExcMsg :: Exception.Message -> IO ()
writeExcMsg = putStrLn . Exception.statusFromMessage
execute ::
Program ->
ALSA.Sequencer SndSeq.DuplexMode ->
Chan Event.WaitResult ->
Term ->
MS.StateT Event.State IO ()
execute p sq waitChan =
let go t = do
s <-
mapExceptionalT
(MW.runWriterT >=> \(ms,log) ->
forM_ log (liftIO . print) >> return ms) $
Rewrite.runEval p (Rewrite.force_head t)
lift $ liftIO $ print s
case Term.viewNode s of
Just ("[]", []) -> return ()
Just (":", [x, xs]) -> do
lift $ resolveT
(liftIO . writeExcMsg)
(Event.play sq waitChan writeExcMsg x)
go xs
_ -> throwT
(termRange s,
"do not know how to handle term\n" ++ show s)
in resolveT
(\(pos, msg) ->
liftIO $ IO.hPutStrLn IO.stderr $ show pos ++ " " ++ msg)
. go