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