activehs-0.3.2: Special.hs
{-# LANGUAGE ScopedTypeVariables, OverloadedStrings, ViewPatterns, PatternGuards, NamedFieldPuns, CPP #-}
module Special
( SpecialTask (..), exerciseServer'
) where
import Smart
import QuickCheck
import Result
import Lang
import Logger
import Html
import Qualify (qualify)
import Hash
import ActiveHs.Base (WrapData2)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Text.XHtml.Strict ((+++))
import Control.DeepSeq
import Control.Concurrent.MVar
import Control.Exception
import System.FilePath ((</>),takeFileName)
import System.Directory (getTemporaryDirectory)
import Control.Concurrent (threadDelay, forkIO, killThread)
import Control.Monad.Trans (liftIO)
#if !MIN_VERSION_base(4,6,0)
import Prelude hiding (catch)
#endif
---------------------------------------------------------------
timeout :: forall b. Int -> IO b -> IO b -> IO b
timeout delay error action = do
v <- newEmptyMVar
t1 <- forkIO $ threadDelay delay >> error >>= putMVar v
t2 <- forkIO $ action >>= putMVar v
x <- takeMVar v
killThread t1
killThread t2
return x
----------------------------
data SpecialTask
= Eval
| Compare String String
| Compare2 T.Text [String] String
| Check String [FilePath] T.Text [String] [([String],String)] String String
exerciseServer'
:: String
-> TaskChan
-> Bool
-> FilePath
-> T.Text
-> Language
-> Hash
-> SpecialTask
-> IO Html
exerciseServer' qualifier ch verbose fn sol lang m5 task = do
let error = do
logStrMsg 0 (logger ch) $ "Server error:" ++ show m5
return $ renderResult $ Error True "Server error."
action = eval task `catch` \(e :: SomeException) -> -- ???
return $ renderResult $ Error True $ show e
timeout (10*1000000) error action
where
eval Eval
= renderResult <$> interp verbose m5 lang ch fn (T.unpack sol) Nothing
eval (Compare hiddenname goodsol)
= do
res <- interp verbose m5 lang ch fn (T.unpack sol) $ Just $ \a -> do
x <- interpret (wrap2 a hiddenname) (as :: WrapData2)
liftIO $ compareMistGen lang (show m5) x $ goodsol
return $ renderResult res
eval (Compare2 env funnames s) = do
fn' <- tmpSaveHs "hs" (show m5) $ env `T.append` sol
case qualify qualifier funnames s of
Left err -> return $ renderResult (Error True err)
Right s2 -> do
res <- interp verbose m5 lang ch fn' s $ Just $ \a -> do
result <- interpret (wrap2 a s2) (as :: WrapData2)
liftIO $ compareClearGen lang (show m5) result
return $ renderResult res
eval (Check ext sourcedirs env funnames is i j) = do
fn' <- tmpSaveHs ext (show m5) $ env `T.append` sol
case ext of
"hs" -> do
ss <- quickCheck qualifier m5 lang ch fn' (T.unpack sol) funnames is
case ss of
ShowFailedTestCase testcase reason ->
return . indent . renderResult $ ShowInterpreter lang 59 (getTwo "eval2" (takeFileName fn) j i j) j 'E' testcase (Just reason)
Message _ _ ->
return . indent $
renderResult ss
+++ (renderResult (ShowInterpreter lang 59 (getTwo "eval2" (takeFileName fn) j i j) j 'E' "" Nothing))
_ ->
return . indent $ renderResult ss
tmpSaveHs :: String -> String -> T.Text -> IO FilePath
tmpSaveHs ext x s = do
tmpdir <- getTemporaryDirectory
let name = "GHCiServer_" ++ x
tmp = tmpdir </> name ++ "." ++ ext
T.writeFile tmp $ case ext of
"hs" -> s
return tmp