25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps 2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows 98c3f30 📝 docs(agent_rules): allow plan execution on current branch 16c7230 📝 docs(prompts): define custom verify layering 8efc4dd 🐛 fix(skills): quote commit-message description bc8498f 🐛 fix(ci): install tomli for gitea tests 55cda3b 🐛 fix(tests): report missing toml parser clearly c0729c7 🐛 fix(playbook): import Optional for cli compatibility 63e24bf 📦 deps(skills): sync thirdparty skills d2f9356 🐛 fix(ci): isolate gitea workflow repos 588b81d 🐛 fix(ci): inline gitea workflow bootstrap e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts 2c5050d ♻️ refactor(skills): rename repo skills source dir f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills 234b335 ✨ feat(workflow): add superpowers planning and execution state tracking c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates 2325409 📝 docs(markdown): clarify optional markdownlint usage 214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes a22b324 📝 docs(templates): add execution and memory-bank prompt templates 223a797 📝 docs(templates): update README for Claude Code and current features 4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules 2431c9d 📝 docs: add claude_md config and use cross-platform paths d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root 6518f0f ✨ feat(playbook): auto-create CLAUDE.md with path discovery 6ec9a45 ✨ feat(skills): add skill_link symlink support + platform-agnostic prompt 9f8b6b5 📝 docs: update README and config example for Claude Code support 79cff6c 📝 docs(skills): add Claude Code platform support 452c6f5 ✨ feat(playbook): auto-inject AGENTS.md into CLAUDE.md e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows 7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory 64950e7 📦 deps(skills): sync thirdparty skills a2e3cb0 ✨ feat(playbook): add no_backup deploy controls 8609d59 🐛 fix(docs): repair reference catalog source links 956da11 🐛 fix(playbook): publish hidden ci test fixes 3f67754 📦 deps(skills): sync thirdparty skills 08ca87b 📦 deps(skills): add karpathy thirdparty sync 96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual 3ed5052 📦 deps(skills): sync thirdparty skills 60108dd 📦 deps(skills): sync thirdparty skills da85d4e 🐛 fix(thirdparty): prune nested project snapshots a2a697e 📦 deps(skills): sync thirdparty skills 9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills 33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields 91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update 2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline 5b9c1e3 📦 deps(skills): sync superpowers 2f2d34a 📝 docs(readme): normalize subtree command spacing 62db7db 🐛 fix(ci): serialize superpowers update and sync 3463223 🐛 fix(ci): use literal superpowers sync paths 48f6de8 📦 deps(skills): sync superpowers 4b23529 🔧 chore(ci): merge superpowers update and sync workflow a56d75b 📦 deps(skills): sync superpowers 84bcefa 🔧 chore(ci): use ci[bot] commit author name 00a07e5 📦 deps(skills): sync superpowers 7b84daf 🐛 fix(templates): enforce main loop progress tracking 51373d7 🔧 chore(ci): automate superpowers sync workflow eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block 79755c6 📦 deps(skills): sync superpowers 836d878 📦 deps(skills): sync superpowers 8216c9f 📦 deps(skills): sync superpowers 9439505 🐛 fix(playbook): address reported repo issues git-subtree-dir: docs/standards/playbook git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
278 lines
6.8 KiB
Markdown
278 lines
6.8 KiB
Markdown
# Debug And Profiler
|
||
|
||
文档类型:语法主线
|
||
是否可直接用于生成代码:仅部分
|
||
是否含已验证可执行示例:是
|
||
是否含已验证反例:是
|
||
遇到不确定时跳转到:[08_control_flow.md](08_control_flow.md)、[30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)、[12_pitfalls.md](12_pitfalls.md)
|
||
|
||
手册位置:第 16 篇,共 32 篇。上一篇:[15_ts_sql.md](15_ts_sql.md)。下一篇:[18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md)。
|
||
|
||
这一篇收拢当前已经验证过的调试、计时、profiler 和调用栈相关入口。
|
||
|
||
## 这一篇解决什么问题
|
||
|
||
回答“`goto`、`DebugReturn`、`DebugRunEnv`、`MTIC` / `MTOC`、`SetProfiler`、`__line__` 和 `__stack_frame` 在当前解释器里怎样写、会怎样表现”。
|
||
|
||
## 必须记住的规则
|
||
|
||
- `goto label_name;` 当前已验证可用,但目标位置当前以 `label label_name; statement` 这种内联形式最稳。
|
||
- 当前正向验证只覆盖“跳到同一函数 / 同一脚本体后面的位置”,不要先把更复杂的跨层跳转边界写成事实。
|
||
- `DebugReturn value;` 在当前解释器里会直接结束整段脚本,后面的语句不会继续执行。
|
||
- `DebugRunEnv(0)` 和 `DebugRunEnv(1)` 当前都可直接调用;它们面向调试客户端的副作用,在 CLI 里不直接可见。
|
||
- `DebugRunEnvDo Func(...)` 当前已验证可直接写,并且会返回被调用函数的结果。
|
||
- `MTIC` 会生成一个计时起点;`MTOC` 和 `MTOC(tick)` 当前都会返回秒数。
|
||
- `SetProfiler(7)` 配合 `GetProfilerInfo(1)`,当前可以在不弹窗的情况下拿到 profiler 信息。
|
||
- `__line__` 当前会返回所在代码行号。
|
||
- `__stack_frame` 当前会返回调用栈帧数组;最小 `ToSTN(...)` 观察结果里,每一项是 `(line, "function")` 这一类二元组。
|
||
|
||
## 已验证语法
|
||
|
||
### `goto`
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
begin
|
||
data := array((1, 2), (3, 4));
|
||
target := 3;
|
||
found := 0;
|
||
for i := 0 to Length(data) - 1 do
|
||
begin
|
||
for j := 0 to Length(data[i]) - 1 do
|
||
begin
|
||
if data[i][j] = target then
|
||
goto found_label;
|
||
end;
|
||
end;
|
||
WriteLn(0);
|
||
goto done_label;
|
||
label found_label; found := 1;
|
||
WriteLn(found);
|
||
label done_label; WriteLn(9);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 依次输出 `1`、`9`
|
||
- 说明 `goto found_label;` 当前可以跳到后面的 `label found_label; ...`
|
||
- 也说明当前最稳的目标写法是把 `label` 和第一条目标语句放在同一行
|
||
|
||
跨函数跳转当前没有通过:
|
||
|
||
代码块身份:反例 / 不可照写
|
||
|
||
```text
|
||
program test;
|
||
function Inner();
|
||
begin
|
||
goto out_label;
|
||
end;
|
||
begin
|
||
Inner();
|
||
label out_label; WriteLn(1);
|
||
end.
|
||
```
|
||
|
||
已验证结果:
|
||
|
||
- 上面这段会运行报错,核心信息是 `Goto label can not found!`
|
||
- 当前正向验证只覆盖“同一函数 / 同一脚本体后面的位置”
|
||
- 不要把 `goto` 泛化成能跨函数跳到外层 `label`
|
||
|
||
目标 `label` 单独成行当前也没有通过:
|
||
|
||
代码块身份:反例 / 不可照写
|
||
|
||
```text
|
||
program test;
|
||
begin
|
||
goto done_label;
|
||
label done_label;
|
||
WriteLn("after");
|
||
end.
|
||
```
|
||
|
||
已验证结果:
|
||
|
||
- 上面这种把 `label` 单独放一行、下一行再写目标语句的最小例子,在当前解释器里会报 `Statement missing terminator`
|
||
- 因此当前手册只把 `label name; statement` 这种内联形式写成已验证事实
|
||
|
||
### `DEBUGRETURN`
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
function Inner(bb);
|
||
begin
|
||
DebugReturn bb;
|
||
end;
|
||
begin
|
||
WriteLn("before");
|
||
a := Inner(3);
|
||
WriteLn("after");
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 只输出 `before`
|
||
- 说明 `DebugReturn bb;` 不只是结束 `Inner(...)`,而是直接让整段脚本提前返回
|
||
- 因此 `Inner(3)` 后面的 `WriteLn("after")` 当前不会执行
|
||
|
||
### `DebugRunEnv` 与 `DebugRunEnvDo`
|
||
|
||
`DebugRunEnv(0)` / `DebugRunEnv(1)`:
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
begin
|
||
a := 1;
|
||
DebugRunEnv(0);
|
||
DebugRunEnv(1);
|
||
WriteLn(1);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 输出 `1`
|
||
- 说明这两个调用在当前 CLI 环境里至少能正常执行,不会中断后续语句
|
||
- 但它们把变量 / 系统参数送到调试窗口的效果,在 CLI 中不能直接观察到
|
||
|
||
`DebugRunEnvDo Func(...)`:
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
function Demo(x);
|
||
begin
|
||
y := x + 1;
|
||
return y;
|
||
end;
|
||
begin
|
||
r := DebugRunEnvDo Demo(2);
|
||
WriteLn(r);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 输出 `3`
|
||
- 说明 `DebugRunEnvDo Demo(2)` 当前可以直接写
|
||
- 也说明它当前会把被调用函数的结果继续返回给外层
|
||
|
||
### `MTIC` 与 `MTOC`
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
begin
|
||
t1 := MTIC;
|
||
s := 0;
|
||
for i := 0 to 9999 do
|
||
s := s + i;
|
||
te1 := MTOC(t1);
|
||
t2 := MTIC;
|
||
for j := 0 to 9999 do
|
||
s := s + j;
|
||
te2 := MTOC;
|
||
WriteLn(te1 >= 0);
|
||
WriteLn(te2 >= 0);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 依次输出 `1`、`1`
|
||
- 说明 `MTOC(t1)` 和无参 `MTOC` 当前都能返回可用的秒数结果
|
||
|
||
### `SetProfiler` 与 `GetProfilerInfo`
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
begin
|
||
SetProfiler(7);
|
||
a := 99;
|
||
b := IntToStr(a);
|
||
c := rand(10, 1);
|
||
info := GetProfilerInfo(1);
|
||
WriteLn(IfArray(info));
|
||
WriteLn(Length(info) > 0);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 依次输出 `1`、`1`
|
||
- 说明 `SetProfiler(7)` 当前可以开启 profiler 统计
|
||
- 说明 `GetProfilerInfo(1)` 当前会直接返回 profiler 信息,而且结果是非空数组
|
||
|
||
### `__line__` 与 `__stack_frame`
|
||
|
||
`__line__`:
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
begin
|
||
a := __line__;
|
||
WriteLn(a);
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
- 输出 `3`
|
||
- 说明 `__line__` 当前直接返回所在代码行号
|
||
|
||
`__stack_frame`:
|
||
|
||
代码块身份:已验证可执行示例
|
||
|
||
```tsl
|
||
program test;
|
||
function Inner();
|
||
begin
|
||
return __stack_frame;
|
||
end;
|
||
function Outer();
|
||
begin
|
||
return Inner();
|
||
end;
|
||
begin
|
||
s := Outer();
|
||
WriteLn(ToSTN(s));
|
||
end.
|
||
```
|
||
|
||
已验证运行结果:
|
||
|
||
代码块身份:已验证输出片段
|
||
|
||
```text
|
||
array(
|
||
(11,"__main__"),
|
||
(8,"Outer"))
|
||
```
|
||
|
||
- 说明 `__stack_frame` 当前返回的是调用栈帧数组
|
||
- 在这个最小例子里,可以直接看到调用位置行号和调用者函数名
|
||
|
||
## 跳转指引
|
||
|
||
- 回看主线流程控制:见 [08_control_flow.md](08_control_flow.md)
|
||
- 运行时环境参数:见 [11_runtime_context_and_with.md](11_runtime_context_and_with.md)
|
||
- 回看语法主入口:见 [index.md](index.md)
|
||
- 看运行时服务和全局缓存:见 [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)
|