{-# LANGUAGE ScopedTypeVariables, OverloadedStrings, ViewPatterns, PatternGuards, NamedFieldPuns #-} module Special ( SpecialTask (..), exerciseServer' ) where import Smart import QuickCheck import Result import Lang import Html import Qualify (qualify) import ActiveHs.Base (WrapData2) import Language.Haskell.Interpreter hiding (eval) import Data.Digest.Pure.MD5 (MD5Digest) import qualified Data.Text as T import qualified Data.Text.IO as T import Data.ByteString.UTF8 (fromString) 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 Prelude hiding (catch) --------------------------------------------------------------- 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 T.Text [String] [([String],String)] String String exerciseServer' :: String -> TaskChan -> Bool -> FilePath -> T.Text -> Language -> MD5Digest -> SpecialTask -> IO [Result] exerciseServer' qualifier ch verbose fn sol lang m5 task = do let error = do logMsgWithImportance 5 (logger ch) $ fromString $ "Server error:" ++ show m5 return [Error True "Server error."] action = do res <- eval task res `deepseq` return res `catch` \(e :: SomeException) -> -- ??? return [Error True $ show e] timeout (10*1000000) error action where eval Eval = interp verbose m5 lang ch fn (T.unpack sol) $ \a -> return $ return [] eval (Compare hiddenname goodsol) = interp verbose m5 lang ch fn (T.unpack sol) $ \a -> do x <- interpret (wrap2 a hiddenname) (as :: WrapData2) return $ compareMistGen lang (show m5) x $ goodsol eval (Compare2 env funnames s) = do fn' <- tmpSaveHs (show m5) $ env `T.append` sol case qualify qualifier funnames s of Left err -> return [Error True err] Right s2 -> interp verbose m5 lang ch fn' s $ \a -> fmap (compareClearGen lang (show m5)) $ interpret (wrap2 a s2) (as :: WrapData2) eval (Check env funnames is i j) = do fn' <- tmpSaveHs (show m5) $ env `T.append` sol ss <- quickCheck qualifier m5 lang ch fn' (T.unpack sol) funnames is let ht = head $ [x | ModifyCommandLine x <- ss] ++ [""] return [ShowInterpreter lang 59 (getTwo "eval2" (takeFileName fn) j i j) j 'E' ht ss] tmpSaveHs :: String -> T.Text -> IO FilePath tmpSaveHs x s = do tmpdir <- getTemporaryDirectory let tmp = tmpdir "GHCiServer_" ++ x ++ ".hs" T.writeFile tmp s return tmp