在解释器中实现命令式返回语句

时间:2014-05-09 14:12:50

标签: haskell continuations interpretation

我试图在haskell中实现简单的命令式语言。

一般来说,我的程序是一个语句列表(如算术表达式,if / then,block语句)。我的评估者有简单的状态:词汇范围的堆栈。词法范围只是变量名称到值的映射。每当控制流进入功能或阻塞时,我推动词法范围,当控制流离开功能或阻塞时弹出。

但是我在尝试实施return语句的评估时遇到了问题。 我想要做的是在主评估函数(sources here)中为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语句位于多个嵌套块语句内时,另一个问题是恢复词法范围的堆栈。

我认为我可以通过在评估器中存储一些额外的状态来解决这个问题,但这种方法看起来不是很好。有些东西告诉我延续可以帮助我。但我还不太了解延续情况。

解决此问题的最佳方法是什么?我只需要一个想法,一般概念。

感谢。

1 个答案:

答案 0 :(得分:5)

延续可以在这里工作,但它们过度杀伤。事实上,对于解决任何特定问题,延续几乎总是有点过分。

最简单的解决方案是将必要的逻辑放入Eval类型。如果你让Eval包含&#34的构造函数;这个计算会提前返回这个值&#34;,然后让你对(>>)(>>=)的定义尊重,一切都会有效自动退出。