1Kuinの文とブロック
文の名前 文の中身
ブロック名 識別子(~)
ブロックの中身
end ブロック名
- var n: int
-
- func f(x: float)
- var y: float
- end func
名前 | 分類 | 説明 |
---|---|---|
alias | 文 | 型の別名定義 |
assert | 文 | アサーション |
break | 文 | ブロックを抜ける |
const | 文 | 定数定義 |
do | 文 | 式の実行 |
excode | 文 | コンパイル後コードの直接記述 |
include | 文 | 別ファイルの埋め込み |
ret | 文 | 関数を抜ける |
skip | 文 | ループを1回飛ばす |
throw | 文 | 例外の発生 |
var | 文 | 変数定義 |
block | ブロック | 基本ブロック |
class | ブロック | クラス定義 |
enum | ブロック | 列挙型定義 |
for | ブロック | 回数ループ |
func | ブロック | 関数定義 |
if | ブロック | 条件分岐 |
switch | ブロック | 値による分岐 |
try | ブロック | 例外処理 |
while | ブロック | 条件ループ |
設計の理由
ブロック終端の「end ブロック名」でブロック名を指定させている理由は、C言語の「}」やPascalの「end」などのブロック終端記号が並んだときにどのブロックに対応するものかが解りにくくなるという可読性上の理由です。
コンパイル時の型チェックと同様に、ユーザが意図したコードになっているかをなるべくコンパイラがチェックしたほうがバグが減らせるため、多少冗長になってもブロック名を指定させて、コンパイル時に対応関係をチェックするようにしました。
「end ブロック名」という構文は、Visual Basicに由来します。
2alias文
alias 新しい型名: 既存の型名
3assert文
assert 条件式
4break文
break ブロックの識別子
- 指定した識別子の、blockブロック、forブロック、ifブロック、switchブロック、tryブロック、whileブロックの処理を抜ける。
- ブロックの処理を抜けるとは、そのブロックの「end」の直後にジャンプすることである。
設計の理由
多くの言語では直近のブロックしか抜けることができないため、多重ループを抜ける場合にはフラグの変数を追加するなどの回りくどい方法を行う必要がありました。 そこでKuinでは抜けるブロックの識別子が指定できるようにしました。
またKuinではifブロックを含む多くのブロックがbreak文で抜けられるため、抜けるブロックを混乱しないように識別子は省略できないようにしました。
5const文
const 定数名: 型名 :: 値
- 定義した定数はコンパイル時に値に置き換えられ、実行時にメモリを消費しない。
- const文で指定する値は、コンパイル時に定数に確定できる式でなければならない。
6do文
do 式
- 最後に評価される演算は副作用がなければならない。
設計の理由
単なる式の実行に「do」という構文を必要とする理由は、必ず行頭で処理の意味を示すというルールを一貫することで可読性とコンパイル速度を向上させる狙いがあります。
とはいえ式の実行は高頻度で行われるため、なるべくタイプ数が少なくなるように2文字に抑えました。
7excode文
excode 文字列の値
8include文
include ファイル名の一部
9ret文
ret
ret 戻り値
- 戻り値の型を指定した関数でret文を使わずに関数を抜けた場合は、戻り値には型のデフォルト値が返る。
設計の理由
多くの言語では「return」ですが、x86アセンブリでは省略形の「ret」が使われ、短いほうを採用しました。
10skip文
skip ブロックの識別子
- 指定した識別子の、forブロック、whileブロックのループを1回スキップする。
- ブロックのループをスキップするとは、そのブロックの「end」の直前にジャンプすることである。
設計の理由
多くの言語では「continue」ですが、長く入力が大変なため「skip」に決定しました。 多くの言語のドキュメントのcontinueの説明に「ループ内の残りの処理をskipする」と書かれているため、「skip」の語のほうが直感的ではないかと思います。
11throw文
throw 例外コード
設計の理由
多くの言語では例外クラスをユーザ側で派生させることで高度な例外処理が行えるようになっていますが、逆に煩雑になり適切に活用されないことが多いため、実用的に扱いやすい「例外コード」だけに絞ることにしました。
12var文
13blockブロック
block
処理
end block
block ブロック名
処理
end block
14classブロック
15enumブロック
16forブロック
for(初期値, 終値)
処理
end for
for ブロック名(初期値, 終値)
処理
end for
for(初期値, 終値, 増減値)
処理
end for
- 初期値、終値、増減値は共にintでなければならない。
- 増減値は、コンパイル時に定数に確定できる、0以外の値でなければならない。
- 数え上げるカウント値は、ブロック名をint型変数として参照することで取得できる。
- ループを繰り返す条件は、「増減値>0」の場合は「カウント値<=終値」、「増減値<0」の場合は「カウント値>=終値」となる。
- 初期値、終値、増減値で指定した式は、forブロックに突入する直前で評価され、ループを繰り返す間に再評価されることはない。
設計の理由
多くの言語のforでは、初期値、終値、増減値のそれぞれで変数を指定する必要があり、間違った変数を指定するとバグの元になっていたため、Kuinではより数え上げに特化させてシンプルな設計にしました。
このため他の言語のように「2倍ずつ増加させる」などの処理が行えなくなっていますが、そのような複雑な処理はwhileを使うべきだと考えます。
17funcブロック
18ifブロック
if(条件)
処理
end if
if ブロック名(条件)
処理
end if
if(条件1)
処理
elif(条件2)
処理
elif(条件3)
処理
else
処理
end if
- 条件はboolでなければならない。
- 条件の式を順番に評価していき、条件が真になった箇所があれば中身を実行してブロックを抜ける。
- どの条件も真にならなかった場合は、else節の中身が実行される。 このときelse節がなければ何もせずにブロックを抜ける。
- 条件がコンパイル時に定数に確定できる値になっているために、常に実行される処理(if・elif・elseの中身)が定まる場合、ifブロックはblockブロックに置換され、実行されない処理はコンパイル時に削除される。
設計の理由
elifは、Pythonなどの一部の言語で用いられている、いわゆる「else if」の略です。
19switchブロック
switch(比較する値)
case 値1
処理
case 値2
処理
end switch
switch ブロック名(比較する値)
case 値1
処理
case 値2
処理
end switch
switch(比較する値)
case 値1, 値2
処理
case 値3の下限 to 値3の上限
処理
end switch
switch(比較する値)
case 値1
処理
case 値2
処理
default
処理
end switch
- 値は大小比較可能な型でなければならない。
- case節は1つ以上存在しなければならない。
- 比較する値と一致するcaseがあるかどうかを調べ、一致したcaseがあれば中身を実行してブロックを抜ける。
- 複数のcaseと一致する場合、先に書かれたcaseが採用される。
- どのcaseとも一致しなかった場合は、default節の中身が実行される。 このときdefault節がなければ何もせずにブロックを抜ける。
- ブロック名を変数のように参照すると、「比較する値」がその型で返る。
設計の理由
C言語などでは、caseの最後でbreakを行わないと次のcaseに突入してしまいますが、次のcaseに突入したいケースは少なくバグの元になりやすいため、Kuinではbreakが無くても自動的にブロックを抜けるようにしました。
その代わりに複数の値に対して同じ処理が行えるよう、case節の条件の書き方を充実させています。
20tryブロック
try
処理
catch
処理
end try
try ブロック名
処理
catch
処理
end try
try
処理
catch 例外コード1, 例外コード2
処理
catch 例外コード下限 to 例外コード上限
処理
end try
try
処理
finally
処理
end try
try
処理
catch
処理
finally
処理
end try
- 少なくともcatch節とfinally節のどちらかは存在しなければならない。
- 発生した例外の例外コードと一致するcatchがあるかどうかを調べ、一致したcatchがあれば中身を実行してブロックを抜ける。
- 複数のcatchと一致する場合、先に書かれたcatchが採用される。
- finally節は、catch節の処理を実行したかどうかにかかわらず、ブロックを抜ける直前で必ず実行される。
- 例外が発生したときにどのcatch節の例外コードにも該当しなかった場合、ブロックを抜けた直後にその例外が再発する。
- finally節内でret、break、skipなどを使って自身のtryブロックを抜けてはならない。 発生していた例外が再発せずに抜けて処理が続行されるため。
- ブロック名を変数として参照すると、例外コードがintで返る。
21whileブロック
while(条件)
処理
end while
while ブロック名(条件)
処理
end while
while(条件, skip)
処理
end while
設計の理由
この「skip」は、C言語などの「do-while」に相当します。