-- module Console where import Term ( Term ) import Program ( Program ) import qualified Program import qualified Time import qualified Term import qualified Event import qualified Rewrite import qualified Exception import qualified Option import qualified ALSA import qualified Sound.ALSA.Sequencer as SndSeq -- import qualified Sound.ALSA.Sequencer.Event as SeqEvent import Control.Concurrent ( forkIO ) import qualified Control.Concurrent.Split.Chan as 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 ( when, (>=>) ) import Control.Functor.HT ( void ) import qualified System.IO as IO import Option.Utility ( exitFailureMsg ) import Prelude hiding ( log ) -- | read rules files, start expansion of "main" main :: IO () main = do opt <- Option.get when (null $ Option.moduleNames opt) $ exitFailureMsg "no module specified" p <- resolveT (exitFailureMsg . Exception.multilineFromMessage) $ Program.chaseMany (Option.importPaths opt) (Option.moduleNames opt) Program.empty ALSA.withSequencer opt $ \sq -> do (waitIn,waitOut) <- Chan.new (visIn,visOut) <- Chan.new void $ forkIO $ Event.listen sq print (Chan.read visOut >>= print) waitIn ALSA.runSend sq ALSA.startQueue Event.runState $ execute (Option.maxReductions $ Option.limits opt) p sq visIn waitOut Term.mainName writeExcMsg :: Exception.Message -> IO () writeExcMsg = putStrLn . Exception.statusFromMessage execute :: Rewrite.Count -> Program -> ALSA.Sequencer SndSeq.DuplexMode -> Chan.In Term -> Chan.Out Event.WaitResult -> Term -> MS.StateT Event.State IO () execute maxRed p sq visIn waitOut = let go t = do s <- mapExceptionalT (MW.runWriterT >=> \(ms,_log) -> {- liftIO (mapM_ print log) >> -} return ms) $ Rewrite.runEval maxRed p (Rewrite.forceHead t) lift $ liftIO $ Chan.write visIn s lift $ void $ Event.runSend sq$ Event.sendEcho Event.visualizeId $ ALSA.latencyNano sq case Term.viewNode s of Just (":", [x, xs]) -> do mdur <- lift $ resolveT (liftIO . fmap (const Nothing) . writeExcMsg) (Event.play sq writeExcMsg x) lift $ Event.wait sq waitOut mdur go xs Just ("[]", []) -> lift $ liftIO $ Time.pause $ ALSA.latencyMicro sq {- says: operation not permitted SeqEvent.syncOutputQueue (ALSA.handle sq) -} _ -> throwT (Term.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