@@ -51,12 +51,14 @@ import Language.Haskell.GHC.ExactPrint.Preprocess
5151
5252import Data.Functor (void )
5353import Data.IORef
54+ import System.IO
5455import System.IO.Unsafe
5556import qualified Data.Map as Map
5657import Data.Maybe
5758
5859import qualified GHC hiding (parseModule )
5960import qualified Control.Monad.IO.Class as GHC
61+ import qualified GHC.Data.Bag as GHC
6062import qualified GHC.Data.FastString as GHC
6163import qualified GHC.Data.StringBuffer as GHC
6264import qualified GHC.Driver.Config.Diagnostic as GHC
@@ -66,14 +68,21 @@ import qualified GHC.Driver.Errors.Types as GHC
6668import qualified GHC.Driver.Session as GHC
6769import qualified GHC.Parser as GHC
6870import qualified GHC.Parser.Header as GHC
69- import qualified GHC.Parser.Lexer as GHC hiding (initParserState )
71+ import qualified GHC.Parser.Lexer as GHC hiding (initParserState , initPragState , lexer )
7072import qualified GHC.Parser.PreProcess.State as GHC
7173import qualified GHC.Parser.PostProcess as GHC
74+ import qualified GHC.Types.Error as GHC
7275import qualified GHC.Types.SrcLoc as GHC
76+ import qualified GHC.Unit.Env as GHC
77+ import qualified GHC.Utils.Misc as GHC
78+ import qualified GHC.Parser.Lexer as Lexer
7379
80+
81+ import GHC.Utils.Exception as Exception
7482import qualified GHC.LanguageExtensions as LangExt
7583import qualified GHC.Parser.PreProcess as GHC
7684import GHC (GhcMonad (getSession ))
85+ import Debug.Trace
7786
7887-- ---------------------------------------------------------------------
7988
@@ -115,9 +124,9 @@ runParser parser flags filename str = GHC.unP parser parseState
115124 -- parseState = GHC.initParserState (GHC.initParserOpts flags) buffer location
116125 -- parseState = GHC.initParserStateWithMacros flags Nothing (GHC.initParserOpts flags) buffer location
117126
118- -- TODO: precompute the macros first, store them in an IORef
119- -- macros = Nothing
120- macros = fromMaybe Map. empty macrosFromIORef
127+ -- macros = fromMaybe Map.empty macrosFromIORef
128+ macros = fromMaybe ( error " macroIORef not set up " ) macrosFromIORef
129+
121130 -- opts0 = GHC.initParserOpts flags
122131 -- opts1 = GHC.enableExtBit GHC.UsePosPragsBit opts0
123132 -- opts = opts1
@@ -438,7 +447,8 @@ initDynFlags useGhcCpp file = do
438447 let logger = GHC. hsc_logger hsc
439448 let unit_env = GHC. hsc_unit_env hsc
440449 let supported_pragmas = " JavaScriptFFI" : GHC. supportedLanguagePragmas dflags0
441- (_, src_opts) <- GHC. liftIO $ GHC. getOptionsFromFile dflags0 unit_env parser_opts0 supported_pragmas file
450+ (_, src_opts) <- GHC. liftIO $ myGetOptionsFromFile dflags0 unit_env parser_opts0 supported_pragmas file
451+ -- error $ "initDynFlags:src_opts: " ++ show (map GHC.unLoc src_opts)
442452 (dflags1, _, _) <- GHC. parseDynamicFilePragma logger dflags0 src_opts
443453 -- Turn this on last to avoid T10942
444454 let dflags2 = dflags1 `GHC.gopt_set` GHC. Opt_KeepRawTokenStream
@@ -481,3 +491,144 @@ initDynFlagsPure fp s = do
481491 return dflags3
482492
483493-- ---------------------------------------------------------------------
494+
495+ myGetOptionsFromFile :: GHC. DynFlags
496+ -> GHC. UnitEnv
497+ -> GHC. ParserOpts
498+ -> [String ] -- ^ Supported LANGUAGE pragmas
499+ -> FilePath -- ^ Input file
500+ -> IO (GHC. Messages GHC. PsMessage , [GHC. Located String ]) -- ^ Parsed options, if any.
501+ myGetOptionsFromFile df unit_env popts supported filename
502+ = Exception. bracket
503+ (openBinaryFile filename ReadMode )
504+ (hClose)
505+ (\ handle -> do
506+ (warns, opts) <- fmap (GHC. getOptions' popts supported)
507+ (myGetPragState df unit_env popts' filename handle
508+ -- >>= \prag_state -> traceToks <$> GHC.lazyGetToks prag_state handle)
509+ >>= \ prag_state -> GHC. lazyGetToks prag_state handle)
510+ GHC. seqList opts
511+ $ GHC. seqList (GHC. bagToList $ GHC. getMessages warns)
512+ $ return (warns, opts))
513+ where -- We don't need to get haddock doc tokens when we're just
514+ -- getting the options from pragmas, and lazily lexing them
515+ -- correctly is a little tricky: If there is "\n" or "\n-"
516+ -- left at the end of a buffer then the haddock doc may
517+ -- continue past the end of the buffer, despite the fact that
518+ -- we already have an apparently-complete token.
519+ -- We therefore just turn Opt_Haddock off when doing the lazy
520+ -- lex.
521+ popts' = GHC. disableHaddock popts
522+
523+ blockSize :: Int
524+ -- blockSize = 17 -- for testing :-)
525+ blockSize = 1024
526+
527+ myGetPragState :: GHC. DynFlags -> GHC. UnitEnv -> GHC. ParserOpts -> FilePath -> Handle -> IO (GHC. PState GHC. PpState )
528+ myGetPragState df unit_env popts filename handle = do
529+ buf <- GHC. hGetStringBufferBlock handle blockSize
530+
531+ let macros = fromMaybe (error " macroIORef not set up" ) macrosFromIORef
532+
533+ -- opts0 = GHC.initParserOpts flags
534+ -- opts1 = GHC.enableExtBit GHC.UsePosPragsBit opts0
535+ -- opts = opts1
536+ let popts = myInitParserOpts df
537+ let loc = GHC. mkRealSrcLoc (GHC. mkFastString filename) 1 1
538+ let prag_state = if Lexer. ghcCppEnabled popts
539+ then GHC. initPragStateWithMacros df unit_env popts buf loc
540+ else GHC. initPragState popts buf loc
541+ return prag_state { GHC. pp = (GHC. pp prag_state) { GHC. pp_defines = macros }
542+ , GHC. buffer = buf }
543+
544+
545+ -- getOptions :: ParserOpts
546+ -- -> [String] -- ^ Supported LANGUAGE pragmas
547+ -- -> StringBuffer -- ^ Input Buffer
548+ -- -> FilePath -- ^ Source filename. Used for location info.
549+ -- -> (Messages PsMessage,[Located String]) -- ^ warnings and parsed options.
550+ -- getOptions opts supported buf filename
551+ -- = getOptions' opts supported (getToks opts filename buf)
552+ -- myGetOptions :: GHC.ParserOpts
553+ -- -> [String] -- ^ Supported LANGUAGE pragmas
554+ -- -> GHC.StringBuffer -- ^ Input Buffer
555+ -- -> FilePath -- ^ Source filename. Used for location info.
556+ -- -> (GHC.Messages GHC.PsMessage,[GHC.Located String]) -- ^ warnings and parsed options.
557+ -- myGetOptions opts supported buf filename
558+ -- = GHC.getOptions' opts supported (myGetToks opts filename buf)
559+
560+ -- getOptions' :: GHC.ParserOpts
561+ -- -> [String]
562+ -- -> [GHC.Located GHC.Token] -- Input buffer
563+ -- -> (GHC.Messages GHC.PsMessage,[GHC.Located String]) -- Options.
564+ -- getOptions' opts supported toks =
565+ -- error $ "getOptions': toks " ++ show toks
566+
567+ traceToks :: [GHC. Located GHC. Token ] -> [GHC. Located GHC. Token ]
568+ traceToks [] = []
569+ traceToks (h: t) = trace (" tok: " ++ show (GHC. unLoc h)) h : traceToks t
570+
571+
572+ -- getToks :: ParserOpts -> FilePath -> StringBuffer -> [Located Token]
573+ -- getToks popts filename buf = lexAll pstate
574+ -- where
575+ -- pstate = initPragState popts buf loc
576+ -- loc = mkRealSrcLoc (mkFastString filename) 1 1
577+
578+ -- lexAll state = case unP (lexer False return) state of
579+ -- POk _ t@(L _ ITeof) -> [t]
580+ -- POk state' t -> t : lexAll state'
581+ -- _ -> [L (mkSrcSpanPs (last_loc state)) ITeof]
582+
583+ -- lazyGetToks :: DynFlags -> UnitEnv -> ParserOpts -> FilePath -> Handle -> IO [Located Token]
584+ -- lazyGetToks df unit_env popts filename handle = do
585+ -- buf <- hGetStringBufferBlock handle blockSize
586+ -- let prag_state = if Lexer.ghcCppEnabled popts
587+ -- then initPragStateWithMacros df unit_env popts buf loc
588+ -- else initPragState popts buf loc
589+ -- unsafeInterleaveIO $ lazyLexBuf handle prag_state False blockSize
590+ -- where
591+ -- loc = mkRealSrcLoc (mkFastString filename) 1 1
592+
593+ -- ....
594+
595+ myGetToks :: GHC. DynFlags -> GHC. UnitEnv -> GHC. ParserOpts -> FilePath -> Handle -> IO [GHC. Located GHC. Token ]
596+ myGetToks df unit_env popts filename handle = do
597+ buf <- GHC. hGetStringBufferBlock handle blockSize
598+ let loc = GHC. mkRealSrcLoc (GHC. mkFastString filename) 1 1
599+ let prag_state = if Lexer. ghcCppEnabled popts
600+ then GHC. initPragStateWithMacros df unit_env popts buf loc
601+ else GHC. initPragState popts buf loc
602+ -- GHC.getToks popts filename buf
603+ return $ lexAll prag_state
604+ where
605+ lexAll state = case GHC. unP (GHC. lexer False return ) state of
606+ GHC. POk _ t@ (GHC. L _ GHC. ITeof ) -> [t]
607+ GHC. POk state' t -> t : lexAll state'
608+ _ -> [GHC. L (GHC. mkSrcSpanPs (GHC. last_loc state)) GHC. ITeof ]
609+
610+
611+ -- getToks :: ParserOpts -> FilePath -> StringBuffer -> [Located Token]
612+ -- getToks popts filename buf = lexAll pstate
613+ -- where
614+ -- pstate = initPragState popts buf loc
615+ -- loc = mkRealSrcLoc (mkFastString filename) 1 1
616+
617+ -- lexAll state = case unP (lexer False return) state of
618+ -- POk _ t@(L _ ITeof) -> [t]
619+ -- POk state' t -> t : lexAll state'
620+ -- _ -> [L (mkSrcSpanPs (last_loc state)) ITeof]
621+
622+
623+ -- doGetToks :: GHC.ParserOpts -> FilePath -> GHC.StringBuffer -> [GHC.Located GHC.Token]
624+ -- doGetToks popts filename buf = lexAll pstate
625+ -- where
626+ -- pstate = initPragState popts buf loc
627+ -- loc = mkRealSrcLoc (mkFastString filename) 1 1
628+
629+ -- lexAll state = case unP (lexer False return) state of
630+ -- GHC.POk _ t@(GHC.L _ GHC.ITeof) -> [t]
631+ -- GHC.POk state' t -> t : lexAll state'
632+ -- _ -> [L (mkSrcSpanPs (last_loc state)) GHC.ITeof]
633+
634+ -- ---------------------------------------------------------------------
0 commit comments