Compilation 第四,解释还是编译?

Compilation 第四,解释还是编译?,compilation,forth,Compilation,Forth,据说Forth程序可以“编译”,但如果它们有只在运行时计算的单词,我看不出这是怎么回事。例如,有一个单词DOES>,它存储单词以便在运行时进行评估。如果这些单词包括评估或解释单词,则运行时需要词典 为了支持这样的语句,这意味着整个单词列表(字典)必须嵌入到程序中,本质上就是解释程序(不是编译程序)所做的事情 这似乎会阻止您使用Forth编译小程序,因为整个字典必须嵌入到程序中,即使您只使用字典中的一小部分单词 这是正确的,还是有什么方法可以在不嵌入字典的情况下编译Forth程序?(可能根本不使用

据说Forth程序可以“编译”,但如果它们有只在运行时计算的单词,我看不出这是怎么回事。例如,有一个单词
DOES>
,它存储单词以便在运行时进行评估。如果这些单词包括
评估
解释
单词,则运行时需要词典

为了支持这样的语句,这意味着整个单词列表(字典)必须嵌入到程序中,本质上就是解释程序(不是编译程序)所做的事情

这似乎会阻止您使用Forth编译小程序,因为整个字典必须嵌入到程序中,即使您只使用字典中的一小部分单词


这是正确的,还是有什么方法可以在不嵌入字典的情况下编译Forth程序?(可能根本不使用运行时单词??)

Forth程序可以使用或不使用单词头进行编译。标题包括单词名(称为“名称空间”)

在您描述的场景中,如果程序可能包括运行时evalutation调用,例如
EVALUATE
,则需要标头

  • 字典可以分为三个逻辑上不同的部分:名称空间、代码空间和数据空间。程序执行需要代码和数据,而名称通常不需要

  • 普通的Forth程序通常不会进行任何运行时计算。因此,在大多数情况下,编译程序中不需要这些名称

  • 编译了
    之后的代码
    ,因此不会在运行时对其进行计算。它在运行时执行

  • 即使包含名称,它们通常也不会增加程序的大小

  • 许多Forth确实有办法从程序中删除名称。有些人有一个删除单词标题(名称)的开关。其他的有交叉编译器,它们在编译时将名称保留在主机系统中,但生成没有名称的目标代码

不,不需要嵌入或编译整个词典。剩下的只是所用单词的列表,以及它们的父单词(&祖父母,等等)。单词的名称也不是必需的,单词的位置就足够了。用这种方法编译的Forth代码可以非常紧凑,在可执行大小上可以与汇编语言相媲美,甚至超过汇编语言

举例证明:Tom Almy's,一个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编译成117字节的.COM文件,A
wc
程序编译成3K.COM文件(源代码为5K)。没有字典或外部库(除了标准的MSDOS调用,即它运行的操作系统)。

Forth可能是一个从外部让你头疼的问题,因为该语言没有标准的实现。人们看到的大部分是福斯早期的作品,当时作者查尔斯·摩尔(Charles Moore)仍在按摩自己的思想。或者更糟糕的是,自制的系统,人们会因为它有一个堆栈而发出,但实际上并没有发出

那么Forth是解释还是编译的呢? 简单回答:两者都有

早年: 福斯有一个面向程序员的文本解释器。如此解释:检查

但是。。。“:”字符使编译器能够“编译”语言中单词的地址,因此它是“编译”的,而不是本机代码。它是代码在内存中的地址列表。聪明的一点是,这些地址可以用一个列表“解释器”运行,在大多数机器上只有2或3条指令,而在旧的8位CPU上则有更多指令。这意味着它仍然是相当快,相当节省空间。 这些系统更像是一个映像系统,因此系统与您的程序一起运行,但其中一些系统内核在整个运行时都是8K字节,包括编译器和解释器。不是重物

这就是大多数人认为的福斯。参见JonesForth了解一个有文化的例子。(这在当时被称为“线程代码”,不要与多线程混淆)

1990年 Forth gurus和Chuck Moore开始意识到,在现代机器上,Forth语言原语可能只有一条机器指令,那么为什么不编译指令而不是地址呢。这对于32位机器非常有用,因为地址有时比指令大。然后,他们可以用处理器的本机调用/返回指令替换小3指令解释器。这被称为子程序线程。前端解释器没有消失。它只是启动了本机代码子例程

今天 商用Forth系统生成本机代码,内联许多/大多数原语,并执行现代编译器中的许多其他优化技巧。 他们仍然有一个面向程序员的解释器。:-)

您还可以购买(或构建)Forth交叉编译器,为不同的CPU创建独立的可执行文件,包括多任务、TCP/IP堆栈,猜猜看,如果您需要,文本解释器可以编译到可执行文件中,作为远程调试和配置的选项


那么Forth是解释还是编译的呢?还是两者都有。

是的,但是DOES>子句可以包含EVALUATE或exploration单词。我已经更新了我的答案来澄清这一点。@TylerDurden,任何一个词都可以在其中进行评估。单词的DOES>部分没有什么特别之处。我已经接受了这个答案,因为很长时间没有进一步的答案,但它确实完全回答了我的问题,因为它确实解决了一个程序是否需要将整个词典包含在“编译”中的基本问题程序,以及这是否会取消Forth程序被视为编译的资格。如果您需要mor