第四,解释还是编译?
Forth, interpreted or compiled?
据说 Forth 程序可以是 "compiled",但如果它们的单词仅在运行时求值,我不明白这是怎么回事。例如,单词 DOES>
存储用于运行时评估的单词。如果这些单词包含 EVALUATE
或 INTERPRET
单词,那么在运行时将需要字典。
为了支持这样的语句,这意味着整个单词列表(词典)必须嵌入到程序中,本质上就是解释程序(不是编译程序)所做的。
这似乎会阻止您使用 Forth 编译小程序,因为整个字典必须嵌入到程序中,即使您只使用了字典中的一小部分单词。
这是正确的,还是有什么方法可以在不嵌入字典的情况下编译 Forth 程序? (也许根本不使用运行时词??)
Forth 程序可以带或不带字编译headers。 headers 包含单词名称(称为 "name space")。
在您描述的场景中,程序可能包含 run-time 评估调用,例如 EVALUATE
,将需要 headers。
字典可以分为逻辑上不同的三个部分:名称space、代码space和数据space。程序执行需要代码和数据,名字通常不需要。
一个普通的 Forth 程序通常不会做任何 运行时间评估。所以在大多数情况下,编译程序中不需要这些名称。
DOES>
后的代码是编译过的,所以在运行时不求值。它在 运行 时间 执行。
即使包含名称,它们通常不会增加程序大小。
许多 Forths 确实有办法从程序中省略名称。有些有一个开关来删除单词 headers (名称)。其他的交叉编译器在编译期间将名称保留在主机系统中,但生成没有名称的目标代码。
不,整个词典不需要嵌入,也不需要编译。需要保留的只是所用单词的列表,以及它们的父单词(& grandparents,etc.)。并且单词的偶数名称不是必需的,单词位置就足够了。 Forth 用这种方法编译的代码可以尽可能地紧凑,在可执行文件的大小上可以与汇编语言相媲美甚至超过汇编语言。
示例证明:Tom Almy 的 ForthCMP,一个 80 年代到 90 年代的 MSDOS 编译器,它缩小了可执行代码。它的自述文件说:
. Compiles Forth into machine code -- not interpreted.
. ForthCMP is written in Forth so that Forth code can be executed
during compilation, as is customary in Forth applications.
. Very fast -- ForthCMP compiles Forth code into an executable file
in a single pass.
. Generated code is extremely compact. Over 110 Forth "primitives"
are compiled in-line. ForthCMP performs constant expression
folding, strength reduction, register optimization, DO...LOOP
optimization, tail recursion, and various "peephole"
optimizations.
. Built-in assembler.
4C.COM
在 dosemu
或 dosbox
.
等模拟器下运行
A "Hello World" compiles into a 117 byte .COM file, a wc
program 编译成 3K .COM 文件(来自 5K 的源代码)。没有字典或外部库,(除了标准的 MSDOS 调用,即它运行的 OS)。
Forth 可能很难从外部引起您的注意,因为该语言没有标准的实现。人们看到的大部分内容都来自 Forth 的早期,当时作者(Charles Moore)仍在讨论他自己的想法。或者更糟的是,人们称之为 Forth 的自制系统,因为它有一个堆栈但实际上不是 Forth。
那么 Forth 是解释型还是编译型?
简短回答:两者
早年:
Forth 有一个面向程序员的文本解释器。所以解释:检查
但是...“:”字符使编译器能够“编译”语言中单词的地址,因此它被“编译”但不是作为本机机器代码。它是代码在内存中的地址列表。聪明的部分是这些地址可以 运行 带有一个列表“解释器”,在大多数机器上只有 2 或 3 条指令,而在旧的 8 位 CPU 上更多一些。这意味着它仍然非常快并且非常 space 高效。
这些系统更像是一个图像系统,所以是的,系统与您的程序一起运行,但其中一些系统内核在整个 运行 时间(包括编译器和解释器)中为 8K 字节。不是繁重的工作。
这就是大多数人认为的 Forth。有关文字示例,请参阅 JonesForth。 (这在当时被称为“线程代码”,不要与多线程混淆)
1990 年代左右
Forth 大师和 Chuck Moore 开始意识到 Forth 语言原语在现代机器上可以和一条机器指令一样小,所以为什么不只编译指令而不是地址。这对 32 位机器非常有用,因为地址有时比指令大。然后他们可以用处理器的本机 CALL/Return 指令替换小的 3 指令解释器。这称为子例程线程。前端解释器并没有消失。它只是启动了本地代码子例程
今天
商业 Forth 系统生成本机代码、内联 many/most 原语并执行您在现代编译器中看到的许多其他优化技巧。
他们仍然有面向程序员的翻译。 :-)
您还可以购买(或构建)Forth 交叉编译器,为不同的 CPU 创建独立的可执行文件,包括多任务、TCP/IP 堆栈,猜猜看,文本解释器可以是编译到可执行文件中,作为远程调试和配置的选项(如果需要)。
那么 Forth 是解释型还是编译型?还是两者。
你说得对,执行 INTERPRET(EVALUATE、LOAD、INCLUDE 等)的程序必须有字典。这几乎不是缺点,因为即使是 64 位可执行文件对于 Linux 或 MS-Windows 也只是 50 K。像 MSP430 这样的现代单板计算机可以在闪存中存储整个词典。分别参见 ciforth 和 noforth。然后是脚本。如果您使用 Forth 作为脚本语言,它类似于 perl 或 python 脚本很小,并且不包含整个语言。它要求您的计算机上安装了该语言。
对于非常小的计算机,您可以求助于交叉编译或使用 umbellical Forth,其中字典位于主机上并通过串行线进行通信和编程。这些是通常不需要的特殊技术。在 sbc 上的那些情况下,您不能使用解释代码,因为显然那里没有字典。
注意:提及 DOES> 指令并不能使问题更清楚。我建议您将其编辑掉。
据说 Forth 程序可以是 "compiled",但如果它们的单词仅在运行时求值,我不明白这是怎么回事。例如,单词 DOES>
存储用于运行时评估的单词。如果这些单词包含 EVALUATE
或 INTERPRET
单词,那么在运行时将需要字典。
为了支持这样的语句,这意味着整个单词列表(词典)必须嵌入到程序中,本质上就是解释程序(不是编译程序)所做的。
这似乎会阻止您使用 Forth 编译小程序,因为整个字典必须嵌入到程序中,即使您只使用了字典中的一小部分单词。
这是正确的,还是有什么方法可以在不嵌入字典的情况下编译 Forth 程序? (也许根本不使用运行时词??)
Forth 程序可以带或不带字编译headers。 headers 包含单词名称(称为 "name space")。
在您描述的场景中,程序可能包含 run-time 评估调用,例如 EVALUATE
,将需要 headers。
字典可以分为逻辑上不同的三个部分:名称space、代码space和数据space。程序执行需要代码和数据,名字通常不需要。
一个普通的 Forth 程序通常不会做任何 运行时间评估。所以在大多数情况下,编译程序中不需要这些名称。
DOES>
后的代码是编译过的,所以在运行时不求值。它在 运行 时间 执行。即使包含名称,它们通常不会增加程序大小。
许多 Forths 确实有办法从程序中省略名称。有些有一个开关来删除单词 headers (名称)。其他的交叉编译器在编译期间将名称保留在主机系统中,但生成没有名称的目标代码。
不,整个词典不需要嵌入,也不需要编译。需要保留的只是所用单词的列表,以及它们的父单词(& grandparents,etc.)。并且单词的偶数名称不是必需的,单词位置就足够了。 Forth 用这种方法编译的代码可以尽可能地紧凑,在可执行文件的大小上可以与汇编语言相媲美甚至超过汇编语言。
示例证明:Tom Almy 的 ForthCMP,一个 80 年代到 90 年代的 MSDOS 编译器,它缩小了可执行代码。它的自述文件说:
. Compiles Forth into machine code -- not interpreted.
. ForthCMP is written in Forth so that Forth code can be executed
during compilation, as is customary in Forth applications.
. Very fast -- ForthCMP compiles Forth code into an executable file
in a single pass.
. Generated code is extremely compact. Over 110 Forth "primitives"
are compiled in-line. ForthCMP performs constant expression
folding, strength reduction, register optimization, DO...LOOP
optimization, tail recursion, and various "peephole"
optimizations.
. Built-in assembler.
4C.COM
在 dosemu
或 dosbox
.
A "Hello World" compiles into a 117 byte .COM file, a wc
program 编译成 3K .COM 文件(来自 5K 的源代码)。没有字典或外部库,(除了标准的 MSDOS 调用,即它运行的 OS)。
Forth 可能很难从外部引起您的注意,因为该语言没有标准的实现。人们看到的大部分内容都来自 Forth 的早期,当时作者(Charles Moore)仍在讨论他自己的想法。或者更糟的是,人们称之为 Forth 的自制系统,因为它有一个堆栈但实际上不是 Forth。
那么 Forth 是解释型还是编译型? 简短回答:两者
早年: Forth 有一个面向程序员的文本解释器。所以解释:检查
但是...“:”字符使编译器能够“编译”语言中单词的地址,因此它被“编译”但不是作为本机机器代码。它是代码在内存中的地址列表。聪明的部分是这些地址可以 运行 带有一个列表“解释器”,在大多数机器上只有 2 或 3 条指令,而在旧的 8 位 CPU 上更多一些。这意味着它仍然非常快并且非常 space 高效。 这些系统更像是一个图像系统,所以是的,系统与您的程序一起运行,但其中一些系统内核在整个 运行 时间(包括编译器和解释器)中为 8K 字节。不是繁重的工作。
这就是大多数人认为的 Forth。有关文字示例,请参阅 JonesForth。 (这在当时被称为“线程代码”,不要与多线程混淆)
1990 年代左右 Forth 大师和 Chuck Moore 开始意识到 Forth 语言原语在现代机器上可以和一条机器指令一样小,所以为什么不只编译指令而不是地址。这对 32 位机器非常有用,因为地址有时比指令大。然后他们可以用处理器的本机 CALL/Return 指令替换小的 3 指令解释器。这称为子例程线程。前端解释器并没有消失。它只是启动了本地代码子例程
今天 商业 Forth 系统生成本机代码、内联 many/most 原语并执行您在现代编译器中看到的许多其他优化技巧。 他们仍然有面向程序员的翻译。 :-)
您还可以购买(或构建)Forth 交叉编译器,为不同的 CPU 创建独立的可执行文件,包括多任务、TCP/IP 堆栈,猜猜看,文本解释器可以是编译到可执行文件中,作为远程调试和配置的选项(如果需要)。
那么 Forth 是解释型还是编译型?还是两者。
你说得对,执行 INTERPRET(EVALUATE、LOAD、INCLUDE 等)的程序必须有字典。这几乎不是缺点,因为即使是 64 位可执行文件对于 Linux 或 MS-Windows 也只是 50 K。像 MSP430 这样的现代单板计算机可以在闪存中存储整个词典。分别参见 ciforth 和 noforth。然后是脚本。如果您使用 Forth 作为脚本语言,它类似于 perl 或 python 脚本很小,并且不包含整个语言。它要求您的计算机上安装了该语言。
对于非常小的计算机,您可以求助于交叉编译或使用 umbellical Forth,其中字典位于主机上并通过串行线进行通信和编程。这些是通常不需要的特殊技术。在 sbc 上的那些情况下,您不能使用解释代码,因为显然那里没有字典。
注意:提及 DOES> 指令并不能使问题更清楚。我建议您将其编辑掉。