步骤4:用例 21_var_temp(VAR_TEMP 每周期重置语义)+ 文档更新 + 修复 store_target STORE 缺 func 隐藏 bug

This commit is contained in:
2026-08-26 18:01:08 +08:00
parent 536ad1a96b
commit 92e91350cc
12 changed files with 80 additions and 7 deletions
+1 -1
View File
@@ -125,7 +125,7 @@ bit = 2
**POU**`PROGRAM` / `FUNCTION` / `FUNCTION_BLOCK`(含对应 `END_*`)。
**变量段**`VAR` / `VAR_INPUT` / `VAR_OUTPUT` / `VAR_GLOBAL`(仅 `gvl.file` 顶层)/ `VAR_EXTERNAL`
**变量段**`VAR` / `VAR_INPUT` / `VAR_OUTPUT` / `VAR_GLOBAL`(仅 `gvl.file` 顶层)/ `VAR_EXTERNAL` / `VAR_TEMP`(每次调用重新初始化,不跨周期持久;FB 内不占实例字段)
**类型**19 种(`BOOL`/`SINT`/`INT`/`DINT`/`LINT`/`BYTE`/`WORD`/`DWORD`/`LWORD`/`USINT`/`UINT`/`UDINT`/`ULINT`/`REAL`/`LREAL`/`TIME`/`DATE`/`TOD`/`DT`);内建 FB 15 条(`TON`/`TOF`/`TP`/`CTU`/`DCTU`/`CTD`/`DCTD`/`CTUD`/`DCTUD`/`R_TRIG`/`F_TRIG`/`SR`/`RS`/`PWM`/`RTC`,关键字,不可作变量名;FB 名三层判定:toml fb 表 → 用户 FB → 类型名)。
+1 -1
View File
@@ -91,7 +91,7 @@ struct Symbol {
| 13 | PWM | in BOOL, pt TIME, duty REAL, q BOOL, et TIME |
| 14 | RTC | enable BOOL, date DATE, tod TOD |
- 实例布局 = 类型字段表的一份拷贝;字段偏移编译期按 1/2/4/8 对齐计算(字段类型决定宽度),实例 = 槽表 1 条
- 实例布局 = 类型字段表的一份拷贝`VAR_TEMP` 不是字段,不持久,编译期映射为帧寄存器 + 每次调用初值装载);字段偏移编译期按 1/2/4/8 对齐计算(字段类型决定宽度),实例 = 槽表 1 条
## 错误
+2 -1
View File
@@ -26,6 +26,7 @@
| 18_tof_ctu | 正例 | 编译+执行 | ok | |
| 19_recursive_call | 负例 | 编译 | REJECTED ok | link error: recursive call |
| 20_line1 | 正例 | 编译+执行 | ok | 真值表 4 行全对 |
| 21_var_temp | 正例 | 编译+执行 | ok | VAR_TEMP 每周期重置(a=10107/10108/10109 |
## line1 真值表(回放:io.input 顺序 EmergencyStop, I0_0I0_1=0 未绑定)
@@ -36,4 +37,4 @@
| 1 | 0 | 0 | ok(急停生效) |
| 0 | 1 | 1 | ok |
**结论:20/20 用例符合期望,ctest 14/14,全部绿。**
**结论:21/21 用例符合期望,ctest 14/14,全部绿。**
+2 -1
View File
@@ -570,7 +570,8 @@ namespace {
if (!compile_expr(f, value, tmp, func_of_name(sym.type_name))) {
return false;
}
E_slot(f, "STORE", tmp, git->second);
const size_t st = E_slot(f, "STORE", tmp, git->second);
set_func(f.code.data() + st, func_of_global(target));
return true;
}
+8
View File
@@ -0,0 +1,8 @@
# 期望:编译通过;VAR_TEMP 每周期重置,VAR 跨周期持久
- FB Foo`tmp`VAR_TEMP 初值 100)每周期重置 → `tmp := tmp + 1` 恒为 101
`persist`VAR)跨周期累积 1、2、3…
`out = tmp * 100 + persist` = 10101、10102、10103…
- MAIN`t`(VAR_TEMP 初值 5)每周期重置 → `t := t + 1` 恒为 6
- 全局 `a = f.out + t`:周期 1/2/3 = 10107 / 10108 / 10109(差 1 仅来自 persist
tmp 与 t 若不重置则偏差 100 / 1)
+4
View File
@@ -0,0 +1,4 @@
(* globals.st *)
VAR_GLOBAL
a : INT;
END_VAR
+12
View File
@@ -0,0 +1,12 @@
(* main.st *)
PROGRAM MAIN
VAR
f : Foo;
END_VAR
VAR_TEMP
t : INT := 5;
END_VAR
t := t + 1;
f(in := TRUE);
a := f.out + t;
END_PROGRAM
+18
View File
@@ -0,0 +1,18 @@
(* motor.st *)
FUNCTION_BLOCK Foo
VAR_INPUT
in : BOOL;
END_VAR
VAR_OUTPUT
out : INT;
END_VAR
VAR
persist : INT;
END_VAR
VAR_TEMP
tmp : INT := 100;
END_VAR
tmp := tmp + 1;
persist := persist + 1;
out := tmp * 100 + persist;
END_FUNCTION_BLOCK
+11
View File
@@ -0,0 +1,11 @@
[project]
name = "case21"
entry = "program MAIN"
cycle_limit = 1000
dt_ms = 10
[files]
st = ["globals.st", "motor.st", "main.st"]
[gvl]
file = "globals.st"
+1
View File
@@ -65,6 +65,7 @@ namespace {
{"18_tof_ctu", Outcome::Ok, ""},
{"19_recursive_call", Outcome::CompileError, "recursive call"},
{"20_line1", Outcome::Ok, ""},
{"21_var_temp", Outcome::Ok, ""},
};
bool run_case(const char* dir, Outcome want, const char* keyword) {
+1 -1
View File
@@ -202,7 +202,7 @@ static bool test_all_cases() {
}
++n;
}
CHECK(n == 20);
CHECK(n == 21);
return true;
}
+19 -2
View File
@@ -37,11 +37,19 @@ static int g_checks = 0;
// ---- 数据区槽访问 ----
/// 槽宽 = 与下一槽 addr 的差(紧凑布局下按实际宽读写,避免覆盖相邻槽)
/// 槽宽 = 与下一槽 addr 的差(紧凑布局下按实际宽读写,避免覆盖相邻槽)
/// 最后一槽(下一槽越界返回 0)按值区剩余字节兜底。
static uint32_t slot_width(const vm::Machine& m, int s) {
const uint32_t a = m.slot_addr(static_cast<uint32_t>(s));
const uint32_t b = m.slot_addr(static_cast<uint32_t>(s + 1));
return (b > a && b - a < 8) ? (b - a) : 8;
if (b > a && b - a < 8) {
return b - a;
}
if (b == 0) {
const uint32_t rem = static_cast<uint32_t>(m.data_len()) - a;
return rem < 8 ? rem : 8;
}
return 8;
}
static int64_t slot(const vm::Machine& m, int s) {
@@ -357,6 +365,15 @@ static bool test_cases_positive() {
CHECK(make_machine("tests/cases/18_tof_ctu", &m, &err));
CHECK(m.run_cycle() == vm::Fault::None);
// 21 VAR_TEMPtmp/t 每周期重置,persist 累积 → a = 10107/10108/10109
CHECK(make_machine("tests/cases/21_var_temp", &m, &err));
m.run_cycle();
CHECK(slot(m, 0) == 10107);
m.run_cycle();
CHECK(slot(m, 0) == 10108);
CHECK(m.run_cycle() == vm::Fault::None);
CHECK(slot(m, 0) == 10109);
// 20 line1I 组合 → Q0_0 真值表(槽 0=急停 1=I0_0 2=I0_1 3=Q0_0
CHECK(make_machine("tests/cases/20_line1", &m, &err));
struct {