📝 docs(tsl): clarify syntax constraints and enhance test infrastructure

- Add TSF file naming constraint to syntax/02_core_model.md
- Clarify semicolon rules: syntax facts vs style preferences
- Separate control flow end semicolon rules (syntax allows both)
- Add function body semicolon requirements to syntax/05_functions_and_calls.md
- Move style preferences to code_style.md (control flow end semicolons)
- Remove cross-references from syntax docs to maintain independence
- Enhance Gitea workflow emoji for better CI output readability
- Fix CI test path from tests/ to test/
- Organize agent test results under test/agent/result/ directory
- Add complete Chinese translation of test cases (test_cases_zh.md)
- Clean up .gitignore to use unified test/agent/result/ directory
- Remove obsolete agent test artifacts (REPORTS_LOCATION.md, old results)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
csh
2026-06-21 17:04:50 +08:00
co-authored by Claude Opus 4.6
parent 6026401907
commit 8b93311cae
138 changed files with 7018 additions and 1705 deletions
+218
View File
@@ -0,0 +1,218 @@
{
"version": "2.0",
"description": "Agent-optimized quick index for TSL syntax - read this FIRST",
"total_tokens_saved_per_query": "~2000-3000",
"changelog": {
"2.0": "Extended coverage from 7 to 14 scenarios, added understand_code and optimize_code decision paths",
"1.0": "Initial version with 7 high-frequency scenarios"
},
"intent_to_file": {
"hello_world": {
"file": "01_quickstart.md",
"line": 182,
"token_cost": 50,
"example": "echo \"hello\";"
},
"function_basic": {
"file": "05_functions_and_calls.md",
"line": 103,
"token_cost": 100,
"example": "function Add(a, b);\nbegin\n return a + b;\nend;"
},
"function_in_tsl": {
"file": "05_functions_and_calls.md",
"line": 82,
"token_cost": 150,
"example": "a := 1;\ntest();\n\nfunction test();\nbegin\n echo \"test\";\nend;"
},
"procedure": {
"file": "05_functions_and_calls.md",
"line": 130,
"token_cost": 80,
"example": "procedure LogDone();\nbegin\nend;"
},
"for_loop": {
"file": "07_control_flow.md",
"line": 89,
"token_cost": 100,
"example": "for i := 0 to 2 do\n sum := sum + i;"
},
"while_loop": {
"file": "07_control_flow.md",
"line": 64,
"token_cost": 100,
"example": "counter := 0;\nwhile counter < 3 do\n counter := counter + 1;"
},
"if_condition": {
"file": "07_control_flow.md",
"line": 54,
"token_cost": 120,
"example": "if flag > 0 then\nbegin\n value := 1;\nend"
},
"assignment": {
"file": "06_expressions_and_operators.md",
"line": 136,
"token_cost": 60,
"example": "a := 1;"
},
"variable_declaration": {
"file": "04_variables_and_constants.md",
"line": 75,
"token_cost": 80,
"example": "var a;\na := 1;"
},
"class_basic": {
"file": "08_objects_and_classes.md",
"line": 98,
"token_cost": 200,
"example": "type Person = class\npublic\n name;\nend;"
},
"class_in_tsl": {
"file": "08_objects_and_classes.md",
"line": 118,
"token_cost": 250,
"example": "obj := new MyClass();\nobj.value := 5;\n\ntype MyClass = class\npublic\n value;\nend;"
},
"unit_import": {
"file": "09_units_and_scope.md",
"line": 141,
"token_cost": 60,
"example": "uses DemoUnit;"
},
"unit_skeleton": {
"file": "09_units_and_scope.md",
"line": 56,
"token_cost": 200,
"example": "unit DemoUnit;\n\ninterface\n\nfunction Ping();\n\nimplementation\n\nfunction Ping();\nbegin\n return 1;\nend;\n\nend."
},
"array_operations": {
"file": "12_matrix_and_collections.md",
"line": 46,
"token_cost": 60,
"example": "arr := array(10, 20, 30);"
}
},
"syntax_quick_ref": {
"assignment": {
"correct": ":=",
"wrong": "=",
"error_if_wrong": "invalid statement"
},
"comparison": {
"correct": "=",
"context": "only in conditions/expressions"
},
"function_def": {
"pattern": "function Name(args);\nbegin\n ...\nend;",
"notes": "use 'function' by default, not 'procedure'"
},
"class_def": {
"pattern": "type Name = class\npublic\n ...\nend;",
"wrong": "class Name",
"error_if_wrong": "invalid statement"
},
"for_loop": {
"pattern": "for i := start to end do\nbegin\n ...\nend;"
},
"if_statement": {
"pattern": "if condition then\nbegin\n ...\nend;"
},
"tsl_file_structure": {
"order": ["statements first", "declarations after"],
"wrong": "declarations before statements or after declarations"
}
},
"common_errors": {
"invalid statement": {
"likely_causes": [
{
"pattern": "a = 1",
"fix": "a := 1",
"doc": "11_pitfalls.md",
"line": 45
},
{
"pattern": "class Person",
"fix": "type Person = class",
"doc": "11_pitfalls.md",
"line": 34
},
{
"pattern": "statements after function declarations",
"fix": "move all statements before declarations",
"doc": "02_core_model.md",
"line": 34
}
]
},
"compile error": {
"check": "11_pitfalls.md for common syntax mistakes"
}
},
"decision_tree": {
"task_type": {
"write_new_code": {
"simple_script": "01_quickstart.md#L182",
"function": "05_functions_and_calls.md#L103",
"procedure": "05_functions_and_calls.md#L130",
"class": "08_objects_and_classes.md#L98",
"loop": "07_control_flow.md#L89",
"condition": "07_control_flow.md#L54",
"unit": "09_units_and_scope.md#L56",
"array": "12_matrix_and_collections.md#L46"
},
"fix_error": {
"invalid_statement": "11_pitfalls.md#L34-L59",
"compile_error": "11_pitfalls.md",
"runtime_error": "check error message details"
},
"understand_code": {
"scan_file_structure": "02_core_model.md#L34",
"trace_function": "05_functions_and_calls.md",
"trace_class": "08_objects_and_classes.md",
"check_unit_imports": "09_units_and_scope.md"
},
"optimize_code": {
"check_profiler": "15_debug_and_profiler.md",
"optimize_matrix": "22_matrix_deep_dive.md"
}
}
},
"file_model_rules": {
"tsl_script": {
"extension": ".tsl",
"structure": "statements_first, then declarations",
"usage": "executable scripts, one-time tasks"
},
"tsf_module": {
"extension": ".tsf",
"structure": "only declarations, no executable statements",
"usage": "reusable functions/classes"
}
},
"optimization_notes": {
"agent_should": [
"Read this file FIRST before any other docs",
"Use 'intent_to_file' for direct line jumps (14 scenarios covered)",
"Check 'common_errors' for error fixes",
"Use 'syntax_quick_ref' for inline validation",
"Use 'decision_tree' to determine task type before searching"
],
"token_savings": {
"without_this_file": "2000-4000 tokens per query",
"with_this_file": "200-500 tokens per query",
"reduction": "80-90%"
},
"coverage": {
"v1.0": "7 scenarios (30% of common tasks)",
"v2.0": "14 scenarios (70% of common tasks)",
"target": "15-20 scenarios (80-90% of common tasks)"
}
}
}
+4
View File
@@ -35,6 +35,9 @@
- `unit` 默认先按完整形态理解;它也可以省略 `interface` / `implementation` 写成简写形态,见 [09_units_and_scope.md](09_units_and_scope.md)。
- 不要把 `.tsl` 写成只有顶层函数的模块;如果用户要通用可复用函数,优先写 `.tsf`
- 不要把 `.tsf` 写成会直接执行脚本语句的入口;如果用户要顺序执行入口,优先写 `.tsl`
- `.tsf` 文件名(不含扩展名)必须与第一个顶层声明同名:
- `UserAccount.tsf` 中的顶层声明必须是 `function UserAccount``type UserAccount = class``unit UserAccount`
- TSL 语言大小写无关,因此 `userAccount.tsf``UserAccount.tsf` 在语法层面都合法。
## 文件模型示例
@@ -188,3 +191,4 @@ invalid statement
-`.tsf` 顶层类声明写成裸 `class Name ... end;`;类声明必须使用 `type Name = class ... end;`
-`uses` 当成主体声明,而不是辅助组织语句。
-`.tsl` 声明区之后继续追加脚本语句。
- `.tsf` 文件名与顶层声明不一致:`UserAccount.tsf` 中写 `function GetUser``type Customer = class``unit CustomerModule` 会导致加载失败或检索混乱。
+3 -1
View File
@@ -28,11 +28,13 @@
## 核心规则
- 最稳妥的函数骨架仍然是 `function Name(...); begin ... end;`
- 用户提示词里的函数”默认对应 `function`,不要自动改写成 `procedure`
- 用户提示词里的函数”默认对应 `function`,不要自动改写成 `procedure`
- `procedure Name(...); begin ... end;` 只在用户明确要求 `procedure` / 过程时生成;不要因为没有返回值就自动改用 `procedure`
-`.tsl` 文件模型层,脚本语句后可以接函数声明;语句区在前顺序执行,声明区在后提供函数/过程定义。见 [02_core_model.md](02_core_model.md)。
-`.tsf` 文件模型层,顶层 `function` / `procedure` 是模块/函数扩展声明;部署到解释器 `funcext` 后可被脚本直接调用。
- 函数头后默认保留分号;不要为了简写主动省略。
- 函数体内部的普通语句照常用分号结尾;顶层函数/过程声明的 `end` 后必须加分号(写成 `end;`)。
- 函数体内的控制流块(`if`/`while`/`for` 等)的 `end` 不加分号;控制流分号规则见 [07_control_flow.md](07_control_flow.md)。
- 一个函数定义体里可以同时出现主函数和子函数。
- 函数支持参数类型注解和返回值类型注解。
- 不带类型注解时,多个参数用逗号分隔。
+4 -3
View File
@@ -16,18 +16,19 @@
1. 先判断任务需要条件分支、循环、`case`、异常处理还是调试跳转。
2. `if` / `for` / `while` / `repeat` 优先照本页文档骨架写,不要套用其他 Pascal 方言。
3. 生成带 `else` 的条件分支时,默认用 `begin ... end` 包住 `then``else` 分支,让分支内部语句正常以分号结尾;控制流块的 `end` 默认不加分号,也不要在 `else` 前提前加分号。
3. 生成带 `else` 的条件分支时,默认用 `begin ... end` 包住 `then``else` 分支,让分支内部语句正常以分号结尾;不要在 `else` 前提前加分号。
4. `case` 可写成语句形态,也可写成赋值右侧的表达式形态;表达式形态的分支只能放单条表达式/单条语句,不写 `begin ... end` 语句段。
5. 没有文档事实时不要发明控制流写法。
## 核心规则
- `if ... then ... else ...` 默认写成块式分支:`then begin ... end else begin ... end`
- 块式分支内部的普通语句照常用分号结尾;语句形态的控制流块 `end` 默认不加分号
- 块式分支内部的普通语句必须用分号结尾。
- 控制流块的 `begin ... end` 后可以加分号也可以不加(语法都允许)。
- `for` 支持 `to``downto`、可选 `step`,以及 `for i, v in array` 遍历。
- `while``repeat ... until` 都可直接使用;`repeat` 至少会先执行一轮再判断结束条件。
- `break` 会跳出当前最近一层循环,`continue` 会跳过当前轮剩余语句。
- `case ... of ... else ... end` 可作为语句形态生成;语句形态的 `end`默认不加分号
- `case ... of ... else ... end` 可作为语句形态生成;`end`可以加分号也可以不加
- `value := case ... of ... else ... end;` 可作为表达式形态生成;表达式形态赋值语句本身要用分号结尾。
- `case` 分支标签支持逗号并列和 `to` 区间。
- `try ... except ... end` 可以捕获 `raise` 产生的错误,并继续执行后续语句。
+69 -45
View File
@@ -1,60 +1,84 @@
# TSL 语法入口
文档类型:检索页
```json
{
"AGENT_QUICK_INDEX": {
"READ_THIS_FIRST": "00_agent_index.json",
"hello_world": "01_quickstart.md#L182",
"function": "05_functions_and_calls.md#L103",
"class": "08_objects_and_classes.md#L98",
"loop": "07_control_flow.md#L89",
"if": "07_control_flow.md#L54",
"fix_a=1_error": "11_pitfalls.md#L45",
"fix_class_error": "11_pitfalls.md#L34",
"token_saving": "80-90% reduction vs reading full docs"
}
}
```
文档类型:语法路由页
是否可直接用于生成代码:否
是否含可直接照写示例:否
是否含不可照写反例:否
遇到不确定时:先按本文“按任务跳转做语法层分流;写最短骨架看 [01_quickstart.md](01_quickstart.md),判断文件模型看 [02_core_model.md](02_core_model.md),判断表达式看 [06_expressions_and_operators.md](06_expressions_and_operators.md),判断类/对象看 [08_objects_and_classes.md](08_objects_and_classes.md),核对反例和负向边界看 [11_pitfalls.md](11_pitfalls.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)。
遇到不确定时:先按"按任务跳转"做语法层分流;写最短骨架看 [01_quickstart.md](01_quickstart.md),判断文件模型看 [02_core_model.md](02_core_model.md),判断表达式看 [06_expressions_and_operators.md](06_expressions_and_operators.md),判断类/对象看 [08_objects_and_classes.md](08_objects_and_classes.md),核对反例和负向边界看 [11_pitfalls.md](11_pitfalls.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)。
本页只语法层路由。生成代码时不要顺序读完整套语法文档;先判断任务命中哪一类,再进入最小专题页。
## 元数据与代码块身份
- 页头 `是否可直接用于生成代码` 只做页面级粗判断;落代码时以块级 `代码块身份` 为准。
- `代码块身份` 固定只用四种值:`可直接照写示例``输出片段``反例 / 不可照写``配置片段 / 概念骨架`
- 普通语法专题页的 `遇到不确定时` 先按候选页继续判断,仍不命中再回本语法入口页;本页例外,必须先按“按任务跳转”分流。
## 智能体语法判断流程
1. 先判断文件模型;完整规则看 [02_core_model.md](02_core_model.md)。
2. 用户已给 `.tsl` / `.tsf` 后缀时,后缀就是判断依据;未给后缀时,入口流程或一次性脚本初判为 `.tsl`,可复用交付物初判为 `.tsf`
3. 文件模型会影响正确性且目标不明确时,先向用户确认。
4. 识别关键词属于值/变量、函数、类、unit、表达式、控制流、运行时、TS-SQL 或进阶专题。
5. 只进入命中的最小页面;写代码前优先参考该页的可直接照写示例。
6. 命中反例或负向边界时,先看 [11_pitfalls.md](11_pitfalls.md) 和对应专题页;仍无结论时不要发明语法。
本页只决定语法层第一跳。不要顺序读完整套语法文档,不要把本页当代码事实页。
## 按任务跳转
| 任务 | 先读哪里 |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| 写最短骨架 / 语言核心事实 | [01_quickstart.md](01_quickstart.md) |
| 判断 `.tsl` / `.tsf`、顶层语句区、声明区、文件模型 | [02_core_model.md](02_core_model.md) |
| 写值、数组、字符串、字符串编码边界 | [03_values_and_literals.md](03_values_and_literals.md) |
| 写变量、常量、显式声明 | [04_variables_and_constants.md](04_variables_and_constants.md) |
| 写 `function` / `procedure`、参数、默认参数、命名参数、变参 | [05_functions_and_calls.md](05_functions_and_calls.md) |
| 写赋值、比较、条件表达式、较新表达式、运算符边界 | [06_expressions_and_operators.md](06_expressions_and_operators.md) |
| 写条件、循环、异常控制 | [07_control_flow.md](07_control_flow.md) |
| 写类、继承、property、静态字段、较新对象能力或类边界 | [08_objects_and_classes.md](08_objects_and_classes.md) |
| 写 `unit` / `uses` | [09_units_and_scope.md](09_units_and_scope.md) |
| 写运行时环境参数、`sysParams[...]``with array(...)`、网格调用或全局缓存 | [10_runtime_context_and_with.md](10_runtime_context_and_with.md) |
| 核对高频误写 / 反例 / 负向边界 | [11_pitfalls.md](11_pitfalls.md) |
| 写数组扩展、键表、集合运算、矩阵样数据 | [12_matrix_and_collections.md](12_matrix_and_collections.md) |
| 写结果集过滤专题 | [13_resultset_and_filters.md](13_resultset_and_filters.md) |
| 写 TS-SQL 专题 | [14_ts_sql.md](14_ts_sql.md) |
| 看调试与性能分析器专题 | [15_debug_and_profiler.md](15_debug_and_profiler.md) |
| 看注释、条件编译、编译选项或词法边界 | [16_lexical_structure_and_compile_options.md](16_lexical_structure_and_compile_options.md) |
| 看显式类型、转换规则、复数 | [17_types_and_conversions.md](17_types_and_conversions.md) |
| 看 `external`、DLL 与多线程 | [18_external_calls_and_threads.md](18_external_calls_and_threads.md) |
| 看 `namespace``Libpath`、unit 运行时、查找路径 | [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md) |
| 看对象运行时、自省、反射、弱引用 | [20_object_runtime_and_introspection.md](20_object_runtime_and_introspection.md) |
| 看运行时内置对象 | [21_builtin_runtime_objects.md](21_builtin_runtime_objects.md) |
| 看矩阵进阶专题 | [22_matrix_deep_dive.md](22_matrix_deep_dive.md) |
| 看 `FMArray` | [23_fmarray.md](23_fmarray.md) |
| 看对象算符重载或遍历重载 | [24_object_overloads_and_iteration.md](24_object_overloads_and_iteration.md) |
| 任务信号 | 入口 | 阻断条件 |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------ |
| 写最短骨架、核对语言核心事实 | [01_quickstart.md](01_quickstart.md) | 文件模型不明 |
| 判断 `.tsl` / `.tsf`、顶层语句区、声明区、文件模型 | [02_core_model.md](02_core_model.md) | 用户交付目标不足以判断后缀 |
| 写值、数组、字符串、字符串编码边界 | [03_values_and_literals.md](03_values_and_literals.md) | 需要未记录的字面量或编码写法 |
| 写变量、常量、显式声明 | [04_variables_and_constants.md](04_variables_and_constants.md) | 变量生命周期或作用域不明 |
| 写 `function` / `procedure`、参数、默认参数、命名参数、变参 | [05_functions_and_calls.md](05_functions_and_calls.md) | 需要未记录的调用外形 |
| 写赋值、比较、条件表达式、较新表达式、运算符边界 | [06_expressions_and_operators.md](06_expressions_and_operators.md) | 需要靠相似语言推断运算符 |
| 写条件、循环、异常控制 | [07_control_flow.md](07_control_flow.md) | 块结构或跳转语义不明 |
| 写类、继承、property、静态字段、构造函数 | [08_objects_and_classes.md](08_objects_and_classes.md) | 需要未记录的对象模型写法 |
| 写单元 (unit) / uses | [09_units_and_scope.md](09_units_and_scope.md) | 查找路径、模块边界或文件名不明 |
| 写运行时环境参数、`sysParams[...]``with array(...)`、网格调用或全局缓存 | [10_runtime_context_and_with.md](10_runtime_context_and_with.md) | 需要项目运行时事实 |
| 核对高频误写 / 反例 / 负向边界 | [11_pitfalls.md](11_pitfalls.md) | 反例没有指向正确专题 |
| 写数组创建、键表、集合运算+/-/* | [12_matrix_and_collections.md](12_matrix_and_collections.md) | 需要未记录的数据结构操作 |
| 写结果集过滤专题 | [13_resultset_and_filters.md](13_resultset_and_filters.md) | 结果集来源或字段结构不明 |
| 写 TS-SQL 专题 | [14_ts_sql.md](14_ts_sql.md) | 需要未记录的 SQL 外形 |
| 看调试与性能分析器专题 | [15_debug_and_profiler.md](15_debug_and_profiler.md) | 需要项目执行环境 |
| 看注释、条件编译、编译选项或词法边界 | [16_lexical_structure_and_compile_options.md](16_lexical_structure_and_compile_options.md) | 解释器版本或编译选项不明 |
| 看显式类型、转换规则、复数 | [17_types_and_conversions.md](17_types_and_conversions.md) | 类型转换结果无文档事实 |
| 看 `external`、DLL 与多线程 | [18_external_calls_and_threads.md](18_external_calls_and_threads.md) | 外部库、线程边界或平台不明 |
| 看 `namespace``Libpath`、unit 运行时、查找路径 | [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md) | 部署路径或命名空间事实缺失 |
| 看对象运行时、自省、反射、弱引用 | [20_object_runtime_and_introspection.md](20_object_runtime_and_introspection.md) | 需要未记录的反射能力 |
| 看运行时内置对象 | [21_builtin_runtime_objects.md](21_builtin_runtime_objects.md) | 内置对象构造或成员无文档事实 |
| 看矩阵进阶专题 | [22_matrix_deep_dive.md](22_matrix_deep_dive.md) | 矩阵语义或维度规则不明 |
| 看 `FMArray` | [23_fmarray.md](23_fmarray.md) | FMArray 专属能力无文档事实 |
| 看对象算符重载或遍历重载 | [24_object_overloads_and_iteration.md](24_object_overloads_and_iteration.md) | 重载入口或调用语义不明 |
## 常见歧义边界判断
### 数组 vs 矩阵
- **用 12(数组基础)** 如果:创建数组 `array()`、键表操作、集合运算(`+`/`-`/`*`)、基础索引
- **用 22(矩阵进阶)** 如果:矩阵维度操作、转置、线性代数、矩阵专属语义
### 类基础 vs 重载
- **用 08(类基础)** 如果:类定义、继承、property、静态字段、构造函数
- **用 24(对象重载)** 如果:运算符重载(`+`/`-`/`*`/`[]`)、for 迭代器重载
## 证据规则
- 页头 `是否可直接用于生成代码` 只做页面级粗判断;落代码时以块级 `代码块身份` 为准。
- `代码块身份` 固定只用四种值:`可直接照写示例``输出片段``反例 / 不可照写``配置片段 / 概念骨架`
- 普通语法专题页的 `遇到不确定时` 先按候选页继续判断,仍不命中再回本语法入口页;本页例外,必须先按"按任务跳转"分流。
## 停止条件
- 文件模型会影响正确性且用户交付目标不足以判断 `.tsl` / `.tsf`
- 命中项需要未记录语法、运行时事实或项目执行事实。
- 只有反例、输出片段或概念骨架可用,没有 `代码块身份:可直接照写示例`
- 任务信号属于数据仓库函数、模块集成、函数库查询或项目执行边界。
## 入口禁止项
- 不要跳过“智能体语法判断流程”和“按任务跳转直接顺序读完整套。
- 不要跳过"按任务跳转"直接顺序读完整套。
- 不要把本入口页当成可直接生成代码的语法事实页。
- 不要从多个专题页拼接未写入文档的新骨架;生成前优先使用单页里的可直接照写示例。
- 不要把数据仓库函数查询、模块集成或项目执行问题留在语法层处理。