📝 docs(tsl-syntax-reference): document verified facts from FAQ corpus
从 FAQ 语料(2018 篇镜像)与参考页做完 169 条逐条差集,补入 6 组此前未收录的语言 事实。每条先用 TSL.exe 实跑观察行为,再收敛成 39 条断言的回归门,在 TSLGen2、 AnalyseNG.NET、TSL 三个解释器上均通过后才写入。 - 16 页:0/0 得 nan、2/0 得 inf;nan 的 = > < >= <= 恒假而 <> 为真;nan 沿算术 传播;nil 在乘除减里按 0 参与 - 04 页:整体赋值免声明,但对未建立的变量写单元格赋值会报「变量类型不是Array」 - 07 页:相邻两个 if 是两条独立语句都会执行;for..in 单控制变量拿到的是键不是值; 二维数组按行推进,行本身是数组(新增 syntax-07-013) - 21 页:子矩阵赋值语句求值为 0;t[:,:] 按位置复制不按列名对齐(新增 syntax-21-019);| 列并时同名字符串列键由右操作数覆盖(新增 syntax-21-018) - 13 页:select 输出列表同名列后者覆盖前者,须用 as 改名(新增 syntax-13-032) 三条 FAQ 说法实跑不复现,故未写入:12574 的括号消歧、19857 的 -2147483648 字面量限制、31474 的 :. bugfix 记录。15305/11045 的用户/公用/共享函数同名解析 优先级需要服务端多账号环境,本地无法验证,仍为已知缺口。 lexicon.json 为 16 页补两个页级 alias,使 nan/nil 语义能被自然语言查询命中。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,9 +13,12 @@
|
||||
<!-- section-id: syntax-07-002 -->
|
||||
|
||||
- `if ... then ... else ...` 默认写成块式分支:`then begin ... end else begin ... end`。
|
||||
- 两个相邻的 `if ... then begin ... end` 是两条**独立**语句,两个条件都会求值、都可能执行;只有写了 `else` 才是互斥分支。
|
||||
- 块式分支内部的普通语句必须用分号结尾。
|
||||
- 控制流块的 `begin ... end` 后可以加分号也可以不加(语法都允许)。
|
||||
- `for` 支持 `to`、`downto`、可选 `step`,以及 `for i, v in array` 遍历。
|
||||
- `for ... in` 也可以只写一个控制变量:`for i in array do` 里的 `i` 是行下标/键,不是行值;要拿到行值就写两个控制变量。
|
||||
- 二维数组按 `for i, v in array` 遍历时按行推进,`v` 本身是整行数组;要落到单元格需要再嵌套一层 `for ... in`。
|
||||
- 计数 `for` 的初值、终值和步长确定后,循环次数随之固定;循环体内不要给控制变量赋值。
|
||||
- `for i, v in array` 遍历期间,不要修改被遍历数组或其中元素。
|
||||
- `while` 和 `repeat ... until` 都可直接使用;`repeat` 至少会先执行一轮再判断结束条件。
|
||||
@@ -77,6 +80,47 @@ writeLn(counter);
|
||||
0
|
||||
```
|
||||
|
||||
相邻两个 `if` 与 `if ... else` 的区别:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
trace := "";
|
||||
if 1 then
|
||||
begin
|
||||
trace := trace + "A";
|
||||
end
|
||||
if 1 then
|
||||
begin
|
||||
trace := trace + "B";
|
||||
end
|
||||
writeLn(trace);
|
||||
|
||||
trace2 := "";
|
||||
if 1 then
|
||||
begin
|
||||
trace2 := trace2 + "A";
|
||||
end
|
||||
else
|
||||
begin
|
||||
trace2 := trace2 + "B";
|
||||
end
|
||||
writeLn(trace2);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 第一段输出 `AB`:两个 `if` 是两条独立语句,条件都为真所以都执行
|
||||
- 第二段输出 `A`:`if ... else` 是一条语句,两支互斥
|
||||
- 所以“多个条件里只能命中一个”必须写 `else`,靠相邻 `if` 排列不成立
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
AB
|
||||
A
|
||||
```
|
||||
|
||||
### `for` 的几种主干写法
|
||||
|
||||
<!-- section-id: syntax-07-005 -->
|
||||
@@ -166,6 +210,73 @@ for i, value in numbers do
|
||||
230
|
||||
```
|
||||
|
||||
### `for ... in` 的控制变量个数
|
||||
|
||||
<!-- section-id: syntax-07-013 -->
|
||||
|
||||
<!-- tags: 遍历只写一个变量, 键还是值, 遍历二维数组, 每行是数组, 嵌套遍历 -->
|
||||
|
||||
一个控制变量拿到的是下标/键,两个才拿到行值:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
data := array("a": 1, "b": 5, "c": 3, "d": -2);
|
||||
total := 0;
|
||||
for i, value in data do
|
||||
total := total + value;
|
||||
writeLn(total);
|
||||
|
||||
keys := "";
|
||||
for i in data do
|
||||
keys := keys + i;
|
||||
writeLn(keys);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 先输出 `7`:两个控制变量时,`value` 是行值
|
||||
- 再输出 `abcd`:只写一个控制变量时,它是行下标/键,不是行值
|
||||
- 所以想累加数值却只写一个控制变量,会拿到键而不是值
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
7
|
||||
abcd
|
||||
```
|
||||
|
||||
二维数组按行推进,每个 `value` 本身是一行数组:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
rows := array(("A": 1, "B": 2), ("A": 3, "B": 4));
|
||||
colA := 0;
|
||||
for i, value in rows do
|
||||
colA := colA + value["A"];
|
||||
writeLn(colA);
|
||||
|
||||
all := 0;
|
||||
for i, value in rows do
|
||||
for j, cell in value do
|
||||
all := all + cell;
|
||||
writeLn(all);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 先输出 `4`:`value` 是整行数组,可以直接按列键取 `value["A"]`
|
||||
- 再输出 `10`:要落到每个单元格,需要再嵌套一层 `for ... in`
|
||||
- 所以二维数组不会被自动摊平成单元格序列
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
4
|
||||
10
|
||||
```
|
||||
|
||||
### `break` 与 `continue`
|
||||
|
||||
<!-- section-id: syntax-07-006 -->
|
||||
@@ -500,6 +611,9 @@ end
|
||||
- 把控制流问题和函数文件模型问题混在一起排查。
|
||||
- 在计数 `for` 循环体里给控制变量赋值。
|
||||
- 在 `for ... in` 遍历期间修改被遍历数组或其中元素。
|
||||
- 用相邻两个 `if ... then begin ... end` 表达互斥分支;它们是两条独立语句,需要互斥就写 `else`。
|
||||
- 在 `for ... in` 只写一个控制变量却当成行值使用;单变量拿到的是下标/键。
|
||||
- 以为二维数组会被 `for ... in` 摊平成单元格序列;它按行推进,行本身是数组。
|
||||
|
||||
代码块身份:反例 / 不可照写
|
||||
|
||||
|
||||
Reference in New Issue
Block a user