1. 我们要实现什么
编译器不是神秘黑盒。这个系列会用 TypeScript 实现一条完整流水线:源码先变成 Token,再被 Parser 组织成 AST,经过语义检查后降低为 IR,最后生成字节码并交给虚拟机执行。
MiniLang 的目标很小:变量、表达式、if、while、函数和块级作用域。范围小,才能把编译器每一层讲清楚。
let total: number = 0;
let i: number = 1;
while (i <= 3) {
total = total + i;
i = i + 1;
}
print(total);
2. 编译流水线
一条实用流水线可以拆成五个稳定边界。Lexer 只关心字符如何组成 Token;Parser 只关心 Token 如何组成 AST;语义阶段检查名称和类型;IR 让控制流更明确;字节码让虚拟机能逐条执行。
type PipelineResult = {
tokens: Token[];
ast: Program;
ir: IRFunction[];
bytecode: Instruction[];
};
function compile(source: string): PipelineResult {
const tokens = new Lexer(source).scanTokens();
const ast = new Parser(tokens).parseProgram();
const checked = new TypeChecker().check(ast);
const ir = lowerToIR(checked);
const bytecode = emitBytecode(ir);
return { tokens, ast: checked, ir, bytecode };
}