概括。
所有这些特殊标记 , , [
,]
都作为可执行名称从扫描器中出来。并被定义为产生一个标记类型对象(因此它们本身不是运算符,但它们是在所有运算符所在的位置定义的可执行名称)。并且被定义为过程或操作符,其执行方式与任何其他过程或操作符一样。这些使用运算符来查找左括号。但是所有这些标记都由扫描仪特殊处理,扫描仪可以识别它们而没有周围的空白,因为它们是其分隔符集的一部分。<<
>>
[
<<
systemdict
]
>>
counttomark
细节。
这完全取决于你什么时候看。让我们追溯一下解释器对这些标记做了什么。我将用一个字符串来说明这一点,但它与文件的工作原理相同。
所以如果你有一个输入字符串
([4 5 6]) cvx exec
cvx
使文字对象可执行。程序流是一个文件对象,也标记为可执行文件。exec
将对象推入执行堆栈,解释器在内部解释器处理循环的下一次迭代中遇到该对象。执行程序流时,可执行文件对象位于执行堆栈的最顶端。
解释器token
用来调用扫描器。扫描程序会跳过初始空格,然后读取所有非空格字符直到下一个分隔符,然后尝试将字符串解释为数字,但未能将其变为可执行名称。括号是定界符集的一部分,因此被称为“自定界”。所以扫描器读取一个括号字符,停止读取,因为它是一个分隔符,发现它不能是一个数字,所以它产生一个可执行名称。
Top of Exec Stack | Operand Stack
(4 5 6]) [ |
接下来,解释器循环执行任何可执行文件(除非它是一个数组)。执行令牌意味着从字典中加载它,然后执行定义(如果它是可执行的)。[
定义为-mark-
对象,与mark
定义名称相同。从技术上讲,它不是操作员或程序,它只是一个定义。自动加载发生是因为名称来自扫描仪并设置了可执行标志。
(4 5 6]) | -mark-
然后扫描器产生 4、5 和 6,它们是数字并被直接推入操作数堆栈。6 由]
在流上推回的 定界。
(]) | -mark- 4 5 6
解释器不执行这些数字,因为它们是不可执行的,但如果它执行了,它会是一样的。执行一个数字的动作只是将它压入堆栈。
然后,扫描仪终于遇到了右支架]
。这就是魔法发生的地方。自定界,后面不需要任何空格。扫描器产生可执行文件名]
,解释器通过加载来执行它,它发现......
{ counttomark array astore exch pop }
或者可能是执行此操作的实际操作员。但是,是的。counttomark
产生元素的数量。array
创建该大小的数组。astore
用堆栈中的元素填充数组。并exch pop
一劳永逸地丢弃那个讨厌的标记。
对于字典,<<
与 完全相同[
。它留下一个标记。然后你排列一些键值对,并且>>
是对...产生影响的过程
{ counttomark dup dict begin 2 idiv { def } repeat pop currentdict end }
制作字典。定义所有对。弹出标记。拿出字典。此版本的过程尝试通过将其设置为双倍大小来创建快速字典。将2 idiv
to 移到前面dup
以制作一个小字典。
因此,从哲学上讲,counttomark
是您正在使用的运算符。并且它需要一个不用于其他任何东西的特殊对象类型,marktype 对象,-mark-
. 其余的只是语法糖,让您访问这种堆栈计数能力来创建线性数据结构。
附录
这是一个模拟解释器循环读取的过程currentfile
。
{currentfile token not {exit} if dup type /arraytype ne {exec} if }loop
exec
负责load
ing(并进一步执行)任何可执行文件名。从中可以看出,这token
确实是扫描仪的名称;并且解释器循环直接遇到的过程(数组)不会被执行( type /arraytype ne {exec} if
)。
然而,使用token
字符串可以让你做一些很酷的事情。例如,您可以使用替换名称动态构造过程主体。这很像一个 lisp 宏。
/makeadder { % n . { n add }
1 dict begin
/n exch def
({//n add}) token % () {n add} true
pop exch pop % {n add}
end
} def
token
从字符串中读取整个过程,将立即评估的名称 //n
替换为其当前定义的值。请注意,扫描程序一次读取一个可执行数组,在返回之前在内部有效地执行[
... ] cvx
(在某些解释器中,例如我自己xpost
的在单独的内存中。但是 2 级垃圾收集使这在很大程度上无关紧要)。
还有bind
一个运算符通过用运算符对象本身替换运算符名称来修改过程。这些技巧可帮助您在速度关键的过程(如内部循环)中排除名称查找。