Home English

Kuina-chan

くいなちゃんOct 17, 2017


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

Kuinの文とブロック

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

 文の名前 文の中身

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

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

alias文

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

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

alias文は、関数の外のグローバルな領域や、クラス内にも記述できます。

assert文

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

 assert 条件式

満たすべき条件を書くことで、プログラムの信頼性を高めること目的です。 条件はboolで書きます。
assert文は、リリースビルド時には存在しないものとして読み飛ばされるため、実行時の処理負荷はありません。

break文

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

 break ブロックの識別子

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

const文

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

 const 定数名: 型名 ::

const文は、関数の外のグローバルな領域や、クラス内にも記述できます。
const文の仕様はconst文の仕様の通りです。
const文の仕様

do文

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

 do

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

ret文

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

 ret

 ret 戻り値

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

skip文

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

 skip ブロックの識別子

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

throw文

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

 throw 例外コード

例外コードはintで指定します。 具体的な値は、Kuin例外コードを参照してください。
例外が発生するとその瞬間から関数を次々と抜けてアプリは終了しますが、tryブロックを使うと途中で発生した例外を捕まえて処理を続行することができます。 エラーが起こった場所で例外を発生させ、エラーを処理したいところでtryブロックを使います。
設計の理由
 多くの言語では例外クラスをユーザ側で派生させることで高度な例外処理が行えるようになっていますが、逆に煩雑になり適切に活用されないことが多いため、実用的に扱いやすい「例外コード」だけに絞ることにしました。

var文

「var文」は変数を定義します。 詳しくは、変数と関数を参照してください。
var文は、関数の外のグローバルな領域や、クラス内にも記述できます。

blockブロック

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

 block
     処理
 end block

 block ブロック名
     処理
 end block

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

classブロック

「classブロック」はクラスを定義します。 詳しくは、クラスを参照してください。
classブロックは、関数の外のグローバルな領域や、クラス内にも記述できます。

enumブロック

「enumブロック」は列挙型を定義します。 詳しくは、列挙型を参照してください。
enumブロックは、関数の外のグローバルな領域や、クラス内にも記述できます。

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を使うべきだと考えます。

funcブロック

「funcブロック」は関数を定義します。 詳しくは、変数と関数を参照してください。
funcブロックは、関数の外のグローバルな領域や、クラス内にも記述できます。

ifブロック

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

 if(条件)
     処理
 end if

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

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

ifブロックでは、複数のelif節を連ねたり、最後にelse節を書くこともできますが、いずれも省略できます。
ifブロックの仕様はifブロックの仕様の通りです。
  • 条件はboolでなければならない。
  • 条件の式を順番に評価していき、条件が真になった箇所があれば中身を実行してブロックを抜ける。
  • どの条件も真にならなかった場合は、else節の中身が実行される。 このときelse節がなければ何もせずにブロックを抜ける。
  • 条件がコンパイル時に定数に確定できる値になっているために、常に実行される処理(if・elif・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節の条件の書き方を充実させています。

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ブロックを抜けることは、発生していた例外が再発せずに抜けて処理が続行されるため、行うべきではない。
  • ブロック名を変数のように参照すると、例外コードがintで返る。
tryブロックの仕様

whileブロック

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

 while(条件)
     処理
 end while

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

 while(条件, skip)
     処理
 end while

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