Files
Interpreter/Doc/compiler/STCompiler使用说明.md
T
Admin 0ebf193ff9 阶段 D 步骤 11:文档同步 + 提交(指令配置全流程收尾)。
- stb文件格式.md:288 字节真实拆解(头 104 含型号标识 STATOR1@0x48、函数表 0x68、
  代码 0x80 fn0 RET=0x21、数据段 0xC8 7 槽、SHA-256 尾 0x100);工具验证与执行器关系更新
- STCompiler使用说明.md:--machine 参数(编译/disasm 必填、打印模式不需要)、
  .stb 加固说明、288 字节示例、当前状态(可编译+可执行+配置驱动)
- 执行器入口.md:读取时型号/SHA 校验拒绝
- ctest 14/14 全绿
2026-08-21 22:35:20 +08:00

159 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STCompiler 使用说明
把 ST 工程(`project.toml` + 若干 `.st`)编译成单一映像 `.stb`。执行由 `BytecodeExecutor`12.9/12.10 实现)负责。
## 构建
```bash
cmake --preset gcc-debug # 配置
cmake --build --preset gcc-debug # 编译
ctest --test-dir build/gcc-debug # 测试(当前 9 个用例)
```
可执行文件:`build/gcc-debug/compiler/STCompiler`
## 用法
```text
STCompiler <project.toml> [-o <name>.stb] --machine <machine.toml>
STCompiler <name>.stb --disasm --machine <machine.toml>
```
| 参数 | 作用 |
|---|---|
| `<project.toml>` | 工程文件(必填) |
| `-o <name>.stb` | 编译并写出映像文件(+ sidecar);**缺省时只打印文件集合与工程哈希**(不需 `--machine` |
| `--machine <machine.toml>` | 机器定义(指令 opcode / 类型 / FB 布局,见 `Doc/isa/指令配置.md`);**编译与 `--disasm` 必填**,加载/校验失败报错退出 |
| `<name>.stb --disasm` | **反汇编一个已编译的映像**(不重新编译,见下) |
| `--help` | 打印帮助 |
退出码:`0` 成功;`1` 失败(错误信息打到 stderr)。
## 反汇编(--disasm
对已编译的 `.stb` 逐段查看:段摘要(含型号与 SHA 校验)、函数表逐条指令(文件绝对偏移)、常量表、数据段 hex。
```bash
$ STCompiler line1.stb --disasm --machine machine.toml
image: line1.stb (288 bytes, 2 functions, 4 globals, entry fn 1)
dt_ms=10 cycle_limit=100000 hash=0xc3fe4ae74ad45900 model=STATOR1 sha=ok
functions:
fn 0: nregs=8, offset=0, len=1
0x0080 RET
fn 1: nregs=13, offset=4, len=17
0x0084 LOAD_I r8, 1
0x0088 STORE_GLOBAL r8, 4
...
data (56 bytes):
0x0000: ...
```
说明:
- 指令偏移是**文件绝对字节偏移**,可直接对照 `xxd line1.stb`
- 映像里**没有符号名**(函数表只有 fn_id,数据段无名字映射),因此按 `fn 0` / `fn 1`、槽号显示
- `model=` 显示型号标识(`machine.toml [meta]` 生成);`sha=ok|BAD` 显示文件尾 SHA-256 校验结果
- 文件损坏或打不开 → `error: ...` 退出码 1
## 编译产物(.stb 加固)
- **型号标识[32]**`[meta] name + version` 拼成(如 `"STATOR1"`),写进头偏移 72
- **SHA-256 文件尾[32]**:对文件尾之前全部内容计算;compiler 写侧与 vm 读侧各实现一份
- 执行器读取时型号不匹配 / SHA 不符 → 直接拒绝(详见 `Doc/isa/指令与映像.md` 12.13 修订)
## 示例(line1
```bash
$ STCompiler examples/line1/project.toml
project: line1
files:
globals.st
motor.st
main.st
hash: 0xc3fe4ae74ad45900
$ STCompiler examples/line1/project.toml -o line1.stb --machine compiler/machine.toml
compiled: line1.stb (288 bytes, 2 functions, 4 globals)
```
产物:`line1.stb`(288 字节:头 104 含型号标识 + 各段 + SHA-256 文件尾)+ `line1.runtime.toml`sidecar)。指令见 `Doc/isa/指令与映像.md`,结构拆解见 `Doc/isa/stb文件格式.md`
## 工程文件(project.toml
只做三件事:**列出源文件、指定唯一 GVL、可选地把已声明全局接到硬件**。不声明变量。
| 字段 | 必填 | 说明 |
|---|---|---|
| `project.name` | 是 | 工程名 |
| `project.entry` | 是 | 第一版必须 `"program MAIN"` |
| `project.cycle_limit` | 是 | 每周期指令上限(>0) |
| `project.dt_ms` | 是 | 本周期 Δt 毫秒(>0),给内置 FB 定时器 |
| `files.st` | 是 | 源文件列表(非空数组) |
| `gvl.file` | 否 | 唯一允许 `VAR_GLOBAL` 的文件;已在 `files.st` 则不重复收录 |
| `[[io.input]]` / `[[io.output]]` | 否 | `var` + `channel` + `bit``var` 必须已在 GVL 声明 |
```toml
[project]
name = "line1"
entry = "program MAIN"
cycle_limit = 100000
dt_ms = 10
[files]
st = ["globals.st", "motor.st", "main.st"]
[gvl]
file = "globals.st"
[[io.input]]
var = "EmergencyStop"
channel = 0
bit = 2
```
## ST 子集(第一版)
**POU**`PROGRAM` / `FUNCTION` / `FUNCTION_BLOCK`(含对应 `END_*`)。
**变量段**`VAR` / `VAR_INPUT` / `VAR_OUTPUT` / `VAR_GLOBAL`(仅 `gvl.file` 顶层)/ `VAR_EXTERNAL`
**类型**`BOOL` / `INT` / `TIME`;内建 FB 类型 `TON` / `TOF` / `TP` / `CTU` / `CTD` / `CTUD` / `R_TRIG` / `F_TRIG`(关键字,不可作变量名)。
**语句**:赋值 `:=``IF / ELSIF / ELSE / END_IF``WHILE / END_WHILE`、FB 调用 `fb(in := ..., ...);`、字段读 `fb.Q`
**表达式**:字面量(`TRUE`/`FALSE`、整数、`T#10ms` 式 TIME)、`NOT``AND`/`OR`**短路**)、比较 `= <> < <= > >=`(不连锁)、算术 `+ - * /`、一元负号、函数调用 `Add(3, 4)`
**函数**:结果 = 函数名赋值(`Add := a + b;`);返回类型 `FUNCTION Add : INT`;调用约定:结果 r0、参数 r1..r7(最多 7 个输入,函数内只读)、变量与临时从 r8 起(见 `Doc/compiler/寄存器码.md`)。
**限制(v1 明确不做)**:指针 / `REF` / `CLASS` / `ANY` / `VAR_IN_OUT`(语法层直接拒绝)、链式比较、FB 字段赋值、`REAL`、字符串、用户类型套娃、隐式类型转换、函数循环调用(链接层拒绝)、`FUNCTION` 写全局(类型检查层拒绝,含经 `VAR_EXTERNAL`)。
## 编译管线与错误类别
```
project.toml + .st
→ 词法(lex error)→ 语法(syntax error)→ 链接(link error
→ 类型检查(type error)→ 寄存器码(codegen error)→ .stb
```
错误消息前缀即阶段:`lex error` / `syntax error` / `link error` / `type error` / `codegen error`,均带文件与行列(`type error` 仅带文件)。
| 类别 | 示例 |
|---|---|
| `lex error` | 非法字符、未闭合注释、坏 `T#` 字面量 |
| `syntax error` | 缺 `END_*``VAR_IN_OUT` 等保留名、链式比较 |
| `link error` | 非 GVL 文件写 `VAR_GLOBAL`、同名全局、io.var 未在 GVL、未声明实例、循环调用 |
| `type error` | `FUNCTION` 写全局、AND 吃 INT、赋值类型不匹配、FB 输入类型不匹配 |
| `codegen error` | 寄存器溢出、写 io.input、写函数输入 |
## 样例与测试
- `examples/line1/`:最小闭环(MAIN + MotorStarter FB + I/O + 全局),给人看
- `tests/cases/01~20/`20 个用例(每份 `project.toml` + `.st` + `EXPECTED.md`),编译结果按表
- `tests/`CTest`compiler_toml` / `lexer_tokens` / `parser_syntax` / `linker_links` / `typecheck_types` / `codegen_slice1` / `machine_config` / `vm_cycles` / `cases_all` / `cli_*`
## 当前状态
- ✅ 可编译:14 个正例用例全部产出 `.stb`(含型号标识 + SHA-256);6 个负例按期望拒绝
- ✅ 执行:`BytecodeExecutor` 加载 `.stb` 跑扫描周期(型号/SHA 校验、回放、单步)
- ✅ 配置驱动:指令 opcode / 类型元数据 / FB 布局来自 `compiler/machine.toml``--machine`