Kagari
キーワードを入力してドキュメントを検索します。

構文

式と文

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

ブロックと文

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;後述
式文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

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)。パターンを参照してください。
  • 型注釈 : Type は省略できます。省略すると型は推論されます。
  • 初期化子 = expr は省略できます。初期化子なしで宣言した束縛は、読む前に代入しなければなりません。代入前に読むと、実行時パニックでゲームが停止します。
  • パターンが mut を付けない限り、束縛は不変です。不変の束縛への代入は E3017 です。初期化子なしで宣言した束縛への最初の代入も含みます。そのような束縛は let mut で宣言してください。
  • pushdown fn の中では、ローカル変数は有限型の値を持ち(E3008)、クロージャや参照は持てません(E3015、E3014)。

リテラル

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

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

パス

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 と同じ働きをします(ソースファイルとモジュールを参照)。

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

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

演算子

優先順位と結合性

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

演算子結合性
パス、リテラル、( … )、ブロック、フォーム、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 と書きます。

オペランドの型

演算子オペランド結果
+ - * / %同じ Rust 整数型の 2 値、Int の 2 値、Decimal 2 つ、Rat 2 つ数値を参照。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 型の等価性は構造的に比較します。言語トレイトを参照してください。

as

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

代入と複合代入

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 のままです。数値を参照してください。

呼び出しとメソッド呼び出し

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

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

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

フィールドと添字

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 です。末尾を越える添字は実行時パニックになり、定数評価中なら E4005 です。

構造体、タプル、配列の式

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 は型レベル定数です

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

範囲

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 はなく、.. 単独は残余パターンです。範囲パターンを参照してください。範囲は for ループで使います。制御フローとループを参照してください。

クロージャ

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)は値、参照、クロージャにあります。要点は次のとおりです。

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

? 演算子

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 です。? は定数式にはなりません。

最終更新日 2026年10月29日