直接递归的消去规则:
基本思路:将递归调用的地方用等价的非递归代码来代替,并对return语句做适当处理。
13条规则:处理直接递归调用和return语句,将之转换成等价的迭代代码。
初始化
⑴ 在过程的开始部分,插入说明为栈的代码并将其初始化为空: StackType Stack[1..SIZE]
Top ← 0
在一般情况下,这个栈用来存放参数、局部变量和函数的值、每次递归调用的返回地址。
⑵ 将标号L1附于第一条可执行语句。
...
L1:第一条可执行语句
...
然后对于每一处递归调用都用一组执行下列规则的指令来代替。
处理递归调用语句
⑶ 将所有参数和局部变量的值存入栈。
Top ← Top +1
Stack[Top] ← …
栈顶指针可作为一个全程变量来看待。
⑷ 建立第i个新标号Li,并将标号的下标i存入栈。这个标号的i值将用来计算返回地址。
Top ← Top +1
Stack[Top] ← i
此标号放在规则⑺所描述的程序段中。
⑸ 计算这次调用的各实在参数(可能是表达式)的值,并把这些值赋给相应的形式参数。
⑹ 插入一条无条件转向语句转向过程的开始部分:
goto L1
(以上完成一次递归调用)
对退出点的处理
⑺ 如果这过程是函数,则对递归过程中含有此次函数调用的那条语句做如下处理:将该语句的此次函数调用部分用从栈顶
取回该函数值的代码来代替,其余部分的代码按原描述方式照抄,并将⑷中建立的标号附于这条语句上。
如果此过程不是函数,则将⑷中建立的标号附于⑹所产生的转移语句后面的那条语句。
以上步骤消去过程中的递归调用。
下面对过程中出现return语句进行处理。
注:纯过程结束处的end可看成是一条没有值与之联系的return语句
对每个有return语句的地方,执行下述规则:
⑻ 如果栈为空,则执行正常返回。
if top = 0 then return(…)
⑼ 否则,将所有输出参数(带有返回值的出口参数,out/ inout型)的当前值赋给栈顶上的那些对应的变量。
Stack[n] ← …
⑽ 如果栈中有返回地址标号的下标,就插入一条此下标从栈中退出的代码,并把这个下标赋给一个未使用的变量。
addr ← Stack[Top]
Top ← Top -1
⑾ 从栈中退出所有局部变量和参数的值并把它们赋给对应的变量。
⑿ 如果这个过程是函数,则插入以下指令,这些指令用来计算紧接在return后面的表达式并将结果值存入栈顶。
Top ← Top +1
Stack[Top] ←表达式的值
⒀ 用返回地址标号的下标实现对该标号的转向。
if addr = i then goto Li
递归转非递归(13条消除规则)