3.2 栈机器和 FORTH 语言

    FORTH 语言开发于 1958 年左右 3,是一种几乎没有语法的语言。

    3于 1969 年发布。

    其设计者 Charles H. Moore 说 FORTH 是最简单的计算机语言 4。他认为,世上所有的程序设计语言都具备一定的可读性,但初次接触某种 语言的人常常感到困惑,这是由于它们的语法往往晦涩难懂且变化多端。而 FORTH 语言将语法控制到最少的程度缓和了这一问题 5。

    4《言語設計者たちが考えること》,Federico Biancuzzi、Shane Warden 编/伊藤真浩、 顷末和义、佐藤嘉一、铃木幸敏、村上雅章译,O'Reilly Japan,2010 年,p.66。中文版为《编程之魂:与 27 位编程语言创始人对话》,电子工业出版社于 2010 年 4 月出版,闫怀志译。
    5《言語設計者たちが考えること》,pp. 70-71。

    我们试着讲一下 FORTH 这门语言,看一下它和现在的语言有什么不同。

    计算的流程

    那么号称语法最少的 FORTH 语言是如何编写代码的呢? FORTH 语言中,1 加 2 是这样书写的:

    1 2 +

    我们来看一下这行代码是如何执行的。作为其一大特点,FORTH 语言使用了被称为栈的数值预存空间,如图 3.1 上方开口的格子所示。代码从头开始执行,处理器首先遇到的是数值 1, 于是在栈中放 1。然后遇到数值 2,再次把 2 存进栈。最后遇到 + 号。这个符号被定义的功能是,从栈中取出前面两个数值,再把其相加的结果存入栈。于是,从栈中把 1 和 2 取出来,加法运算后的结果 3 被放入栈中。

    空标题文档 - 图1

    图 3.1 利用栈的运算逻辑

    如何表达计算顺序

    这种语言是如何区别 1 加 2 再与 3 相乘即 (1+2)3 和 2 乘以 3 再与 1 相加即 1+(23) 这两种计算的呢?

    1 加 2 再乘以 3 可以表达为:6

    6希望实际执行一下 FORTH 语言的读者可以到笔者制作的网页上尝试一下:http://nhiro.org/learn_language/FORTH-on-browser.html
    1 2 + 3 *

    2 乘 3 再加 1 可以表达为:

    2 3 * 1 +

    基本上与日语中的语序是一致的 7。如果 1、2、3 的顺序很重要的话,也可以进行如下表达:

    7日语中以上两个算式的表达分别是:1 と 2 を足した(+)ものに 3 を掛ける()、2 と 3 を掛けた()ものに 1 を足す(+)。相关数值和运算符在日语语句中出现的次序与表达式是一致的。——译者注
    1 2 3 * +

    即 1 和 2 乘以 3 的结果相加。在 FORTH 语言中不需要括号也不需要导入优先次序的规则就可以表达计算顺序。

    现在仍然使用的栈机器

    如今,估计大家很少再用 FORTH 这种基于栈的语言直接编写代码了。但是在一些不常见的场合仍然会看到它的身影。比如,Java、Python、Ruby 1.9 这些语言使用了栈机器型的 VM。VM 执行的命令行和 FORTH 语言是一样的。用 Python、Ruby 或 Java 等语言写出来的程序,在机器内部先被转换(编译)成像 FORTH 语言一样的程序,然后再运行。

    我们用 Python 语言实际执行看一下。通过 Python 语言自带的库文件 dis,我们可以显示 VM 执行的命令行 8。

    8行末编号是笔者加上去的。
    Python
    >>> import dis
    >>> dis.dis(lambda x, y, z: (x + y) * z)
    0 LOAD_FAST 0 (x) ❶
    3 LOAD_FAST 1 (y) ❷
    6 BINARY_ADD ❸
    7 LOAD_FAST 2 (z) ❹
    10 BINARY_MULTIPLY ❺
    11 RETURN_VALUE

    (x+y) z 这行代码,被依次编译为命令行:❶将 x 压入栈→ ❷将 y 压入栈→ ❸把栈上两数相加→ ❹将 z压入栈→ ❺把栈上两数相乘。这和 FORTH 一样,是按 x y + z 的顺序排列的。