-
Notifications
You must be signed in to change notification settings - Fork 0
Development
HZY1618yzh edited this page Jul 27, 2026
·
1 revision
本文档介绍 mio 编译器的内部实现,帮助开发者理解和贡献代码。
mio/
├── src/
│ ├── token.hpp # 词法单元定义
│ ├── lexer.hpp # 词法分析器
│ ├── types.hpp # 类型系统
│ ├── ast.hpp # 抽象语法树
│ ├── parser.hpp # 语法分析器
│ ├── codegen.hpp # LLVM 代码生成器
│ ├── main.cpp # 编译器入口
│ ├── build.sh # Linux/macOS 构建脚本
│ └── build.ps1 # Windows 构建脚本
├── include/ # 标准库头文件
│ ├── stdio.mio
│ ├── string.mio
│ ├── stdlib.mio
│ ├── math.mio
│ └── std.mio
└── lib/ # 预编译库
└── windows/
└── *.lib
lexer.hpp 将源代码字符串转换为 Token 序列。
关键功能:
- 跳过空白字符和
#注释行 - 识别标识符、关键字、数字(十进制/十六进制)
- 解析字符串和字符字面量(支持转义:
\n,\t,\r,\\,\",\',\0) - 解析
@宏指令(@if,@elif,@else,@end) - 提供
peek()预读功能 -
is_template_instantiation()检测模板实例化
关键字表:
import, extern, var, const, if, else, elif, while, for,
break, continue, goto, return, struct, enum, union, class,
namespace, public, private, protected, virtual, override,
static, operator, true, false, this, macro, template,
typename, sizeof
types.hpp 定义 Mio 语言的类型表示。
MioType 结构:
class MioType {
MioTypeKind kind; // 类型种类
std::string name; // 类型名称(struct/enum/union)
int array_size; // 数组大小
MioType* base_type; // 基类型(指针/数组)
std::vector<MioType*> param_types; // 参数类型(函数/模板)
};类型种类(MioTypeKind):
- 基本类型:VOID, I8-I128, U8-U128, USIZE, ISIZE, F32, F64, BOOL, CHAR
- 复合类型:STRUCT, ENUM, UNION, ARRAY, FUNC, POINTER
ast.hpp 定义所有 AST 节点类型。
节点分类:
| 分类 | 节点类型 |
|---|---|
| 程序 | PROGRAM, IMPORT |
| 声明 | VAR_DECL, CONST_DECL, FUNC_DEF |
| 类型定义 | STRUCT_DEF, ENUM_DEF, UNION_DEF, CLASS_DEF, NAMESPACE_DEF |
| 语句 | BLOCK, IF_STMT, WHILE_STMT, FOR_STMT, BREAK_STMT, CONTINUE_STMT, GOTO_STMT, LABEL_STMT, RETURN_STMT, EXPR_STMT |
| 表达式 | BINARY_EXPR, UNARY_EXPR, CALL_EXPR, INDEX_EXPR, MEMBER_EXPR, IDENT_EXPR, INT_LIT, FLOAT_LIT, STRING_LIT, BOOL_LIT, CHAR_LIT, ARRAY_LIT, CAST_EXPR, ASSIGN_EXPR, SIZEOF_EXPR |
| 高级 | MACRO_DEF, TEMPLATE_DEF |
辅助结构:
-
TemplateParam— 模板参数(类型参数/值参数) -
TemplateArg— 模板实参 -
Param— 函数参数 -
Field— 结构体/类字段 -
Variant— 枚举变体 -
UnionField— 联合体字段 -
InitField— 构造函数初始化列表项
parser.hpp 采用递归下降解析,将 Token 序列转换为 AST。
表达式优先级(从低到高):
- 赋值(
=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=) - 逻辑或(
||) - 逻辑与(
&&) - 按位或(
|) - 按位异或(
^) - 按位与(
&) - 相等性(
==,!=) - 关系性(
<,>,<=,>=) - 移位(
<<,>>) - 加减法(
+,-) - 乘除模(
*,/,%) - 一元运算符(
-,!,~,*,&) - 后缀运算符(调用
(), 索引[], 成员./->) - 主表达式(字面量、标识符、括号、数组、转换、sizeof)
导入解析:
- 支持
import stdio;和import "file.mio";两种语法 - 递归解析被导入文件,防止重复导入
- 搜索路径:当前目录 →
-I指定路径
模板解析:
-
template<T:typename>— 类型参数 -
template<T:typename, len:i32=100>— 值参数(带默认值) - 支持函数模板和类模板
codegen.hpp 将 AST 转换为 LLVM IR,并调用 LLD 链接器生成可执行文件。
LLVM 集成:
- 使用
llvm::IRBuilder生成 IR - 支持 LLVM 优化传递(-O0 到 -O3)
- 使用 LLD(coff/elf/macho 驱动)进行链接
类型映射:
| Mio 类型 | LLVM 类型 |
|---|---|
| i8/u8/char | i8 |
| i16/u16 | i16 |
| i32/u32 | i32 |
| i64/u64/isize/usize | i64 |
| i128/u128 | i128 |
| f32 | float |
| f64 | double |
| bool | i1 |
| T* | pointer |
| T[N] | [N x T] 或 pointer(N=0) |
| struct/class | struct type |
| enum | i32 |
代码生成流程:
-
genProgram()— 遍历顶层声明 -
genFuncDef()— 生成函数定义 -
genStructDef()/genClassDef()— 生成类型定义 -
genExpr()— 生成表达式代码 -
emitLLVM()/emitAssembly()/emitObject()— 输出中间产物 -
linkExecutable()— 调用 LLD 链接
虚函数表(vtable):
- 为每个包含虚函数的类生成 vtable 类型
- 在构造函数中初始化 vtable 指针
- 虚函数调用通过 vtable 间接调用
名称修饰:
- 命名空间成员:
namespace::name - 全局变量访问:
::name表示根命名空间 - 模板实例化:
name_Type1_Type2_...
| 对象 | 管理方式 |
|---|---|
| AST 节点 |
new/delete,析构函数递归释放子节点 |
| MioType |
new/delete,析构函数递归释放子类型 |
| Token |
tok_new/tok_free
|
| 字符串 |
mioStrndup/malloc/free
|
-
词法分析:未知字符生成
TOK_ERROR -
语法分析:
error_count计数,输出格式文件名:行:列: error: 消息 -
代码生成:
error()输出错误信息 -
main 函数:捕获
std::exception和未知异常
g++ -std=c++17 -o mioc src/main.cpp -lLLVM# 使用 build.ps1 脚本
.\src\build.ps1- C++17 兼容编译器
- LLVM 22.1.x
- LLD 链接器
- 遵循现有代码风格(无空格缩进,紧凑格式)
- 修改后运行测试验证
- 确保跨平台兼容性(Windows/Linux/macOS)
- 更新相关文档