ihaskell 0.3.0.3 → 0.3.0.4
raw patch · 10 files changed
+37/−154 lines, 10 filesdep +ghci-libdep ~ghc-parsersetup-changed
Dependencies added: ghci-lib
Dependency ranges changed: ghc-parser
Files
- Setup.hs +2/−0
- ihaskell.cabal +8/−5
- installation/ipython.sh +1/−1
- installation/update.sh +1/−1
- profile/profile.tar binary
- src/IHaskell/Eval/Evaluate.hs +14/−67
- src/IHaskell/Eval/Lint.hs +1/−1
- src/IHaskell/Eval/Parser.hs +5/−77
- src/IHaskell/IPython.hs +1/−1
- src/Main.hs +4/−1
Setup.hs view
@@ -5,6 +5,8 @@ import Codec.Archive.Tar (create) import System.Directory (getDirectoryContents) +-- This is currently *not used*. build-type is Simple.+-- This is because it breaks installing from Hackage. main = defaultMainWithHooks simpleUserHooks { preBuild = makeProfileTar }
ihaskell.cabal view
@@ -7,7 +7,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.3.0.3+version: 0.3.0.4 -- A short (one-line) description of the package. synopsis: A Haskell backend kernel for the IPython project.@@ -37,7 +37,7 @@ category: Development -build-type: Custom+build-type: Simple -- Constraint on the version of Cabal needed to build this package. cabal-version: >=1.16@@ -64,7 +64,8 @@ directory -any, filepath -any, ghc ==7.6.*,- ghc-parser -any,+ ghc-parser >=0.1.1,+ ghci-lib >=0.1, ghc-paths ==0.1.*, haskeline -any, here -any,@@ -141,7 +142,8 @@ directory -any, filepath -any, ghc ==7.6.*,- ghc-parser -any,+ ghc-parser >=0.1.1,+ ghci-lib >=0.1, ghc-paths ==0.1.*, haskeline -any, here -any,@@ -183,7 +185,8 @@ directory -any, filepath -any, ghc ==7.6.*,- ghc-parser -any,+ ghc-parser >=0.1.1,+ ghci-lib >=0.1, ghc-paths ==0.1.*, haskeline -any, here -any,
installation/ipython.sh view
@@ -32,4 +32,4 @@ # Install IPython itself. echo "Installing IPython (this may take a while)."-pip install -e git+https://github.com/ipython/ipython.git@$COMMIT#egg=ipython-dev+pip install -e git+https://github.com/gibiansky/ipython.git@$COMMIT#egg=ipython-dev
installation/update.sh view
@@ -16,5 +16,5 @@ # Update IPython. echo "Updating IPython (this may take a while)."- pip install --upgrade -e git+https://github.com/ipython/ipython.git@$COMMIT#egg=ipython-dev+ pip install --upgrade -e git+https://github.com/gibiansky/ipython.git@$COMMIT#egg=ipython-dev fi;
profile/profile.tar view
binary file changed (99840 → 85504 bytes)
src/IHaskell/Eval/Evaluate.hs view
@@ -72,6 +72,9 @@ import Paths_ihaskell (version) import Data.Version (versionBranch) +import Language.Haskell.GHC.Interpret+import Language.Haskell.GHC.Util+ data ErrorOccurred = Success | Failure deriving (Show, Eq) debug :: Bool@@ -104,18 +107,15 @@ , "import qualified System.IO as IHaskellSysIO" ] -- -- | Run an interpreting action. This is effectively runGhc with -- initialization and importing. First argument indicates whether `stdin` -- is handled specially, which cannot be done in a testing environment. interpret :: Bool -> Interpreter a -> IO a interpret allowedStdin action = runGhc (Just libdir) $ do- -- Set the dynamic session flags- originalFlags <- getSessionDynFlags- let dflags = xopt_set originalFlags Opt_ExtendedDefaultRules+ initGhci -- If we're in a sandbox, add the relevant package database+ dflags <- getSessionDynFlags sandboxPackages <- liftIO getSandboxPackageConf let pkgConfs = case sandboxPackages of Nothing -> extraPkgConfs dflags@@ -123,10 +123,7 @@ let pkg = PkgConfFile path in (pkg:) . extraPkgConfs dflags - void $ setSessionDynFlags $ dflags { hscTarget = HscInterpreted,- ghcLink = LinkInMemory,- pprCols = 300,- extraPkgConfs = pkgConfs }+ void $ setSessionDynFlags $ dflags { extraPkgConfs = pkgConfs } initializeImports @@ -291,20 +288,6 @@ evalPager = "" } -doc :: GhcMonad m => SDoc -> m String-doc sdoc = do- flags <- getSessionDynFlags- unqual <- getPrintUnqual- let style = mkUserStyle unqual AllTheWay- let cols = pprCols flags- d = runSDoc sdoc (initSDocContext flags style)- return $ Pretty.fullRender Pretty.PageMode cols 1.5 string_txt "" d- where- string_txt :: Pretty.TextDetails -> String -> String- string_txt (Pretty.Chr c) s = c:s- string_txt (Pretty.Str s1) s2 = s1 ++ s2- string_txt (Pretty.PStr s1) s2 = unpackFS s1 ++ s2- string_txt (Pretty.LStr s1 _) s2 = unpackLitString s1 ++ s2 wrapExecution :: KernelState@@ -318,50 +301,19 @@ evalPager = "" } --- | Set dynamic flags.------ This was adapted from GHC's InteractiveUI.hs (newDynFlags).-setDynFlags :: [String] -- ^ Flags to set.- -> Interpreter [ErrMsg] -- ^ Errors from trying to set flags.-setDynFlags ext = do- -- Try to parse flags.- flags <- getSessionDynFlags- (flags', unrecognized, warnings) <- parseDynamicFlags flags (map noLoc ext) - -- First, try to check if this flag matches any extension name.- let restorePkg x = x { packageFlags = packageFlags flags }- let restoredPkgs = flags' { packageFlags = packageFlags flags}- GHC.setProgramDynFlags restoredPkgs- GHC.setInteractiveDynFlags restoredPkgs-- -- Create the parse errors.- let noParseErrs = map (("Could not parse: " ++) . unLoc) unrecognized- allWarns = map unLoc warnings ++ - ["-package not supported yet" | packageFlags flags /= packageFlags flags']- warnErrs = map ("Warning: " ++) allWarns- return $ noParseErrs ++ warnErrs- -- | Return the display data for this command, as well as whether it -- resulted in an error. evalCommand :: Publisher -> CodeBlock -> KernelState -> Interpreter EvalOut evalCommand _ (Import importStr) state = wrapExecution state $ do write $ "Import: " ++ importStr- importDecl <- parseImportDecl importStr- context <- getContext-- -- If we've imported this implicitly, remove the old import.- let noImplicit = filter (not . implicitImportOf importDecl) context- setContext $ IIDecl importDecl : noImplicit+ evalImport importStr - flags <- getSessionDynFlags+ -- Warn about `it` variable. return $ if "Test.Hspec" `isInfixOf` importStr then displayError $ "Warning: Hspec is unusable in IHaskell until the resolution of GHC bug #8639." ++ "\nThe variable `it` is shadowed and cannot be accessed, even in qualified form." else mempty- where- implicitImportOf :: ImportDecl RdrName -> InteractiveImport -> Bool- implicitImportOf _ (IIModule _) = False- implicitImportOf imp (IIDecl decl) = ideclImplicit decl && ((==) `on` (unLoc . ideclName)) decl imp evalCommand _ (Module contents) state = wrapExecution state $ do write $ "Module:\n" ++ contents@@ -428,7 +380,7 @@ -- If not a kernel option, must be a dyn flag. Nothing -> do- errs <- setDynFlags [flag]+ errs <- setFlags [flag] let display = case errs of [] -> mempty _ -> displayError $ intercalate "\n" errs@@ -441,7 +393,7 @@ -- Apply many flags. flag:manyFlags -> do- firstEval <- evalCommand output (Directive SetDynFlag flags) state+ firstEval <- evalCommand output (Directive SetDynFlag flag) state case evalStatus firstEval of Failure -> return firstEval Success -> do@@ -485,10 +437,7 @@ evalCommand _ (Directive GetType expr) state = wrapExecution state $ do write $ "Type: " ++ expr- result <- exprType expr- flags <- getSessionDynFlags- let typeStr = showSDocUnqual flags $ ppr result- return $ formatType typeStr+ formatType <$> getType expr evalCommand _ (Directive LoadFile name) state = wrapExecution state $ do write $ "Load: " ++ name@@ -812,11 +761,8 @@ evalCommand _ (Declaration decl) state = wrapExecution state $ do write $ "Declaration:\n" ++ decl- names <- runDecls decl-- dflags <- getSessionDynFlags- let boundNames = map (replace ":Interactive." "" . showPpr dflags) names- nonDataNames = filter (not . isUpper . head) boundNames+ boundNames <- evalDeclarations decl+ let nonDataNames = filter (not . isUpper . head) boundNames -- Display the types of all bound names if the option is on. -- This is similar to GHCi :set +t.@@ -824,6 +770,7 @@ then return mempty else do -- Get all the type strings.+ dflags <- getSessionDynFlags types <- forM nonDataNames $ \name -> do theType <- showSDocUnqual dflags . ppr <$> exprType name return $ name ++ " :: " ++ theType
src/IHaskell/Eval/Lint.hs view
@@ -17,7 +17,7 @@ import IHaskell.Types import IHaskell.Display import IHaskell.IPython-import IHaskell.Eval.Parser+import IHaskell.Eval.Parser hiding (line) data LintSeverity = LintWarning | LintError deriving (Eq, Show)
src/IHaskell/Eval/Parser.hs view
@@ -50,11 +50,6 @@ | ParseError StringLoc ErrMsg -- ^ An error indicating that parsing the code block failed. deriving (Show, Eq) --- | Store locations along with a value.-data Located a = Located LineNumber a deriving (Eq, Show)-instance Functor Located where- fmap f (Located line a) = Located line $ f a- -- | Directive types. Each directive is associated with a string in the -- directive code block. data DirectiveType@@ -70,14 +65,6 @@ | GetDoc -- ^ Get documentation for an identifier via Hoogle. deriving (Show, Eq) --- | Unlocate something - drop the position.-unloc :: Located a -> a-unloc (Located _ a) = a---- | Get the line number of a located element.-line :: Located a -> LineNumber-line (Located l _) = l- -- | Parse a string into code blocks. parseString :: GhcMonad m => String -> m [Located CodeBlock] parseString codeString = do@@ -88,7 +75,7 @@ Parsed {} -> return [Located 1 $ Module codeString] Failure {} -> do -- Split input into chunks based on indentation.- let chunks = layoutChunks $ dropComments codeString+ let chunks = layoutChunks $ removeComments codeString result <- joinFunctions <$> processChunks [] chunks -- Return to previous flags. When parsing, flags can be set to make@@ -268,69 +255,6 @@ ] parseDirective _ _ = error "Directive must start with colon!" ---- | Split an input string into chunks based on indentation.--- A chunk is a line and all lines immediately following that are indented--- beyond the indentation of the first line. This parses Haskell layout--- rules properly, and allows using multiline expressions via indentation. -layoutChunks :: String -> [Located String]-layoutChunks = go 1- where- go :: LineNumber -> String -> [Located String]- go line = filter (not . null . unloc) . map (fmap strip) . layoutLines line . lines-- layoutLines :: LineNumber -> [String] -> [Located String]- -- Empty string case. If there's no input, output is empty.- layoutLines _ [] = []-- -- Use the indent of the first line to find the end of the first block.- layoutLines lineIdx all@(firstLine:rest) = - let firstIndent = indentLevel firstLine- blockEnded line = indentLevel line <= firstIndent in- case findIndex blockEnded rest of- -- If the first block doesn't end, return the whole string, since- -- that just means the block takes up the entire string. - Nothing -> [Located lineIdx $ intercalate "\n" all]-- -- We found the end of the block. Split this bit out and recurse.- Just idx -> - let (before, after) = splitAt idx rest in- Located lineIdx (joinLines $ firstLine:before) : go (lineIdx + idx + 1) (joinLines after)-- -- Compute indent level of a string as number of leading spaces.- indentLevel :: String -> Int- indentLevel (' ':str) = 1 + indentLevel str-- -- Count a tab as two spaces.- indentLevel ('\t':str) = 2 + indentLevel str- - -- Count empty lines as a large indent level, so they're always with the previous expression.- indentLevel "" = 100000-- indentLevel _ = 0---- Not the same as 'unlines', due to trailing \n-joinLines :: [String] -> String-joinLines = intercalate "\n"---- | Drop comments from Haskell source.-dropComments :: String -> String-dropComments = removeOneLineComments . removeMultilineComments- where- -- Don't remove comments after cmd directives- removeOneLineComments (':':'!':remaining) = ":!" ++ takeWhile (/= '\n') remaining ++ - removeOneLineComments (dropWhile (/= '\n') remaining)- removeOneLineComments ('-':'-':remaining) = removeOneLineComments (dropWhile (/= '\n') remaining)- removeOneLineComments (x:xs) = x:removeOneLineComments xs- removeOneLineComments x = x-- removeMultilineComments ('{':'-':remaining) = - case subIndex "-}" remaining of- Nothing -> ""- Just idx -> removeMultilineComments $ drop (2 + idx) remaining- removeMultilineComments (x:xs) = x:removeMultilineComments xs- removeMultilineComments x = x- -- | Parse a module and return the name declared in the 'module X where' -- line. That line is required, and if it does not exist, this will error. -- Names with periods in them are returned piece y piece.@@ -344,3 +268,7 @@ case unLoc <$> hsmodName (unLoc mod) of Nothing -> error "Module must have a name." Just name -> return $ split "." $ moduleNameString name++-- Not the same as 'unlines', due to trailing \n+joinLines :: [String] -> String+joinLines = intercalate "\n"
src/IHaskell/IPython.hs view
@@ -40,7 +40,7 @@ -- | Which commit of IPython we are on. ipythonCommit :: Text-ipythonCommit = "8858f7eecc31f363ec8b391ac0d9698f99d556a5"+ipythonCommit = "4a08574f74201ef7ca39a4e80d19a2d158ab6950" -- | The IPython profile name. ipythonProfile :: String
src/Main.hs view
@@ -301,8 +301,11 @@ unless (null pager) $ modifyMVar_ pagerOutput (return . (++ pager ++ "\n")) - -- Run code and publish to the frontend as we go. let execCount = getExecutionCounter state+ -- Let all frontends know the execution count and code that's about to run+ inputHeader <- liftIO $ dupHeader replyHeader InputMessage+ send $ PublishInput inputHeader (Chars.unpack code) execCount+ -- Run code and publish to the frontend as we go. updatedState <- evaluate state (Chars.unpack code) publish -- Notify the frontend that we're done computing.