RLE and MIT Computation Center // Memo 39

LISP 1.5 新编译器_

一份来自 1962 年的备忘录,宣告了编程史上首个“自举”编译器的诞生。

作者: T. Hart & M. Levin

🏷️ 分类: 技术 历史
🔖 标签: #LISP #编译器 #编程历史 #MIT #自举编译器 #计算机科学

革命性的性能飞跃

快 40 倍的执行速度

编译后的子程序比S-表达式解释执行快约40倍,这是数量级的提升。

节省 80% 的存储空间

编译后的代码体积通常仅为原始S-表达式定义的20-30%。

核心突破:第一个自我编译的编译器

这个编译器完全由 LISP 语言编写。它的机器码版本是通过一个史无前例的过程获得的:让其自身的 LISP 源码(S-表达式)在解释器中运行,从而编译出它自己。

编译器 (S-表达式)

LISP 源码

LISP 解释器

执行环境

编译器 (机器码)

最终产物

三步编译管线

1

PASSONE

对 S-表达式进行分析和重写。标记特殊变量、优化函数调用方式、并将部分递归改写为更高效的 PROG 迭代循环。

2

PHASE2

将优化后的 S-表达式生成为汇编语言。解决计算顺序、参数定位、存储分配和条件转移等核心问题。

3

LAP

LISP 汇编程序 (LISP Assembly Program),将汇编代码转换为最终的可执行机器码子程序。

程序员指南:自由变量的处理

编译器和解释器可以自由混合使用,但必须正确声明“自由变量”(未在当前函数中绑定的变量)。这是确保代码正确性的关键。

SPECIAL

当一个变量仅在编译函数之间作为自由变量使用时声明。

  • 机制: 变量被分配到固定的内存地址,可被任何编译函数直接引用,效率高。
  • 存取: 存入新值时,旧值会自动压入堆栈,函数返回时恢复。
  • 声明: SPECIAL ((VAR1 VAR2...))

COMMON

当变量需要在编译函数和解释函数之间传递,或者作为函数参数时声明。

  • 机制: 变量存储在一个“A-list”(关联列表)上,该列表在解释器和编译代码间传递。
  • 处理: 编译函数对其的处理方式与解释器完全相同,兼容性最好。
  • 声明: COMMON ((VAR1 VAR2...))

底层揭秘:LINK 的动态链接

为了实现编译/解释代码的无缝混合,编译器采用了一种巧妙的动态链接机制。

首次调用函数时:

STR (Store and Trap)

一个陷阱指令,执行被 LINK 捕获

LINK 处理后:

TSX (Transfer and Set Index)

指令被替换,后续直接调用机器码

如果目标是 LISP 源码 (EXPR),LINK 会连接到解释器执行它。