@@ -101,6 +101,7 @@
|
||||
- 连续标量比较才用 `:>`、`:<`、`:<>`、`:==`、`:>=`、`:<=`。
|
||||
- 数组逐元素链式比较才用 `::>`、`::<`、`::<>`、`::==`、`::>=`、`::<=`。
|
||||
- 混合两类以上运算符时,优先用括号明确分组,不依赖跨语言记忆里的优先级。
|
||||
- TSL 的主要优先级从高到低是:成员/下标/调用,`not`、前置自增减与倒数/逆等一元运算,字符串 `$`,幂,乘除移位,加减(包括一元正负号)与集合/位运算,比较与 `in`/`like`/`is`,`and`/`or`,冒号,赋值,表达式前导 `@`;同级通常从左到右。
|
||||
|
||||
边界规则:
|
||||
|
||||
@@ -566,6 +567,113 @@ writeLn(if 2 > 1 then 2 else 1);
|
||||
|
||||
`if condition then true_value else false_value` 必须带 `else`,否则不是本页可照写的表达式形态。
|
||||
|
||||
### 运算符优先级
|
||||
|
||||
<!-- section-id: syntax-06-015 -->
|
||||
|
||||
<!-- tags: 运算符优先级, 谁先计算, 先乘除后加减, and or 优先级, 表达式加括号 -->
|
||||
|
||||
下表是面向当前正式文档已收录运算符的保守分组,数字越小优先级越高:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| 级别 | 主要形态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 0 | `()`、`[]`、`.`、`?.`、函数调用 | 分组、访问、下标与调用最先结合。 |
|
||||
| 1 | `not`、前置 `++` / `--`、`!`、`.!`、`.!!` | 逻辑非、前置自增减与倒数/逆等一元运算。 |
|
||||
| 2 | `$` | 字符串连接。 |
|
||||
| 3 | `^`、`~`、`:^` | 幂、开方与对应矩阵形态。 |
|
||||
| 4 | `*`、`/`、`\`、`%`、`div`、`mod`、`shl`、`shr`、`rol`、`ror` | 乘除、取余与移位。 |
|
||||
| 5 | `+`、`-`、一元正号 / 负号、集合运算、点前缀位/逻辑运算 | 加减、一元正负号及同组语言运算;因此幂先于一元正负号结合,例如 `-2 ^ 2` 等于 `-(2 ^ 2)`。 |
|
||||
| 6 | 比较、`is`、`in`、`sqlin`、`like`、链式比较 | 关系判断。 |
|
||||
| 7 | `and`、`or` | 低于比较,因此 `a > 1 and b < 2` 按两个比较再逻辑与理解。 |
|
||||
| 8 | `:` | 冒号相关表达式形态。 |
|
||||
| 9 | `:=` 与各类复合赋值 | 赋值接近最低优先级。 |
|
||||
| 10 | `@` | 表达式对象前导最低。 |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
同级运算通常从左到右求值。为了避免不同语言之间的优先级记忆混淆,混合两类以上运算符时仍推荐显式加括号:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
value := 1 + 2 * 3;
|
||||
signedPower := -2 ^ 2;
|
||||
flag := (2 > 1) and (1 < 2);
|
||||
writeLn(value);
|
||||
writeLn(signedPower);
|
||||
writeLn(flag);
|
||||
```
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
7
|
||||
-4
|
||||
1
|
||||
```
|
||||
|
||||
稀有矩阵运算符的详细优先级以其专题页为准;不要用本表外推尚未写入正式文档的符号。
|
||||
|
||||
### 静态计算表达式 `static`
|
||||
|
||||
<!-- section-id: syntax-06-016 -->
|
||||
|
||||
<!-- tags: 静态计算, 只计算一次, 表达式缓存, static name, 按键缓存 -->
|
||||
|
||||
表达式前的 `static` 会缓存第一次计算结果。带 `name` 时,名称表达式是缓存键:同一键复用第一次结果,不同键分别计算。
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
echo StaticValue(), ",", StaticValue();
|
||||
|
||||
function StaticValue();
|
||||
begin
|
||||
return static NextValue();
|
||||
end;
|
||||
|
||||
function NextValue();
|
||||
begin
|
||||
global static_calls;
|
||||
static_calls += 1;
|
||||
return static_calls;
|
||||
end;
|
||||
```
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
1,1
|
||||
```
|
||||
|
||||
按键分别缓存:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
echo NamedValue("A"), ",", NamedValue("A"), ",", NamedValue("B");
|
||||
|
||||
function NamedValue(key);
|
||||
begin
|
||||
return static NextValue() name key;
|
||||
end;
|
||||
|
||||
function NextValue();
|
||||
begin
|
||||
global named_static_calls;
|
||||
named_static_calls += 1;
|
||||
return named_static_calls;
|
||||
end;
|
||||
```
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
1,1,2
|
||||
```
|
||||
|
||||
这不是类成员的 `static` 字段;类静态成员见 [08_objects_and_classes.md](08_objects_and_classes.md)。缓存结果具有运行时状态,不要用它保存每次调用都必须重新计算的值。
|
||||
|
||||
### 表达式对象
|
||||
|
||||
<!-- section-id: syntax-06-007 -->
|
||||
@@ -847,6 +955,8 @@ writeLn(value);
|
||||
- 把 `if` 表达式写成没有 `else` 的半句。
|
||||
- 把本页明确的 `c?.a?.[1]` 外推成所有深链式空安全访问都可靠。
|
||||
- 从其他语言推断 TSL 运算符能力。
|
||||
- 把类成员 `static field;` 与表达式前导 `static Expression [name Key]` 当成同一种语法。
|
||||
- 在复杂混合表达式里依赖其他语言的优先级记忆而省略括号。
|
||||
|
||||
代码块身份:反例 / 不可照写
|
||||
|
||||
|
||||
Reference in New Issue
Block a user