Lexer V2:
- 19 类型关键字(BOOL..DT);FB 名不再设关键字(IDENT)
- FLOAT_LIT(1.5/2.5e3)、进制前缀(2#/8#/16# 换算十进制)
- 日期字面量 D#/TOD#/DT#(历法换算 1970 纪元、闰年、值域检查)
Parser V2:
- TypeRef 字符串化(TypeKind{Scalar,FbBuiltin,FbUser},名字小写)
- ExprKind 增 LitReal/LitDate/LitTod/LitDt;Expr.double_value
- IDENT 类型统一 FbUser(内建判定在 Linker 查 fb 表)
Typecheck V2:
- TType 19 + Unresolved(字面量未定型)
- 禁隐式转换(赋值/算术/比较严格同型)
- resolve_to:未定型→消费点定型+值域检查(BOOL 0/1、无符号负数、
溢出、浮点仅 REAL/LREAL);算术按 kind 允许(TIME 仅 ±)
- Call 实参按函数参数类型;check_project 加 cfg
Linker V2:
- FbField.type_name 字符串化;内建 FB 布局查 machine.toml [[fb]] 表
(删 8 个硬编码布局,带缓存);link_project 加 cfg
Codegen V2:
- 浮点/日期字面量(LOADK func 8/4/4/6;LitReal 按 REAL 装载,LREAL TODO)
- 算术/比较 func 按操作数类型(expr_func)
- TypeKind 连锁适配
main.cpp:link/check 传 cfg;--disasm 头 22 字段逐行中文注释(L5)
+ slots 节;StbView 补 offset_const/offset_funcs
测试适配:parser/linker/typecheck/vm/cases 适配新接口与 V2 语义。
ctest 11/13(vm_cycles/cases_all 待阶段 4)。codegen_test 仍剥离(阶段 3-2 重写)。
StScan
子集 ST + 扫描周期虚拟机。IEC 风格的子集 ST:用 project.toml 组织多个 .st,编译成单一映像,由寄存器虚拟机按扫描周期执行。
方案见 Doc/初步计划.md,模块文档见 Doc/索引.md。
多个 .st + machine.toml(指令/类型/FB 布局)
↑ project.toml 列出源文件;machine.toml 唯一事实来源
↓
STCompiler(compiler 库:词法 / 语法 → 符号表 → 类型检查 → 寄存器码 → 链接;编码查 machine.toml)
↓
<name>.stb 映像(头 104 含型号标识 + 段 + SHA-256 文件尾)+ <name>.runtime.toml sidecar
↓
BytecodeExecutor(vm 库按扫描周期执行;型号/SHA 校验;喂 I、收 Q、给 Δt、回放)
目录
.
├── CMakeLists.txt # 顶层工程:加入各目标,并启用测试
├── cmake/ # CMake 辅助(警告、C++ 标准等),不是业务模块
├── isa/ # 共享契约:指令、映像、定宽类型
├── compiler/ # ST / toml 编译器(库)+ STCompiler 可执行入口
├── vm/ # 寄存器虚拟机(库)
├── executor/ # BytecodeExecutor:加载 .stb + sidecar 并执行
├── examples/ # 样例工程(给人看、跑通最小闭环)
│ └── line1/ # MAIN + Motor FB + I/O
│ ├── project.toml
│ ├── globals.st
│ ├── motor.st
│ └── main.st
├── tests/ # 自动化用例(语法、链接、指令、回放)
├── third_party/ # 第三方(如 toml 解析),compiler 私有链接
└── Doc/ # 设计文档
样例和测试是数据,不做成 CMake 库。每个用例是一份 toml + 若干 .st,按工程子目录存放。
模块与 CMake 目标
三个静态库与两个可执行,与目录一一对应。compiler 与 vm 不互相链接。指令/类型/FB 布局的唯一事实来源是 compiler/machine.toml(编译器运行时加载);isa 归执行器侧(vm 依赖),只管指令定义。依赖方向:STCompiler → compiler、BytecodeExecutor → vm → isa。
| 目录 | 目标 | 类型 | 依赖 | 职责 |
|---|---|---|---|---|
isa/ |
isa |
STATIC |
无 | 指令定义(Op/Instr/Encode/Types/饱和/disasm),归执行器侧 |
compiler/ |
compiler |
STATIC |
toml++(私有) | 读 toml、收齐 .st、解析、链接、定址、类型检查、编寄存器码、写 .stb(指令 opcode/类型/FB 布局全部来自 machine.toml) |
vm/ |
vm |
STATIC |
isa |
一台 VM、一个入口、一份映像;扫描周期、寄存器、FB、有界 CALL / RET;自带 .stb 读实现 + 型号/SHA-256 校验 |
compiler/ |
STCompiler |
EXECUTABLE |
compiler |
STCompiler <project.toml> -o <name>.stb --machine <machine.toml>:编译并写映像 + sidecar;--disasm 可反汇编 |
executor/ |
BytecodeExecutor |
EXECUTABLE |
vm、isa |
BytecodeExecutor <name>.stb:加载映像 + sidecar,采样 I、执行 PROGRAM MAIN、写回 Q、用 Δt 推进定时器 / 计数器、回放 |
词法、语法、符号表、检查、codegen、链接都留在 compiler 一个库里,不再拆 CMake 子库。
isa
归执行器侧(vm 依赖),只管指令定义:Op 枚举 / Instr 打包 / Encode(编解码·disasm)/ Types(饱和)。执行器执行 switch 在 vm。
compiler
toml 不声明变量,只列出源文件、指定唯一 GVL、可选地把已有全局接到硬件。VAR_GLOBAL 第一版只允许出现在 gvl.file(如 globals.st)。指令 opcode / 类型元数据 / FB 布局全部来自 compiler/machine.toml(STCompiler --machine 加载,强校验后编译)。
vm
每个扫描周期:采样 I → 从 PROGRAM MAIN 的 pc=0 执行到 RET → 写回 Q → 用本周期 Δt 推进内置 FB。无 GC、无堆、无线程;变量编译期分配。读取 .stb 时校验型号标识与 SHA-256(不匹配/篡改 → 拒绝)。
executor(BytecodeExecutor)
STCompiler 编译出 <name>.stb(含型号标识 + SHA-256)+ <name>.runtime.toml(sidecar:I/O 绑定);BytecodeExecutor 加载后按扫描周期跑。dt_ms / cycle_limit 从映像头取。
examples/ 与 tests/
| 目录 | 用途 |
|---|---|
examples/line1/ |
计划中的最小样例:全局、MotorStarter FB、PROGRAM MAIN |
tests/ |
冻关键字、指令、符号表、链接错误(重复 VAR_GLOBAL、io.var 未声明等) |
tests/ 通过 add_test 调 STCompiler / BytecodeExecutor,或直接链接 compiler + vm。样例工程数据按「一份 toml + 若干 .st」分子目录存放,不做成 library。