基本構文
LuneScript の基本的な構文について説明します。Lua の文法をベースにしつつ、静的型付けによる安全性を高めるための拡張が行われています。
コメント
LuneScript では C++ スタイルのコメントが使用できます。
//: 行末までのコメント (1行コメント)/* ... */: 複数行コメント
// これは1行コメントです
let val = 1; // 行の途中からでも書けます
/*
これは
複数行の
コメントです
*/
Lua 5.3 の
// (切り捨て除算) は、LuneScript ではコメントとして扱われます。
切り捨て除算を行いたい場合は、int 同士の除算を行うか、明示的なキャストや関数を使用してください。
変数宣言
変数は let キーワードを使用して宣言します。LuneScript は静的型付け言語であるため、変数は型を持ちます。
基本的な宣言
let val: int = 1;
変数名の後に :型名 を記述します。宣言と同時に初期化を行うことが一般的です。
初期値の型が宣言された型と異なる場合、コンパイルエラーとなります。
// Error: int 型の変数に real 型の値は代入できません
let param: int = 1.5;
型推論
初期値が与えられている場合、型宣言を省略することができます。コンパイラが右辺の値から型を推論します。
let val1 = 10; // int として推論
let val2 = 1.5; // real として推論
let val3 = "test"; // str として推論
let val4 = true; // bool として推論
型を明示する必要があるのは、主に以下のようなケースです。
nilable型 (T!) の変数にnilを初期値として与える場合:let val: int! = nil;- 空のリストやマップを定義する場合:
let list: List<int> = []; - スーパークラスの型で変数を受けたい場合:
let obj: SuperClass = new SubClass();
可変 (Mutable) と 不変 (Immutable)
let で宣言された変数は、デフォルトで 不変 (Immutable) です。再代入はできません。
再代入可能な変数を宣言するには、mut キーワードを使用します。
let mut count = 0;
count = count + 1; // OK
let fixed = 10;
// fixed = 20; // Error: Immutable variable cannot be modified
フロー解析による初期化 (変数初期化漏れ検知)
LuneScript では、変数の宣言時に初期化を行わなくても構いませんが、変数を参照する前には必ず初期化されている必要があります。
コンパイラはフロー解析を行い、すべての実行パスで変数が初期化されているかをチェックします(変数初期化漏れ検知)。
fn check( flag: bool ) {
let val: int;
if flag {
val = 10;
} else {
val = 20;
}
// すべてのパスで初期化されているため OK
print( val );
}
もし初期化されていないパスが存在する場合、コンパイルエラーとなります。
fn errorCase( flag: bool ) {
let val: int;
if flag {
val = 10;
}
// else 節がないため、flag が false の場合に初期化されない
// print( val ); // Error: variable 'val' may be uninitialized
}
このフロー解析による初期化は「遅延初期化」であり、mut 宣言は不要です(一度だけ代入されるため)。
スコープブロック
波括弧 { ... } で囲まれた部分はスコープブロックとなります。ブロック内で宣言された変数は、そのブロックの外からはアクセスできません。
let outer = 1;
{
let inner = 2;
print( outer, inner ); // 1 2
}
// print( inner ); // Error: 'inner' is undefined
シャドーイングの禁止:
LuneScript では、外側のスコープで既に定義されている変数と同名の変数を内側のスコープで定義すること(シャドーイング)はできません。
意図しない変数の参照ミスを防ぐための制約です。
LuneScript では、外側のスコープで既に定義されている変数と同名の変数を内側のスコープで定義すること(シャドーイング)はできません。
意図しない変数の参照ミスを防ぐための制約です。
let val = 1;
{
// Error: shadowing symbol of val
// let val = 2;
}