🐛 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:
@@ -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(...)`,但**关键字重载不需要 `::` 指定全局**:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user