从零写一门小语言
大部分的 C++ 教程都是讲解各种语法:函数怎么写、class 怎么写、什么是指针。
学完之后,你可以写出一些代码,但大概率会有这种感觉,程序到底怎么跑起来?一听解释器、编译器、汇编、运行时就觉得很远,栈、寄存器、链接这些词就和魔法一般。这套教程就是为这种状态准备的。
我们不教某个框架,不教某个库,也不是刷题课。不依赖任何第三方库,我们会用标准 C++ 语法实现一门很小的 Lisp 风格语言,从解释器语义开始,一路把程序编译成 x86-64 汇编。
你会亲手实现:
- 源代码怎样被拆成 token
- token 怎样变成语法树
- 语法树如何被解释器求值
- 同一棵语法树如何一步一步转换为汇编
听起来像是在做一个玩具语言,但真正练的是最顶级内功心法:程序如何从文本变成结构、结构如何表达语义、语义如何落到机器指令。
这些理解会反过来改变你写 C++ 的方式。你会更清楚数据结构为什么这样设计,模块边界为什么要分开,错误处理为什么要有上下文,底层问题为什么不能只靠猜。
这套能力不会过时,因为几乎所有程序都在做类似的事:把现实里的问题、规则和关系,映射成代码里的数据结构和执行步骤。在解释器和编译器里,这个过程会被完整拆开,你能清楚看到每一步是怎么发生的。
很多课程都采用分模块的教学方式,每个章节讲解一个模块,等快学完了才能将整体的拼图拼好。而我们更喜欢增量式的教学方式,在第一章的小语言只支持加法,但是却会完整地带你走通整个流程,整体保持一个很小、很完整的程序。后面的每一章都会只引入一个简单的核心概念,然后在已有的框架上不停迭代,你不会一下子被工业级框架的复杂度压住,可以反复运行、修改、验证。
你不需要一开始就懂汇编,也不需要学过编译原理。在每次引入新的概念时,都会进行详细的讲解。如果你学过了 C++ 基础语法,那就已经足够开始了。
让我们从一个最小的程序开始,把这条路一步一步走完。在终点,我们再会!
章节目录
- 第 0 章 工具与运行方式
- 0.0 路线图
- 0.1 运行代码
- 0.2 命令是怎么进入代码的
- 0.3 make 简介
- 第 1 章 数字与加法
- 1.0 合抱之木,生于毫末
- 1.1 从两个表达式开始:整数和加法
- 1.2 AST:从字符串到 C++ 可操作的结构
- 1.3 Lexer:把源码切成 token
- 1.4 Parser:把 token 组成 AST
- 1.5 解释器:沿着 AST 直接算结果
- 1.6 IR:编译器的草稿步骤
- 1.7 汇编基础:寄存器、栈槽和返回值
- 1.8 compile:把 IR 翻译成汇编
- 1.9 本章总结
- 1.10 练习
- 第 2 章 变量与 let
- 2.0 无名,天地之始;有名,万物之母
- 2.1 从名字开始:变量和 let
- 2.2 AST:给名字留位置
- 2.3 Parser:读出 identifier 和 let
- 2.4 解释器:环境与变量查找
- 2.5 IR:把用户名字变成内部名字
- 2.6 汇编:为 copy 增加翻译规则
- 2.7 本章总结
- 2.8 练习
- 第 3 章 条件表达式
- 3.0 有无相生,前后相随
- 3.1 从顺序计算到条件选择
- 3.2 AST:给条件和分支留位置
- 3.3 Parser:读出谓词和 if
- 3.4 解释器:先判断,再选择
- 3.5 IR:把一条直线变成几条可选择的路
- 3.6 IR lowering:把 AST 变成分支和汇合
- 3.7 汇编:让 CPU 真的选择道路
- 3.8 本章总结
- 3.9 练习