body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
代码指针域中包含有一个程序段的地址,每当一个定义被引用时该程序段就首先被执行。因此,又称该程序段为运行时间代码,不同类型的定义具有不同的运行时间代码。运行时间代码决定了一个词的类别,决定了该词的特性及如何对待和处理放在该词参数域中的数据。
三种不同类型的定义,常数、变量和冒号定义。CONSTANT、VARIABLE 和 冒号定义 可以给词典增加新词,所以又把它们称为 定义词。
如果由代码指针域所指着的运行时间代码是由汇编代码来定义的,则定义一个新的定义词的格式是:
: 新定义词名 CREATE ... ;CODE 汇编代码
其中汇编代码是由汇编助记符编写的程序段。
如果运行时间代码是由冒号定义规定的话:
: 新定义词名 CREATE ... DOES> ... ;
CREATE 使用输入流中下一个字符串作为名字在词典中建立一个入口,CREATE 后面的内容规定词典中如何编译一个新的定义,DOES> 后面的内容规定新定义的运行时间代码。
// 定义一个 双字长常数 : DCONSTANT CREATE , , DOES> DUP 2 + @ SWAP @ ; |
123.456 DCONSTANT CON1 CON1 D. |
运行时间行为:
任何由 CREATE 所创立的词的“缺省”的运行时间代码行为是返回其词身的地址。而词身在词典中的大小,格式及最初的内容则是由定义词在编译阶段的行为决定的,也就是定义词中跟随在 CREATE 之后的词决定。
CREATE 名称 生成<名称>的词典项目。在<名称>生成之后,下一个可利用的词典单元就是<名称>的参数域中的第一个字节,随后执行<名称>时,<名称>的参数域中的第一个字节的地址被留在堆栈中,CREATE并不给<名称>的参数域分配空间。
CREATE 定义的词的代码指针CFA就是CREATE的运行时间代码,当定义的词被执行时,把潜在的参数域(PFA)地址压栈。
DOES> 运行时间:标志它的编译部分的结束和运行时间的开始。运行时间的操作由高级形式 FORTH 编写。在运行时间,被定义的词的参数域地址压栈。
延迟词:
当一个冒号定义被引用时,组成该冒号定义的各个词就被顺序执行。即词典中一个冒号定义的功能是固定不变的。
定义这样的词,定义它的时候勿需确定它的功能;这种在编译时不规定功能,其功能延迟到以后再规定的词叫做延迟词。FORTH 中用 DEFER 来定义。
: DEFER ( - ) (建立一个延迟词) CREATE (建立延迟词首部) 2 ALLOT (参数域为一个单元) DOES> @ EXECUTE ; (运行时间代码) |
当定义词 DEFER 运行时,在词典中建立一个词身位一个单元的延迟词,并规定延迟词的运行时间代码;当延迟词执行时,把其 pfa 单元内的地址交给 EXECUTE 执行。 |
: WARNING ." Uninitialized" ; : DEFER CREATE ['] WARNING , DOES> @ EXECUTE ; // 这样定义防止DEFER定义词未赋值么有执行代码无法继续执行下去 |
为了简化规定延迟词的功能的工作(即把某一个定义的编译地址填入延迟词的 pfa 单元)所用到的定义是 IS :
: IS ( cfa - ) ' >BODY ! ; 把跟着的词的 pfa 单元置为参数栈顶的地址。
上面的操作可以这样写
//为了能在冒号定义内部也能使用 IS ,把 IS 的定义改进如下:
STATE ( - addr) 具有编译状态的变量。STATE 之值非 0 ,表明系统处于编译状态;为零,则表明系统处于解释(执行)状态。 |
: (IS) ( cfa - ) ( IS的执行时间行为) R@ @ >BODY ! (得到目标地址) R> 2+ >R ; ( 调整 IP ) |
: IS ( cfa - ) 把跟着的词身(pfa)置为参数栈顶的数值。若在冒号定义内使用,则IS作用于在冒号定义中跟着它的词。 STATE @ IF COMPILE (IS) 系统处于编译状态则做此工作。 ELSE ' >BODY ! 系统处于解释状态做此工作。 THEN ; IMMEDIATE 由于 IS 在冒号定义内部也要能使用,所以它必须是立即词。 |