# 式と文

Kagari は Rust の構文を持つ式指向の言語です。ブロックは式であり、`if` と `match` は値を生み、文は `;` で終わります。この章では、パーサーが受け付けるすべての式と、コンパイラーが加える規則を挙げます。制御フローの式（`if`、`match`、ループ、`break`、`continue`、`return`）は[制御フローとループ](./control-flow.md)に、`.kix` のフォーム（`s!(…)`、`t![…]`、`column![…]` など）は[フォーム](./forms.md)にあります。

## ブロックと文 {#blocks-and-statements}

```kis
const fn label_width(chars: Int<0, 40>) -> u32 {
    let n: u32 = chars.into();
    let padding = 8;
    n * 16 + padding
}
```

ブロック `{ … }` は文を順に実行します。最後の式の後に `;` がなければ、その式の値がブロックの値です。そうでなければブロックの値は `()` です。ブロックはスコープを開き、その中の `let` 文の束縛は閉じ括弧 `}` で終わります。

ブロックに書けるもの:

| 文 | 形 | 備考 |
| -- | -- | ---- |
| `let` 文 | `let pat: Type = expr;` | [後述](#let-and-let-mut) |
| 式文 | `expr;` | 値は捨てられます。`#[must_use]` な値を捨てると `W3023` です |
| ブロック様の式 | `if …`、`match …`、`loop`、`while`、`for`、`{ … }`、`name!{…}` 形式のフォーム | `;` は不要です |
| アイテム | `fn`、`struct`、`enum`、`const`、`use` など | ブロックの中で宣言するアイテムです。ファイルモジュール（`mod name;`）は `E1005` です |
| 空文 | `;` | 無視されます |

**ブロック様の式は文を終えます。** 文の先頭にあるブロック、`if`、`match`、`loop`、`while`、`for`、および `choice!{…}` のような波括弧のフォームは、`;` なしで完結した文になります。その後に続くものは式の続きになりません。したがって `if c { a } else { b } - 1` は 2 つの文であり、`{ … } (x)` はブロックの後に括弧付きの式が続いたもので、呼び出しではありません。値を使うには `(if c { a } else { b }) - 1` と書きます。

2 つの式文の間に `;` がないのは構文エラー（`E0001`）です。

### `let` と `let mut` {#let-and-let-mut}

```kis
let n = 3;
let mut total: u32 = 0;
let (x, y) = (1, 2);
let Point { x: px, y: py } = origin();
let mut later: bool;
```

`let` はパターンの変数を値に束縛します。

- パターンは反駁不能でなければなりません。つまり型のすべての値に一致する必要があります（`E2038`）。[パターン](./patterns.md#refutability)を参照してください。
- 型注釈 `: Type` は省略できます。省略すると型は推論されます。
- 初期化子 `= expr` は省略できます。初期化子なしで宣言した束縛は、読む前に代入しなければなりません。代入前に読むと、実行時パニックでゲームが停止します。
- パターンが `mut` を付けない限り、束縛は不変です。不変の束縛への代入は `E3017` です。**初期化子なしで宣言した束縛への最初の代入も含みます**。そのような束縛は `let mut` で宣言してください。
- `pushdown fn` の中では、ローカル変数は[有限型](../concepts/kinds.md#finite-types)の値を持ち（`E3008`）、クロージャや参照は持てません（`E3015`、`E3014`）。

## リテラル {#literals}

| リテラル | 例 | 型 |
| -------- | -- | -- |
| 整数 | `42`、`1_000`、`0xFF`、`0o17`、`0b1010`、`5u8`、`300i64` | 文脈から推論される整数型。接尾辞があれば型が決まります。[数値](./numbers.md)を参照 |
| 小数 | `0.5`、`1.0`、`12.75` | `Decimal` |
| 文字列 | `"Mio"`、`"line one\nline two"` | `Text` |
| 真偽値 | `true`、`false` | `bool` |
| ユニット | `()` | `()` |

文字、バイト、生文字列、浮動小数点数のリテラルはなく、指数表記もありません。`-5` は `5` に単項 `-` を適用したもので、1 つの負のリテラルとして型付けされます。トークンの正確な構文（エスケープ、接尾辞、桁区切り）は[字句構造](./lexical.md)にあります。

## パス {#paths}

```kis
ROUTE
Route::Azusa
std::time::ms(500)
Self::new()
super::helpers::clamp(x)
asset::<ImageAsset>("bg/room.png")
rng_choose::<Coin>()
```

パスは、ローカル変数、引数、アイテム（関数、定数、static、ユニット構造体、enum のバリアント）、関連アイテムを指します。セグメントは `::` で区切ります。`self`、`super`、`crate`、`Self` は Rust と同じ働きをします（[ソースファイルとモジュール](./modules.md)を参照）。

式の中では、ジェネリクス引数はターボフィッシュ `::<…>` で書きます。ジェネリクス引数は、型、整数リテラル（`-` 付きも可）、または[型レベル定数](./constants.md#type-level-constants)を入れたブロック `{ … }` です。

式の中のパスが値以外のもの（モジュールや名前付きフィールドを持つ構造体など）を指すと `E2009` です。未知の名前は `E1016` です。

## 演算子 {#operators}

### 優先順位と結合性 {#precedence-and-associativity}

パーサーに基づく、結合の強い順の表です。

| 演算子 | 結合性 |
| ------ | ------ |
| パス、リテラル、`( … )`、ブロック、フォーム、`if`、`match`、ループ | — |
| フィールド `a.b`、タプルフィールド `a.0`、メソッド呼び出し `a.m(…)`、呼び出し `f(…)`、添字 `a[i]`、`?` | 左から右 |
| 単項 `-`、`!`、`*`（参照外し）、`&`、`&mut` | 前置 |
| `as`（常にエラー、`E2019`） | 左 |
| `*` `/` `%` | 左 |
| `+` `-` | 左 |
| `<<` `>>` | 左 |
| `&` | 左 |
| `^` | 左 |
| `\|` | 左 |
| `==` `!=` `<` `>` `<=` `>=` | なし。`a < b < c` は構文エラー |
| `&&` | 左 |
| `\|\|` | 左 |
| `..` `..=` | 左。範囲は連鎖させるものではありません |
| `=` `+=` `-=` `*=` `/=` `%=` `^=` `&=` `\|=` `<<=` `>>=` | 右 |
| `return`、`break`、クロージャ `\|…\| body` | できるだけ右まで伸びます |

この表は Rust と同じですが、範囲は非結合ではなく左結合です。比較演算子は連鎖できないので、`a < b && b < c` と書きます。

### オペランドの型 {#operand-types}

| 演算子 | オペランド | 結果 |
| ------ | ---------- | ---- |
| `+` `-` `*` `/` `%` | 同じ Rust 整数型の 2 値、`Int` の 2 値、`Decimal` 2 つ、`Rat` 2 つ | [数値](./numbers.md)を参照。`Int` の算術は結果の範囲を計算します |
| `&` `\|` `^` | 同じ Rust 整数型の 2 値、または `bool` 2 つ | オペランドの型 |
| `<<` `>>` | Rust 整数 2 つ（型は異なってもよい） | 左オペランドの型 |
| `==` `!=` | `Eq` である 1 つの型の 2 値（そうでなければ `E2017`） | `bool` |
| `<` `>` `<=` `>=` | 1 つの型の整数 2 つ、`Int` の 2 値、`Decimal` 2 つ、`Rat` 2 つ | `bool` |
| `&&` `\|\|` | `bool` 2 つ。右辺は必要なときだけ実行されます | `bool` |
| 単項 `-` | 符号付き Rust 整数、`Int`（範囲が反転します）、`Decimal`、`Rat` | オペランドの型 |
| 単項 `!` | `bool`（論理否定）または Rust 整数（ビット反転） | オペランドの型 |
| 単項 `*` | 参照 `&T` または `&mut T`（そうでなければ `E2033`） | `T` |
| `&e`、`&mut e` | 任意の式。`&mut` には可変な場所が必要です（`E3017`） | `&T`、`&mut T` |

整数型は暗黙には混ざりません。`Int` と Rust 整数、または異なる 2 つの Rust 整数型に演算子を適用するとエラーです（`E2014`、`E2001`）。片方を `.into()` か `.saturate()` で変換してください。ビット演算子には Rust 整数が必要で、`Int` に使うと `E2015` です。除数の `Int` の範囲が 0 を含む除算や剰余は `E2016` です。順序は数値にだけ定義されており、タプル、`Text`、enum に `<` を使うと `E2015` です。`Eq` 型の等価性は構造的に比較します。[言語トレイト](../special/traits.md)を参照してください。

### `as` {#as}

`as` は Rust と同じ優先順位で構文解析されますが、キャストはすべてエラー（`E2019`）です。整数の変換には `x.into()`（損失なし、コンパイル時に検査）か `x.saturate()`（範囲内に丸める）を使います。[数値](./numbers.md)を参照してください。

## 代入と複合代入 {#assignment-and-compound-assignment}

```kis
total = 0;
AFFECTION_MIO += 1;
point.x = 10;
scores[i] -= 1;
```

`place = value` は値を格納します。`place op= value` は、演算子 `+ - * / % ^ & | << >>` について `place = place op value` と同じです。代入は型 `()` の式です。

左辺は可変な場所でなければなりません（`E3017`）。

- `mut` で宣言したローカル変数または引数
- `pushdown fn` の中の物語変数（`static mut`）
- 可変な場所のフィールド `a.b` または要素 `a[i]`
- `r` が `&mut T` であるときの `*r`、および `&mut T` を通してたどったフィールドや要素

定数、不変の `static`、呼び出し結果のような一時値、`&T` を通してたどったものには代入できません。

`Int` の場所への複合代入は、その型の境界で**飽和**します。右辺には任意の `Int` 値を書けます。値 5 を持つ `Int<0, 5>` に `AFFECTION_MIO += 1` を実行しても 5 のままです。[数値](./numbers.md)を参照してください。

## 呼び出しとメソッド呼び出し {#calls-and-method-calls}

```kis
fade(ms(500))
Confession()
screen.entity(AZUSA).image()
x.into()
scores.get(0)
```

`f(a, b)` は関数、関数ポインター、クロージャを呼び出します。`f` には任意の式を書けます。引数の数は一致しなければならず（`E2024`）、呼び出せない値を呼び出すと `E2025` です。どの関数種別がどれを呼べるかは[関数種別](../concepts/kinds.md#call-rules)にあります。

`receiver.method(args)` は、レシーバーの型の `impl` で宣言されたメソッド、または標準トレイトが提供するメソッドを呼び出します。レシーバーは、メソッドの `self`、`&self`、`&mut self` に合わせて自動的に借用または参照外しされます。`&mut self` のメソッドには可変な場所が必要です（`E3017`）。`Type::function(args)` は関連関数を呼び出します。メソッドのジェネリクス引数はターボフィッシュで書きます: `x.m::<T>(…)`。未知のメソッドは `E2022`、`self` を持たない関連関数をメソッド構文で呼ぶと `E2023` です。

## フィールドと添字 {#fields-and-indexing}

```kis
point.x
pair.0
nested.0.1
grid[row][col]
```

- `a.name` は名前付きフィールドを読みます。`a.0`、`a.1` などはタプルやタプル構造体のフィールドを読みます。`t.0.1` は 2 回のフィールドアクセスです。参照は自動的に参照外しされます。未知のフィールドは `E2020` です。
- `a[i]` は配列または `Vec<T>` の要素を読みます（他の型では `E2032`）。添字は整数で、整数リテラルの添字は `usize` です。末尾を越える添字は実行時パニックになり、[定数評価](./constants.md#const-evaluation-errors)中なら `E4005` です。

## 構造体、タプル、配列の式 {#struct-tuple-and-array-expressions}

```kis
Point { x: 1, y: 2 }
Point { x, y }
Shape::Rect { w: 10, h: 20 }
EntityId(216)
Route::None
(1, true)
(5,)
[1, 2, 3]
[false; 8]
```

| 式 | 備考 |
| -- | ---- |
| `Path { field: value, … }` | 構造体、または構造体形式の enum バリアント。すべてのフィールドを与える必要があります（`E2021`）。未知のフィールドは `E2020` です。`Path { x }` は `Path { x: x }` の省略形です。構造体更新構文 `..base` はありません |
| `Path(a, b)` | タプル構造体またはタプルバリアント。そのコンストラクターは関数です |
| `Path` | ユニット構造体またはユニットバリアント |
| `(a, b)`、`(a,)`、`()` | タプル。要素が 1 つのタプルには末尾のカンマが必要で、`(a)` は単に `a` です |
| `[a, b, c]` | 列挙した要素の配列。要素の型は 1 つです |
| `[value; N]` | `N` 個のコピーからなる配列。`N` は[型レベル定数](./constants.md#type-level-constants)です |

構造体式は、`if` と `while` の条件、`match` の検査対象、`for` の反復対象には直接書けません。`{` が本体の開始と解釈されるためです。括弧で囲んでください: `if p == (Point { x: 0, y: 0 }) { … }`。

## 範囲 {#ranges}

```kis
0..4      // 0, 1, 2, 3
3..=5     // 3, 4, 5
```

`a..b`（終端を含まない）と `a..=b`（終端を含む）は `Range<T>` を作ります。`Range<T>` は `start`、`end`、`inclusive` のフィールドを持つ std の構造体です。`T` は両端が変換できる型で、`0..7` は `Range<Int<0, 7>>` です。範囲式には両端が必要で、`a..`、`..b`、`..=b`、`..` は `E2030` です。パターンとしては `a..` と `..=b` がありますが、`..b` はなく、`..` 単独は残余パターンです。[範囲パターン](./patterns.md#range-patterns)を参照してください。範囲は `for` ループで使います。[制御フローとループ](./control-flow.md#for-loops)を参照してください。

## クロージャ {#closures}

```kis
|x| x + 1
|| nav::back()
|a: u32, b: u32| a * b
|mut screen| { screen.hud().text_window().change(Visibility::Hidden).apply_animation(instant()); screen }
|v| -> u32 { v * 2 }
```

`|params| body` はクロージャです。引数は反駁不能なパターンで、型は省略できます。`||` は引数なしです。本体は任意の式ですが、戻り値の型 `-> T` を書く場合は本体をブロックにします。`move` はありません。クロージャは使う変数を常に値でキャプチャします。

クロージャにできることとその型（`Fn(A) -> B`、`pushdown Fn(A) -> B`、`const Fn(A) -> B`）は[値、参照、クロージャ](./values.md)にあります。要点は次のとおりです。

- 何もキャプチャしないクロージャは、その種別の関数ポインターに変換されます。レンダーをその場に書けるのはこのためです。関数ポインターが必要な場所にキャプチャするクロージャを書くと `E2036` です。
- `pushdown fn` の中では、クロージャは第二級です。引数として渡して呼び出せますが、ローカル変数への格納、返却、キャプチャはできません（`E3015`）。

## `?` 演算子 {#the-try-operator}

```kis
fn first_score(scores: Vec<u32>) -> Option<u32> {
    let first = scores.get(0)?;
    Some(first * 10)
}
```

`Option<T>` に対する `expr?` は `Some` の中の `T` を与えるか、囲む関数から `None` を返します。`Result<T, E>` に対しては `Ok` の中の `T` を与えるか、その `Err` を返します。囲む関数は `Option`、または同じエラー型の `Result` を返さなければなりません。そうでない場合と、それ以外の型に使った場合は `E2034` です。`?` は定数式にはなりません。
