playbook/docs/tsl/syntax/21_builtin_runtime_objects.md

285 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TSL 内置运行时对象
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
遇到不确定时:先按本页候选页继续判断;[20_object_runtime_and_introspection.md](20_object_runtime_and_introspection.md)、[10_runtime_context_and_with.md](10_runtime_context_and_with.md)、[11_pitfalls.md](11_pitfalls.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
这一篇只收运行时内置对象的文档明确最小模型。这里讲的是语言运行时对象,不是金融业务 API。
## 本篇职责
回答“写普通 TSL/TSF 脚本时,哪些内置对象可以直接创建,最小可用接口是什么,哪些对象其实依赖特定运行上下文”。
## 智能体内置运行时对象判断流程
1. 先判断要访问哪个内置运行时对象,以及它是不是语言对象而非业务 API。
2. 只照本页明确的最小读写路径使用内置对象。
3. 不要把金融业务上下文对象和语言运行时对象混在一起。
4. 需要系统参数或 `with` 后缀时跳转到运行时上下文页。
5. 没有对应代码块时不要发明内置运行时对象写法。
## 核心规则
- `TStringList` 可以直接用 `new TStringList()` 创建。
- `TStringList` 支持数字下标、字符串键下标、`Count` 和 `Add(...)`
- `THashedStringList` 可以直接创建,最小用法与 `TStringList` 接近,适合按名称快速取值。
- 流对象应先按 `TStream` 家族理解;普通脚本里的最小可靠入口是 `TMemoryStream` 这种具体类型。
- 直接 `new TStream()` 会失败,错误信息包含 `function:TStream compile error or not found`
- `TMemoryStream` 支持 `Write(...)`、`Read(...)`、`Position`、`Size`。
- `TFileStream` 可以带目录别名、文件名和打开模式创建,并支持 `TStream` 的读写位置模型。
- `TCipher` 不是“无参即可创建”的对象;`new TCipher()` 会失败。
- `TCipher` 的最小写法是 `new TCipher(2)`,然后设置 `Password` 再做 `Encrypt(...)` / `Decrypt(...)`
- `TRsa` 可以直接创建;先 `GenerateKey(...)`,再读取 `PublicKey` / `PrivateKey` 或执行公私钥加解密。
- `TIniFile` 适合读写磁盘 INI 文件;`TMemIniFile` 适合内存 INI 数据。
- `MailMsg``MessagePart` 可以直接创建并设置消息字段,但发送邮件流程属于 SMTP 对象/外部服务边界。
- `TWebRequest``TWebResponse` 在普通脚本里不作为可直接 `new` 的对象。
- 因此Web 请求 / 响应对象不要直接写进普通脚本模板;它们应视为特定运行上下文对象。
- 本页不承担对象完整方法表;只收能让 agent 稳定生成代码的最小入口。
- 本页失败创建示例只用于边界判断,不作为业务代码模板复制。
## 可直接照写示例
### `TStringList`
代码块身份:可直接照写示例
```tsl
obj := new TStringList();
obj.CommaText := "A=aaa,B=bbb,C=222";
writeLn(obj[1]);
writeLn(obj["B"]);
writeLn(obj.Count);
obj.Add("D=444");
writeLn(obj.Count);
```
结果说明:
- 依次输出 `B=bbb`、`bbb`、`3`、`4`
- 说明既可以按数字下标取整行,也可以按键名取 `Name=Value` 里的值
### `THashedStringList`
代码块身份:可直接照写示例
```tsl
obj := new THashedStringList();
obj.Add("A=aaa");
obj.Add("B=bbb");
writeLn(obj.Count);
writeLn(obj["B"]);
```
结果说明:
- 依次输出 `2`、`bbb`
- 说明 `THashedStringList` 可按 `Name=Value` 的名称键读取值
### `TStream` 家族的最小可靠入口:`TMemoryStream`
代码块身份:可直接照写示例
```tsl
mem := new TMemoryStream();
buffer := "ABC";
mem.Write(buffer, 3);
mem.Position := 0;
outbuf := "xxx";
mem.Read(outbuf, 3);
writeLn(outbuf);
writeLn(mem.Size);
```
结果说明:
- 依次输出 `ABC`、`3`
- 说明普通脚本里应优先使用 `TMemoryStream` 这类具体流对象。
`TFileStream` 可直接打开文件并沿用 `TStream``Write(...)` / `Read(...)` / `Position` / `Size` 模型:
代码块身份:可直接照写示例
```tsl
file_name := "object_probe.txt";
stream := new TFileStream("", file_name, 65535);
buffer := "ABC";
stream.Write(buffer, 3);
writeLn(stream.Size);
stream.Position := 0;
outbuf := "xxx";
stream.Read(outbuf, 3);
writeLn(outbuf);
```
结果说明:
- 依次输出 `3`、`ABC`
- `TFileStream("", file_name, 65535)` 可作为最小读写文件流骨架
`TStream` 创建反例:
代码块身份:反例 / 不可照写
```text
base := new TStream();
writeLn(ifObj(base));
```
结果说明:
- 上面这种写法会报 `function:TStream compile error or not found`
- 不要把裸 `TStream` 当成可直接创建对象。
### `TCipher`
无参创建反例:
代码块身份:反例 / 不可照写
```text
bad := new TCipher();
writeLn(ifObj(bad));
```
结果说明:
- 上面这种写法会报 `New Class TCipher Error.`
- `TCipher` 不要无参创建。
带模式参数创建:
代码块身份:可直接照写示例
```tsl
cipher := new TCipher(2);
cipher.Password := "Tinysoft";
enc := cipher.Encrypt("abc");
writeLn(enc <> "abc");
writeLn(cipher.Decrypt(enc));
```
结果说明:
- 依次输出 `1`、`abc`
- 说明 `TCipher` 必须按“带模式参数创建”来写,随后可稳定走 `Password -> Encrypt -> Decrypt`
### `TRsa`
代码块身份:可直接照写示例
```tsl
rsa := new TRsa();
rsa.GenerateKey(1024);
plain := "abc";
enc := rsa.PubEncrypt(plain);
writeLn(rsa.PriDecrypt(enc));
enc2 := rsa.PriEncrypt(plain);
writeLn(rsa.PubDecrypt(enc2));
writeLn(length(rsa.PublicKey) > 0);
writeLn(length(rsa.PrivateKey) > 0);
```
结果说明:
- 依次输出 `abc`、`abc`、`1`、`1`
- 说明 `TRsa` 先生成密钥,再用公钥加密 / 私钥解密,或私钥加密 / 公钥解密
### `TIniFile` 与 `TMemIniFile`
磁盘 INI 文件:
代码块身份:可直接照写示例
```tsl
ini := new TIniFile("", "object_probe.ini");
ini.WriteString("S", "K", "V");
writeLn(ini.ReadString("S", "K", ""));
ini.WriteInteger("S", "N", 123);
writeLn(ini.ReadInteger("S", "N", 0));
```
结果说明:
- 依次输出 `V`、`123`
- 说明 `TIniFile` 适合直接读写磁盘 INI 文件
内存 INI 数据:
代码块身份:可直接照写示例
```tsl
ini := new TMemIniFile();
ini.WriteString("S", "K", "V");
writeLn(ini.ReadString("S", "K", ""));
```
结果说明:
- 输出 `V`
- 说明 `TMemIniFile` 可不依赖磁盘文件,直接读写内存 INI 数据
### `MailMsg` 与 `MessagePart`
代码块身份:可直接照写示例
```tsl
msg := new MailMsg();
msg.Subject := "Hello";
msg.Body := "BodyText";
msg.Sender := "sender@example.com";
msg.Recipients := "to@example.com";
writeLn(msg.Subject);
writeLn(msg.Body);
writeLn(length(msg.AsString) > 0);
part := new MessagePart();
part.ContentType := "text/plain";
part.Body := "PartBody";
writeLn(part.ContentType);
writeLn(part.Body);
```
结果说明:
- 依次输出 `Hello`、`BodyText`、`1`、`text/plain`、`PartBody`
- 说明 `MailMsg` / `MessagePart` 可作为消息数据对象使用
- 发送邮件应回到 SMTP 对象和外部服务配置,不在本页生成连接/认证/发送模板
### `TWebRequest` / `TWebResponse` 的普通脚本边界
代码块身份:反例 / 不可照写
```text
req := new TWebRequest();
resp := new TWebResponse();
```
结果说明:
- `new TWebRequest()` 会报 `function:TWebRequest compile error or not found`
- `new TWebResponse()` 会报 `function:TWebResponse compile error or not found`
- 普通脚本里Web 请求 / 响应对象不能直接按普通 `new ...()` 脚本对象来写。
## 本页不生成的范围
- `FTP` / `SMTP` / `POP3` 的连接、认证、上传下载、发送邮件和收取邮件流程。
- `TWebRequest` / `TWebResponse` 的 Web 请求响应流程。
- `TCookie` / `TCookieCollection`
- `THandleStream`
- `TRegistryIniFile`
- `TSessionMan` / `TSession`
这些对象不作为本页可生成业务流程不要因为源资料里出现过就默认生成连接、认证、网络访问、Web 请求响应或会话管理代码。
## 禁止项
- 不要直接把 `new TStream()` 写成普通脚本里的可靠创建方式。
- 不要无参创建 `TCipher`;最小可靠写法是 `new TCipher(2)` 后再设置 `Password`
- 不要把 `TWebRequest` / `TWebResponse` 写进普通脚本模板。
- 不要把 `MailMsg.AddText(...)` 当成默认消息正文写法;普通正文优先设置 `Body`
- 不要在缺少主机、账号、密码、端口和协议要求时生成 `FTP` / `SMTP` / `POP3` 连接流程。
- 不要把未写入文档资料里的内置对象,当成语法事实。
- 不要把本页反例块里的失败创建代码包进 `try/except` 后当成业务模板。