Skip to content

Commit e773cbc

Browse files
committed
adjust grade function to give feedback in multiple stages
1 parent c7cd07f commit e773cbc

2 files changed

Lines changed: 52 additions & 31 deletions

File tree

src/Haskell/Template/Task.hs

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -363,42 +363,47 @@ whileOpen h =
363363

364364
grade
365365
:: MonadIO m
366-
=> (m () -> IO b)
366+
=> (forall a. m a -> (a -> m ()) -> (a -> m ()) -> IO (b, Maybe b))
367367
-> (forall c . Doc -> m c)
368368
-> (Doc -> m ())
369369
-> FilePath
370370
-> String
371371
-> String
372-
-> IO b
372+
-> IO (b, Maybe b)
373373
grade eval reject inform tmp task submission =
374-
withTempDirectory tmp "Template" $ \ dirname -> eval $ do
375-
when ("System.IO.Unsafe" `isInfixOf` submission)
376-
$ void $ reject "wants to use System.IO.Unsafe"
377-
when ("unsafePerformIO" `isInfixOf` submission)
378-
$ void $ reject "wants to use unsafePerformIO"
379-
(mConfig, rawModules) <- splitConfigAndModules reject task
380-
config <- addDefaults reject mConfig
381-
let exts = extensionsOf config
382-
((moduleName', template), others) <-
383-
nameModules (reject . string) exts rawModules
384-
files <- liftIO $ ((moduleName', submission) : others)
385-
`forM` \(mName, contents) -> do
386-
let fname = dirname </> mName <.> "hs"
387-
strictWriteFile fname contents
388-
return fname
389-
let existingModules = map takeBaseName
390-
$ filter ((".hs" ==) . takeExtension)
391-
$ filter (`notElem` [".",".."]) files
392-
modules = ["Test"] `union` existingModules
393-
solutionFile = dirname </> (moduleName' <.> "hs")
394-
liftIO $ do
395-
unless ("Test" `elem` existingModules) $
396-
strictWriteFile (dirname </> "Test" <.> "hs") $ testModule moduleName'
397-
strictWriteFile (dirname </> "TestHelper" <.> "hs") testHelperContents
398-
strictWriteFile (dirname </> "TestHarness" <.> "hs")
399-
$ testHarnessFor solutionFile
400-
do
374+
withTempDirectory tmp "Template" $ \ dirname -> do
375+
let
376+
prepare = do
377+
when ("System.IO.Unsafe" `isInfixOf` submission)
378+
$ void $ reject "wants to use System.IO.Unsafe"
379+
when ("unsafePerformIO" `isInfixOf` submission)
380+
$ void $ reject "wants to use unsafePerformIO"
381+
(mConfig, rawModules) <- splitConfigAndModules reject task
382+
config <- addDefaults reject mConfig
383+
let exts = extensionsOf config
384+
((moduleName', template), others) <-
385+
nameModules (reject . string) exts rawModules
386+
files <- liftIO $ ((moduleName', submission) : others)
387+
`forM` \(mName, contents) -> do
388+
let fname = dirname </> mName <.> "hs"
389+
strictWriteFile fname contents
390+
return fname
391+
let existingModules = map takeBaseName
392+
$ filter ((".hs" ==) . takeExtension)
393+
$ filter (`notElem` [".",".."]) files
394+
modules = ["Test"] `union` existingModules
395+
solutionFile = dirname </> (moduleName' <.> "hs")
396+
liftIO $ do
397+
unless ("Test" `elem` existingModules) $
398+
strictWriteFile (dirname </> "Test" <.> "hs") $ testModule moduleName'
399+
strictWriteFile (dirname </> "TestHelper" <.> "hs") testHelperContents
400+
strictWriteFile (dirname </> "TestHarness" <.> "hs")
401+
$ testHarnessFor solutionFile
402+
401403
let noTest = delete "Test" modules
404+
pure (config, exts, template, modules, noTest, solutionFile)
405+
406+
syntax (config, exts, template, modules, noTest, solutionFile) = do
402407
compilation <- liftIO $ runInterpreter (compiler dirname config noTest)
403408
checkResult reject compilation reject Nothing $ const $ return ()
404409
when (runIdentity $ allowModifying config) $ do
@@ -408,10 +413,14 @@ grade eval reject inform tmp task submission =
408413
compileWithArgsAndCheck dirname reject undefined config noTest True
409414
void $ getHlintFeedback rejectWithHint config dirname solutionFile True
410415
matchTemplate reject config 2 exts template submission
416+
417+
semantics (config, _, _, modules, noTest, solutionFile) = do
411418
result <- liftIO $ runInterpreter (interpreter dirname config modules)
412419
checkResult reject result reject Nothing $ handleCounts reject inform
413420
compileWithArgsAndCheck dirname reject inform config noTest False
414421
void $ getHlintFeedback inform config dirname solutionFile False
422+
423+
eval prepare syntax semantics
415424
where
416425
testHarnessFor file =
417426
let quoted xs = '"' : xs ++ "\""

test/Haskell/Template/TaskSpec.hs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import Control.Monad.Catch (
1414
MonadThrow (..),
1515
)
1616
import Control.Monad.IO.Class (liftIO)
17-
import Control.Monad.Trans.Writer (execWriterT, tell)
17+
import Control.Monad.Trans.Writer (execWriterT, runWriterT, tell)
1818
import Data.List (intercalate, isPrefixOf)
1919
import Data.List.Extra (split)
2020
import Data.Maybe (fromJust)
@@ -165,7 +165,19 @@ gradeIO task submission = do
165165
tmp <- getTemporaryDirectory
166166
withTempDirectory tmp "Grade-test" $ \dir -> do
167167
setCurrentDirectory dir
168-
grade execWriterT (throwM . CustomException) (tell . show) dir task submission
168+
let eval prepare syntax semantics = do
169+
(params,setupResult) <- runWriterT prepare
170+
syntaxResult <- execWriterT $ syntax params
171+
semanticsResult <- execWriterT $ semantics params
172+
pure (setupResult ++ syntaxResult, Just semanticsResult)
173+
(syntax,mSemantics) <- grade
174+
eval
175+
(throwM . CustomException)
176+
(tell . show)
177+
dir
178+
task
179+
submission
180+
pure $ syntax ++ fromJust mSemantics
169181

170182
hlintIO :: SolutionConfig -> String -> Bool -> IO [Either String String]
171183
hlintIO config content asError = do

0 commit comments

Comments
 (0)