Re: Build Your Own Haskell Compiler #0.3
讀檔與蒐集
用了 readFile
,就脫離不了 IO
。於是只好把希望得到的,放在 IO
裡面:
readModule :: String -> IO (Maybe (Module SrcSpanInfo))
一開始先來個 do
,躲到 IO
裡面去:
readModule mod = do
content <- readFile $ modName ++ ".hs"
let res = parseModule content
return $ case res of
ParseOk mod -> Just mod
ParseFailed _ msg -> Nothing
蒐集 AST 中 import 的 Module
時,要用到 readModule
的結果, IO
也跟著出現了:
collectModule :: Module SrcSpanInfo -> IO (M.Map String Bool)
這件事一直讓我想起 What Color is Your Function 。對了,別忘記 import Map
:
import Language.Haskell.Exts.Annotated
import qualified Data.Map.Strict as M
並在 my-project.cabal
中補上 containers
:
executable my-project-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, my-project
, containers
, haskell-src-exts
default-language: Haskell2010
先試著蒐集不重複的 Module
就好,不遞迴讀檔:
collectModule mod = do
retrun $ case mod of
Module _ mModuleHead _ imports _ -> go M.empty imports where
modName = case mModuleHead of
Just (ModuleHead _ (ModuleName _ name) _ _) -> name
Nothing -> "Main"
go acc [] = acc
go acc (m : ms) =
let
(Module _ name) = importModule m
in
case M.member name acc of
False -> go (M.insert name True acc) ms
True -> go acc ms
_ -> M.empty
回到 main
,可以這樣印出單一個檔案中 import 的東西:
main = do
mMod <- readModule "A"
res <- case mMod of
Just mod -> collectModule mod
Nothing -> return M.empty
putStrLn $ show res