§4 表达式与控制流
4.0 运算符宪法(v0.7)
- 一义一符:每个语义恰好一个拼写。Bool 逻辑或只有
||;取默认只有or/.or()一对;永不引入同义别名或拼法糖。 - 符号/关键字分工律:符号运算符 = 纯 Bool 值域组合(
&&/||/!);关键字中缀 = 触及不可失败语义的运算(or取默认)。 - 永不挪用律:
&&/||永不做位运算(位运算恒走bit模块方法,§4.5);|永远是闭包定界符,永不是运算符。 - 角色分离律:
||的"零参闭包/逻辑或"是一个 token 的两个语法角色,由语法位置唯一判定(§4.7),不是语义多义。
4.1 绑定
let pattern [: Type] = expr不可变绑定;var可变绑定;必须初始化(无未初始化读取)。对let绑定的重赋值(含+=族)= E2080(v0.9,C 宿主已强制;本门判据 = 赋值左目的最内层绑定为let局部——var/形参/闭包形参/for·match 模式绑定不在本门)。- 绑定模式:标识符、
_(丢弃)、元组模式let (a, b) = pair。 - 遮蔽允许(§2.4)。
4.2 赋值
= 与 += -= *= /= %=是语句,不是表达式(禁止if (a = b)类误读)。- 合法目标:
var绑定、经可变访问路径的var字段、切片/数组元素(仅当切片绑定根为var;&T[]只读视图恒不可写)。可变性判定:目标路径的根绑定必须为var,且沿途字段声明为var(类引用穿越详见 §7.5)。
4.3 优先级(低 → 高)
| 层 | 运算符 | 结合 |
|---|---|---|
| 0 | \|\|(逻辑或,短路;仅 Bool) |
左 |
| 1 | or(取默认) |
左 |
| 2 | && |
左 |
| 3 | == != < > <= >= |
不可链 |
| 4 | .. ..=(range) |
无 |
| 5 | + - +% -% |
左 |
| 6 | * / % |
左 |
| 7 | 一元 - ! |
右 |
| 8 | 后缀:调用 () 索引 [] 成员 . 类型实参 [] 传播 ? |
左 |
4.4 布尔与取默认
&&/||短路逻辑与/或,仅接受Bool(否则 E2010;诊断判定对齐实现口径:仅已知非 Bool 标量类别报错,聚合/未知类型放行);!逻辑非,仅接受Bool(违规 E2010,判定口径同上;v0.8 明文化)。比较不可链:a < b && b < c。- 否决注记(v0.7):v0.6 曾以"防二义"为由不引入
||。经审计,零参闭包与逻辑或的冲突由语法位置完全消解(§4.0 原则 4、§4.7;||在表达式起始位置为闭包参数表、中缀位置为逻辑或,两位置互斥且完备),否决理由不再成立,故引入。or仍为取默认专属(§4.0 原则 1、2)。 x or 默认值:Option/Result 成功取值、失败取默认;等价x.or(默认值);两个形式并存但语义唯一(钉子)。非 Option/Result 左侧:求值后回落默认值(三线实现统一口径,v0.8 发射面对齐)。
4.5 算术
- 二元
+两侧均为Str时为拼接(2026-09-08 修订,T2;此前仅插值为惯例)。单侧Str或其他算符(- * / %)遇Str仍为 E2010。 - 默认检查算术:整数溢出/除零 panic(消息含 "overflow"/"division by zero");release 可由构建配置关闭溢出检查(除零永不关)。
- 显式回绕:
+% -%;%为求余,结果符号随被除数(同 Rust%,非欧几里得模);位运算经 stdlib(bit模块)。 - 索引永远边界检查(safe 子集无 unchecked),越界 panic("index out of bounds")。索引表达式接受任意整数类型。
4.6 控制流
if是表达式:作为值时else必需;各分支类型必须一致(或Void)。match是表达式:
match value {
Pattern1 => expr1
Pattern2 => { ...; exprN }
}
- 臂换行分隔;穷尽性编译期强制(E2030),枚举新增变体 → 所有非通配 match 报错。
- 模式:字面量、通配
_、绑定、变体(元组/具名字段)、元组、结构模式。 - 循环:
while cond、for pattern in iter;range0..n/0..=n是惰性迭代值;无do-while。 - break / continue(v0.7):语句,非表达式,不携带值;绑定同函数体内最近的 enclosing 循环。三道静态门:E2070 循环外;E2071 越过带 Drop impl 局部的作用域(v1 静态拒绝——C 直映发射无 cleanup 路径,RAII 合同优先;本限制按规范明文可解除,解除为纯增量);E2072 穿越闭包边界(闭包体是独立函数)。
scope {}与own (arena) {}不是循环,不参与绑定。 - 块是表达式:块的最后表达式为块值;
return退出函数,return的类型为Never参与推断。
4.7 闭包
|x| x + 1 // 单表达式体
|| expr // 零参
|var a| { ...; a } // 可变参数 + 块体,块值为返回值
|x: I32| -> I32 { x * 2 }
- 零参闭包与
||的角色分离(v0.7):||出现在表达式起始位置(无左操作数,如实参位、赋值右侧起始)→ 零参闭包参数表;出现在中缀位置(已有左操作数)→ 逻辑或(§4.3 第 0 层)。两位置互斥且完备,词法器产出统一 token。 - 闭包捕获 = 创建时拷贝绑定值(T27 裁决终态,2026-09-30;full 档与 arena 档同语义)。闭包创建后,外层绑定的再赋值对闭包不可见(创建时快照即规范语义)。可变共享仅经显式单元:
Mutex[T]/Atomic[T]/Global[T](E3070 = 该规则的语义执行,非警告);own 块内闭包禁用。业内对齐:Java/Kotlin effectively-final 同构;按引用捕获留作 GC 成熟后的能力扩展位(§6.2,与终态不冲突)。 - 闭包的类型是函数类型
fn(Params) -> Ret(§3.1)——接受闭包的参数以函数类型声明,如Mutex.with_mut(f: fn(var T) -> R);闭包字面量在期望函数类型的上下文中自动适配。 - 闭包 Send 判定:闭包(及函数类型的值)在 spawn 处按字面捕获逐个检查(E3010);经 channel/静态存储传递时,函数类型的值视为捕获不可知 → 非 Send(§7.4)。
4.8 UFCS(统一调用语法)
recv.m(a)首先解析为"以recv为第一实参的函数/方法";解析顺序:类型自身固有方法 → 当前可见 trait 的 impl 方法(§3.4)→ 前奏。21.double()≡double(21);链式调用可读、不引入 OOP 继承。
4.9 scope / own 表达式
scope { |s| ... }:结构化并发作用域表达式,块值为表达式值(§7.2)。own (arena) { ... }:所有权模式块,块值受出块规则约束(§6.3)。
4.10 test 块
test "名称" { ... }顶层声明;仅在ctron test下编译运行;块值忽略。- 前奏断言:
assert(cond)、assert_eq(a, b)、assert_ne(a, b)(T: Eq + Show);expect(msg)(§5.2)。 - 断言失败 = panic,消息含期望/实际值的
Show表示——AI 可读的失败输出。
4.11 字符串插值(语义)
"hi {name} x{n}" 脱糖为片段 fmt 拼接(一次 String 构造,分配属性 alloc);片段支持字段/方法链,不支持语句与嵌套 {}。
4.12 与测试集的对应
tests/01_basics.ct(运算/控制流/UFCS)、tests/02_option_result.ct(match/?)、tests/06_concurrency.ct(闭包/scope)、tests/01_overflow.panic.ct(检查算术)。