🐛 fix(tsl_syntax): repair lookup engine and reconcile reference facts

lookup.py: exempt code-anchored ASCII identifiers from the mixed
zh/en gate so exact hits are no longer dropped; dedup parent/child
sections in results; validate write-prelude anchors in --check.

references: correct interpreter-verified facts (case-as-expression,
control-flow semicolons, __line__/__stack_frame, tslObjects order,
destroy timing, ErrDefine, truncated outputs), fix headings, scope
qualifiers and reversed quotes; strip dead preamble metadata from all
24 pages.

packaging: exclude __pycache__/*.pyc from playbook and bundle copies;
update build test file-count assertion to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
csh
2026-07-13 09:16:57 +08:00
co-authored by Claude Fable 5
parent 923bce91b0
commit b597edfc70
29 changed files with 356 additions and 256 deletions
@@ -1,10 +1,5 @@
# TSL 快速落代码规则
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
本篇只回答两个落代码前问题:用户已给出 `.tsl` / `.tsf` 后缀时,智能体如何按后缀组织代码;以及生成代码前必须先核对哪些语言硬规则。
## 本篇职责
@@ -44,7 +39,7 @@
- “顶层函数骨架”“顶层函数定义体”:只指 `function` 骨架;不要因为任务没有返回值就自动改成 `procedure`
- `class function` / “类方法”:同一件事;前者是代码关键字写法,后者是中文描述。
## 起手骨架选择规则
## 任务到文件模型的选择规则
| 任务 | 起手骨架 |
| ------------------------------------ | ------------------------------ |
@@ -1,10 +1,5 @@
# TSL 文件模型规则
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
本篇说明 TSL 的文件模型判断规则:智能体如何区分 `.tsl` 可执行脚本与 `.tsf` 可复用声明文件,如何识别脚本语句区和声明区,以及为什么很多错误其实是“文件模型选错了”。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 值与字面量
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇整理基本类型、字面量、数组、字符串、字符串编码边界与基础值模型,避免把值规则分散在函数或金融示例里。
## 本篇职责
@@ -470,8 +465,7 @@ writeLn(result);
说明:
- `%d` 是整数占位符
- `%s` 是字符串占位符
- 示例里的 `%d` / `%s` 分别对应整数、字符串占位;只为读懂本例
- `format` 的完整占位符规范使用 `tsl-api-reference` skill 按名查询。
### `formatdatetime` 日期格式化
@@ -494,9 +488,7 @@ writeLn(result);
说明:
- `yyyy` 表示四位年
- `mm` 表示两位月份
- `dd` 表示两位日期
- 示例里的 `yyyy-mm-dd` 对应四位年、两位月、两位日;只为读懂本例
- `formatdatetime` 的完整格式说明使用 `tsl-api-reference` skill 按名查询。
## 默认生成模板
@@ -1,10 +1,5 @@
# TSL 变量与常量
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇收拢变量与常量初始化规则。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 函数与调用
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只负责 `function` / `procedure` 的定义、调用、参数传递和值返回。跨 `unit` 声明边界、外部系统交互和业务函数库只在本页保留最小边界。
## 本篇职责
@@ -27,13 +22,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)。
- 函数体内的控制流块(`if`/`while`/`for` 等)的 `end` 后加不加分号都合法;唯一例外是 `if``then``end``else` 之间不能加分号。控制流分号规则见 [07_control_flow.md](07_control_flow.md)。
- 一个函数定义体里可以同时出现主函数和子函数。
- 函数支持参数类型注解和返回值类型注解。
- 不带类型注解时,多个参数用逗号分隔。
@@ -154,7 +149,7 @@ end;
2
```
### 签名增强
### 签名增强:参数类型与返回值类型注解
带参数类型和返回值类型:
@@ -356,7 +351,7 @@ end;
99
```
### 调用增强
### 调用增强:命名参数与混用规则
命名参数调用:
@@ -977,13 +972,12 @@ writeLn(intToStr(value: 200));
代码块身份:反例 / 不可照写
```text
writeLn(Pack(a: 1, 2, c: 3));
function Pack(a, b, c);
begin
return a * 100 + b * 10 + c;
end;
begin
writeLn(Pack(a: 1, 2, c: 3));
end.
```
不要在同一次调用里“先进入命名参数模式,再退回位置参数”。这类写法会直接编译失败,错误信息包含 `paramname: not found`
@@ -1,10 +1,5 @@
# TSL 表达式与运算符
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇集中放语言级表达式与运算符。智能体写代码时,只使用本页和对应专题页已经明确的表达式事实,不要把其他语言或外部资料里的运算符习惯直接搬进 TSL。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 控制流
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只收录流程控制与异常控制,不讨论金融语义。
## 本篇职责
@@ -468,7 +463,6 @@ end
- 在 `else` 前面误加分号。
- 生成没有分号的裸分支赋值,例如 `then value := 1 else ...`;带 `else` 时用块式分支。
- 以为 `try ... finally` 会吞掉异常。
- 把 `case` 写成赋值右侧表达式。
- 在还没搞清表达式规则前,先把复杂业务函数塞进条件里。
- 把控制流问题和函数文件模型问题混在一起排查。
@@ -1,17 +1,12 @@
# TSL 对象与类
文档类型:语法主线
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇收拢面向对象语法,只保留语言层规则。
## 本篇职责
回答“`type Name = class`、字段、`static`、方法、`property`、析构、类类型、继承和对象创建在 TSL 里怎样写”。
本页后半段有少量依赖 `unit` 的双文件示例;如果你还没建立 `unit` / `uses` 的多文件心智模型,先看 [09_units_and_scope.md](09_units_and_scope.md)。
本页后半段有少量依赖 `unit` 的双文件示例;`unit` / `uses` 的多文件模型事实见 [09_units_and_scope.md](09_units_and_scope.md)。
## 智能体对象/类判断流程
@@ -43,7 +38,7 @@
- 基础 `property` 形态:`property Name read fieldOrMethod write fieldOrMethod`
- `property Name: Type ...` 这种类型注解写法可用。
- 参数化 `property` 可用;本页只写基础模式。
- 参数化 `property` 的 accessor 方法记录两种常见模式:读方法接同参数个数写方法接“参数个数 + 赋值值”。
- 参数化 `property` 的 accessor 方法记录两种常见模式:读方法接同参数个数(如 `getItem(i)`),也可以写成无参形态(如 `getDateV()`);写方法接“参数个数 + 赋值值”。
- 索引型 `property` 可用;调用时用圆括号 `obj.Prop(index)`
- 固定 `index` property 可用;它可以把某个固定索引直接映射成普通属性读写。
- `class(Name)``findClass("Name")` 都可以拿到类类型。
@@ -57,7 +52,7 @@
- 创建对象有两种方式:`new ClassName()` 最常用,`createObject(...)` 作为次选。
- 普通本地类实例化默认生成 `new ClassName()``createObject("ClassName")``createObject(ClassType)` 只在字符串类名、类类型变量或跨 `unit` 路径场景生成。
- 如果类里定义了 `function create(...)``new``createObject("ClassName", ...)``createObject(ClassType, ...)` 都可以透传构造参数,也都支持默认参数和命名参数。
- 析构写法是无参 `function destroy();`对象引用设为 `nil` 时会触发它。
- 析构写法是无参 `function destroy();`;对象的最后一个引用被清空(如设为 `nil`时会触发它。存在别名引用时,只清空其中一个引用不会触发。
- 工厂式 `self(0)` / `self(1)` 可用;不要生成 `self()` 这种无参工厂式写法。
- 跨 `unit` 类路径创建和继承属于多文件边界;相关事实见 [09_units_and_scope.md](09_units_and_scope.md) 和 [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md),不要从普通单文件 `new` / `createObject` 规则直接泛化。
- `{$ifdef parentClassInUnit}` 为真,可用于探测“继承和构造单元中的类”能力是否可用。
@@ -750,8 +745,8 @@ end;
输出说明:
- `read getItem` 这种读方法接同参数个数”的写法可以通过
- `write setItem` 这种写方法接参数个数 + 赋值值”的写法可以通过
- `read getItem` 这种读方法接同参数个数”的写法可以通过
- `write setItem` 这种写方法接参数个数 + 赋值值”的写法可以通过
- 上述例子中的 `obj.Item(2)` 输出 `x`
### 对象创建与类类型
@@ -904,7 +899,7 @@ end;
- `findClass("MathBox").Add(...)` 可以调用类方法
- 上述例子依次输出 `7``11`
### 类方法、重载、继承与析构
### 重载、继承与析构
`overload` 方法:
@@ -1,10 +1,5 @@
# TSL unit 与作用域
文档类型:语法主线
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只讲“怎么写和怎么调用 `unit`”。`namespace`、查找路径、`unit` 生命周期、`tsl.conf` 与运行时入口统一放到 [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md)。
## 本篇职责
@@ -43,9 +38,9 @@
- 只写在 `implementation` 里的函数,对 `unit` 外部不可见。
- 出现重名接口时,未限定调用按 `uses` 从后往前解析;最后一个 `uses` 的同名接口优先。
- 要显式指定某个 `unit` 的接口,可以用 `UnitA.Ping()``unit(UnitA).Ping()``call("UnitA.Ping")`
- `unit` 生命周期、接口状态、命名空间和查找路径细节,转去看 [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md)。
- `unit` 生命周期、接口状态、命名空间和查找路径细节 [19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md)。
## 可直接照写示例
## 示例与行为
### 最小 `unit`
@@ -495,8 +490,6 @@ end;
end.
```
后面的多文件片段只在需要 `uses`、可见性或重名解析时再回来看。
## 禁止项
- 把依赖外部 `unit``uses` 例子误当成单文件最小示例。
@@ -1,10 +1,5 @@
# TSL 运行时上下文、服务与全局缓存
文档类型:语法主线
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只处理运行时环境参数、块环境 `with` 语句、`with` 后缀、`#` 网格调用、`timeout` 后缀、`dupvalue(...)` 和全局缓存,不处理任何金融业务语义。
## 本篇职责
@@ -48,6 +43,8 @@
## 可直接照写示例
### `setSysParam` / `getSysParam` / `sysParams[...]` 基础读写
直接设置和读取系统参数:
代码块身份:可直接照写示例
@@ -163,7 +160,9 @@ writeLn(getSysParam("b"));
- 块后输出 `1``9`
- 说明 `with **` 不继承未传入的外层系统参数,并且块结束后恢复外层系统参数
沿用同一个 `TestDo.tsf`,看 `with array(...)` 的覆盖边界:
### 后缀 `with array(...)`:网格调用的临时覆盖
`#Func(...) with array(...)` 在一次网格调用里临时覆盖系统参数,调用结束后恢复外层原值。下面用一个 `TestDo.tsf` 演示覆盖边界:
代码块身份:配置片段 / 概念骨架
代码块说明:多文件结构骨架;依赖函数文件查找路径,不是可直接复制的单文件最小示例。
@@ -193,7 +192,7 @@ writeLn(getSysParam("b"));
- 调用结束后,外层 `getSysParam("b")` 输出 `8`
- 说明 `with array(...)` 是“只在该次调用里临时覆盖,再恢复外部原值”
沿用上一个 `TestDo.tsf`,只把 `main.tsl` 改成下面这样:
沿用上面的 `TestDo.tsf`,只把 `main.tsl` 改成下面这样(外层未预设参数)
代码块身份:配置片段 / 概念骨架
代码块说明:多文件结构骨架;依赖函数文件查找路径,不是可直接复制的单文件最小示例。
@@ -231,7 +230,7 @@ end;
结果说明:
- `#AddOne(5)` 可以执行
- `dupvalue(r)` 返回最终结果 `6`
- `dupvalue(#AddOne(5))` 返回最终结果 `6`
代码块身份:输出片段
@@ -303,9 +302,7 @@ writeLn(cached_data[0], ',', cached_data[1], ',', cached_data[2]);
说明:
- TSL 标识符大小写无关,`setGlobalCache``SetGlobalCache` 等价
- 推荐使用小写 `setGlobalCache``getGlobalCache` 以保持一致性
- `setGlobalCache(key, value)` 写入缓存,可选第三参数指定过期时间(秒)
- `getGlobalCache(key, out_var)` 读取缓存到输出变量
- 示例只展示 `setGlobalCache(key, value)` / `getGlobalCache(key, out_var)` 的最小调用形态;完整参数规格(含过期时间等可选参数)用 `tsl-api-reference` skill 按名查询
### `checkGlobalCacheExpired`
@@ -324,7 +321,7 @@ writeLn(checkGlobalCacheExpired(cache_ref));
- 刚取出的缓存引用上,`checkGlobalCacheExpired(cache_ref)` 返回 `0`
- 同名缓存被重新设置后,旧引用上的 `checkGlobalCacheExpired(cache_ref)` 返回 `1`
### 写入后会实例化
### 缓存值本地写入后会实例化
代码块身份:可直接照写示例
@@ -398,7 +395,7 @@ begin
end;
```
需要缓存时, `setGlobalCache` / `getGlobalCache` 那一节选择模板
需要缓存时,默认模板是 `setGlobalCache(key, value)` 写入、`getGlobalCache(key, out_var)` 读取
## 禁止项
@@ -1,10 +1,5 @@
# TSL 高频误写
文档类型:反例索引页
是否可直接用于生成代码:否
是否含可直接照写示例:否
是否含不可照写反例:是
这一篇不讲新知识,只做反例索引。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 数组、键表、矩阵样数据与集合运算
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:否
这一篇收拢 `array(...)` 的扩展用法:顺序数组、字符串键表、嵌套数组、本页明确的矩阵样比较,以及 `in` / `sqlin` / `union2` / `intersect` / `minus` / `outersect` 这类去重型集合关系。
## 本篇职责
@@ -29,7 +24,7 @@
- `in` / `not in` 处理的是元素存在关系,以及左侧为数组时的子集关系。
- `sqlin` / `not sqlin` 处理的是行存在关系;左侧要当成一整行去匹配右侧结果集。
- `union2``intersect``minus``outersect` 都按“行”运算,而不是按单元格逐个运算。
- 集合运算结果会折叠重复行;如果需求是保留重复记录,改看 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
- 集合运算结果会折叠重复行;保留重复记录的过滤规则见 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
- 当数据本身就是一维数组时,按行集合运算和按元素集合运算是一致的。
- 左侧是数组时,先判定需求语义:子集关系用 `in`,整行存在关系用 `sqlin`
@@ -137,6 +132,9 @@ writeLn(1 not in array(0, 2));
0
1
1
1
0
1
```
`sqlin` 按整行判断左侧是否存在于右侧结果集中:
@@ -198,7 +196,7 @@ outersect_rows := left_rows outersect right_rows;
- 集合运算先把数据当成“行集合”来看,再做包含、并交差。
- 过滤运算先保留“原结果集里的每一条命中记录”;因此重复行会保留下来。
- 需要“集合关系”时留在本页。
- 需要“从原表里筛出哪些行”时看 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
- “从原表里筛出哪些行”的过滤规则见 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
## 默认生成模板
@@ -211,7 +209,7 @@ matched := 1 in array(1, 2, 3);
row_matched := array(1, 2) sqlin array((1, 2), (3, 4));
```
### 点前缀比较算符产生逻辑数组
## 点前缀比较算符产生逻辑数组
点前缀比较(`.=``.<>``.>``.>=``.<``.<=`)对数组/矩阵逐元素比较,返回真假值数组:
@@ -274,7 +272,7 @@ writeLn("子集 (1,0):", subset[1][0]);
- `a[indexes]` 按下标提取对应行,等价于 `select * from a where [0] > 0.5 end`
- `mfind` 的完整用法见 [22_matrix_deep_dive.md](22_matrix_deep_dive.md)
### 非完全矩阵缺位当 0 处理
## 非完全矩阵缺位当 0 处理与标量广播
基础算符作用于非完全矩阵(行长度不一致或字符串键不对齐的数组)时,对应位置不存在或为 `nil` 时**默认当 0 处理**
@@ -341,15 +339,15 @@ writeLn("(1,1):", result[1][1]);
## 禁止项
- 不要把字符串下标按数组的 `0` 起始规则来写;字符串索引事实见 [03_values_and_literals.md](03_values_and_literals.md)。
- 不要把字符串下标按数组的 `0` 起始规则来写;字符串下标从 `1` 开始,详见 [03_values_and_literals.md](03_values_and_literals.md)。
- 不要把矩阵链式比较 `::...` 和标量链式比较混写成同一种语法。
- 不要把 `in``sqlin` 当成同一个概念。
- 不要期待 `union2` 保留重复行。
- 不要用集合运算去做保留原始重复记录”的过滤任务。
- 不要把二维结果集默认当成按元素逐个比较”的集合运算。
- 左侧数组要表达这些值是否都属于右侧集合”时,用 `in`
- 左侧数组要表达这一整行是否存在于右侧结果集”时,用 `sqlin`
- `minus` 表达集合差集;如果任务要求保留左侧原始重复次数,改走 [13_resultset_and_filters.md](13_resultset_and_filters.md) 的过滤规则
- 不要用集合运算去做保留原始重复记录”的过滤任务。
- 不要把二维结果集默认当成按元素逐个比较”的集合运算。
- 左侧数组要表达这些值是否都属于右侧集合”时,用 `in`
- 左侧数组要表达这一整行是否存在于右侧结果集”时,用 `sqlin`
- `minus` 表达集合差集;保留左侧原始重复次数的过滤规则见 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
- 不要在本页发明结果集过滤、TS-SQL 查询、写回语法或更大矩阵函数族。
- 不要把普通 `array(...)` 自动升级成 `FMArray``FMArray` 专属事实见 [23_fmarray.md](23_fmarray.md)。
- 不要把点前缀比较 `.>` 和矩阵链式比较 `::>` 混用;`.>` 返回逻辑数组,`::>` 是链式比较。
@@ -1,10 +1,5 @@
# TSL 结果集与过滤
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只讲结果集过滤语法:怎样按某一列过滤、怎样按整行过滤、怎样只返回行下标,以及怎样按字段列表过滤。它不负责 TS-SQL 查询语法,也不把去重型集合运算和业务选股逻辑混进来。
## 本篇职责
@@ -168,8 +163,8 @@ sub_result := rows[keep_index, array("A", "C")];
- 过滤运算按“原结果集中的每一行是否命中”来决定保留或排除。
- 集合运算按“行集合”来做并、交、差;结果默认会折叠重复行。
- 需要保留重复记录时,优先看这一篇
- 需要去重后的并集、交集、差集时,优先看 [12_matrix_and_collections.md](12_matrix_and_collections.md)。
- 保留重复记录的过滤规则由本页负责
- 去重后的并集、交集、差集事实见 [12_matrix_and_collections.md](12_matrix_and_collections.md)。
## 默认生成模板
@@ -1,15 +1,10 @@
# TSL TS-SQL
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇是 TS-SQL 的唯一语法入口:内存数组查询、返回形态、字段访问、`where` / `group by` / `order by`、一维数组查询、多表 `join`(含 `left join`)、`insert` / `update` / `delete` 写回、`thisGroup``thisRowIndex``refMaxOf` / `refMinOf` 都在这里收拢。
## 本篇职责
回答写 TS-SQL 查询和写回时,怎样从最小 `select ... from ... end` 骨架开始,逐步处理筛选、分组、排序、多表联接(含 LEFT JOIN)、组内子查询、极值引用,以及如何用 `insert`/`update`/`delete` 修改内存数组”。
回答写 TS-SQL 查询和写回时,怎样从最小 `select ... from ... end` 骨架开始,逐步处理筛选、分组、排序、多表联接(含 LEFT JOIN)、组内子查询、极值引用,以及如何用 `insert`/`update`/`delete` 修改内存数组”。
## 智能体 TS-SQL 判断流程
@@ -27,7 +22,7 @@
- TS-SQL 是 TSL 自带的类 SQL 查询语法,不是金融业务函数库。
- 基础查询文档骨架是:以 `select` / `sselect` / `vselect` / `mselect` 开始,以 `end` 收尾。
- `from` 后面可以直接跟内存数组结果集。
- 在内存二维结果集上,文档字段访问写法是 `["字段名"]`
- 在内存二维结果集上,文档字段访问写法是 `["字段名"]`;列没有名字(如直接来自数组)时用位置下标 `[0]``[1]` 访问
- 在一维数组上做 TS-SQL 时,优先使用 `thisRow``thisRowIndex`
- `select` 返回二维结果,`sselect` 返回一维结果,`vselect` 返回单值,`mselect` 返回 `Matrix`
- `where``group by``order by` 可以直接接在 `from` 后面继续使用;`order by` 支持 `asc`/`desc` 与多列逗号分隔。
@@ -314,7 +309,7 @@ writeLn("(1,1):", result[1]["vb"]);
- `on` 子句指定联接条件,用 `[1].["k"] = [2].["k"]` 匹配键
- 其他联接类型:`right join`(保留右表)、`full join`(保留双方)、`cross join`(笛卡尔积)
### JOIN 家族其余形态
### `right join` / `full join` / `cross join` 与逗号联接
`right join` / `full join` 的不匹配行同样用 `nil` 填充:
@@ -439,7 +434,7 @@ writeLn("(1,0):", a[1]["id"]);
- `insert into 数组变量` 直接修改原数组
- `insertfields([字段列表])` 指定要插入的字段
- `values(...)` 提供对应值,可以写多组 `values``values` 实现批量插入
- `values(...)` 提供对应值,可以连续写多组 `values(...)` 实现批量插入
批量插入可以直接跟一个同结构数组,`insertfields` 也支持一次给多字段赋值:
@@ -573,11 +568,13 @@ writeLn(mrows(a));
代码块身份:可直接照写示例
```tsl
a := array(("cls": "A", "en": 90), ("cls": "A", "en": 80), ("cls": "B", "en": 85));
a := array(("cls": "A", "en": 90), ("cls": "A", "en": 80), ("cls": "A", "en": 90), ("cls": "B", "en": 85));
distinct_rows := select distinct ["cls"] from a end;
distinct_sum := vselect sumof(distinct ["en"]) from a end;
plain_sum := vselect sumof(["en"]) from a end;
writeLn(mrows(distinct_rows));
writeLn(distinct_sum);
writeLn(plain_sum);
```
代码块身份:输出片段
@@ -585,12 +582,13 @@ writeLn(distinct_sum);
```text
2
255
345
```
说明:
- `select distinct [字段]` 折叠重复行
- `sumof(distinct [字段])` 只对不同值求和:`90 + 80 + 85 = 255`
- `sumof(distinct [字段])` 只对不同值求和:`90 + 80 + 85 = 255`;不加 `distinct` 时重复的 `90` 计两次,得 `345`
### `as` 别名、`as nil` 与字段区间
@@ -805,10 +803,7 @@ integer
### `aggof` 自定义聚集扩展
> 代码块身份:仅服务端可执行示例
> 本地 `TSL.exe` 会报 `AggOf Init Error`;下例在服务端(pyTSL)验证通过。
`aggof('名称', 表达式)` 调用一个自定义回调函数做聚集:
`aggof('名称', 表达式)` 调用一个自定义回调函数做聚集。本地 `TSL.exe` 会报 `AggOf Init Error`;下例在服务端(pyTSL)验证通过:
代码块身份:仅服务端可执行示例
@@ -855,6 +850,7 @@ TS-SQL 的最短默认骨架如下:
代码块身份:可直接照写示例
```tsl
source_rows := array((1, 10), (2, 20));
query_result := select * from source_rows end;
```
@@ -894,7 +890,7 @@ query_result := select A from source_rows end;
query_result := select [0] from values end;
```
这种对一维数组直接用 `[0]` 的写法虽然返回长度为 `3` 的结果,但取到的值是 `nil`,不能当成可靠入口。对一维数组应改用 `thisRow``thisRowIndex`
这种对一维数组直接用 `[0]` 的写法虽然返回与源数组等长的结果,但取到的值是 `nil`,不能当成可靠入口。对一维数组应改用 `thisRow``thisRowIndex`
代码块身份:反例 / 不可照写
@@ -1,10 +1,5 @@
# TSL 调试与性能分析器
文档类型:语法主线
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇收拢本页明确的调试、计时、性能分析器和调用栈相关入口。
## 本篇职责
@@ -116,7 +111,7 @@ end;
结果说明:
- 只输出 `before`
- 说明 `debugReturn bb;` 不只是结束 `Inner(...)`,而是直接让整段脚本提前返回
- 说明 `debugReturn value;` 不只是结束 `Inner(...)`,而是直接让整段脚本提前返回
- 因此 `Inner(3)` 后面的 `writeLn("after")` 不会执行
### `debugRunEnv``debugRunEnvDo`
@@ -215,8 +210,8 @@ writeLn(line_number);
结果说明:
- 输出 `3`
- 说明 `__line__` 直接返回所在代码行号
- 输出 `1`
- 说明 `__line__` 直接返回所在代码行号(这里 `__line__` 在脚本第 1 行)
`__stack_frame`
@@ -242,12 +237,12 @@ end;
```text
array(
(11,"__main__"),
(8,"Outer"))
(1,"__main__"),
(10,"Outer"))
```
- 说明 `__stack_frame` 返回的是调用栈帧数组
- 在这个最小例子里,可以直接看到调用位置行号和调用者函数名
- 在这个最小例子里,可以直接看到调用位置行号和调用者函数名`__main__` 在第 1 行调用 `Outer()``Outer` 在第 10 行调用 `Inner()`
## 禁止项
@@ -1,10 +1,5 @@
# TSL 词法结构与编译选项
文档类型:语法深水专题
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇吸收语法手册里“词法层”和“编译期开关”相关内容:标识符、注释、条件编译和依赖编译选项。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 类型与转换
文档类型:语法深水专题
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇吸收语言基础里“数据类型、初始值、弱类型行为、类型转换、复数类型”这一层。
## 本篇职责
@@ -256,6 +251,7 @@ writeLn(z2);
1
4
3
5-2j
```
共轭、模与等值比较:
@@ -269,7 +265,7 @@ writeLn(abs(z));
writeLn(real(c));
writeLn(imag(c));
if 3.15 = 3.15 + 0j then
writeLn(1);
writeLn(1)
else
writeLn(0);
```
@@ -1,10 +1,5 @@
# TSL 外部调用与线程
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇吸收函数专题里和外部系统交互有关的部分:`external`、动态库调用、原生函数指针包装、C 回调和线程调用。
## 本篇职责
@@ -59,6 +54,7 @@ function Tick64Alias(): int64; stdcall; external "kernel32.dll" name "GetTickCou
Linux / POSIX 环境的同类最小骨架:
代码块身份:可直接照写示例
代码块说明:仅类 Unix 环境可执行(依赖 `libc.so.6`);Windows 下不可照抄,本块只演示 `.so` 库名写法。
```tsl
writeLn(getpid() > 0);
@@ -171,7 +167,7 @@ end;
结果说明:
- 输出 `1`
- 说明类常量字符串可以用于 `external kernel_dll` 这种 DLL 名位置
- 说明类常量字符串(如 `kKernelDll`可以用于 `external kKernelDll` 这种 DLL 名位置
不作为可写事实边界:
@@ -201,8 +197,8 @@ end;
结果说明:
- `fp <> nil` 输出 `1`
- `##f(3, 4)` 输出 `7`
- `func_ptr <> nil` 输出 `1`
- `##wrapped_func(3, 4)` 输出 `7`
- 说明 `makeInstance(...)` 生成的函数指针可以再通过 `function(...); external fp;` 包装回 TSL 侧调用
### 线程模式最小正例
@@ -1,10 +1,5 @@
# TSL 命名空间、Libpath 与 unit 运行时
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇收拢 `unit` 的运行时行为,以及 `.tsf` / `namespace` / `libpath` 的查找规则。`unit` 的基础写法、`uses` 位置和重名解析,统一放在 [09_units_and_scope.md](09_units_and_scope.md)。
## 本篇职责
@@ -1,10 +1,5 @@
# TSL 对象运行时与反射
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇收拢对象模型里不适合继续堆在基础类主线里的运行时内容:类信息、函数句柄、对象状态、引用计数、运行时对象枚举、弱引用与自动弱引用。普通类声明、继承、构造和普通对象创建仍以 [08_objects_and_classes.md](08_objects_and_classes.md) 为主线;本页只在用户明确需要运行时反射、内省、对象生命周期或弱引用能力时进入。
## 本篇职责
@@ -40,7 +35,7 @@
- `functionInfo` 至少可以读出 `functionname``returntype``classname` 这几个字段。
- `tslObjects(1)` 会按类名分组返回对象信息,并且分组项里的 `"obj"` 字段可以重新拿到可调用对象。
- 对象赋值会延长对象存活;只有最后一个引用清空后才会触发 `destroy()`
- `self` 在本页只用于需要本实例对象引用的运行时函数,例如 `objectstate(self)`普通成员访问仍按 [08_objects_and_classes.md](08_objects_and_classes.md) 的规则,不加 `self` 前缀。
- `self` 表示本实例对象引用;本页在需要该引用的场景使用它,如传给运行时函数`objectstate(self)`)或保存自身引用(`sca := self;`)。普通成员访问仍按 [08_objects_and_classes.md](08_objects_and_classes.md) 的规则,不加 `self` 前缀。
- 弱引用能力的条件编译宏是 `weakptr`;自动弱引用相关宏是 `autoWeak`
- `weakRef(obj)` 可以创建弱引用;对象仍存活时,`weakref_get(w)` 可以拿回强引用。
- `checkWeakRef(w)` 在对象仍存活时返回 `1`,对象已释放后返回 `-1`
@@ -355,15 +350,15 @@ end;
代码块身份:可直接照写示例
```tsl
objA := new TestClass01(100);
objB := new TestClass01(101);
objsInfo := tslObjects(1);
writeLn(length(objsInfo["TestClass01"]));
newObjA := objsInfo["TestClass01"][0, "obj"];
writeLn(newObjA is class(TestClass01));
writeLn(newObjA.add(1, 2));
objA := new TestClass01(100);
objB := new TestClass01(101);
type TestClass01 = class
public
value;
@@ -575,6 +570,8 @@ end;
上面这种给段落切换关键字**加分号**(`weakRef;` / `autoRef;`)的写法会编译失败,错误信息包含 `invalid class definition`。关键在分号:段落切换关键字要像 `public` / `private` 那样**不带分号**独占一行,带分号后被当成独立语句才报错。正确的段落式写法见下一段。
### 段落式 `weakRef` / `autoRef` 的正确写法
段落式 `weakRef` / `autoRef`(不带分号)像 `public` / `private` 一样切换后续成员的弱引用属性:
代码块身份:可直接照写示例
@@ -1,10 +1,5 @@
# TSL 内置运行时对象
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只收运行时内置对象的文档明确最小模型。这里讲的是语言运行时对象,不是金融业务 API。
## 本篇职责
@@ -76,7 +71,7 @@ writeLn(list["B"]);
- 依次输出 `2``bbb`
- 说明 `THashedStringList` 可按 `Name=Value` 的名称键读取值
### `TStream` 家族的最小可靠入口:`TMemoryStream`
### `TStream` 家族的最小可靠入口:`TMemoryStream``TFileStream`
代码块身份:可直接照写示例
@@ -1,20 +1,15 @@
# TSL 矩阵深水专题
文档类型:语法深水专题
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只讲矩阵专用语法主干:矩阵初始化、数列构造、矩阵逆/广义逆、矩阵乘除乘方、矩阵转置、矩阵拼接、矩阵尺寸与索引、矩阵遍历、子矩阵和 `mfind` 查找。它和 [12_matrix_and_collections.md](12_matrix_and_collections.md) 的分工是:`12` 讲普通数组与集合关系,这一篇讲矩阵专用构造、运算、遍历、子矩阵和矩阵查找接口。
## 本篇职责
回答怎样直接构造全零矩阵、全一矩阵、随机矩阵、单位矩阵、空矩阵和数列数组,怎样写矩阵逆/广义逆,怎样进行矩阵乘除乘方,怎样转置矩阵,怎样拼接矩阵,怎样拿到矩阵的行数、列数、行索引和列索引,怎样遍历矩阵、取/改子矩阵,以及怎样用 `mfind` 找到或替换符合条件的单元格”。
回答怎样直接构造全零矩阵、全一矩阵、随机矩阵、单位矩阵、空矩阵和数列数组,怎样写矩阵逆/广义逆,怎样进行矩阵乘除乘方,怎样转置矩阵,怎样拼接矩阵,怎样拿到矩阵的行数、列数、行索引和列索引,怎样遍历矩阵、取/改子矩阵,以及怎样用 `mfind` 找到或替换符合条件的单元格”。
## 智能体矩阵深水判断流程
1. 先判断要写矩阵初始化、数列构造、矩阵逆/广义逆、矩阵尺寸与索引读取、矩阵遍历、子矩阵,还是 `mfind` 查找/替换。
2. 基础数组矩阵样比较先回看 `12_matrix_and_collections.md`
2. 基础数组矩阵样比较的事实在 [12_matrix_and_collections.md](12_matrix_and_collections.md)
3. `mrows` / `mcols` / `msize` 等函数只照文档返回形态写。
4. 需要逐单元执行语句块时用 `matrix::begin ... end`;需要把表达式结果写回每个单元时用 `matrix ::= expression`
5. 需要遍历到嵌套数组最深层时用 `matrix:.begin ... end``matrix:.= expression`
@@ -25,8 +20,8 @@
## 核心规则
- 矩阵初始化函数的参数规格使用 `tsl-api-reference` skill 按名查询;本页只保留矩阵行为示例返回形态边界。
- `zeros(...)``ones(...)``rand(...)``nils(...)``eye(...)` 都可以直接用于矩阵初始化。
- 矩阵初始化和基础函数的具体参数规格使用 `tsl-api-reference` skill 按名查询;本页只保留矩阵行为示例返回形态边界和跨函数通用的广播 / `ErrDefine` / `ErrReplace` 机制
- `zeros(...)``ones(...)``rand(...)``nils(...)``eye(...)` 都可以直接用于矩阵初始化;全 `nil` 单元的“空矩阵”用 `nils(...)` 构造
- `zeros(3)``ones(3)``nils(2)` 这类单参数写法可以直接生成一维结果。
- `zeros(2, 3)``rand(2, 3)` 这类双参数写法可以直接生成二维矩阵。
- `zeros(2, array("A", "B"))` 这种写法可以直接生成带列名的二维结果。
@@ -525,7 +520,7 @@ B
0
```
### 矩阵乘法、除法、乘方:`:*``:/``:^`
### 矩阵乘法、除法、左除、乘方:`:*``:/``:\``:^`
`:*` 是矩阵乘法(区别于逐元素乘 `*`):
@@ -603,7 +598,7 @@ writeLn(result[1][0]);
说明:
- `:\` 左除用于解线性方程组 `A * X = B`,等价于 `X = A^(-1) * B`
- `:\` 左除用于解线性方程组 AX = B(数学记法),等价于先求逆再矩阵乘:`!a :* b`
- **右侧 `b` 必须是列向量**(用 `array((4), (8))` 而非 `array(4, 8)`
- `a :\ b` 返回 `array((2.0), (2.0))`,即 `X` 的列向量
- 当 A 行数 > 列数时返回最小二乘解,行数 < 列数时返回一个可行解
@@ -699,10 +694,34 @@ array(2.0,NAN,3.0)
说明:
- `sqrt(data, 1, -999)` 中,第二参数 `ErrDefine=1` 表示允许 NIL 不允许错误
- `ErrReplace=-999` 是错误位置的替换值(本例中 `-1` 的平方根为错误,但 `ErrDefine=1` 保留为 NAN
- `ErrDefine` 取值:`0`=不允许错误和 NIL、`1`=允许 NIL 不允许错误、`2`=错误值保留为原值
- `ErrReplace``ErrDefine=0``1` 时生效,用于替换错误/NIL 位置
- `ErrDefine` 取值:`0`=不允许错误和 NIL(两者都替换为 `ErrReplace`)、`1`=允许 NIL 不允许错误NIL 保留,错误替换为 `ErrReplace`)、`2`=错误和 NIL 都保留原值(`ErrReplace` 不生效)
- 「错误」指输入无效(如 NIL、类型不符);数学定义域产生的 `NAN` 结果(如 `sqrt(-1)`)不属于错误位置,任何 `ErrDefine` 档位下都不会被 `ErrReplace` 替换,本例输出保留 `NAN` 即因如此
- 不带 `ErrDefine` / `ErrReplace` 时,无效输入会直接运行报错
无效输入在不同 `ErrDefine` 档位下的替换差异:
代码块身份:可直接照写示例
```tsl
data := array(4, nil, "AAA", 9);
writeLn(tostn(sqrt(data, 0, -999)));
writeLn(tostn(sqrt(data, 1, -999)));
writeLn(tostn(sqrt(data, 2, -999)));
```
代码块身份:输出片段
```text
array(2.0,-999,-999,3.0)
array(2.0,NIL,-999,3.0)
array(2.0,NIL,"AAA",3.0)
```
说明:
- `ErrDefine=0` 把 NIL 和错误值 `"AAA"` 都替换成 `-999`
- `ErrDefine=1` 保留 NIL、只替换错误值
- `ErrDefine=2` 全部保留原值
另一个例子:
@@ -871,7 +890,7 @@ writeLn("(1,3):", result[1][3]);
(1,3): 8
```
`:|` 非完全矩阵补 `nil``|` 不补:
普通 `array` 非完全矩阵`:|` 缺位`nil``|` 直接顺接不补
代码块身份:可直接照写示例
@@ -887,16 +906,17 @@ writeLn("bar 结果 (1,2):", bar_result[1][2]);
代码块身份:输出片段
```text
colon 结果列数: 6
colon (1,2): nil
bar 结果 (1,2): 1
colon 结果列数:6
colon (1,2):<NIL>
bar 结果 (1,2):2
```
说明:
- `union` / `&=` 用于行方向拼接
- `|` / `:|` 用于列方向拼接
- 非完全矩阵(行长度不一致)`:|` 会在缺位补 `nil`,而 `|` 不补
- 普通 `array`非完全矩阵(行长度不一致)`:|` 按原列位置对齐、缺位补 `nil``|` 把两行元素直接顺接(本例第 1 行变成 `(2,3,2,3)`,所以 `[1][2]``2`
- 上述差异只适用于普通 `array``FMArray``|``:|` 行为一致且行数不齐时补 `0`,见 [23_fmarray.md](23_fmarray.md)
- 对应的复合赋值形式:`&=`(行并)、`|=`(列并)、`:|=`(列并补 nil
## 默认生成模板
@@ -923,7 +943,7 @@ matrix_value := zeros(2, 3);
- 用 `::` 期待遍历到任意深度;深度遍历使用 `:.`
- 子矩阵赋值时用形状不匹配的矩阵硬塞。
- 把 `union` 的复合赋值写成 `union=`;正确写法是 `&=`
- 一维数组直接 `union` 期待得到二维结果;需要先双转置 ` `b `` 变成行向量。
- 一维数组直接 `union` 期待得到二维结果;需要先对它连用两次转置前缀(双转置)变成行向量。
- 在基础函数异常参数时用分号分隔;正确写法用逗号:`sqrt(data, 1, -999)`
代码块身份:反例 / 不可照写
@@ -1,10 +1,5 @@
# TSL FMArray
文档类型:语法深水专题
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
这一篇只讲 `FMArray` 文档主干能力:怎样构造 `FMArray`、怎样判断类型、怎样和 `Array` 互转、怎样读取尺寸、做基础运算、做多维转置与维度交换、做矩阵连接、参与 `select/mselect`,以及 `insert/delete/update` 语法边界。
## 本篇职责
@@ -33,7 +28,7 @@
- `union2` 支持 `FMArray` / `Array` 混合运算;结果类型跟随左值。
- 对超过二维的 `FMArray`,反引号转置会把全部维度倒置;`mswap` 可只交换指定维度。
- `union` 可做按行连接且不去重,但列结构必须兼容。
- `|``:|` 都可做矩阵并右方(按列连接);行数不一致时会用 `0` 补齐,并且两者表现一致。
- `|``:|` 都可做矩阵并右方(按列连接);`FMArray`行数不一致时会用 `0` 补齐,并且两者表现一致(普通 `array` 上两者行为不同:`:|` 缺位补 `nil``|` 直接顺接,见 [22_matrix_deep_dive.md](22_matrix_deep_dive.md)
- 对 `FMArray` 做普通 `select` 不会保留 `FMArray` 类型;`mselect` 也不会返回 `dataType=27`
- `insert into a array(...)``delete from a where ...;``update a set ... where ... end;` 都能作用于 `FMArray`,但三者的收尾形式并不完全相同。
@@ -76,6 +71,11 @@ writeLn(f2[0,0], ',', f2[0,1], ',', f2[1,0], ',', f2[1,1]);
0
1
1
3
1,2,3
2
2
1,2,3,4
```
### `mInit``mInitDiag``mRand`
@@ -1,10 +1,5 @@
# TSL 对象重载与迭代
文档类型:语法深水专题
是否可直接用于生成代码:仅部分
是否含可直接照写示例:是
是否含不可照写反例:否
这一篇只讲对象直接参与语言级操作的文档能力:基础算符重载、`[]` 重载、`for in` 重载,以及 `mrows` / `mcols` / `msize` 这类矩阵关键字重载。
## 本篇职责
@@ -90,7 +85,7 @@ end;
- 依次输出 `20``0``1``1`
- 说明 `obj + value` 可以通过成员 `operator +` 接管
- 说明带 `is_left` 的比较算符可以同时处理 `obj < value``value < obj`
- 私有成员用尾随下划线的 `real_part_` / `imaginary_part_`,对外`PascalCase` property 暴露
- 本例私有成员 `real_part_` / `imaginary_part_`,对外通过 property 暴露(命名风格本身不属于本页事实)
代码块身份:输出片段
@@ -137,18 +132,32 @@ end;
### `[]` 重载:`operator[0]` / `operator[1]`
沿用上一段的 `bb` 类与测试主体,只把读取签名从 `function operator[](index);` 改成 `function operator[0](index, s1);`
读取签名也可以写成 `function operator[0](index, s1);`(与上一段 `operator[]` 等价的另一组写法)
代码块身份:配置片段 / 概念骨架
代码块身份:可直接照写示例
```tsl
t := array(1, 2, 3, 4, 5);
b := new IndexableBox(t);
writeLn(b[2]);
b[3] := 999;
writeLn(b.data[3]);
type IndexableBox = class
public
// 其余字段、create()、operator[1] 和测试主体同上一段
data;
function create(v);
begin
data := v;
end;
function operator[0](index, s1);
begin
return data[index];
end;
function operator[1](index, v);
begin
data[index] := v;
end;
end;
```
@@ -207,7 +216,7 @@ end;
- 说明 `operator for(flag)` 可以重载 `for in`
- 也说明同一个对象可以按返回值形态同时支持“单变量遍历”和“索引 + 值遍历”
### `mrows` / `mcols` / `msize` 重载
### `mrows` / `mcols` / `msize` 重载(带参形态,支持下标列表)
代码块身份:可直接照写示例
@@ -263,7 +272,7 @@ end;
- 说明 `mrows(obj)``mcols(obj)``msize(obj)` 都可由对象重载接管
- 说明对象方法式调用 `obj.mcols(1)` 也可继续取得列下标列表
### `++` `+=`
### `++` / `+=` / `--` / `-=` 自增自减重载
代码块身份:可直接照写示例
@@ -306,8 +315,8 @@ end;
结果说明:
- 依次输出 `11``11``12``17`
- 说明前置 `++` 会直接修改对象状态
- 说明这个最小样例里,后置 `counter++` 返回的是递增前快照
- 前置 `++counter``v``0` 分支,直接原地修改对象状态
- 后置 `counter++` `v = 0` 分支:分支构造并返回递增后的新对象,运行时用它更新 `counter` 本身,而后置表达式的取值是递增前的原对象(所以 `c.data``11``counter.data``12`
- 说明 `operator += (v)` 可以接管 `counter += 5`
`--``-=` 与之对称:
@@ -349,7 +358,7 @@ end;
- 输出 `7`
- 说明 `operator -= (v)` 可以接管 `counter -= 3`
- `operator--(v)``operator++(v)` 结构对称:`v = 0` 分支返回递减前快照,否则原地递减
- `operator--(v)``operator++(v)` 结构对称:`v = 0`(后置)分支构造并返回递减后的新对象供运行时更新变量本身,后置表达式的取值是递减前的原对象;`v``0`(前置)时原地递减
### 二进制函数重载:`operator funcName`
@@ -435,7 +444,8 @@ end;
结果说明:
- 输出 `array(1,314)``ret``1`(转换成功),出参 `msg``314`
- 说明类内需要调用被重载的同名全局函数时,用 `::` 前缀指定全局版本,否则会递归回自己
- 重载的分派按实参类型决定:本类对象走重载版本,非对象实参(如 `value` 是字符串)走全局版本
- 因此当被重载的实参已经不是本类对象(如上面 `DateToStr` 两例把对象拆成基础类型再调用)时,不加 `::` 也不会递归;只有当传给同名函数的实参仍是本类对象时才会递归回自己,这时用 `::` 前缀强制指定全局版本
- 重载函数支持通过参数传出返回值(`msg` 作为出参被赋值)
### `::` / `:.` 遍历重载与 `mcell` / `mrow` / `mcol` / `mIndexCount` / `mIndex`
@@ -512,7 +522,7 @@ end;
- `:.`(深度遍历)重载方式与 `::` 相同,把内部 `data::begin ... end` 换成 `data:.begin ... end` 即可
- 遍历体里用到的 `mcell` / `mrow` / `mcol` / `mIndexCount` / `mIndex` 必须各自重载,否则报 `override function not found`
### 关键字函数重载:`msize` / `mrows` / `mcols`
### `mrows` / `mcols` / `msize` 重载(无参形态,只取数量且免 `::`
`msize` / `mrows` / `mcols` 这类关键字函数也能重载,形态同二进制函数重载 `[class] function operator KeyWord(...)`,但**关键字重载不需要 `::` 指定全局**