# Lab2 小组协作修改方案（可直接执行）

## 1. 目标与现状

当前仓库的最小实现只能覆盖：

1. 局部 int 变量的 alloca/load/store。
2. 整数字面量、变量引用、加法表达式。
3. return 语句。
4. 单函数 main 的最小流程。

Lab2 的目标是把语法覆盖扩展到课程要求范围，并通过 IR 验证链路。

统一验收标准：

1. 能生成结构正确的 IR。
2. 通过脚本运行并和 .out 比对一致。
3. 最终覆盖 test/test_case 下应测样例。

---

## 2. 团队分工建议

建议至少拆成 4 条工作线并行推进。

### A. IR 基础设施组（你负责）

负责文件：

- include/ir/IR.h
- src/ir/Instruction.cpp
- src/ir/IRBuilder.cpp
- src/ir/Type.cpp
- src/ir/BasicBlock.cpp
- src/ir/Function.cpp
- src/ir/Module.cpp
- src/ir/IRPrinter.cpp

职责：

1. 补齐 IR 指令与构建接口（算术、比较、分支、调用、内存访问等）。
2. 保证基本块终结规则与 use-def 关系一致。
3. 保证 IRPrinter 输出格式可被 llc/clang 工具链接受。

### B. 语义分析组（Sema）

负责文件：

- include/sem/Sema.h
- include/sem/SymbolTable.h
- src/sem/Sema.cpp
- src/sem/SymbolTable.cpp
- src/sem/ConstEval.cpp

职责：

1. 名称绑定、作用域管理、重复定义与未定义检查。
2. 常量表达式求值与 const 相关约束。
3. 为 IRGen 提供稳定的绑定结果。

### C. IR 生成组（IRGen）

负责文件：

- include/irgen/IRGen.h
- src/irgen/IRGenFunc.cpp
- src/irgen/IRGenStmt.cpp
- src/irgen/IRGenExp.cpp
- src/irgen/IRGenDecl.cpp
- src/irgen/IRGenDriver.cpp

职责：

1. 按语法树节点生成 IR。
2. 正确构造控制流图（if/while/break/continue）。
3. 正确处理函数定义、调用、参数、局部变量与数组访问。

### D. 测试与集成组

负责内容：

- 脚本化回归。
- 失败样例归因（grammar/sema/irgen/ir/printer 哪层出错）。
- 每日合并后 smoke test。

---

## 3. 必须先对齐的接口约定（第一天完成）

这一步不做，后面会高频返工。

### 3.1 Sema -> IRGen 约定

1. 变量使用节点如何唯一绑定到声明节点。
2. 函数符号如何绑定（函数重名、参数信息、返回类型）。
3. 块作用域遮蔽规则：同名变量按最近作用域优先。

### 3.2 IRGen -> IRBuilder 约定

1. 每类语句/表达式映射到哪些构建接口。
2. 基本块终结规则：ret/br 后禁止继续在同块插指令。
3. 比较和逻辑运算的返回类型与约定值。
4. 调用约定：参数顺序、返回值处理、void 调用行为。

### 3.3 IR -> IRPrinter 约定

1. 新增指令的打印语法。
2. 类型打印规则（int/float/ptr/array/function）。
3. 全局对象、函数声明与定义的输出顺序。

### 3.4 IR 第一版接口清单（函数名级别，建议 Day1 冻结）

这份清单用于你先做 src/ir，其他同学按接口跟随开发。

第一批只覆盖 M1 到 M3 的最小闭环，M4 和 M5 另开第二版接口。

1. 当前已存在并继续保留

- IRBuilder.CreateConstInt(int v)
- IRBuilder.CreateBinary(Opcode op, Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateAdd(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateAllocaI32(const std::string& name)
- IRBuilder.CreateLoad(Value* ptr, const std::string& name)
- IRBuilder.CreateStore(Value* val, Value* ptr)
- IRBuilder.CreateRet(Value* v)

2. 第一版必须新增（M1）

- Opcode 扩展：Div、Mod
- IRBuilder.CreateSub(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateMul(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateDiv(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateMod(Value* lhs, Value* rhs, const std::string& name)
- 一元负号先复用 CreateSub(0, x)
- 一元逻辑非先复用比较接口（见下一条）

3. 第一版建议新增（M1 到 M3）

- CmpOp 枚举：Eq、Ne、Lt、Le、Gt、Ge
- IRBuilder.CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateBr(BasicBlock* target)
- IRBuilder.CreateCondBr(Value* cond, BasicBlock* true_bb, BasicBlock* false_bb)

4. 第二版预留（M2）

- IRBuilder.CreateCall(Function* callee, const std::vector<Value*>& args, const std::string& name)
- Function 需要完整函数签名表示（返回类型 + 形参类型）

5. 基本块终结规则（第一版必须执行）

1. terminator 指令包含 Ret、Br、CondBr。
2. BasicBlock 一旦出现 terminator，禁止继续追加普通指令。
3. IRGen 负责在新块上重新设置插入点。

6. 参数与类型约定（第一版）

1. M1 到 M3 阶段先统一为 i32 值语义。
2. cond 分支条件统一约定为 i32，0 为假，非 0 为真。
3. CreateBinary 输入输出类型必须一致；不一致直接报错。

7. 打印约定（IRPrinter 第一版）

1. Sub、Mul、Div、Mod、比较、Br、CondBr、Call 必须同步可打印。
2. 新增指令的打印格式由 IR 组给出单页示例，IRGen 组按示例比对。

8. 接口冻结与变更流程

1. Day1 晚上冻结第一版接口，不再改函数签名。
2. Day2 到 Day3 只允许修实现 bug，不改接口名字和参数。
3. 必须改接口时，提前半天发迁移说明并提供一条替代写法。

---

## 4. 分阶段里程碑（按功能从低风险到高风险）

## M1：整数基础表达式与赋值

目标样例：

- test/test_case/functional/simple_add.sy
- test/test_case/functional/11_add2.sy
- test/test_case/functional/13_sub2.sy
- test/test_case/functional/36_op_priority2.sy

完成定义：

1. 支持赋值语句。
2. 支持一元 + - !。
3. 支持二元 + - * / %。
4. 支持比较表达式的语义与 IR 生成。

## M2：函数与作用域

目标样例：

- test/test_case/functional/09_func_defn.sy
- test/test_case/functional/25_scope3.sy

完成定义：

1. 多函数定义。
2. 参数传递与函数调用。
3. 块级作用域与变量遮蔽正确。

## M3：控制流

目标样例：

- test/test_case/functional/29_break.sy

完成定义：

1. if/else。
2. while。
3. break/continue（循环栈管理）。

## M4：数组与全局对象

目标样例：

- test/test_case/functional/05_arr_defn4.sy
- test/test_case/functional/22_matrix_multiply.sy

完成定义：

1. 数组定义、初始化与下标访问。
2. 全局变量/常量。
3. constExp 维度与初始化相关检查。

## M5：浮点（若课程阶段要求）

目标样例：

- test/test_case/functional/95_float.sy

完成定义：

1. float 类型与常量。
2. int/float 隐式转换。
3. float 运算、比较、控制流条件。

---

## 5. 你负责的 src/ir 详细任务清单

建议按下面顺序提交，每次只做一类能力，便于联调。

### T1. 指令枚举和 IRBuilder 基础扩展

1. 补齐一元/二元整数运算。
2. 补齐比较与条件分支指令。
3. 提供统一的 CreateBinary、CreateCmp、CreateBr、CreateCondBr、CreateCall。

### T2. 基本块与终结指令约束

1. BasicBlock 显式记录 terminator。
2. 插入终结指令后拒绝继续插普通指令。
3. Function 级别提供校验接口（可用于 debug 断言）。

### T3. 类型与函数签名表达

1. 类型系统支持函数参数和返回类型表达。
2. 调用点参数个数与签名一致性检查（至少 debug 模式可查）。

### T4. IRPrinter 同步

1. 新增指令全部可打印。
2. 打印结果可通过 llc。
3. 保证测试输出稳定（避免不必要随机命名波动）。

### T5. 数组与地址计算（如果 M4 开启）

1. 元素地址计算接口。
2. 多维下标线性化或 GEP 风格接口。

---

## 6. 每日协作机制（必须执行）

1. 每天固定 15 分钟站会：同步昨天完成、今天计划、阻塞点。
2. 每个接口变更先发讨论再改，避免主干反复冲突。
3. 每个里程碑前冻结接口半天，只做修 bug 和联调。

推荐沟通模板：

1. 我改了什么接口。
2. 旧行为与新行为差异。
3. 受影响文件。
4. 调用方需要同步的改动。
5. 最晚切换时间点。

---

## 7. 分支与提交流程

1. 一人一功能分支，不直接在主分支开发。
2. 提交粒度小而清晰：一个提交只解决一类问题。
3. 提交信息建议：feat(ir), fix(irgen), fix(sema), test(lab2)。
4. 合并前必须附上通过样例列表。

---

## 8. 统一验证命令

构建：

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=OFF
cmake --build build -j "$(nproc)"
```

单样例验证：

```bash
./scripts/verify_ir.sh test/test_case/functional/simple_add.sy test/test_result/function/ir --run
```

功能样例批量验证：

```bash
for f in test/test_case/functional/*.sy; do
  echo "== $f =="
  ./scripts/verify_ir.sh "$f" test/test_result/function/ir --run || break
done
```

---

## 9. 风险与应对

1. 风险：grammar 变更导致 visitor 接口失配。
应对：变更 grammar 后第一时间重新生成 ANTLR 文件并通知 Sema/IRGen。

2. 风险：IRPrinter 语法偏差导致 llc 失败。
应对：新增指令时同步补打印和最小样例回归。

3. 风险：组员并行修改同一接口冲突严重。
应对：接口 owner 机制，IR 接口由 IR 组最终拍板。

4. 风险：只测 simple_add，阶段性误判成功。
应对：每个里程碑绑定指定样例集，全部通过才进入下一阶段。

---

## 10. 本周可执行排期（示例）

1. Day1：接口对齐会，完成 M1 任务拆分。
2. Day2：IR 组完成 T1/T2，Sema/IRGen 同步接入。
3. Day3：打通 M1 全样例。
4. Day4：推进 M2（函数与作用域）。
5. Day5：推进 M3（控制流）并做一次集成回归。

如果进度顺利，再进入 M4（数组与全局）。
