E.9 对象内部结构

Emacs Lisp 提供了丰富的数据类型集合。其中一些类型,如 cons 单元、整数和字符串,几乎所有 Lisp 方言都通用。另一些类型,如标记(markers)和缓冲区(buffers),则非常特殊,是提供用 Lisp 编写编辑器命令的基本支持所必需的。为了实现如此多样的对象类型,并提供一种在解释器各子系统之间高效传递对象的方式,存在一组 C 数据结构,以及一种用于表示指向所有这些结构的指针的特殊类型,该类型被称为 带标签指针(tagged pointer)

在 C 语言中,带标签指针是 Lisp_Object 类型的对象。此类的任何已初始化变量始终保存以下基本数据类型之一的值:整数、符号、字符串、cons 单元、浮点数或类向量对象。每种数据类型都有对应的标签值。所有标签均由 enum Lisp_Type 枚举,并放置在 Lisp_Object 的 3 位位域中。其余的位是值本身。整数是直接值(immediate),即直接由这些 值位(value bits)表示;而所有其他对象都由指向从堆中分配的对应对象的 C 指针表示。Lisp_Object 的宽度取决于平台和配置:通常等于底层平台指针的宽度(即在 32 位机器上为 32 位,在 64 位机器上为 64 位),但也存在一种特殊配置,其中 Lisp_Object 为 64 位,但所有指针为 32 位。后者的设计初衷是,通过对 Lisp_Object 使用 64 位的 long long 类型,来克服 32 位系统上 Lisp 整数取值范围有限的问题。

以下在 lisp.h 中定义的 C 数据结构用于表示整数之外的基本数据类型:

struct Lisp_Cons

Cons 单元,用于构造列表的对象。

struct Lisp_String

字符串,用于表示字符序列的基本对象。

struct Lisp_Vector

数组,一种可通过索引访问的固定大小的 Lisp 对象集合。

struct Lisp_Symbol

符号,通常用作标识符的唯一命名实体。

struct Lisp_Float

浮点数值。

这些类型是内部类型系统的一等公民。由于标签空间有限,所有其他类型都是 Lisp_Vectorlike 的子类型。类向量子类型由 enum pvec_type 枚举,几乎所有复杂对象(如窗口、缓冲区、框架和进程)都属于此类别。

下面描述 Lisp_Vectorlike 的一些子类型。缓冲区对象代表要显示和编辑的文本。窗口是显示结构的一部分,用于显示缓冲区或作为在同一框架上递归放置其他窗口的容器。(请勿将 Emacs Lisp 窗口对象与用户界面系统(如 X)管理的窗口实体混淆;在 Emacs 术语中,后者称为框架。)最后,进程对象用于管理子进程。