步骤4:用例 21_var_temp(VAR_TEMP 每周期重置语义)+ 文档更新 + 修复 store_target STORE 缺 func 隐藏 bug
This commit is contained in:
@@ -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 → 类型名)。
|
||||
|
||||
|
||||
@@ -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
@@ -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_0;I0_1=0 未绑定)
|
||||
|
||||
@@ -36,4 +37,4 @@
|
||||
| 1 | 0 | 0 | ok(急停生效) |
|
||||
| 0 | 1 | 1 | ok |
|
||||
|
||||
**结论:20/20 用例符合期望,ctest 14/14,全部绿。**
|
||||
**结论:21/21 用例符合期望,ctest 14/14,全部绿。**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,4 @@
|
||||
(* globals.st *)
|
||||
VAR_GLOBAL
|
||||
a : INT;
|
||||
END_VAR
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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) {
|
||||
|
||||
@@ -202,7 +202,7 @@ static bool test_all_cases() {
|
||||
}
|
||||
++n;
|
||||
}
|
||||
CHECK(n == 20);
|
||||
CHECK(n == 21);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+19
-2
@@ -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_TEMP:tmp/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 line1:I 组合 → Q0_0 真值表(槽 0=急停 1=I0_0 2=I0_1 3=Q0_0)
|
||||
CHECK(make_machine("tests/cases/20_line1", &m, &err));
|
||||
struct {
|
||||
|
||||
Reference in New Issue
Block a user