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

ser*_*eyz 3 continuations haskell interpretation

我正在尝试在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) = ...
Run Code Online (Sandbox Code Playgroud)

evalStatements功能上的特殊情况对我来说看起来很难看.并且这种方法不起作用BlockStatement,因为return语句可以在这个块语句中.当return语句位于多个嵌套块语句内时,另一个问题是恢复词法范围的堆栈.

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

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

谢谢.

Car*_*arl 5

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

最简单的解决方案是将必要的逻辑放入您的Eval类型中.如果你Eval为"使用这个值提前返回的计算"包含一个构造函数,然后进行定义(>>)(>>=)尊重它,那么一切都会自动解决.