豫言独立实现技术规范
本规范供未参与豫言开发的实现者从零编写编译器,并与既有豫言对象文件及运行时互操作。它固定描述仓库提交 4cdeca11600fed16338793a494b6eecaae94485a,称为“本基线”;不是对未来版本的推测。阅读顺序如下,两种语言版本以相同章节和规则编号对应。
- 词法与语法:字符扫描、语法、结合与语法糖。
- 类型与模块:名称、类型判断、隐参求解、构造器及文件身份。
- 执行与编译:求值、异常、擦除、闭包、递归、控制流及代码生成。
- 原生二进制接口:值、堆、栈、调用、链接符号、GC 与 C 互操作。
- 网页汇编接口:WASI 与 WasmGC 的不同契约。
- 基线与实现依据:固定基线、源码索引、ABI 阅读示例与文档审阅准则。
- 规约关系表、运行时接口表:完整数据附表。
总〇:兼容的含义
ABI 兼容指:同一目标平台、同一模块身份和定义序号下,新实现产生的函数、值与对象文件可供旧实现使用,旧实现产物也可供新实现使用;跨边界调用、返回、异常和回收后仍然正确。只打印相同结果或只通过自举,不足以证明这一点。
本规范划定三种检验,不能混为一谈:
| 层次 | 必须相同 | 不要求相同 |
|---|---|---|
| 源语言兼容 | 接受/拒绝边界、求值轨迹、结果、可观察失败类别 | 内部 AST 名称、诊断堆栈全文、编译速度 |
| 对象接口兼容 | 数据布局、调用协议、公开符号、定义身份、GC 根与存储约定 | 本地临时名、寄存器分配、优化算法、私有续延编号 |
| 逐字节产物复现 | 相同工具链、编译选项、路径、编号、优化及调试信息下的整个产物 | 不能由 ABI 兼容自动推出 |
本文件集的交付物是技术文档,目标是让陌生实现者不依赖原作者解释,即可理解语言算法及二进制接口。实现者可以采用不同前端、不同 IR 和不同优化器,但不可自行“修正”本基线的可观察兼容怪异处。
总一:约束用语
“必须”表示本基线兼容所需;“可”表示实现策略自由;“禁止”表示不能将其当作可互操作输入。“兼容缺陷”表示实现存在冲突或危险边界,需保留其事实并限定适用范围,不表示推荐语言设计。
没有稳定定义的行为,不以猜测填补。特别是原生 C 有符号溢出、越界、不安全转换、失效续延以及 ABI 不匹配调用,不在可承诺的稳定行为集合内。试图对这些行为实现“所有机器均完全相同”没有可实现的契约。
总二:实现边界
一个独立编译器至少具备:UTF-8 源文输入;模块解析与有序定义表;语法分析;静态检查;运行时值生成;程序及模块入口;C 外部调用;闭包与递归;异常/提前返回;GC 安全点;与平台工具链链接。
标准库是豫言源码库,可由新编译器编译;C 系统原语可链接基线运行时。此模式无需重写文件系统、套接字等整个操作系统封装,也不依赖原编译器参与代码生成。若还要替换运行时,则须实现接口表对应的实际 C 签名与行为,并通过原编译器产物调用新运行时的验收。
源码入口、模块接口与对象文件不是同一种输入:只拿到一个旧 .o,不足以恢复类型别名、隐参和构造器身份。独立前端必须同时获得依赖源码,或从本规范规定的接口记录重建等价的检查后接口。运行时标签不能替代编译期类型。
总三:最小数据模型
实现可以使用下列概念记录,字段顺序仅在明确写为 ABI 时才有二进制约束。
- 类型:内建;刚性类型变量;名义构造器;构造器应用;连续显式箭头;连续隐式全称类型;元组类型。
- 表达式:常量;局部引用;文件定义引用;显/隐函数;调用头及有序实参;局部绑定;递归;条件;顺序;元组及投影;模式匹配;类型标注;外调。
- 文件接口项:原始文件身份、定义名、有序索引、类别、已检查类型、透明类型体或名义构造器身份;重导出保留来源。
- 无类型中间值:单位、整数、小数、字节串、闭包、元组、构造器实例、引用;静态类型与隐参不占调用槽位。
- 原生控制状态:当前豫言帧、分配指针、返回函数及续延编号、存活值、异常处理器。
局部绑定可用唯一 ID 或一基 de Bruijn 索引。所有替换须避免捕获;不能按名称做无作用域的文本替换。稳定符号由模块身份和定义索引决定,私有局部 ID 不得泄入公共接口。
总四:基线纪律
改变源路径、声明列表、构造器次序或目标平台,都可能改变 ABI。交付时附源提交、编译器可执行文件 SHA-256、运行时 SHA-256、目标三元组、工具链版本、优化选项、依赖解析结果及输出摘要。
文档维护时逐项核对源码、双语条件和接口表。已明确的实现事实写成具体规则;实现自相矛盾或尚无稳定语义的边界,明确标出其适用范围,不替语言作未经依据的承诺。