# TSL 文件模型规则

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

## 本篇职责

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

本页负责文件模型判断；具体语法外形的事实分别见：函数 / 过程 [05_functions_and_calls.md](05_functions_and_calls.md)，类 [08_objects_and_classes.md](08_objects_and_classes.md)，`unit` / `uses` [09_units_and_scope.md](09_units_and_scope.md)，赋值和表达式 [06_expressions_and_operators.md](06_expressions_and_operators.md)。[01_quickstart.md](01_quickstart.md) 只作为最短骨架和高频硬规则速查。

## 智能体文件模型判断流程

1. 后缀是第一证据：用户明确要求 `.tsl` 时，按可执行脚本写；用户明确要求 `.tsf` 时，按可复用声明文件写。
2. 没有后缀时看交付目标：入口流程、脚本任务或一次性执行逻辑对应 `.tsl`；可复用交付物（函数、过程、类、模块或扩展文件）对应 `.tsf`；如果只是脚本内部封装函数或类，仍按 `.tsl` 处理。
3. 目标仍不明确时先问用户；不要把脚本入口和可复用模块替用户合并成一个猜测文件。
4. 写 `.tsl` 时，先生成脚本语句区；需要函数、过程或类时，把声明区放在语句区之后。
5. 写 `.tsf` 时，生成顶层函数 / 过程 / 类声明，或 `unit`；不要写成会直接顺序执行的脚本入口。
6. 没有文档证据时不要发明文件模型；只能使用对应专题事实、项目自身文档或项目专属规则，否则记录文档缺口。

## 文件模型核心规则

- 用户已给出 `.tsl` / `.tsf` 后缀时，后缀就是判断依据；未给后缀时，再按交付目标判断。
- 未给后缀时，入口流程、脚本任务或一次性执行逻辑对应 `.tsl`；可复用交付物（函数、过程、类、模块或扩展文件）对应 `.tsf`；只是脚本内部封装函数或类时，仍按 `.tsl` 处理；仍不明确时向用户确认。
- `.tsl` 脚本按两段理解：语句区在前并按顺序执行；声明区在后，可放 `function / procedure` 或 `type Name = class`。
- `.tsf` 里的非 `unit` 顶层函数 / 过程可按函数扩展理解：部署到解释器 `funcext` 后，`.tsl` 可以直接调用；顶层类声明只按可复用声明理解；`unit` 按模块组织理解。
- `uses` 可以出现在顶层，但这里只把它当成辅助语句，不把它当成主体声明；函数体和类定义体里的位置限制见 [09_units_and_scope.md](09_units_and_scope.md)。
- 裸 `class Name` 不作为类定义写法使用。
- 在 `.tsl` 中，不要在声明区之后继续追加脚本语句。
- `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` 在语法层面都合法。

## 文件模型示例

使用这些示例时遵守：

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

### `.tsl` 文件模型

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

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

```tsl
a := 1;
```

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

`.tsl` 语句区后接函数声明区：

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

```tsl
a := 1;
Test();

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

代码块身份：输出片段

```text
test
```

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

`.tsl` 语句区后接类声明区：

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

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

type MyClass = class
    Value;
end;
```

代码块身份：输出片段

```text
5
```

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

### `.tsf` 文件模型

`.tsf` 顶层函数的最小形态：

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

```tsl
function Demo();
begin
    return 1;
end;
```

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

代码块身份：输出片段

```text
1
```

`.tsf` `unit` 的最小形态：

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

```tsl
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](09_units_and_scope.md)。

代码块身份：输出片段

```text
1
```

### 文件模型反例

不可照写形态：

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

```text
class DemoType
end;
```

上面这种裸 `class` 顶层写法会编译失败。

代码块身份：输出片段

```text
invalid statement
```

## 文件模型归类速查

任务目标是判断文件属于哪一种模型时，使用下面这组归类：

- `.tsl` 脚本语句区：直接写会顺序执行的语句。
- `.tsl` 声明区：在语句区之后写 `function ... begin ... end;`、`procedure ... begin ... end;` 或 `type Name = class ... end;`。
- `.tsf` 顶层函数 / 过程：写可部署到 `funcext` 的 `function` / `procedure` 文件。
- `.tsf` 顶层类声明：写 `type Name = class ... end;`，只按可复用声明理解；类细节见 [08_objects_and_classes.md](08_objects_and_classes.md)。
- `.tsf` 顶层单元：默认先写 `unit ... interface ... implementation ... end.`；简写形态见 [09_units_and_scope.md](09_units_and_scope.md)。

## 文件模型禁止项

- 把 `.tsl` 当成 `.tsf` 来写，只给一个顶层函数，不写任何会执行的脚本语句。
- 因为 `.tsl` 脚本内部需要函数或类，就自动改成 `.tsf`。
- 把 `.tsf` 当成 `.tsl` 来写，在模块文件里直接堆顺序执行的脚本语句。
- 把 `.tsf` 顶层类声明写成裸 `class Name ... end;`；类声明必须使用 `type Name = class ... end;`。
- 把 `uses` 当成主体声明，而不是辅助组织语句。
- 在 `.tsl` 声明区之后继续追加脚本语句。
- `.tsf` 文件名与顶层声明不一致：`UserAccount.tsf` 中写 `function GetUser` 或 `type Customer = class` 或 `unit CustomerModule` 会导致加载失败或检索混乱。
