- 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
287 lines
8.3 KiB
Markdown
287 lines
8.3 KiB
Markdown
# TSL 内置运行时对象
|
|
|
|
这一篇只收运行时内置对象的文档明确最小模型。这里讲的是语言运行时对象,不是金融业务 API。
|
|
|
|
## 本篇职责
|
|
|
|
回答“写普通 TSL/TSF 脚本时,哪些内置对象可以直接创建,最小可用接口是什么,哪些对象其实依赖特定运行上下文”。
|
|
|
|
## 核心规则
|
|
|
|
- `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`
|
|
|
|
<!-- tags: 字符串列表, 存一批字符串, 键值文本, 逗号文本 -->
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
list := new TStringList();
|
|
list.CommaText := "A=aaa,B=bbb,C=222";
|
|
writeLn(list[1]);
|
|
writeLn(list["B"]);
|
|
writeLn(list.Count);
|
|
list.Add("D=444");
|
|
writeLn(list.Count);
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- 依次输出 `B=bbb`、`bbb`、`3`、`4`
|
|
- 说明既可以按数字下标取整行,也可以按键名取 `Name=Value` 里的值
|
|
|
|
### `THashedStringList`
|
|
|
|
<!-- tags: 哈希列表, 快速查名字, 大量键查找 -->
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
list := new THashedStringList();
|
|
list.Add("A=aaa");
|
|
list.Add("B=bbb");
|
|
writeLn(list.Count);
|
|
writeLn(list["B"]);
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- 依次输出 `2`、`bbb`
|
|
- 说明 `THashedStringList` 可按 `Name=Value` 的名称键读取值
|
|
|
|
### `TStream` 家族的最小可靠入口:`TMemoryStream` 与 `TFileStream`
|
|
|
|
<!-- tags: 内存流, 文件流, 读写文件, 二进制读写, 存到文件 -->
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```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`
|
|
|
|
<!-- tags: 加密解密, 对称加密, 密文 -->
|
|
|
|
无参创建反例:
|
|
|
|
代码块身份:反例 / 不可照写
|
|
|
|
```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`
|
|
|
|
<!-- tags: 非对称加密, 公钥私钥, 签名, RSA -->
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```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`
|
|
|
|
<!-- tags: 配置文件读写, ini, 读配置项 -->
|
|
|
|
磁盘 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`
|
|
|
|
<!-- tags: 发邮件, 邮件正文, 附件 -->
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```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` 的普通脚本边界
|
|
|
|
<!-- tags: 网页请求, http 对象, web 环境限制 -->
|
|
|
|
代码块身份:反例 / 不可照写
|
|
|
|
```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` 后当成业务模板。
|