标签:style blog class code tar ext
或许在加入continuation之前要先讲讲费这么大劲做这个有什么意义。 毕竟用不用continuation的计算结果都是一样的。
不过,这是一个兴趣使然的系列,学习这些知识应该完全出于好奇与好玩的想法。
所以我才不会告诉你们通过控制continuation可以实现call-with-current-continuation和异常处理等功能呢。
我先简要描述一下加入continuation后解释器是怎么工作的。 加入continuation后的解释器是以迭代的方式工作的。
迭代的状态量有两个,第一个是一个待求值的表达式或者求到的值,第二个是Continuation。 假设解释器的输入是M
,那么一开始的状态表示为?M,mt?
v
。 第一个状态量是个表达式M
,这时解释器开始对M
求值。 这个过程用记号→
v
表示。 这个过程可能会将一些“下一步要做的事”保存到continuation。 求值到最后,状态会变为?V,κ?
c
(如果没有无限循环)。 注意到下标变成c,V
是一个值,所以不能再求值了,下一步要做的是从continuation κ
中取出“下一步要做的事”执行。 这个过程也叫做“将continuation κ
应用到值V
”,用记号→
c
表示。 一个解释器的执行过程就是→
v
和→
c
交替运行,就好像太极里阴阳交替一样。 解释器执行到最后状态会变成?V,mt?
c
,已求得值V
,又没有“下一步要做的事”,也就是运行结束了,输出V
。 说了这么多,本质上整个过程还是一句话:递归转迭代。顺便一提,加入continuation后的解释器叫做CK machine。
先列出目前为止的所有求值过程(call-by-value):
eval(X)
eval(b)
eval(λX.M)
eval((+MN))
eval((?MN))
eval((iszeroM))
eval((iszeroM))
eval((MN))
eval((fixX
1
X
2
M))
=
=
=
=
=
=
=
=
=
X
b
λX.M
eval(M)+eval(N)
eval(M)?eval(N)
true
其中eval(M)=0
false,
其中eval(M)≠0
eval(L[X←eval(N)])
其中eval(M)=λX.L
λX
2
.M[X
1
←(fixX
1
X
2
M)]


下面分别介绍各个情况下如何加入continuation。
值与fix表达式
值是最简单的情况,直接应用continuation。
?X,κ?
v
?b,κ?
v
?λX.M,κ?
v

→
v
→
v
→
v

?X,κ?
c
?b,κ?
c
?λX.M,κ?
c



fix表达式和值的情况类似:
?(fixX
1
X
2
M),κ?
v

→
v

?λX
2
.M[X
1
←(fixX
1
X
2
M)],κ?
c



基本运算
用(o
n
M
1
M
2
...M
n
)
表示基本运算,其中o
n
是运算符,M
1
,...,M
n
是参数,n
是代表参数个数。 在我们的语言里目前有两个两参数的基本运算o
2
={+,?}
和一个单参数的基本运算o
1
={iszero}
。
计算基本运算前要先对所有参数求值。这里规定从左到右求值。 当解释器在求第i
个参数M
i
的值时,需要保存到continuation的数据有: 运算符o
n
、 已求到的值V
1
,...,V
i?1
(其中V
1
=eval(M),...,V
i?1
=eval(M
i?1
)
) 以及还没求值的参数M
i+1
,...,M
n
。 因此,包含基本运算的continuation定义为:
κ

=
|
mt
?opd,κ,o
n
,(V
1
...V
i?1
),(M
i+1
...M
n
)?


求值过程为:
?(o
n
M
1
M
2
...M
n
),κ?
v
?V,?opd,κ,o
n
,(M
i+1
...M
n
),(V
1
...V
i?1
)??
c
?V,?opd,κ,o
n
,(),(V
1
...V
n?1
)??
c

→
v
→
c
→
c


?M
1
,?opd,κ,o
n
,(M
2
...M
n
),()??
v
?M
i+1
,?opd,κ,o
n
,(...M
n
),(V
1
...V
i?1
V)??
v
?V
′
,κ?
c
其中V
′
=o
n
(V
1
,...,V
n?1
,V)


函数调用
函数调用(MN)
先计算M
的值,N
保存到continuation:
?(MN),κ?
v

→
v

?M,?arg,κ,N??
v



M
计算完后从continuation取出N
计算(我们采用call-by-value的调用方式),同时保存M
的计算结果V
:
?V,?arg,κ,N??
c

→
c

?N,?fun,κ,V??
v



N
也计算完后,进行β
归约:
?V,?fun,κ,λX.L??
c

→
c

?L[X←V],κ?
v



这个地方很有意思,可以看到函数调用最后β
归约的过程不会使continuation增长。
所有求值过程中,会导致continuation增长的几个过程是基本运算中对参数的计算过程、函数调用中对函数的计算过程以及对参数的计算过程。
一般也认为函数调用中函数的这个位置(也就是(MN)
中M
这个位置)也算参数位置, 所以判断一个函数调用是不是尾调用的依据是:
这个函数调用表达式是不是在一个参数位置,如果在参数位置,就不是尾调用。
上面分析的求值过程里增加了两种continuation:
κ

=
|
|
...
?arg,κ,N?
?fun,κ,V?


代码实现
函数value-of/k是→
v
。 函数apply-cont是→
c
。 编写代码要注意对value-of/和apply-cont的调用都必须是尾调用。
过程→
v
的代码:

出于写起来方便的原因,使用函数来保存continuation。 用(end-cont)表示空的continuation mt。
(end-cont)只有在程序结束的时候才会运行一次。 这里让(end-cont)打印了个">> Done!",这个打印只会运行一次。
如果打印了超过一次,或者没打印,那么代码肯定有错。
过程→
c
的代码:

寄存器风格的代码实现
这小节换个方式写代码。 求值过程有两个状态量:当前计算的表达式和当前的continuation。
我们用两个全局变量the-exp和the-cont来保存这两个状态量。 使用全局变量后,函数value-of/k和apply-cont就不再需要参数。
另外,还需要一个全局变量来保存下一步是要进行→
v
还是→
c
。 这个全局变量叫the-pc。 这三个全局变量被称作寄存器(所以叫寄存器风格)。 当the-pc的值为逻辑假#f时,解释器运行结束。
现在解释器运行时就是不断的执行the-pc直到the-pc的值是#f。 mainloop是这个主循环的过程:

进入主循环的过程前要先初始化寄存器:
过程value-of/k不再需要参数,用寄存器the-exp代替原来的exp1,the-cont代替原来的cont。
当然还有其他一些修改。代码如下:


过程apply-cont的修改和value-of/k类似。 代码如下:


思考
- 对宏展开过程translate和替换过程substitute做递归转迭代是否意义不大,为什么?
- 加入continuation后call-by-name的调用方式下的求值过程和代码实现?
简单易懂的程序语言入门小册子(7):基于文本替换的解释器,加入continuation,重构解释器,布布扣,bubuko.com
简单易懂的程序语言入门小册子(7):基于文本替换的解释器,加入continuation,重构解释器
标签:style blog class code tar ext
原文地址:http://www.cnblogs.com/skabyy/p/3704849.html