- Typecheck.h/cpp:三型(BOOL/INT/TIME)求值,AND/OR/NOT 只吃 BOOL、算术只吃 INT(TIME 无算术)、比较同型、IF/WHILE 条件必须 BOOL - FUNCTION 禁写全局(含经 VAR_EXTERNAL)——用例 14 点亮;函数名赋值=返回类型 - FB 命名实参匹配字段类型;FB 实例不能当值 - typecheck_test:23 断言(用例 14 + 8 类负例 + 13 个正例),ctest 8/8
79 lines
3.6 KiB
Markdown
79 lines
3.6 KiB
Markdown
# 类型检查(12.7)
|
||
|
||
compiler 模块的类型规则检查。输入:`Project` + 各 `.st` 的 `Unit`(AST)+ `LinkResult`(符号已解析);输出:通过或 `type error`。全工程定案见 [`初步计划.md`](../初步计划.md) 12.7。
|
||
|
||
## 做 / 不做
|
||
|
||
**做**
|
||
|
||
- `:=`、比较、算术的类型规则;`AND` / `OR` / `NOT` 只吃 `BOOL`
|
||
- `FUNCTION` 禁止写全局(含经 `VAR_EXTERNAL`)——用例 14
|
||
- FB 调用:命名输入类型匹配;`fb.Q` 字段存在且类型对
|
||
- 表达式求值类型:`BOOL` / `INT` / `TIME` 三型
|
||
- 无隐式宽化;`INT` 与 `TIME` 不混用
|
||
|
||
**不做(第一版)**
|
||
|
||
- 常量折叠、溢出区间检查(INT 字面量范围,饱和在 VM 层)
|
||
- `FUNCTION` 实参与形参的个数/类型核对(12.7 未要求,只核对 FB 命名输入)
|
||
- 变量初始化表达式的类型核对(语法层已限字面量)
|
||
|
||
## 表达式求值类型
|
||
|
||
```cpp
|
||
enum class TType { Bool, Int, Time };
|
||
```
|
||
|
||
| 节点 | 规则 | 结果 |
|
||
|---|---|---|
|
||
| `LitBool` / `LitInt` / `LitTime` | — | Bool / Int / Time |
|
||
| `VarRef` | 查符号(局部/输入/输出/外部/全局)类型 | 符号类型 |
|
||
| `Field` | 实例字段类型(布局已由 12.6 提供) | 字段类型 |
|
||
| `Not` | 操作数必须 Bool | Bool |
|
||
| `And` / `Or` | 两侧必须 Bool(短路已由语法层保留) | Bool |
|
||
| `Cmp` | 两侧同型(Bool/Int/Time 均可比较) | Bool |
|
||
| `Add/Sub/Mul/Div` | 两侧必须 Int(**TIME 无算术**,INT 与 TIME 不混用) | Int |
|
||
| `Neg` | 操作数必须 Int | Int |
|
||
| `Call` | 函数存在(12.6 已验);结果 = 函数返回类型 | 返回类型 |
|
||
| `VarRef` 指向 FB 实例 | 实例不能当值 | type error |
|
||
|
||
## 语句规则
|
||
|
||
| 语句 | 规则 |
|
||
|---|---|
|
||
| `Assign`(普通) | 左值类型 == 表达式类型;左值可为局部/输入/输出/外部/全局 |
|
||
| `Assign`(函数名,FUNCTION 内) | 表达式类型 == 函数返回类型(用例 13 约定) |
|
||
| **`FUNCTION` 内左值是全局/外部** | **拒绝:`function cannot write global`(用例 14,含经 VAR_EXTERNAL)** |
|
||
| `FbCall` | 每个命名实参表达式类型 == 实例对应字段类型(布局 12.6 已校验存在性) |
|
||
| `If` / `While` | 条件表达式必须 Bool |
|
||
|
||
## 错误
|
||
|
||
稳定前缀 `type error`,带文件与行列(尽量带):
|
||
|
||
```text
|
||
type error: AND operands must be BOOL (main.st, line 5, col 9)
|
||
type error: type mismatch in assignment to 'q0_0' (INT vs BOOL) (main.st, line 6, col 13)
|
||
type error: function cannot write global 'g1' (main.st, line 3, col 5)
|
||
type error: TIME has no arithmetic (main.st, line 4, col 12)
|
||
type error: FB input 'pt' expects TIME (main.st, line 5, col 16)
|
||
```
|
||
|
||
## 完成标准
|
||
|
||
1. 用例 14(FUNCTION 写全局)→ `type error`(12.6 已放行,本阶段点亮)
|
||
2. line1 / 用例 07 / 13 / 15 / 17 等合法工程类型检查通过
|
||
3. 负例:AND 吃 INT、赋值类型不匹配、INT+TIME、NOT INT、FB 输入类型不匹配、比较异型 → `type error`
|
||
4. 全部构建 + `ctest` 无回归
|
||
|
||
---
|
||
|
||
## 执行计划(单步确认)
|
||
|
||
1. **`Typecheck.h`(新建 `compiler/include/compiler/Typecheck.h`)**:`TType` + `check_project` 声明
|
||
2. **`Typecheck.cpp` 前半**:符号类型解析(VarRef/Field/Call/字面量)+ 表达式递归定类型
|
||
3. **`Typecheck.cpp` 后半**:语句规则(Assign 含函数名/FUNCTION 禁写全局、FbCall 实参、IF/WHILE 条件)
|
||
4. **`typecheck_test`(`tests/src/typecheck_test.cpp` + CMake)**:用例 14 + 负例 + 正例
|
||
5. **验证**:`cmake --build` + `ctest`(新增 `typecheck_types` 后 8/8 全绿)
|
||
6. **提交**:`Typecheck.h/cpp` + `typecheck_test` + 文档
|