Home English

Kuina-chan

くいなちゃんAug 22, 2017


プログラミング言語Kuin」の文とブロックについてです。

Kuinの文とブロック

Kuinで関数の中に書くことができる文とブロックは、概ね文とブロックの構造をしています。
文とブロック

 文の名前

 ブロック名 識別子()
     ブロックの中身
 end ブロック名

例えば変数定義と関数定義のように、変数定義は文、関数定義はブロックの構造になっています。
var n: int
  
func f(x: float)
  var y: float
end func
変数定義と関数定義
文は1行で書かれ、ブロックは複数行に渡って書かれるという違いがあります。 ブロックの中にはさらに文やブロックが入ります。
Kuinにおける文とブロックはKuinの文とブロックの通りです。
Kuinの文とブロック
名前 分類 説明
var 変数定義
const 定数定義
alias 型の別名定義
do 式の実行
ret 関数を抜ける
break ブロックを抜ける
skip ループを1回飛ばす
throw 例外の発生
assert アサーション
func ブロック 関数定義
enum ブロック 列挙型定義
class ブロック クラス定義
block ブロック 基本ブロック
ifdef ブロック 静的分岐ブロック
if ブロック 条件分岐
switch ブロック 値による分岐
while ブロック 条件ループ
for ブロック 回数ループ
try ブロック 例外処理
それぞれの文とブロックについて、以下で詳しく説明します。
設計の理由
 ブロック終端の「end ブロック名」でブロック名を指定させている理由は、C言語の「}」やPascalの「end」などのブロック終端記号が並んだときにどのブロックに対応するものかが解りにくくなるという可読性上の理由です。
 コンパイル時の型チェックと同様に、ユーザが意図したコードになっているかをなるべくコンパイラがチェックしたほうがバグが減らせるため、多少冗長になってもブロック名を指定させて、コンパイル時に対応関係をチェックするようにしました。

var文

「var文」は変数を定義します。 詳しくは、変数と関数を参照してください。

const文

「const文」は定数を定義します。 定数とは、値を書き換えることができない変数です。 定義の方法は変数と同様です(const文の構文)。
const文の構文

 const 定数名: 型名 ::

「値」は省略することができません。
const文の仕様はconst文の仕様の通りです。
const文の仕様

alias文

「alias文」は既存の型に別名を付けて新しい型を定義します(alias文の構文)。
alias文の構文

 alias 新しい型名: 既存の型名

do文

「do文」は式を実行する文です(do文の構文)。
do文の構文

 do

do文の仕様はdo文の仕様の通りです。
  • 最後に評価される演算は副作用がなければならない。
do文の仕様
設計の理由
 単なる式の実行に「do」という構文を必要とする理由は、必ず行頭で処理の意味を示すというルールを一貫することで可読性とコンパイル速度を向上させる狙いがあります。
 とはいえ式の実行は高頻度で行われるため、なるべくタイプ数が少なくなるように2文字に抑えました。

ret文

「ret文」は関数を抜ける文です(ret文の構文)。
ret文の構文

 ret

 ret 戻り値

ret文の仕様はret文の仕様の通りです。
  • 戻り値の型を指定した関数では戻り値を返さなければならず、戻り値の型を指定しなかった関数では戻り値を返してはならない。
  • 戻り値の型を指定した関数でret文を使わずに関数を抜けた場合は、戻り値には型のデフォルト値が返る。
ret文の仕様
設計の理由
 多くの言語では「return」ですが、x86アセンブリでは省略形の「ret」が使われるため、短いほうを採用しました。

break文

「break文」はブロックを抜ける文です(break文の構文)。
break文の構文

 break ブロックの識別子

break文の仕様はbreak文の仕様の通りです。
  • 指定した識別子の、blockブロック、ifdefブロック、ifブロック、switchブロック、whileブロック、forブロック、foreachブロック、tryブロックを抜ける。
  • ブロックを抜けるとは、そのブロックの「end」の直後にジャンプすることである。
break文の仕様
設計の理由
 多くの言語では直近のブロックしか抜けることができないため、多重ループを抜ける場合にはフラグの変数を追加するなどの回りくどい方法を行う必要がありました。 そこでKuinでは抜けるブロックの識別子が指定できるようにしました。
 またKuinではifブロックを含む多くのブロックがbreak文で抜けられるため、抜けるブロックを混乱しないように識別子は省略できないようにしました。

skip文

「skip文」はループを1回スキップする文です(skip文の構文)。
skip文の構文

 skip ブロックの識別子

skip文の仕様はskip文の仕様の通りです。
  • 指定した識別子の、whileブロック、forブロック、foreachブロックのループを1回スキップする。
  • ブロックのループをスキップするとは、そのブロックの「end」の直前にジャンプすることである。
skip文の仕様
設計の理由
 多くの言語では「continue」ですが、長く入力が大変なため「skip」に決定しました。 多くの言語のドキュメントのcontinueの説明に「ループ内の残りの処理をskipする」と書かれているため、「skip」の語のほうが直感的ではないかと思います。

throw文

「throw文」は例外を発生させる文です(throw文の構文)。
throw文の構文

 throw 例外コード

 throw 例外コード, 例外メッセージ

throw文で発生させる例外には、例外メッセージを含めることができますが、省略することもできます。
throw文の仕様はthrow文の仕様の通りです。
  • 例外メッセージを省略した場合には、例外メッセージにnullが代入される。
throw文の仕様
例外が発生するとその瞬間から関数を次々と抜けてアプリは終了しますが、後述のtryブロックを使うと途中で発生した例外を捕まえて処理を続行することができます。 エラーが起こった場所で例外を発生させ、エラーを処理したいところでtryブロックを使うという流れで例外は活用されます。
設計の理由
 多くの言語では例外クラスをユーザ側で派生させることで高度な例外処理が行えるようになっていますが、逆に煩雑になり適切に活用されないことが多いため、実用的に扱いやすい「例外コード」と「例外メッセージ」に絞ることにしました。

assert文

「assert文」は条件を満たさなかった場合、デバッグ実行時に例外を発生させる文です(assert文の構文)。
assert文の構文

 assert 条件式

満たすべき条件を書くことで、プログラムの信頼性を高めること目的です。
assert文の仕様はassert文の仕様の通りです。
  • リリースビルドではassert文は削除されるため実行時に処理負荷はなくなります。
assert文の仕様

funcブロック

「funcブロック」は関数を定義します。 詳しくは、変数と関数を参照してください。

enumブロック

「enumブロック」は列挙型を定義します。 詳しくは、列挙型を参照してください。

classブロック

「classブロック」はクラスを定義します。 詳しくは、クラスを参照してください。

blockブロック

「blockブロック」は何もしないブロックです(blockブロックの構文)。
blockブロックの構文

 block
     処理
 end block

 block ブロック名
     処理
 end block

スコープを分けたり、breakで抜ける用途で使われます。

ifdefブロック

「ifdefブロック」は指定したビルドモードでのみ有効化されるブロックです(ifdefブロックの構文)。
ifdefブロックの構文

 ifdef(ビルドモード)
     処理
 end ifdef

 ifdef ブロック名(ビルドモード)
     処理
 end ifdef

ifdefブロックの仕様はifdefブロックの仕様の通りです。
  • ビルドモードに「dbg」を記述するとリリースビルド時に削除される。
  • ビルドモードに「rls」を記述するとデバッグビルド時に削除される。
ifdefブロックの仕様

ifブロック

「ifブロック」は条件によって処理を分岐させるブロックです(ifブロックの構文)。
ifブロックの構文

 if(条件)
     処理
 end if

 if ブロック名(条件)
     処理
 end if

 if(条件1)
     処理
 elif(条件2)
     処理
 elif(条件3)
     処理
 else
     処理
 end if

ifブロックでは、複数のelif節を連ねたり、最後にelse節を書くこともできますが、いずれも省略できます。
ifブロックの仕様はifブロックの仕様の通りです。
  • 条件の式を順番に評価していき、条件が真になった箇所があれば中身を実行してブロックを抜ける。
  • どの条件も真にならなかった場合は、else節の中身が実行される。 このときelse節がなければ何もせずにブロックを抜ける。
ifブロックの仕様
設計の理由
 elifはPythonなどの一部の言語で用いられている、いわゆる「else if」の略です。

switchブロック

「switchブロック」は値によって処理を分岐させるブロックです(switchブロックの構文)。
switchブロックの構文

 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

switchブロックでは、複数のcase節を連ねたり、最後にdefault節を書くこともできます。 default節は省略できます。
case節の値は「,」で区切って複数指定したり、「a to b」と書くことで「a以上b以下」という範囲を指定することもできます。
switchブロックの仕様はswitchブロックの仕様の通りです。
  • case節は1つ以上存在しなければならない。
  • 比較する値と一致する値があるかどうかを順番に調べていき、一致した箇所があれば中身を実行してブロックを抜ける。
  • どの値とも一致しなかった場合は、default節の中身が実行される。 このときdefault節がなければ何もせずにブロックを抜ける。
switchブロックの仕様
設計の理由
 C言語などでは、caseの最後でbreakを行わないと次のcaseに突入してしまいますが、次のcaseに突入したいケースは少なくバグの元になりやすいため、Kuinではbreakが無くても自動的にブロックを抜けるようにしました。
 その代わりに複数の値に対して同じ処理が行えるよう、case節の条件の書き方を充実させています。

whileブロック

「whileブロック」は条件を満たす限りループし続けるブロックです(whileブロックの構文)。
whileブロックの構文

 while(条件)
     処理
 end while

 while ブロック名(条件)
     処理
 end while

 while(条件, skip)
     処理
 end while

skipを指定すると、最初の条件判断をスキップし、必ず1回は処理が行われるようになります。
設計の理由
 この「skip」は、C言語などの「do-while」に相当します。

forブロック

「forブロック」は数え上げながらループするブロックです(forブロックの構文)。
forブロックの構文

 for(初期値, 終値)
     処理
 end for

 for ブロック名(初期値, 終値)
     処理
 end for

 for(初期値, 終値, 増減値)
     処理
 end for

forブロックでは、初期値から終値まで増減値ずつ増減しながら繰り返します。 増減値は省略すると「1」と解釈されます。
forブロックの仕様はforブロックの仕様の通りです。
  • 初期値、終値、増減値は共にintでなければならない。
  • 増減値は、コンパイル時に定数に確定できる、0以外の値でなければならない。
  • 数え上げるカウント値は、ブロック名をint型変数のように参照することで取得できる。
  • ループを繰り返す条件は、「増減値>0」の場合は「カウント値<=終値」、「増減値<0」の場合は「カウント値>=終値」となる。
  • 初期値、終値、増減値で指定した式は、forブロックに突入する直前で評価され、ループを繰り返す間に再評価されることはない。
forブロックの仕様
設計の理由
 多くの言語のforでは、初期値、終値、カウント値のそれぞれで変数を指定する必要があり、間違った変数を指定するとバグの元になっていたため、Kuinではより数え上げに特化させてシンプルな設計にしました。
 このため他の言語のように「2倍ずつ増加させる」などの処理が行えなくなっていますが、そのような複雑な処理はwhileを使うべきだと考えます。

tryブロック

「tryブロック」は発生した例外を処理するブロックです(tryブロックの構文)。
tryブロックの構文

 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

try節内で例外が発生すると、該当するcatch節にジャンプして処理が行われます。 また、例外が発生しても発生しなくてもfinally節は必ず実行されます。
例外が発生すると次々と関数を抜けていきますが、catch節を使うことで例外を捕まえることができ、finally節を使うことでリソース解放などの確実に行いたい処理を行っておくことができます。
catch節の値は「,」で区切って複数指定したり、「a to b」と書くことで「a以上b以下」という範囲を指定したり、省略することもできます。
最後にfinally節を書くこともできますが、省略できます。
tryブロックの仕様はtryブロックの仕様の通りです。
  • 少なくともcatch節とfinally節のどちらかは存在しなければならない。
  • 発生した例外の例外コードと一致するcatch節があるかどうかを順番に調べていき、一致した箇所があれば中身を実行してブロックを抜ける。
  • finally節は、catch節の処理を実行したかどうかにかかわらず、ブロックを抜ける直前で必ず実行される。
  • 例外が発生したときにどのcatch節の例外コードにも該当しなかった場合、ブロックを抜けた直後にその例外が再発する。
  • finally節内でret、break、skipなどを使って自身のtryブロックを抜けることは、発生していた例外が再発せずに抜けて処理が続行されるため、行うべきではない。
tryブロックの仕様
1503413331ja