Commit 10991eb1 authored by Razzi Abuissa's avatar Razzi Abuissa

Implement pragma handling

parent 1c3d12c5
...@@ -192,7 +192,7 @@ layoutChunks = go 1 ...@@ -192,7 +192,7 @@ layoutChunks = go 1
-- | Drop comments from Haskell source. -- | Drop comments from Haskell source.
-- Simply gets rid of them, does not replace them in any way. -- Simply gets rid of them, does not replace them in any way.
removeComments :: String -> String removeComments :: String -> String
removeComments = removeOneLineComments . removeMultilineComments 0 removeComments = removeOneLineComments . removeMultilineComments 0 0
where where
removeOneLineComments str = removeOneLineComments str =
case str of case str of
...@@ -211,11 +211,11 @@ removeComments = removeOneLineComments . removeMultilineComments 0 ...@@ -211,11 +211,11 @@ removeComments = removeOneLineComments . removeMultilineComments 0
where where
dropLine = removeOneLineComments . dropWhile (/= '\n') dropLine = removeOneLineComments . dropWhile (/= '\n')
removeMultilineComments nesting str = removeMultilineComments nesting pragmaNesting str =
case str of case str of
-- Don't remove comments after cmd directives -- Don't remove comments after cmd directives
':':'!':remaining ->":!" ++ takeLine remaining ++ ':':'!':remaining ->":!" ++ takeLine remaining ++
removeMultilineComments nesting (dropWhile (/= '\n') remaining) removeMultilineComments nesting pragmaNesting (dropWhile (/= '\n') remaining)
-- Handle strings. -- Handle strings.
'"':remaining -> '"':remaining ->
...@@ -223,19 +223,28 @@ removeComments = removeOneLineComments . removeMultilineComments 0 ...@@ -223,19 +223,28 @@ removeComments = removeOneLineComments . removeMultilineComments 0
then then
let quoted = takeString remaining let quoted = takeString remaining
len = length quoted in len = length quoted in
'"':quoted ++ removeMultilineComments nesting (drop len remaining) '"':quoted ++ removeMultilineComments nesting pragmaNesting (drop len remaining)
else else
removeMultilineComments nesting remaining removeMultilineComments nesting pragmaNesting remaining
'{':'-':'#':remaining ->
'{':'-':remaining -> removeMultilineComments (nesting + 1) remaining if nesting == 0
then "{-#" ++ removeMultilineComments nesting (pragmaNesting + 1) remaining
else removeMultilineComments nesting pragmaNesting remaining
'#':'-':'}':remaining ->
if nesting == 0
then if pragmaNesting > 0
then '#':'-':'}':removeMultilineComments nesting (pragmaNesting - 1) remaining
else '#':'-':'}':removeMultilineComments nesting pragmaNesting remaining
else removeMultilineComments nesting pragmaNesting remaining
'{':'-':remaining -> removeMultilineComments (nesting + 1) pragmaNesting remaining
'-':'}':remaining -> '-':'}':remaining ->
if nesting > 0 if nesting > 0
then removeMultilineComments (nesting - 1) remaining then removeMultilineComments (nesting - 1) pragmaNesting remaining
else '-':'}':removeMultilineComments nesting remaining else '-':'}':removeMultilineComments nesting pragmaNesting remaining
x:xs -> x:xs ->
if nesting > 0 if nesting > 0
then removeMultilineComments nesting xs then removeMultilineComments nesting pragmaNesting xs
else x:removeMultilineComments nesting xs else x:removeMultilineComments nesting pragmaNesting xs
[] -> [] [] -> []
takeLine = takeWhile (/= '\n') takeLine = takeWhile (/= '\n')
......
...@@ -882,6 +882,9 @@ evalCommand _ (ParseError loc err) state = do ...@@ -882,6 +882,9 @@ evalCommand _ (ParseError loc err) state = do
evalComms = [] evalComms = []
} }
evalCommand output (Pragma pragmas) state = do
write $ "Got pragmas " ++ show pragmas
evalCommand output (Directive SetExtension $ unwords pragmas) state
hoogleResults :: KernelState -> [Hoogle.HoogleResult] -> EvalOut hoogleResults :: KernelState -> [Hoogle.HoogleResult] -> EvalOut
hoogleResults state results = EvalOut { hoogleResults state results = EvalOut {
......
...@@ -48,6 +48,7 @@ data CodeBlock ...@@ -48,6 +48,7 @@ data CodeBlock
| Directive DirectiveType String -- ^ An IHaskell directive. | Directive DirectiveType String -- ^ An IHaskell directive.
| Module String -- ^ A full Haskell module, to be compiled and loaded. | Module String -- ^ A full Haskell module, to be compiled and loaded.
| ParseError StringLoc ErrMsg -- ^ An error indicating that parsing the code block failed. | ParseError StringLoc ErrMsg -- ^ An error indicating that parsing the code block failed.
| Pragma [String] -- ^ A list of GHC pragmas (from a {-# LANGUAGE ... #-} block)
deriving (Show, Eq) deriving (Show, Eq)
-- | Directive types. Each directive is associated with a string in the -- | Directive types. Each directive is associated with a string in the
...@@ -86,10 +87,11 @@ parseString codeString = do ...@@ -86,10 +87,11 @@ parseString codeString = do
return result return result
where where
parseChunk :: GhcMonad m => String -> LineNumber -> m (Located CodeBlock) parseChunk :: GhcMonad m => String -> LineNumber -> m (Located CodeBlock)
parseChunk chunk line = Located line <$> parseChunk chunk line
if isDirective chunk | isDirective chunk = return $ Located line $ parseDirective chunk line
then return $ parseDirective chunk line | isPragma chunk = return $ Located line $ parsePragma chunk line
else parseCodeChunk chunk line | otherwise = Located line <$> parseCodeChunk chunk line
processChunks :: GhcMonad m => [Located CodeBlock] -> [Located String] -> m [Located CodeBlock] processChunks :: GhcMonad m => [Located CodeBlock] -> [Located String] -> m [Located CodeBlock]
processChunks accum remaining = processChunks accum remaining =
...@@ -100,25 +102,39 @@ parseString codeString = do ...@@ -100,25 +102,39 @@ parseString codeString = do
-- If we have more remaining, parse the current chunk and recurse. -- If we have more remaining, parse the current chunk and recurse.
Located line chunk:remaining -> do Located line chunk:remaining -> do
block <- parseChunk chunk line block <- parseChunk chunk line
activateParsingExtensions $ unloc block activateExtensions $ unloc block
processChunks (block : accum) remaining processChunks (block : accum) remaining
-- Test wither a given chunk is a directive. -- Test whether a given chunk is a directive.
isDirective :: String -> Bool isDirective :: String -> Bool
isDirective = startswith ":" . strip isDirective = startswith ":" . strip
-- Test if a chunk is a pragma.
isPragma :: String -> Bool
isPragma = startswith "{-#" . strip
-- Number of lines in this string. -- Number of lines in this string.
nlines :: String -> Int nlines :: String -> Int
nlines = length . lines nlines = length . lines
activateParsingExtensions :: GhcMonad m => CodeBlock -> m () activateExtensions :: GhcMonad m => CodeBlock -> m ()
activateParsingExtensions (Directive SetExtension ext) = void $ setExtension ext activateExtensions (Directive SetExtension ext) = void $ setExtension ext
activateParsingExtensions (Directive SetDynFlag flags) = activateExtensions (Directive SetDynFlag flags) =
case stripPrefix "-X" flags of case stripPrefix "-X" flags of
Just ext -> void $ setExtension ext Just ext -> void $ setExtension ext
Nothing -> return () Nothing -> return ()
activateParsingExtensions _ = return ()
activateExtensions (Pragma extensions) = void $ setAll extensions
where
setAll :: GhcMonad m => [String] -> m (Maybe String)
setAll (ext:extensions) = do
err <- setExtension ext
case err of
Nothing -> setAll extensions
Just err -> return $ Just err
setAll [] = return Nothing
activateExtensions _ = return ()
-- | Parse a single chunk of code, as indicated by the layout of the code. -- | Parse a single chunk of code, as indicated by the layout of the code.
parseCodeChunk :: GhcMonad m => String -> LineNumber -> m CodeBlock parseCodeChunk :: GhcMonad m => String -> LineNumber -> m CodeBlock
parseCodeChunk code startLine = do parseCodeChunk code startLine = do
...@@ -211,6 +227,20 @@ joinFunctions blocks = ...@@ -211,6 +227,20 @@ joinFunctions blocks =
conjoin :: [CodeBlock] -> CodeBlock conjoin :: [CodeBlock] -> CodeBlock
conjoin = Declaration . intercalate "\n" . map str conjoin = Declaration . intercalate "\n" . map str
-- | Parse a pragma of the form {-# LANGUAGE ... #-}
parsePragma :: String -- ^ Pragma string.
-> Int -- ^ Line number at which the directive appears.
-> CodeBlock -- ^ Pragma code block or a parse error.
parsePragma ('{':'-':'#':pragma) line = Pragma $ extractPragma pragma
where
extractPragma :: String -> [String]
-- | After removing commas, extract words until a # is reached
extractPragma pragmas = case (words $ takeWhile (/= '#') $ filter (/= ',' ) pragmas) of
[] -> []
x:xs -> xs -- remove the first word (such as LANGUAGE)
-- | Parse a directive of the form :directiveName. -- | Parse a directive of the form :directiveName.
parseDirective :: String -- ^ Directive string. parseDirective :: String -- ^ Directive string.
-> Int -- ^ Line number at which the directive appears. -> Int -- ^ Line number at which the directive appears.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment