I have some code that evaluates primitive programs. Program is a list of statements (expression, block, return statement). Result of evaluation is last evaluated expression.
The translation is fairly mechanical.
Keep in mind that in the continuation monad, return
feeds the value into the continuation.
evalStmt :: Statement -> Cont Value Value
evalStmt (Expr val) =
let res = Value val
in return res
evalStmt (Block stmts) = evalBlock stmts
evalStmt (Return val) = cont $ \_ -> Value val
evalBlock :: [Statement] -> Cont Value Value
evalBlock [] = return Undefined
evalBlock [st] = evalStmt st
evalBlock (st:rest) = evalStmt st >> evalBlock rest
evalProgram :: [Statement] -> Value
evalProgram stmts = runCont (evalBlock stmts) id
And to simulate early returns, we just ignore the continuation given to Return val
and just return the value we have.