mueval 0.9.1.1 → 0.9.1.1.2
raw patch · 6 files changed
+71/−35 lines, 6 filesdep +QuickCheckdep −utf8-stringdep ~base
Dependencies added: QuickCheck
Dependencies removed: utf8-string
Dependency ranges changed: base
Files
- Mueval/ArgsParse.hs +14/−3
- Mueval/Context.hs +7/−0
- Mueval/Interpreter.hs +46/−28
- README.md +1/−1
- mueval.cabal +3/−2
- tests.sh +0/−1
Mueval/ArgsParse.hs view
@@ -1,10 +1,9 @@+{-# LANGUAGE CPP #-} module Mueval.ArgsParse (Options(..), interpreterOpts, getOptions) where import Control.Monad (liftM) import System.Console.GetOpt -import qualified Codec.Binary.UTF8.String as Codec (decodeString)- import Mueval.Context (defaultModules, defaultPackages) -- | See the results of --help for information on what each option means.@@ -15,6 +14,7 @@ , loadFile :: String , user :: String , printType :: Bool+ , typeOnly :: Bool , extensions :: Bool , namedExtensions :: [String] , noImports :: Bool@@ -31,6 +31,7 @@ , user = "" , loadFile = "" , printType = False+ , typeOnly = False , extensions = False , namedExtensions = [] , noImports = False@@ -69,6 +70,9 @@ Option "i" ["inferred-type"] (NoArg (\opts -> opts { printType = True})) "Whether to enable printing of inferred type and the expression (as Mueval sees it). Defaults to false.",+ Option "T" ["type-only"]+ (NoArg (\opts -> opts { typeOnly = True}))+ "Only print the expression and type, don't evaluate the expression. Defaults to false.", Option "r" ["resource-limits"] (NoArg (\opts -> opts { rLimits = True})) "Enable resource limits (using POSIX rlimits). Mueval does not by default since rlimits are broken on many systems.",@@ -98,4 +102,11 @@ -- | Just give us the end result options; this parsing for -- us. Bonus points for handling UTF. getOptions :: [String] -> Either (Bool, String) Options-getOptions = interpreterOpts . map Codec.decodeString+getOptions = interpreterOpts . map decodeString++decodeString :: String -> String+#if __GLASGOW_HASKELL__ >= 702+decodeString = id+#else+decodeString = Codec.decodeString+#endif
Mueval/Context.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} module Mueval.Context ( cleanModules, defaultModules,@@ -29,10 +30,16 @@ "Control.Arrow", "Control.Monad", "Control.Monad.Cont",+#if __GLASGOW_HASKELL__ >= 710+ "Control.Monad.Except",+#else "Control.Monad.Error",+#endif "Control.Monad.Fix", "Control.Monad.Identity",+#if !MIN_VERSION_base(4,7,0) "Control.Monad.Instances",+#endif "Control.Monad.RWS", "Control.Monad.Reader", "Control.Monad.State",
Mueval/Interpreter.hs view
@@ -1,30 +1,33 @@ {-# LANGUAGE PatternGuards #-}+{-# LANGUAGE FlexibleContexts #-} -- TODO: suggest the convenience functions be put into Hint proper? module Mueval.Interpreter where -import Control.Monad (forM_,guard,mplus,unless,when)-import Control.Monad.Trans (MonadIO)-import Control.Monad.Writer (Any(..),runWriterT,tell)-import Data.Char (isDigit)-import Data.List (stripPrefix)-import System.Directory (copyFile, makeRelativeToCurrentDirectory, removeFile, setCurrentDirectory)-import System.Exit (exitFailure)-import System.FilePath.Posix (takeFileName) import qualified Control.Exception.Extensible as E (evaluate,catch,SomeException(..))+import Control.Monad (forM_,guard,mplus,unless,when)+import Control.Monad.Trans (MonadIO)+import Control.Monad.Writer (Any(..),runWriterT,tell)+import Data.Char (isDigit) -import qualified System.IO.UTF8 as UTF (putStrLn)+import System.Directory -import Language.Haskell.Interpreter (eval, set, reset, setImportsQ, loadModules, liftIO,+import System.Exit (exitFailure)+import System.FilePath.Posix (takeBaseName)+import System.IO (openTempFile)++import Data.List++import Language.Haskell.Interpreter (eval, set, reset, setImportsQ, loadModules, liftIO, installedModulesInScope, languageExtensions, typeOf, setTopLevelModules, runInterpreter, glasgowExtensions, OptionVal(..), Interpreter, InterpreterError(..),GhcError(..), Extension(UnknownExtension))-import Language.Haskell.Interpreter.Unsafe (unsafeSetGhcOption)+import Language.Haskell.Interpreter.Unsafe (unsafeSetGhcOption) -import Mueval.ArgsParse (Options(..))+import Mueval.ArgsParse (Options(..)) import qualified Mueval.Resources as MR (limitResources)-import qualified Mueval.Context as MC (qualifiedModules)+import qualified Mueval.Context as MC (qualifiedModules) readExt :: String -> Extension readExt s = case reads s of@@ -39,6 +42,7 @@ interpreter :: Options -> Interpreter (String,String,String) interpreter Options { extensions = exts, namedExtensions = nexts, rLimits = rlimits,+ typeOnly = noEval, loadFile = load, expression = expr, packageTrust = trust, trustedPackages = trustPkgs,@@ -54,13 +58,18 @@ reset -- Make sure nothing is available set [installedModulesInScope := False]- let lfl' = takeFileName load- when (load /= "") $ do liftIO (mvload load)- loadModules [lfl']- -- We need to mangle the String to- -- turn a filename into a module.- setTopLevelModules [takeWhile (/='.') lfl'] + -- if we're given a file of definitions, we need to first copy it to a temporary file in /tmp (cpload),+ -- then tell Hint to parse/read it, then extract the 'module name' of the file,+ -- and tell Hint to expose the module into memory; then we need to store the temporary file's filepath+ -- so we can try to clean up after ourselves later.+ lfl' <- if (load /= "") then (do { lfl <- liftIO (cpload load);+ loadModules [lfl];+ -- We need to mangle the String to+ -- turn a filename into a module.+ setTopLevelModules [takeBaseName load];+ return lfl }) else (return "")+ liftIO $ MR.limitResources rlimits case m of@@ -68,13 +77,15 @@ Just ms -> do let unqualModules = zip ms (repeat Nothing) setImportsQ (unqualModules ++ MC.qualifiedModules) - -- clean up our tmp file here; must be after setImportsQ+ -- clean up our tmp file here; must be *after* setImportsQ when (load /= "") $ liftIO (removeFile lfl') - -- we don't check if the expression typechecks+ -- we don't deliberately don't check if the expression typechecks -- this way we get an "InterpreterError" we can display etype <- typeOf expr- result <- eval expr+ result <- if noEval+ then return ""+ else eval expr return (expr, etype, result) @@ -84,12 +95,19 @@ interpreterSession opts = do r <- runInterpreter (interpreter opts) case r of Left err -> printInterpreterError err- Right (e,et,val) -> when (printType opts) (sayIO e >> sayIO et) >> sayIO val+ Right (e,et,val) -> do when (printType opts)+ (sayIO e >> sayIOOneLine et)+ sayIO val+ where sayIOOneLine = sayIO . unwords . words -mvload :: FilePath -> IO ()-mvload lfl = do canonfile <- makeRelativeToCurrentDirectory lfl- liftIO $ copyFile canonfile $ "/tmp/" ++ takeFileName canonfile- setCurrentDirectory "/tmp" -- will at least mess up relative links+-- | Given a filepath (containing function definitions), copy it to a temporary file and change directory to it, returning the new filepath.+cpload :: FilePath -> IO FilePath+cpload definitions = do+ tmpdir <- getTemporaryDirectory+ (tempfile,_) <- System.IO.openTempFile tmpdir "mueval.hs"+ liftIO $ copyFile definitions tempfile+ setCurrentDirectory tmpdir -- will at least mess up relative links+ return tempfile --------------------------------- -- Handling and outputting results@@ -100,7 +118,7 @@ -- flooding. Lambdabot has a similar limit. sayIO :: String -> IO () sayIO str = do (out,b) <- render 1024 str- UTF.putStrLn out+ putStrLn out when b exitFailure -- | Oh no, something has gone wrong. If it's a compilation error pretty print
README.md view
@@ -60,7 +60,7 @@ # See also -- Chris Done's [`mueval-interactive`](https://github.com/chrisdone/mueval-interactive) fork: a persistent `mueval` (startup is slow) for use in his [Try Haskell.org](http://tryhaskell.org/)+- Chris Done's interactive Haskell REPL website, [Try Haskell!](http://tryhaskell.org/) # Bugs
mueval.cabal view
@@ -1,5 +1,5 @@ name: mueval-version: 0.9.1.1+version: 0.9.1.1.2 license: BSD3 license-file: LICENSE@@ -32,7 +32,8 @@ exposed-modules: Mueval.Parallel, Mueval.Context, Mueval.Interpreter, Mueval.ArgsParse, Mueval.Resources build-depends: base>=4 && < 5, containers, directory, mtl>2, filepath, unix, process,- hint>=0.3.1, show>=0.3, utf8-string, Cabal, extensible-exceptions, simple-reflect+ hint>=0.3.1, show>=0.3, Cabal, extensible-exceptions, simple-reflect,+ QuickCheck ghc-options: -Wall -static executable mueval-core
tests.sh view
@@ -63,7 +63,6 @@ m "sum [1..5] :: Expr" m "foldr f x [1..5]" ## Test defaulting of expressions-m 'show []' -E m '(+1) <$> [1..3]' ## Now let's do file loading echo "module TmpModule (foo, bar) where { foo x = x + 1; bar x = x + 2 }" > "TmpModule.hs"