我正在尝试在 haskell 中实现简单的命令式语言。
一般来说,我的程序是一个语句列表(如算术表达式、if/then、块语句)。我的评估器有简单的状态:词汇范围堆栈。词法范围只是变量名到值的映射。每次控制流进入函数或块时,我都会推动词法范围,并在控制流离开函数或块时弹出。
但是我在尝试执行return
语句评估时遇到了问题。我想要做的是在主评估函数中为 return 语句做一个特殊情况(这里的来源):
evalStatements :: [Statement] -> Eval MaybeValue
-- nothing to evaluate
evalStatements [] = return Nothing
-- current statement is 'return expr',
-- evaluate expr and skip the rest of statements
evalStatements (ret@(ReturnStatement _expr):_stmts) =
leaveLexEnv -- leave current lexical scope
evalStatement ret >>= return
-- this is last statement in function, eval it and leave lexical scope
evalStatements [stmt] = do
res <- evalStatement stmt
leaveLexEnv -- leave current lexical scope
return res
evalStatements (st:stmts) =
evalStatement st >> evalStatements stmts >>= return
evalStatement :: Statement -> MaybeValue
evalStatement (ExprStatemet expr) = ...
evalStatement (IfThenStatement expr stmt) = ...
但是函数中的特殊情况evalStatements
对我来说看起来很丑。而且这种方法不适用于BlockStatement
,因为return
语句可以在这个块语句中。当 return 语句位于多个嵌套块语句中时,另一个问题是恢复词法范围的堆栈。
我想我可以通过在我的评估器中存储一些额外的状态来解决这个问题,但是这种方法看起来不是很好。有些东西告诉我,延续可以在这里帮助我。但我还不太了解延续。
解决这个问题的最佳方法是什么?我只需要一个想法,一般概念。
谢谢。