The*_*net 7 monads haskell abstract-syntax-tree
我有一个由Parsec制作的haskell抽象语法树.我希望能够在同时遍历它时查询其结构,以便将其转换为中间代码.例如,我需要知道我的AST的任何给定函数有多少参数才能进行这种转换.我目前正在做的是将AST传递给每个函数,所以每当我需要进行查找时我都可以调用它,并且我在另一个文件中有辅助函数来为我执行查找.这污染了我的类型签名.特别是当我开始添加更多东西,如累加器.
而不是将AST传递给我听过的每个函数,这对于Reader Monad(对于不改变的状态,AST)和状态Monad(对于确实改变的状态,累加器)来说是一个好工作.
如何从IO monad(gulp)中取出ast 并在Reader Monad中使用它来进行全局查找?
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 -> []
Run Code Online (Sandbox Code Playgroud)
关于Reader Monad进展的更新:我已经将上面的例子变成了这样的东西:(见下文).但现在我想知道由于所有这些字符串输出的积累,我应该使用作家Monad吗?如果是这样,我该怎么做才能写出这两个?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
Run Code Online (Sandbox Code Playgroud)
如果不了解更多有关Jack和Declaration类型的信息,就很难了解如何将其转换为 Reader monad。如果想法是在对象处于ast :: Jack范围内的同时对某些对象执行“映射”或“折叠”,您可以编写
f :: [Declaration] -> Reader Jack [Something]
f decls = mapM go decls where
go :: Declaration -> Reader Jack Something
go (SubDec keyword typ subname params subbody) =
case keyword of
"constructor" -> do
ast <- ask
return (doSomething subbody ast)
Run Code Online (Sandbox Code Playgroud)
然后在您的astas上下文中执行它runReader (f decls) ast。
| 归档时间: |
|
| 查看次数: |
460 次 |
| 最近记录: |