Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ex12 #108

Merged
merged 22 commits into from
Jun 24, 2020
Merged

Ex12 #108

Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
af9390c
(WIP) Add function to judge user's program by both stderr and stdout
Feb 19, 2020
814917e
(WIP) Use Judge instead of calcRight in Exercise.Core
Feb 26, 2020
209dbaf
(WIP) Merge stdout/stderr written by ghc/runhaskell
Mar 4, 2020
b97bea2
(WIP) Always run ghc for judging to split compile error from the erro…
Mar 11, 2020
0f7d5b9
(WIP) Always run ghc for judging to split compile error from the erro…
Mar 18, 2020
cd818d7
(WIP) Always run ghc for judging to split compile error from the erro…
Mar 18, 2020
3fca551
Complete implementation of runHaskell, compileWithGhc, and checkWithGhc
Apr 1, 2020
94e21ab
Compile with new APIs and fix others problems
Apr 8, 2020
fb14f31
Fix no debug print is shown when an exception is thrown in an E2E test
Apr 15, 2020
2c6c010
(WIP) Use strict ByteString to fix a bug caused by lazy IO
Apr 15, 2020
5f4b5bb
Use strict Text and ByteString to avoid lazy IO
May 13, 2020
01fb432
Add debug code to investigate test failure
May 13, 2020
ba29e08
:art: Cosmetic: two lines should be inserted between functions define…
May 20, 2020
ec346fe
Fixing test after changing the design of exercise for ex12
May 20, 2020
06cf28a
(WIP) Implementing judge of ex12
May 20, 2020
5989fcc
Fix build error on Linux
May 27, 2020
cd64521
Add runHaskellExerciseWithStdin, which accepts an arbitrary Judge object
May 27, 2020
f81801c
(WIP) Implementing judge of ex12
May 27, 2020
b2a0acf
Fix build error on Linux
May 27, 2020
07188eb
Implement judge of ex12
Jun 3, 2020
785485d
Add E2E tests for exercise 12
Jun 10, 2020
9acde50
Fix test failure on Linux
Jun 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use strict Text and ByteString to avoid lazy IO
YAMAMOTO Yuji committed May 13, 2020
commit 5f4b5bbd854bd2c99343db6ca2e8d46066f7298a
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
module Education.MakeMistakesToLearnHaskell.Commons.Exercise where

import qualified Data.Aeson.TH as AT
import Data.Text.Lazy (Text)
import Data.Text (Text)


-- | Detailed error message generated by GHC
4 changes: 2 additions & 2 deletions reporter/app/client.hs
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@
{-# LANGUAGE OverloadedStrings #-}

import Control.Exception (throwIO)
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.IO as TI
import qualified Data.Text as T
import qualified Data.Text.IO as TI
import GHC.Generics (Generic)
import Options.Generic (ParseRecord,
getRecord)
Original file line number Diff line number Diff line change
@@ -21,12 +21,12 @@ import Control.Monad (unless)
import Control.Monad.IO.Class (MonadIO,
liftIO)
import qualified Data.Aeson.TH as AT
import qualified Data.ByteString.Lazy as B
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.Encoding as TE
import qualified Data.Text.Lazy.IO as TI
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Text.IO as TI
import qualified Data.ULID as U
import Data.String.AnsiEscapeCodes.Strip.Text.Lazy (stripAnsiEscapeCodes)
import Data.String.AnsiEscapeCodes.Strip.Text (stripAnsiEscapeCodes)
import GHC.Generics (Generic)
import Network.Wai
import Network.Wai.Handler.Warp
@@ -149,8 +149,8 @@ writeFailBy (Exercise.CompileError dCmd dDiag) = do
getHeadSha :: MonadIO m => m T.Text
getHeadSha = do
(out, err) <- P.readProcess_ $ P.proc "git" ["rev-parse", "HEAD"]
liftIO $ B.putStr err
return . T.strip $ TE.decodeUtf8 out
liftIO $ BL.putStr err
return . T.strip . TE.decodeUtf8 $ BL.toStrict out


locking :: IO a -> IO a
12 changes: 6 additions & 6 deletions src/Education/MakeMistakesToLearnHaskell.hs
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ verifySource e file = do
Exit.exitFailure

Exercise.Error details -> do
Error.errLn $ Text.toStrict $ details <> "\n\n"
Error.errLn $ details <> "\n\n"
die "An unexpected error occurred when evaluating your solution."

Exercise.NotVerified -> do
@@ -172,9 +172,9 @@ showExercise e n = do

showMarkdown :: Env -> Text -> String -> IO ()
showMarkdown e md n = do
cssPath <- TextS.pack <$> Paths.getDataFileName "assets/exercise.css"
let htmlBody = CMark.commonmarkToHtml [CMark.optSafe] $ Text.toStrict md
htmlHead = TextS.unlines
cssPath <- Text.pack <$> Paths.getDataFileName "assets/exercise.css"
let htmlBody = CMark.commonmarkToHtml [CMark.optSafe] md
htmlHead = Text.unlines
[ "<!DOCTYPE html>"
, "<html>"
, "<head>"
@@ -184,7 +184,7 @@ showMarkdown e md n = do
, "<body>"
, "<div id=\"container\">"
]
htmlFoot = TextS.unlines
htmlFoot = Text.unlines
[ "</div>"
, "</body>"
, "</html>"
@@ -193,7 +193,7 @@ showMarkdown e md n = do
mkHtmlPath dir = dir <> "/" <> "mmlh-ex" <> n <> ".html"
path <- mkHtmlPath <$> Dir.getTemporaryDirectory

writeUtf8FileS path (htmlHead <> htmlBody <> htmlFoot)
writeUtf8File path (htmlHead <> htmlBody <> htmlFoot)

browserLaunched <- openWithBrowser e (Text.pack path)

Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ execute cname cmdP = do
let prc =
Process.setStdout (Process.useHandleOpen h)
$ Process.setStderr (Process.useHandleOpen h)
$ Process.setStdin (Process.byteStringInput $ commandParametersStdin cmdP)
$ Process.setStdin (Process.byteStringInput . ByteStringLazy.fromStrict $ commandParametersStdin cmdP)
$ Process.proc cname
$ commandParametersArgs cmdP
ecode <- fixingCodePage $ runProcess prc
8 changes: 4 additions & 4 deletions src/Education/MakeMistakesToLearnHaskell/Evaluator/Regex.hs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ module Education.MakeMistakesToLearnHaskell.Evaluator.Regex

import Education.MakeMistakesToLearnHaskell.Evaluator.Types

type GhcToken = (GHC.Token, TextS.Text)
type GhcToken = (GHC.Token, Text)


matchSub :: Regex.RE s a -> [s] -> Maybe a
@@ -45,13 +45,13 @@ singleArgFunApp depth =
<*> (if depth == 0 then pure Nothing else optional $ singleArgFunApp $ depth - 1)

where
symbol :: TextS.Text -> Regex.RE GhcToken ()
symbol :: Text -> Regex.RE GhcToken ()
symbol t = void $ Regex.sym (GHC.SymbolTok, t)

hasSympol :: TextS.Text -> Regex.RE GhcToken Bool
hasSympol :: Text -> Regex.RE GhcToken Bool
hasSympol t = (symbol t $> True) <|> pure False

identifier :: Regex.RE GhcToken TextS.Text
identifier :: Regex.RE GhcToken Text
identifier = snd <$> Regex.psym ((== GHC.VariableTok) . fst)

skipSpace :: Regex.RE GhcToken ()
4 changes: 2 additions & 2 deletions src/Education/MakeMistakesToLearnHaskell/Evaluator/Types.hs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ type ErrorMessage = ByteString
data CommandResult =
CommandResult
!ExitCode -- ^ exit code
!ByteString'.ByteString -- ^ Merged stdout and stderr
!ByteString -- ^ Merged stdout and stderr
deriving Show


@@ -37,7 +37,7 @@ data HasParens =


data SingleArgFunApp = SingleArgFunApp
{ singleArgFunAppFunName :: !TextS.Text
{ singleArgFunAppFunName :: !Text
, singleArgFunAppArg :: !(Maybe SingleArgFunApp)
, singleArgFunAppHasParen :: !HasParens
} deriving (Eq, Show)
2 changes: 1 addition & 1 deletion src/Education/MakeMistakesToLearnHaskell/Exercise/Ex04.hs
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ diag4 code msg
&& "In the first argument of ‘lines’" `Text.isInfixOf` msg =
"HINT: Unfortunately, you have to assign the result of `getContents` with `<-` operator."
| otherwise =
let mtoks = GHC.tokenizeHaskell (Text.toStrict code)
let mtoks = GHC.tokenizeHaskell code
tokPutStr = (GHC.VariableTok, "putStr")
putStrThenSpace =
Regex.sym tokPutStr <* optional (Regex.psym ((== GHC.SpaceTok) . fst))
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ formatSingleArgFunApp = List.unfoldr uf
-- NOTE: The final argument should not be tested because it should be a raw expression.
-- E.g. The `input` argument of `reverse (lines input)`.
if isJust $ singleArgFunAppArg safa2
then Just (Text.fromStrict hint, safa2)
then Just (hint, safa2)
else Nothing
in f =<< singleArgFunAppArg safa1

8 changes: 4 additions & 4 deletions src/Education/MakeMistakesToLearnHaskell/Text/IO.hs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

module Education.MakeMistakesToLearnHaskell.Text.IO
( readUtf8File
, writeUtf8FileS
, writeUtf8File
) where


@@ -18,8 +18,8 @@ readUtf8File path = do
Text.hGetContents hd


writeUtf8FileS :: FilePath -> TextS.Text -> IO ()
writeUtf8FileS path dat =
writeUtf8File :: FilePath -> Text -> IO ()
writeUtf8File path dat =
IO.withFile path IO.WriteMode $ \hd -> do
IO.hSetEncoding hd IO.utf8
TextS.hPutStr hd dat
Text.hPutStr hd dat
13 changes: 6 additions & 7 deletions src/imports/external.hs
Original file line number Diff line number Diff line change
@@ -16,9 +16,9 @@ import Control.Monad (void, unless, when)
import Control.Monad.IO.Class (liftIO)
import qualified Control.Monad.Trans.Maybe as MaybeT
import Data.Bool (bool)
import qualified Data.ByteString.Char8 as ByteString'
import Data.ByteString.Lazy.Char8 (ByteString)
import qualified Data.ByteString.Lazy.Char8 as ByteString
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as ByteString
import qualified Data.ByteString.Lazy.Char8 as ByteStringLazy
import qualified Data.Char as Char
import Data.Functor (($>))
import qualified Data.List as List
@@ -30,10 +30,9 @@ import Data.IORef
)
import Data.Monoid ((<>))
import qualified Data.Text.Encoding.Error as TextEncoding
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as Text
import qualified Data.Text.Lazy.Encoding as TextEncoding
import qualified Data.Text as TextS
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as TextEncoding
import Data.Traversable (for)
import Data.Typeable (Typeable)
import qualified Debug.Trace as Debug
3 changes: 1 addition & 2 deletions src/imports/external/io.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
import qualified Data.Text.IO as TextS
import qualified Data.Text.Lazy.IO as Text
import qualified Data.Text.IO as Text
import qualified Web.Browser as Browser
2 changes: 1 addition & 1 deletion src/imports/io.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <imports/external/io.hs>

import Education.MakeMistakesToLearnHaskell.Text.IO (readUtf8File, writeUtf8FileS)
import Education.MakeMistakesToLearnHaskell.Text.IO (readUtf8File, writeUtf8File)
import qualified Education.MakeMistakesToLearnHaskell.Report.Client as IO
6 changes: 3 additions & 3 deletions src/test/imports/external.hs
Original file line number Diff line number Diff line change
@@ -10,11 +10,11 @@ import Control.Concurrent (forkIO)
import Control.Exception (try, onException)
import Control.Monad (void)
import qualified Data.ByteString.Char8 as ByteString'
import Data.ByteString.Lazy.Char8 (ByteString)
import qualified Data.ByteString.Lazy.Char8 as ByteString
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as ByteString
import Data.Foldable (for_)
import Data.Function ((&))
import qualified Data.Text.Lazy as Text
import qualified Data.Text as Text
import qualified System.Directory as Dir
import qualified System.Environment as Env
import System.Exit (ExitCode (ExitFailure, ExitSuccess))
6 changes: 3 additions & 3 deletions test/Education/MakeMistakesToLearnHaskell/SpecEnv.hs
Original file line number Diff line number Diff line change
@@ -19,17 +19,17 @@ mkDefaultSpecEnv = runIO $ do
}


setRunHaskellFailureWithOutput :: Env -> ByteString -> Env
setRunHaskellFailureWithOutput :: Env -> ByteString'.ByteString -> Env
setRunHaskellFailureWithOutput e err =
e { executeCommand = \_cname _params -> return $ CommandResult (ExitFailure 1) err }


setRunHaskellSuccessWithStdout :: Env -> ByteString -> Env
setRunHaskellSuccessWithStdout :: Env -> ByteString'.ByteString -> Env
setRunHaskellSuccessWithStdout e out =
e { executeCommand = \_cname _params -> return $ CommandResult ExitSuccess out }


setRunHaskellSuccessWithStdinFunction :: Env -> (ByteString -> ByteString) -> Env
setRunHaskellSuccessWithStdinFunction :: Env -> (ByteString'.ByteString -> ByteString'.ByteString) -> Env
setRunHaskellSuccessWithStdinFunction e func =
e {
executeCommand = \_cname params ->