Serialization 在函数式解释器中序列化正在运行的程序
我正在编写一个解释器,该解释器使用Cont Monad的变体在功能上实现。受Smalltalk使用图像捕获正在运行的程序的启发,我正在研究如何序列化正在执行的托管程序,并需要帮助确定如何在高级别上完成此任务 问题陈述 使用contmonad,我可以在解释器中捕获正在运行的程序的当前延续。存储当前延续允许通过调用延续来恢复解释器执行。我想序列化此延续,以便运行程序的状态可以保存到磁盘或由另一个解释器实例加载。但是,我的语言(我的目标和工作都是Javascript)不支持以这种方式序列化函数 我对一种方法感兴趣,这种方法可以用于在给定的执行点(给定一些元数据)构建延续,而无需再次运行整个程序,直到它达到该点为止。最好对解释器本身的实现进行最小的更改 深思熟虑的方法 一种可能有效的方法是将所有控制流逻辑推入程序状态。例如,我目前使用宿主语言对循环行为的递归来表示一个C风格的For循环:Serialization 在函数式解释器中序列化正在运行的程序,serialization,functional-programming,interpreter,monads,continuations,Serialization,Functional Programming,Interpreter,Monads,Continuations,我正在编写一个解释器,该解释器使用Cont Monad的变体在功能上实现。受Smalltalk使用图像捕获正在运行的程序的启发,我正在研究如何序列化正在执行的托管程序,并需要帮助确定如何在高级别上完成此任务 问题陈述 使用contmonad,我可以在解释器中捕获正在运行的程序的当前延续。存储当前延续允许通过调用延续来恢复解释器执行。我想序列化此延续,以便运行程序的状态可以保存到磁盘或由另一个解释器实例加载。但是,我的语言(我的目标和工作都是Javascript)不支持以这种方式序列化函数 我对一
var forLoop = function(init, test, update, body) {
var iter = function() {
// When test is true, evaluate the loop body and start iter again
// otherwise, evaluate an empty statement and finish
return branch(test,
next(
next(body, update),
iter()),
empty);
};
return next(
init,
iter());
};
这是一个很好的解决方案,但是如果我在for循环中途暂停程序,我不知道如何序列化已经建立的延续
我知道我可以使用跳转序列化转换后的程序,但是for循环可以通过跳转操作构造。我的解释器的第一步将生成代码块并将它们保存在程序状态。这些块将捕获托管语言中的某些操作,并可能执行其他块。预处理程序的外观如下所示:
Label Actions (Block of code, there is no sequencing)
-----------------------------------
start: init, GOTO loop
loop: IF test GOTO loop_body ELSE GOTO end
loop_body: body, GOTO update
update: update, GOTO loop
end: ...
这使得每个代码块独立,仅依赖于存储在程序状态中的值
为了序列化,我将保存当前标签名和输入时的状态。反序列化将预处理输入代码以再次构建标签,然后以给定状态在给定标签处恢复。但现在,在实现解释器时,我必须考虑这些块。甚至用构图来隐藏其中的一些内容似乎也有点难看
问题:
有没有解决这个问题的好方法?我是不是想用完全错误的方式序列化一个程序?对于这样的结构,这是可能的吗?经过更多的研究,我对如何做到这一点有了一些想法。但是,我不确定添加序列化是否是我现在想做的事情,因为它会对实现的其余部分产生很大影响 我对这种方法不满意,并且非常希望听到任何替代方案 问题 正如我所指出的,将程序转换为语句列表使序列化更容易。整个程序可以转换成汇编语言,但我想避免这种情况
保持表达式的概念,我原先没有考虑的是函数调用可以发生在深嵌套表达式中。以这个项目为例:
function id(x) { return x; }
10 + id(id(5)) * id(3);
序列化程序应该能够在任何语句中序列化程序,但该语句可能会在表达式中进行计算
主机功能处于该状态
程序状态无法轻松序列化的原因是它包含用于继续的主机函数。这些延续必须转换为数据结构,这些数据结构可以序列化并独立地重构为原始延续所表示的动作。去功能化最常用于以一阶语言表示高阶语言,但我相信它也可以实现序列化
不是所有的连续体都可以在不大幅重写解释器的情况下轻易地失效。由于我们只对特定点上的序列化感兴趣,因此在这些点上的序列化需要解除整个延续堆栈的功能。所以所有语句和表达式都必须失效,但内部逻辑在大多数情况下可以保持不变,因为我们不希望通过内部操作部分地允许序列化
然而,据我所知,由于bind语句,取消功能化在Cont Monad中不起作用。由于缺乏良好的抽象,因此很难使用
关于解决办法的思考
目标是创建一个仅由简单数据结构组成的对象,该对象可用于重建整个程序状态
首先,为了最小化所需的工作量,我将重写语句级解释器,以使用更像状态机的东西,从而更容易序列化。然后,我会解除表达式的功能。函数调用会将剩余表达式的失效延续推送到状态机的内部堆栈上
使程序状态成为可序列化对象
看看语句是如何工作的,我不相信Cont Monad是将语句链接在一起的最佳方法(但我确实认为它在表达式级别和内部操作方面工作得非常好)。状态机似乎是更自然的方法,这也更容易序列化
将编写一台在语句之间进行步进的机器。该状态中的所有其他结构也将可序列化。内置函数必须使用可序列化句柄来标识它们,以便没有函数处于该状态
处理表达式
表达式将被重写以传递失效的延续,而不是宿主函数延续。当在表达式中遇到函数调用时,它捕获失效的当前继续并将其推送到