Parsec から作成された Haskell の抽象構文ツリーがあります。中間コードに変換するために、同時にトラバースしながらその構造を照会できるようにしたいと考えています。たとえば、AST の任意の関数がこの変換を行うために必要なパラメーターの数を知る必要があります。私が現在行っていることは、すべての関数に AST を渡すことです。これにより、ルックアップを行う必要があるときはいつでも AST を呼び出すことができ、別のファイルにルックアップを行うためのヘルパー関数があります。これは私の型シグネチャを汚染しています。特に、アキュムレータのようなものを追加し始めたとき.
私が聞いたすべての関数に AST を渡す代わりに、これは Reader モナド (変化しない状態の場合は AST) と State モナド (変化する状態の場合はアキュムレータ) に適していると聞いています。
IO モナド ( gulp )から ast を取り出し、それを Reader モナドで使用してグローバル ルックアップを行うにはどうすればよいですか?
main = do
putStrLn "Please enter the name of your jack file (i.e. Main)"
fileName <- getLine
file <- readFile (fileName++".jack")
let ast = parseString file
writeFile (fileName++".xml") (toClass ast) --I need to query this globally
putStrLn $ "Completed Parsing, " ++ fileName ++ ".vm created..."
type VM = String
toClass :: Jack -> VM
toClass c = case c of
(Class ident decs) ->
toDecs decs
toDecs ::[Declaration] -> VM -- I don't want to add the ast in every function arg...
toDecs [] = ""
toDecs (x:xs) = case x of
(SubDec keyword typ subname params subbody) ->
case keyword of
"constructor" -> --use the above ast to query the # of local variables here...
toSubBody subbody ++
toDecs xs
otherwise -> []
Reader Monad の進行状況に関する更新: 上記の例を次のように変換しました: (以下を参照)。しかし、文字列出力が蓄積されているため、ライター Monad も使用する必要があるのではないかと考えています。もしそうなら、私はどのように2つの曲を作るべきですか? ReaderT はライターをカプセル化する必要がありますか? またはその逆?Reader と Writer を Monad Transformer として構成しようとせずに受け入れるだけの型を作成する必要がありますか?
main = do
putStrLn "Please enter the name of your jack file (i.e. Main)"
fileName <- getLine
file <- readFile (fileName++".jack")
writeFile (fileName++".xml") (runReader toClass $ parseString file)
putStrLn $ "Completed Parsing, " ++ fileName ++ ".xml created..."
toClass = do
env <- ask
case env of Class ident decs -> return $ toDecs decs env
toDecs [] = return ""
toDecs ((SubDec keyword typ subname params subbody):xs) = do
env <- ask
res <- (case keyword of
"method" -> do return "push this 0\n"
"constructor" -> do return "pop pointer 0\nMemory.alloc 1\n"
otherwise -> do return "")
return $ res ++ toSubBody subbody env ++ toDecs xs env
toDecs (_:xs) = do
decs <- ask
return $ toDecs xs decs
toSubBody (SubBodyStatement states) = do
return $ toStatement states
toSubBody (SubBody _ states) = do
return $ toStatement states
http://hpaste.org/83595 --宣言用