Carbon 语言规范框架的诞生:解读 p000140 提案与 `docs/spec` 目录的落地实践
导读
本文以 Carbon Language 仓库中的提案 p000140-create-initial-rough-framework-for-specification 为核心,系统讲解 Carbon 语言正式规范(specification)的组织框架:它为何要把规范拆分为"语言"与"库"两个部分、按什么原则划分文件、采用哪些写作约定,以及这套框架如何在当前仓库的 docs/spec 目录中一步步落地并充实。读完本文,你将理解 Carbon 规范文档的目录语义、每份文件的定位、段落编号等写作规范,以及规范中的"翻译流水线"与 toolchain 编译器实现之间的对应关系。
一、背景:为什么需要一个规范框架
1.1 问题:规范无从下笔,先要有"骨架"
在 Carbon 语言设计早期,大量语言细节仍在讨论和决策之中。此时撰写完整规范既不现实也无必要,但若完全没有载体,后续一旦有结论就无法有序沉淀。因此提案的 Problem 一节非常直白:
我们需要为规范准备一个粗略的布局(rough layout),以便在细节被确定后可以开始往里面填充内容。
换句话说,这份提案解决的不是"规范写什么",而是"规范放在哪、按什么结构组织"——先搭好架子,再等待内容。
1.2 长远承诺:规范要支撑独立实现
这个"架子"并非临时草稿。仓库中的规范首页 docs/spec/README.md 明确写道:Carbon 承诺拥有一份详细到足以允许独立实现该语言的正式规范;虽然计划提供参考实现,但规范本身是确保语言行为被充分理解、前后自洽的重要工具。这正是 p000140 提案的深层动机——框架的最终目标是一份可让第三方独立实现的语言定义文档。
二、提案核心:语言与库的二分结构
2.1 总体方案
提案提出的方案可以归纳为三条原则:
- 规范拆分为 language(语言)与 library(库)两个顶层部分——前者描述语言本身的语法与语义,后者描述随语言分发的标准库。
- 在语言部分,按"功能大领域"(broad area of functionality)一文件一主题——每个文件覆盖一个功能领域,方便独立维护与交叉引用。
- 文件划分依据语言设计的预期分层(intended layering of the language design)——即按编译器前端处理源码的自然阶段来切分,这为后来与工具链实现对齐埋下了伏笔。
2.2 提案中的初始目录结构
提案原文给出了 spec/ 目录的顶层结构建议(截至该 PR 时):
spec/
├── README.md # 规范总览(Introduction to the specification)
├── lang/ # 语言规范
│ ├── README.md # 语言规范概述与基础(overview and basics)
│ ├── execution.md # 执行语义(Execution semantics)
│ ├── lex.md # 词法分析(Lexical analysis)
│ ├── libs.md # 库与包(Libraries and packages)
│ ├── names.md # 名称与名称绑定/查找(Names and name binding / lookup)
│ ├── parsing.md # 语法分析(Parsing)
│ └── semantics.md # 语义分析(Semantic analysis)
└── lib/
└── README.md # 库规范概述与基础
提案同时强调:这只是起点,随着规范被逐步填充,结构应当持续调整与生长;当时列出的文件大多为空或近乎空的占位符(placeholder)。
2.3 现状:结构被完整采纳
对照当前仓库 docs/spec,可以看到这套结构被一字不差地落地了:
- docs/spec/README.md —— 规范总入口;
- docs/spec/lang 下含
README.md、execution.md、lex.md、libs.md、names.md、parsing.md、semantics.md七个文件; - docs/spec/lib/README.md —— 库规范,目前内容为
TODO占位。
这个"提案提出的结构 = 仓库实际结构"的一致性,本身就是提案在 Carbon 决策流程中落地的最直观证据。
三、写作约定(Conventions):让规范可引用、可检索
提案 Details / Conventions 一节为规范文档制定了三条写作约定,它们是这份规范在排版层面区别于普通技术文档的关键:
- 段落编号:规范中的所有段落(paragraph)都编号,以便于被精确引用(例如"见第 3 节第 2 段")。这种编号机制让评审、实现与测试都能锚定到唯一文本位置。
- 术语斜体:被定义的术语(defined terms)以 斜体 引入,读者可以据此区分"首次定义的术语"与"一般用法"。
- 超链接贯通:规范各节之间大量使用超链接互相引用,形成一张可导航的语义网。
这三条约定在当前规范中已经生效,例如:
- docs/spec/lang/README.md 中,program、Carbon linkage unit、foreign linkage unit、source file 等术语均以斜体引入并配编号列表;
- 同一文件中通过
[linked](#linkage)、[translating](#translation)、lex.md、parsing.md、names.md、libs.md、semantics.md 等链接将各节互相串起。
提示:
docs/spec/README.md中写有"Linkage rules for foreign entities"等TODO标记,说明框架已就位,具体规则仍在补充中——这正是提案预期的"结构先行、内容跟进"演进方式。
四、备选方案:为什么坚持用 Markdown
提案还记录了被否决的备选方案——用其他语言维护规范(如支持自定义排版、文法表示、定义链接能力更强的文档语言)。
备选方案的优势:另一种文档语言可能对自定义排版、文法表示、链接到定义等提供更好支持。
否决的理由(即 Markdown 的劣势对比):
- 引入其他文档语言会增加文档体系的复杂度与不一致性;
- 很难找到一种无需大量定制就能契合规范需求的现成文档语言;
- 从更复杂的文档语言再转换回来,通常比从 Markdown 转换更复杂。
结论:由于 Markdown 文档相对简单,日后无论是手工还是借助 Sphinx 之类的工具将其转换为其他格式,成本都预期保持在较低水平。因此"先 Markdown、必要时再迁移"是一个低成本、高灵活性的决策。当前仓库 docs/spec 下全部规范文件均为 .md,正是这一决策的延续。
五、从骨架到血肉:规范框架中已填充的核心内容
提案之后,规范文件陆续获得了实质性内容。以目前信息密度最高的 docs/spec/lang/README.md 为例,可以看到框架如何被内容填满:
5.1 程序结构(Program structure)
- 一个 program 是若干**链接单元(linkage unit)**的集合;
- Carbon linkage unit 是源文件经翻译的产物,foreign linkage unit 则由其他语言翻译流程产生;
- source file 是 Unicode 码点序列,通常以 UTF-8 编码、
.carbon扩展名存储于磁盘。
5.2 一致性(Conformance)
- 不含任何违反规范中 "shall" 约束的程序是 valid(有效),否则 invalid(无效);
- conforming(符合规范的)实现必须:接受所有有效程序、对要求诊断的无效程序给出诊断、且所有被接受程序的执行语义与规范一致。
5.3 翻译流水线(Translation)——与编译器实现的对应
规范为"源文件翻译为 Carbon 链接单元"定义了如下顺序流程,这正是框架"按语言设计分层划分文件"的体现:
| 步骤 | 规范章节 | 对应实现路径(当前仓库) |
|---|---|---|
| 词法分析:码点序列分解为词法元素 | lex.md | toolchain/lex |
| 丢弃空白与注释,得到 token 序列 | lex.md | toolchain/lex |
| token 解析为抽象语法树 | parsing.md | toolchain/parse |
| 非限定名称绑定到声明 | names.md | toolchain/check |
| 定位并加载每个被导入库的翻译形式 | libs.md | 包/导入处理相关代码 |
| 语义分析:确定类型、语义检查、常量求值、模板实例化 | semantics.md | toolchain/check 与 toolchain/sem_ir |
规范还注明:语义分析之后实现可选用类似模板实例化的过程对泛型做单态化(monomorphize);链接单元包含源文件中所有外部实体或从外部实体可达的实体,可含未单态化的泛型但从不含模板。
从实现侧看,toolchain/driver/compile_driver.cpp 中 CompilationUnit 持有 SemIR::CheckIRId 与 SemIR::File,并有"将 SemIR 降低为 LLVM IR(lower)"的职责注释;toolchain/driver/compile_options.cpp 提供 --dump-sem-ir 等选项用于输出语义分析结果,toolchain/driver/testdata/fail_dump_phase_conflict.carbon 中还可见"compile phase is limited to parse"之类的阶段控制测试。可以说,规范中的分层翻译模型与 toolchain 的 lex → parse → check(SemIR) → lower(LLVM IR) 流水线高度吻合——这就是"按预期分层划分文件"在实现侧的投影。
5.4 链接(Linkage)
- 两个声明若处于同一库、同一作用域且声明同名,则声明同一实体(规范中为外来实体规则、文件局部实体能力留有 TODO);
- 同一实体的所有声明必须使用相同类型;
- 程序中每个从链接单元可达的实体都须由某个链接单元定义;
- 一个实体在程序中不得有多个定义。
5.5 词法与名称的细化
- docs/spec/lang/lex.md:源文件码点序列被划分为连续的 lexical elements;每一步都取能由剩余码点前缀构成的最长有效词法元素(最长匹配原则),即使这会导致后续元素无法形成;规范中词法元素清单仍为 TODO。
- docs/spec/lang/names.md:name 是标识符,两个名称相同当且仅当码点序列相同(归一化问题留作 TODO);scope 分为源文件顶层、模式作用域、块作用域、类型定义四类;声明名字的构造在最内层包围作用域内绑定名称;非限定名称查找即"绑定该名称的最内层作用域中的实体"。
这些内容直接呼应了提案中"随着细节被确定后填充"的规划,也验证了框架在真实演进中的可用性。
六、给规范读者的使用建议
如果你希望跟踪或引用 Carbon 的规范,可以从以下路径切入:
- 从总入口 docs/spec/README.md 开始,了解规范的承诺与当前状态;
- 语言规范以 docs/spec/lang/README.md 为枢纽,按"程序结构 → 一致性 → 翻译 → 链接"的顺序阅读,再进入
lex.md、parsing.md、names.md、semantics.md、execution.md、libs.md各专题; - 库规范暂为空壳(docs/spec/lib/README.md 仅含
TODO),说明该部分尚待设计沉淀; - 规范中凡以编号列出的段落均可作为精确引用锚点,文中 斜体 术语为定义处。
结语
p000140 是一份典型的"过程性"提案:它没有定义任何语言语法,却定义了承载语法的容器。通过"语言/库"二分、按功能领域分层分文件、Markdown 维护与三项写作约定,它为 Carbon 建立了一套可持续生长、可精确引用、与编译器实现分层天然对齐的规范骨架。今天你在 docs/spec 中看到的每一个编号段落、每一条交叉链接,都可以追溯到这份早期提案所奠定的结构决策。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00