跳转到内容

从零开始制作编程语言/决策

来自维基教科书,开放世界开放书籍

你的目标是制作一种编程语言。但是,市场上已经存在许多语言。你制作的语言有什么目的?其实,主要是语法和输出代码的细微差别造成了各种语言的多样性。主要是内存格式和执行速度。但是,一般来说,这两者无法兼得。因此,需要做出一些权衡,最终将决定你语言的重要性以及它在全球市场中的地位。有一些细微的因素,比如变量的通用范围、指令的冗余、编译风格和执行速度差异,这些因素乍一看似乎微不足道,但当它们在一份长长的源代码文件中累积起来时,它们可以决定程序执行时间是几分钟还是几小时。这些细微因素仍然是不断研究新颖且更强大的编程语言的驱动力。以下部分将涵盖你在开始编写语言之前必须做出的几个主要决策。

基础语言

[编辑 | 编辑源代码]

直接编译成机器语言非常困难,通常情况下,下一个最好的步骤是使用汇编语言。但是,即使在汇编语言中,编译所需的实际文件输入和输出操作也非常复杂且难以编写。幸运的是,现在有一些高级语言可以用来编写我们的编译器。请注意,基础语言的选择对于最终输出质量并不重要,但对于编译速度和编译器编写难易程度非常重要。这个项目很可能非常耗时,因此必须选择你感到舒适的语言。

通常情况下,C++ 和 C 等编译型语言的执行速度比解释型语言快得多。但是,它们的缺点是可移植性较低,因此基础语言的选择完全取决于你的优先级。

内存格式

[编辑 | 编辑源代码]

如今内存容量非常大(通常约为 8 GB RAM),因此可以考虑以前不可想象的默认静态内存布局格式。在这种格式下,在函数内声明的变量保持活动状态,即它们即使在函数返回控制权后,也一直保留其值,直到程序终止。这意味着函数可以更长时间地保存其值,这是一个重要的因素,可以使程序更加简短高效。但是,大多数语言都使用所谓的“堆栈”变量,其中变量被推入称为堆栈的内存单元,它们一直保留在那里,直到函数结束。但是,在它们的寿命结束后,堆栈不会被清除,而是保持原样,只是现在它可用于覆盖先前变量的后续变量。但是,这会导致“垃圾值”,从而导致程序错误。此外,它需要一个复杂的数据管理系统。但是,堆栈变量占用的空间更小,访问速度也更快。此外,还有寄存器变量选项,它们保留在寄存器中,寄存器的访问速度比堆栈变量快 30 倍。但是,寄存器变量需要非常复杂的数据管理,这会使编译器更加复杂。

之后,还有汇编中的 .[MODE] 指令选项。这取决于你正在为其编写编译器的处理器类型。对于 808386 处理器,使用 .386;对于 808486 处理器,使用 .486,等等。一些汇编语言支持同一个处理器的多种模式,但是每种模式最适合其自己的特定处理器。此外,还有 MODEL 指令,即 FLAT 模型、BIG、TINY、LARGE 和 MEDIUM。每个模型最适合其自己的类型。在这本书中,我们使用 FLAT 模型。还取决于操作系统的 MODE。在这里,我们使用保护模式,它提供了 16 TB(可能因机器而异)的“虚拟内存”。

此外,在实际内存分配的情况下,分别使用 NEAR 和 FAR 指针用于 NEAR 和 FAR 模型。在保护模式下,操作系统假设 NEAR 模式,因此使用 NEAR 指针。

另一个需要考虑的因素是变量的大小。通常使用三个变量 int、char 和 float。在 32 位环境的 C 编译器中,int 占用 4 字节,char 占用 1 字节,float 占用 8 字节(对于 double)。还有其他指令 short、long、single 和 double,你可能选择包含在你的编程语言中,也可能选择不包含。

大多数汇编器会自行处理内存分配,但是对于某些汇编器,你必须更明确地给出精确的指令,说明你希望将变量放在哪里。

每个语言设计者都知道,如今区分编程语言的最重要因素是执行速度。但是,速度并非易事,如果你想要速度,最好为被称为优化的过程中大量的辛苦付出做好准备。此外,速度往往与内存布局冲突,因此你需要决定哪个对你来说更重要。冗余是另一个因素,但为了消除冗余,你需要编写非常长的算法来检查每种冗余可能性。


Clipboard

待办事项
添加更多细节和因素


华夏公益教科书