Files
csh 40a9885eb4 feat(tsl-syntax-reference): harden retrieval and restructure pages
- flag weak candidates (no intent/heading/identifier/tag hit) and exit 2
  when every candidate is weak: mis-hits used to be indistinguishable
  from real hits, so the retry-with-better-terms loop never fired
- accept multiple ids per --section for batch fetch, failing atomically
  on any unknown id so a partial fetch cannot pass as complete
- move query synonyms and page intent aliases to data/lexicon.json and
  enforce alias/page correspondence in --check; curation data no longer
  lives in the engine
- document the weak-hit rule, batch fetch and prelude-once guidance in
  SKILL.md, with curation discipline in data/README.md
- drop 11_pitfalls.md, renumber the trailing pages and spread retrieval
  tags across topics; lexicon keys are page filenames, so the renumbering
  and the new --check rule cannot land in separate commits
2026-07-29 15:45:47 +08:00

8.7 KiB
Raw Permalink Blame History

TSL 文件模型规则

本篇说明 TSL 的文件模型判断规则:智能体如何区分 .tsl 可执行脚本与 .tsf 可复用声明文件,如何识别脚本语句区和声明区,以及为什么很多错误其实是“文件模型选错了”。

本篇职责

回答“目标文件到底是 .tsl 脚本还是 .tsf 可复用声明文件,以及 .tsl 里的哪些内容会顺序执行、哪些内容只是后置声明”。

本页是文件模型的唯一事实源:后缀判断、语句区 / 声明区顺序、.tsf 顶层声明形态和文件名约束都在这里收口。函数体、类体、unit 内部的语法外形由各自专题页拥有。

文件模型核心规则

  • 用户已给出 .tsl / .tsf 后缀时,后缀就是判断依据;未给后缀时,再按交付目标判断。
  • 未给后缀时,入口流程、脚本任务或一次性执行逻辑对应 .tsl;可复用交付物(函数、过程、类、模块或扩展文件)对应 .tsf;只是脚本内部封装函数或类时,仍按 .tsl 处理;仍不明确时向用户确认,不要把脚本入口和可复用模块合并成一个猜测文件。
  • .tsl 脚本按两段理解:语句区在前并按顺序执行;声明区在后,可放 function / proceduretype Name = class。写 .tsl 时先写语句区,需要函数、过程或类时把声明区放在语句区之后。
  • .tsf 时只写顶层函数 / 过程 / 类声明,或 unit;不要写成会直接顺序执行的脚本入口。
  • .tsf 里的非 unit 顶层函数 / 过程可按函数扩展理解:部署到解释器 funcext 后,.tsl 可以直接调用;顶层类声明只按可复用声明理解;unit 按模块组织理解。
  • uses 可以出现在顶层,但这里只把它当成辅助语句,不把它当成主体声明;函数体和类定义体里的位置限制见 09_units_and_scope.md
  • class Name 不作为类定义写法使用。
  • .tsl 中,不要在声明区之后继续追加脚本语句。
  • unit 默认先按完整形态理解;它也可以省略 interface / implementation 写成简写形态,见 09_units_and_scope.md
  • 不要把 .tsl 写成只有顶层函数的模块;如果用户要通用可复用函数,优先写 .tsf
  • 不要把 .tsf 写成会直接执行脚本语句的入口;如果用户要顺序执行入口,优先写 .tsl
  • .tsf 文件名(不含扩展名)必须与第一个顶层声明同名:
    • UserAccount.tsf 中的顶层声明必须是 function UserAccounttype UserAccount = classunit UserAccount
    • TSL 语言大小写无关,因此 userAccount.tsfUserAccount.tsf 在语法层面都合法。

文件模型示例

使用这些示例时遵守:

  • 可以模仿已经出现的文件模型、语句顺序和块级结构。
  • 不要从示例推断未出现的部署方式、文件名规则或模块查找规则。
  • .tsf 示例后的输出片段只证明部署后可由 .tsl 调用取得结果;不要理解为 .tsf 会独立顺序执行。
  • 扩展写法必须有对应专题事实支持。

.tsl 文件模型

.tsl 脚本语句区的最小形态:

代码块身份:可直接照写示例

a := 1;

代码块说明:这是 .tsl 语句区最小形态,只证明脚本语句可以从文件开头顺序执行。

.tsl 语句区后接函数声明区:

代码块身份:可直接照写示例

a := 1;
Test();

function Test();
begin
    echo "test";
end;

代码块身份:输出片段

test

代码块说明:这个骨架证明 .tsl 语句区可以调用后置函数声明;不要在函数声明区之后继续追加脚本语句。

.tsl 语句区后接类声明区:

代码块身份:可直接照写示例

obj := new MyClass();
obj.Value := 5;
echo obj.Value;

type MyClass = class
    Value;
end;

代码块身份:输出片段

5

代码块说明:这个骨架证明 .tsl 语句区可以通过 new MyClass() 使用后置类声明;普通对象创建默认优先 new ClassName()createObject(...) 也是对象创建方式,但作为次选;需要字符串类名、类类型变量或跨 unit 路径时,更适合用 createObject(...),细节见 08_objects_and_classes.md

.tsf 文件模型

.tsf 顶层函数的最小形态:

代码块身份:可直接照写示例

function Demo();
begin
    return 1;
end;

代码块说明:这个 .tsf 部署为函数扩展后,可由 .tsl 脚本调用 Demo() 并取得返回值;部署方式属于项目执行层,不写进通用语法页。

代码块身份:输出片段

1

.tsf 顶层类声明的最小形态:

代码块身份:可直接照写示例

type UserAccount = class
public
    Name;
    function Describe();
    begin
        return Name;
    end;
end;

代码块说明:这个 .tsf 只按可复用类声明理解,不会自己顺序执行。文件必须命名为 UserAccount.tsf,因为文件名要与第一个顶层声明同名。类成员、可见性和继承的完整事实见 08_objects_and_classes.md

.tsf unit 的最小形态:

代码块身份:可直接照写示例

unit DemoUnit;

interface

function Ping();

implementation

function Ping();
begin
    return 1;
end;

end.

代码块说明:这个 .tsf unit 可由 .tsl 脚本 uses DemoUnit 后调用 Ping(),返回值为 1;调用脚本和查找路径边界见 09_units_and_scope.md

代码块身份:输出片段

1

文件模型反例

顶层裸 class 声明:

代码块身份:反例 / 不可照写

class DemoType
end;

上面这种裸 class 顶层写法会编译失败;顶层类声明必须写成 type DemoType = class ... end;

代码块身份:输出片段

invalid statement

在声明区之后继续写脚本语句:

代码块身份:反例 / 不可照写

a := 1;
test();

function test();
begin
    echo "test";
end;

echo "after declaration";

上面最后一行属于「声明区之后继续写脚本语句」,会编译失败。正确做法是把所有会执行的脚本语句都放在声明区之前。

代码块身份:输出片段

Execute script error at Line:9
function:__main__:line 9: invalid statement

任务到文件模型的选择规则

已经确定任务目标时,按下表选择起手形态:

任务 起手形态 写法
入口流程、脚本任务或一次性执行逻辑 .tsl 脚本语句区 直接写会顺序执行的语句
脚本逻辑需要调用本文件内函数 .tsl 语句区 + 后置函数声明区 语句区之后写 function ... begin ... end;procedure ... begin ... end;
脚本逻辑需要对象状态、字段、方法 .tsl 语句区 + 后置类声明区 语句区之后写 type Name = class ... end;
沉淀可复用函数或过程 .tsf 顶层函数 / 过程 写可部署到 funcextfunction / procedure 文件
沉淀可复用类 .tsf 顶层类声明 type Name = class ... end;,只按可复用声明理解;类细节见 08_objects_and_classes.md
把接口和实现组织进一个模块 .tsf unit 默认先写 unit ... interface ... implementation ... end.;简写形态见 09_units_and_scope.md

补充判断:

  • 不要因为代码里需要函数或类就自动升级成 .tsf.tsl 也可以在语句区后放声明区。
  • 不要把 unit 当成最小起手骨架;只有用户明确要模块接口 / 实现组织,或项目已有 unit 边界时,才进入 unit 写法。

文件模型禁止项

  • .tsl 当成 .tsf 来写,只给一个顶层函数,不写任何会执行的脚本语句。
  • .tsf 当成 .tsl 来写,在模块文件里直接堆顺序执行的脚本语句。
  • uses 当成主体声明,而不是辅助组织语句。
  • .tsf 文件名与顶层声明不一致:UserAccount.tsf 中写 function GetUsertype Customer = classunit CustomerModule 会导致加载失败或检索混乱。