冒号定义的基本结构
I 是由地址解释程序使用的指针,称为“解释程序指针”。
EXIT 是使执行流程返回到当前定义中的下一个高级定义。
对于所有类型的定义,其词典条目的头以及代码指针的格式都相同,但是参数域的格式要根据定义类型的不同而变化。
: PHOTOGRAPH SHUTTER OPEN TIME EXPOSE SHUTTER CLOSE ;
当执行PHOTOGRAPH时,依次执行顺序地址所确定的各个定义。用来读出这些地址并执行每个地址中的定义的机构称为“地址解释程序”。定义结尾的词 ; 将编译 EXIT 的地址。如图所示, EXIT 的地址被安排在词典条目的最后一个单元。当地址解释程序取得这个地址时,就象执行其他词一样执行 EXIT 。
(冒号定义的参数域中所包含的地址通常是代码域地址(cfa),而不是参数域地址(pfa))
执行的嵌套
假设定义 DINNER 由三个词组成
: DINNER SOUP ENTREE DESSERT ;
: ENTREE CHICKEN RICE ;
假设正在执行 DINNER 而且刚执行完 SOUP 。由于 SOUP 后面的词是 ENTREE ,这时解释程序指针指向存放 ENTREE 地址单元。 执行 ENTREE 之前,解释程序指针先增1,以便执行完 ENTREE 时能返回到指针正指向的 DESSERT 去执行。 ; 执行 ENTREE ,首先执行的是 ENTREE 的代码,即由代码域所指向的 : 的代码。这种代码完成两件事:首先把解释程序指针压入返回堆栈保存;其次把它本身的参数域地址(pfa)放入ENTREE的解释程序指针。 这时解释程序指针指向了 CHICKEN ,因此,地址解释程序已准备执行 CHICKEN ;和执行 ENTREE 一样,在执行 CHICKEN 之前,解释程序指针增1指向 RICE ,为返回做准备。然后 CHICKEN 的代码把该指针压入返回堆栈保存,并把 CHICKEN 自身的pfa放入新的解释程序指针。;最后重复上述过程执行 CHICKEN 中所有的定义。执行到 CHICKEN 中的 EXIT 的时候会从返回栈弹出一数并把它放解释程序指针(旧的I)。现在用这个程序解释指针继续执行 RICE 。 依次执行到最后会执行到 EXIT 再弹出返回栈的一个数(最旧的I)放入解释程序指针,为最后执行 DESSERT 作准备。
一步退出
INTERPRET 是一个检查整个输入流的循环结构。INTERPRET 又是终端外层定义 QUIT 的组成部分。QUIT 定义的基本形式如下:
: QUIT BEGIN ( 清除返回堆栈 等待输入 ) INTERPRET ." OK" CR 0 UNTIL ; 括号中的说明表示尚未讨论的词和短语。
如果我们在执行的任何层次中执行 QUIT ,都将立即终止应用程序的执行而重新进入 QUIT 循环,这时将清除返回堆栈(无论栈中有多少层的返回地址,因为现在我们决不能使用它们中的任何一个地址),系统等待输入。
舍弃嵌套
上面 DINNER 执行过程:
若是把定义改成 : ENTREE CHICKEN RICE R> DROP ; R> DROP 是从返回堆栈中清除 DESSERT 的返回地址,该地址是在执行 ENTREE 之前压入返回堆栈的。这样做的话 EXIT 直接返回到第一层。就只会执行 SOUP , CHICKEN 和 RICE , 跳过了第二层。
//这是因为 EXIT 从返回堆栈顶移除返回地址并把它放入解释程序指针。然后解释程序得到其去向的地址开始向上寻找下一层。
从新定义 ENTREE
: ENTREE CHICKEN EXIT RICE ;
这样的话在执行 DINNER 时,我们将在 CHICKEN 之后正确退出返回到 ENTREE 后面下一个词 DESSERT 。
//EXIT 直接舍弃了 RICE 的执行。