# 运算符

## 功能

BT 支持算术、比较、逻辑、位运算、赋值、条件和成员访问等常用运算符。复杂表达式中建议使用括号明确顺序。

## 算术运算符

| 运算符 | 说明 |
| ------ | ------ |
| `+` | 加法或字符串拼接。 |
| `-` | 减法。 |
| `*` | 乘法。 |
| `/` | 除法。 |
| `%` | 取余。 |
| `**` | 幂运算。 |

```bt
x = 12
y = 29 % 5
z = 2 ** 3
```

## 比较运算符

| 运算符 | 说明 |
| ------ | ------ |
| `>` | 大于。 |
| `<` | 小于。 |
| `>=` | 大于等于。 |
| `<=` | 小于等于。 |
| `==` | 宽松等于。 |
| `!=` | 宽松不等于。 |
| `===` | 严格等于，值和类型都一致才返回 true。 |
| `!==` | 严格不等于。 |

```bt
price = 19.99

// 输出：true
print price >= 10

// 输出：false
print 1 === '1'
```

## 逻辑运算符

| 运算符 | 说明 |
| ------ | ------ |
| `&&` | 左侧为真时才执行并返回右侧，否则直接返回左侧。 |
| `||` | 左侧为真时直接返回左侧，否则执行并返回右侧。 |
| `!` | 按 BT 真值规则取反。 |
| `??` | 左侧为 `null` 或 `empty` 时才执行并返回右侧，否则直接返回左侧。 |

```bt
name = input_name ?? '游客'
count = total || 0
user && login(user)
```

## 位运算符

| 运算符 | 说明 |
| ------ | ------ |
| `&` | 按位与，对两个数的二进制表示进行逐位比较，如果两个相应的位都为1，则该位的结果为1，否则为0 |
| `|` | 按位或，对两个数的二进制表示进行逐位比较，如果两个相应的位中至少有一个为1，则该位的结果为1，否则为0 |
| `^` | 按位异或，对两个数的二进制表示进行逐位比较，如果两个相应的位不同，则该位的结果为1，否则为0|
| `~` | 按位取反，对一个数的二进制表示进行逐位取反，即0变为1，1变为0 |
| `<<` | 左移，将一个数的各二进制位全部左移若干位，由符号位（最左边的位）的空位则以0来填充 |
| `>>` | 右移，将一个数的各二进制位全部右移若干位，正数左补0，负数左补1，右边丢弃 |

```bt
x = 20
y = x | 2
z = y >> 2
n = ~0
```

## 赋值运算符

| 运算符 | 说明 |
| ------ | ------ |
| `=` | 赋值，返回右侧表达式的值。 |
| `+=` | 按二元 `+` 计算并写回，支持数值相加和字符串拼接。 |
| `-=` | 按二元 `-` 计算并写回。 |
| `*=` | 按二元 `*` 计算并写回。 |
| `/=` | 按二元 `/` 计算并写回，结果为浮点数。 |
| `%=` | 按二元 `%` 计算并写回。 |
| `<<=` | 按二元 `<<` 计算并写回。 |
| `>>=` | 按二元 `>>` 计算并写回。 |
| `&=` | 按二元 `&` 计算并写回。 |
| `^=` | 按二元 `^` 计算并写回。 |
| `|=` | 按二元 `|` 计算并写回。 |

### 语法

```bt
target = value
target += value
target -= value
```

### 参数

| 参数 | 类型 | 是否必填 | 默认值 | 有效范围或可选值 | 含义 |
| ------ | ------ | ------ | ------ | ------ | ------ |
| `target` | Variable/Array/Object | 是 | 无 | 可变变量、数组数字下标、普通对象字段、类实例字段 | 接收写回结果的可写目标。 |
| `value` | Any | 是 | 无 | 由对应二元运算符决定 | 普通赋值的右值，或复合赋值的右操作数。 |

属性链和动态下标可以作为目标，例如 `config.title`、`items[index]`、`config.article.id`。目标中的对象表达式和下标表达式只求值一次；执行顺序固定为“解析目标引用 → 读取当前值（复合赋值）→ 求右值 → 运算 → 写回同一目标”。

### 返回值

- 普通 `=` 返回右侧表达式的值。
- 复合赋值返回写回后的新值。
- 变量、局部变量、参数和闭包捕获变量沿用各自作用域；复合赋值不能修改常量。

```bt
config = {title: 'BT', article: {id: 0}}
items = [8]

title = (config.title += ' Lang')
id = (config.article.id += 1)
shifted = (items[0] <<= 2)

// 输出：BT Lang
print title

// 输出：1
print id

// 输出：32
print shifted
```

## 自增自减

### 功能与语法

| 运算符 | 返回值 | 写回结果 |
| ------ | ------ | ------ |
| `target++` | 修改前的旧值 | 当前值加 1。 |
| `target--` | 修改前的旧值 | 当前值减 1。 |
| `++target` | 修改后的新值 | 当前值加 1。 |
| `--target` | 修改后的新值 | 当前值减 1。 |

`target` 必须是可写变量、数组数字下标、普通对象字段或类实例字段，当前值只能是 `Int` 或 `Float`。字符串、布尔值、`null`、`empty` 和其他对象不能自增自减。

```bt
i = 1
old = i++
current = ++i

// 输出：1
print old

// 输出：3
print current
```

## 条件运算符

`? :` 根据条件返回两个表达式之一。省略 `:` 右侧时，条件不成立返回 `empty`。

```bt
x = 10
y = x == 10 ? 1 : 2
z = x == 9 ? 7
```

## 成员与调用

| 运算符 | 说明 |
| ------ | ------ |
| `()` | 改变运算顺序或调用函数。 |
| `[]` | 访问数组下标、字符串字符或对象动态字段。 |
| `.` | 访问对象字段或原型方法。 |

```bt

// 输出：H
print ['hello'][0].to_uppercase()
```

## 注意事项

- `&&`、`||` 和 `??` 都是短路求值，左侧已经能决定结果时，右侧函数调用、字段访问或其他表达式不会执行。
- `??` 只处理 `null` 和 `empty`，不会把 `0`、`false`、空字符串当成缺失值。
- `||` 使用 BT 真值规则，`null`、`empty`、`0`、`false`、空字符串、空数组和空对象都视为假。
- 普通赋值、复合赋值和自增自减都会把对象表达式与动态下标固定为同一个目标引用，不会因写回而重复调用目标中的函数。
- 字符串和 Bytes 下标、`BT` / `Math` 静态对象、扩展对象和类定义对象的属性只读；对这些目标赋值会抛出错误。
- `1 += 2`、`foo()++`、`(a + b) += 1` 等非左值会在编译期报错，常量也不能使用复合赋值或自增自减。
- 当前没有 `**=`、`&&=`、`||=`、`??=` 运算符；需要时应使用已有普通赋值和短路表达式明确书写。
