MikoScript 言語仕様
簡単なプログラムの作成と実行
本章では、3例の簡単なプログラムの作成と実行を通じて、本言語の初歩的な使い方を
なるべく平易に説明します。そのため、上中級者の方にとっては、若干もどかしい説明に
なっているところもあります。
なお、本章では、DOS/コマンドプロンプトから、コンソール版の MikoScript を実行
する場合について説明しています。アプリケーション組み込みの MikoScript を実行する
場合は、ここで説明しているやり方とは、異なります。
●セットアップ
MikoScript を Windows 上で使えるようにするには、まず、本スクリプト言語のイン
タプリタ等をダウンロードしてインストールする必要があります。ダウンロードは、本
サイトのホームページからできます。ダウンロードしたアーカイブファイルを解凍する
と、その中に ReadMe.txt というファイルがあります。インストールの仕方は、そこに
書いてありますが、ここでも、記しておきます。
本スクリプト言語のインタプリタは、miko.exe という名前の実行形式のファイルです。
これは、前述のアーカイブファイルに入っています。miko.exe は、コンソールアプリケ
ーションなので、通常、DOS/コマンドプロンプトから起動します。そのため、miko.exe
を入れるディレクトリーに、実行パスが通っている必要があります。簡単には、適当な
ディレクトリーに、miko.exe を入れて、そこにカレントパスを移行して実行するか、ま
たは、既にパスの通った適当なディレクトリーに、miko.exe を入れておいて実行するか
です。後者の場合、カレントパスがどこであっても、実行できるので便利です。一方、
本格的に、MikoScript を使う場合は、本インタプリタ専用のディレクトリーを設けて、
その中に miko.exe を入れておきます。また、その中には、共通の Include や Library
のディレクトリーを作成しておきます。こうすれば、本インタプリタのいろいろな機能を
フルに活用できるようになります。その場合、その専用ディレクトリーに、実行パスを通
しておく必要があります。セットアップに関してはこの程度です。これ以上の特別な操作
は必要ありません。
●簡単なプログラム(例1)の作成と実行
それでは、簡単なプログラムを作って動かしてみましょう。まず、ソースプログラム
を作成します。適当なテキストエディタを使って、次の1行だけを打ち込みます。
print "hello, world!";
これは、「hello, world!」という文字列をコンソールにプリントする本スクリプト言語
で書いたプログラムです。この構文の意味は、後で説明します。このテキストを、適当な
ディレクトリー内の hello.mc という名前のファイルに格納します。このファイル名は、
勿論、これに限定されている訳ではなく、任意の名前が使えます。ここでは、とりあえず、
この名前にしています。本スクリプト言語のソースファイルには、慣習上、.mc という
拡張子を使います。これは強制ではないので、これ以外の拡張子を使っても構いません。
ソースプログラムの作成はこれで終りです。テキストエディタは、終了してください。
次に、プログラムの実行です。DOS/コマンドプロンプトを開いて、先程の hello.mc
が格納されているディレクトリーに、カレントパスを移行します。そこで、以下のコマン
ドを実行します。
miko hello.mc
すると、「hello, world!」という文字列がコンソールに表示されます。以上が、プログ
ラムの作成から実行までの基本的な流れです。
この最初の例からも分かるように、本スクリプト言語のプログラムは、ソースファイル
のテキストとして記述します。それを、インタプリタが読み出して、翻訳して実行すると
いうことになります。この翻訳の過程では、コンパイラ言語の場合とは違って、*.obj や
*.exe 等の余分なファイルを生成しません。これがインタプリタの軽快さの1つです。
●簡単なプログラム(例1)の内容の説明
本スクリプト言語のプログラムでは、C言語のような main 関数を定義する必要はあり
ません。ソースプログラムの最初からが、実行文になります。いわば、メイン関数は、暗
黙で、ソースプログラムの最初から始まります。ちなみに、メイン関数以外の通常の関数
は、この暗黙のメイン関数の中で定義できます。
本スクリプト言語のプログラムは、「文」から成ります。「文」は、「実行文」とも
「構文」とも言います。「文」には、演算文、関数コール文、条件分岐文、反復制御文
など、いろいろあります。これらの詳細は、関係各所で述べます。
上例の print ... も「文」です。print 文を実行すると、print の後に続く各項目の
内容がコンソールにプリントされます。上例では、"hello, world!" という文字列が、そ
のプリント対象の項目です。ところで、この文字列内には、改行がありませんが、つまり、
"hello, world!\n" のようにはなっていませんが、本言語の print は、特別な表記がな
ければ、最後に無条件に改行を付加します。なお、この print ... は、あくまでも「文」
であって、関数コールではありません。そのため、各プリント対象項目の並びを、丸括弧
で囲う必要はありません。
一般に、1つの文の表記は、必ずしも1行で書く必要はありません。複数の行になって
も構いません。そのため、文の最後は、通常、セミコロン ; で区切る必要があります。
print 文も例外ではありません。print 文に関しては、「各種組み込み処理」の章で詳し
く説明します。
●簡単なプログラム(例2)の作成と実行
簡単なプログラムをもう1つ作ってみましょう。これは、以下に示すような、身長(cm)
から適性体重(kg)を求めるプログラムです。なお、この計算式は、日本医師会ホームペー
ジを参考にしています。( http://www.med.or.jp/forest/health/eat/11.html )
height = ::gets( "あなたの身長(cm):" );
height = height'int;
weight = height * height * 22.0 / 10000;
print "あなたの適正体重は、" + weight'f(1) + " kg です";
この4行のプログラムのテキストを、前回と同じ要領で、適当なテキストエディタを使っ
て打ち込みます。こんどは、weight.mc という別のテキストファイルに格納します。さて、
このプログラムの実行ですが、要領は前回と同じです。ただ、ファイル名が変わっている
ので、DOS/コマンドプロンプトから打ち込むコマンドは、以下のようになります。
miko weight.mc
これを実行すると、「あなたの身長(cm):」というプロンプトがコンソールに表われます。
ここで、身長を cm 単位で入力すると、それに対応する適正体重が kg 単位で小数点以下
1桁まで表示されます。以下は、身長が 170 cm の場合の実行例です。
あなたの身長(cm):170
あなたの適正体重は、63.6 kg です
●簡単なプログラム(例2)の内容の説明
この例では、height や weight という「変数」が使われています。変数は、データを
格納をする、いわば入れ物です。変数にデータを格納することを、「代入」と言います。
代入は、演算子の = を使って、A = B のように表記します。ここで、= の左辺、つまり
A が「代入先」になり、= の右辺、つまり、B が「代入元」になります。
代入先の変数は、事前に宣言しておく必要はありません。代入時に存在していなければ、
その時点で自動的に生成されます。存在していれば、それが使われます。変数に代入され
るデータには、数値や文字列など、いろいろなデータ型があります。変数は、その生成時
に特定のデータ型に固定されてしまうのではなく、動的にどのようなデータ型でも代入で
きます。これもインタプリタならではの柔軟さの1つです。データ型については、別章で
詳述します。
代入元は、一般に「式」になります。式は、定数、変数、関数コールだけの単項の場合
もあれば、これらが演算子と組み合わされた複合項になる場合もあります。代入元で使わ
れる変数は、それが使われる以前に既に存在している必要があります。もし存在していな
ければ、「例外」が発生します。例外とは簡単に言えばエラーです。例外の詳細は、別章
で述べます。
コンソールから文字列を入力する場合、gets() という組み込みの関数を使います。こ
の関数の引数は、プロンプト文字列になります。上例の場合、"あなたの身長(cm):" と
いうのがプロンプト文字列です。これは今何を入力しようとしているのかを示すのに使い
ます。gets() 関数を実行すると、コンソールから文字列を入力する状態になります。こ
の状態の時に、キーボードから打ち込まれた各文字は、画面上のプロンプト文字列の右側
に表示されていきます。入力すべき文字列が全て打ち込まれた後、最後に Enter キーが
押されると、入力が確定して、コンソールからの文字列入力が終了します。つまり、
gets() 関数から復帰して来ることになります。その時の関数値は、コンソールから入力
された文字列になります。上例の
height = ::gets( "あなたの身長(cm):" );
では、コンソールから入力された文字列が、変数 height に代入されることになります。
gets() 関数の前には :: が付いていますが、さてこれは何でしょう。C++ 言語の経験
者なら推測がつくと思いますが、:: は、対象の名前(上例の場合は gets )の存在場所
をグローバルスコープに限定する前置演算子です。つまり、上例の ::gets は、グローバ
ルスコープ内にある gets という名前を意味します。
グローバルスコープという用語がでてきましたが、これを説明しておきます。そもそも
「スコープ」とは、一般には、活動対象の範囲とかを意味しますが、プログラミング言語
の用語では、名前の通用する範囲を意味します。一方、グローバルとは、一般には、全世
界的とか広域とかを意味しますが、プログラミング言語の世界では、プログラムが動作す
る範囲の全域という意味になります。従って、グローバルスコープとは、名前の通用する
範囲が全域、つまり、プログラムのどこからでも共通に使えるということを意味します。
ところで、グローバルスコープがあるということは、それとは反義のローカルスコープも
あるということが推測できます。その通りですが、ローカルスコープには、いろいろな種
類があります。「スコープ」については、「スコープ」の章で詳しく説明します。
ところで、上例の height や weight には、:: のようなスコープを規定する演算子は
付いていませんが、その場合、これらの変数のスコープは、どうなるのでしょうか。結論
から言えば、それらのスコープは、グローバルスコープではなく、現関数(この場合、暗
黙のメイン関数)内のローカルスコープになります。これに関しては、「スコープ」等の
章で詳しく説明します。
さて、話題を戻します。コンソールから入力された文字列が、変数 height に代入され
たというところです。この代入されたデータは、その時点ではまだあくまでも文字列です。
以降の算術演算で使用するには、この文字列を数値に変換しておく必要があります。それ
を行なうのが、次の行の
height = height'int;
です。ここで、ちょっと見慣れない height'int という表記があります。これは、本言語
が導入した新しい関数コール形式です。この場合、int が関数で、height がその主対象
データ、つまり、第1引数になります。ちなみに、これを一般的な表記にすると、
int( height )
となります。または、オブジェクト指向的な表記にすると、
height.int()
となります。これらの表記を比較すると、本言語の表記では、まず丸括弧が不要なために
簡素になっていることが分かります。この表記には他にも、いろいろなメリットがありま
すが、ここでは話題が逸れてしまうので、その説明は省略することにします。この詳細は、
「関数」の章の「リレー型関数コール形式」の節で述べます。
次に、'int 関数ですが、これは、システム組み込み関数で、対象の文字列を整数値に
変換します。上例の場合、height に格納されている、コンソールから入力された文字列
を、整数値に変換します。従って、
height = height'int;
で、height に cm 単位の身長の整数値が代入されることになります。ここで、ちょっと
注目すべきことがあります。それは、この代入の前後で、変数 height の中身のデータ型
式が、文字列から整数値に変わっているということです。これは大したことではないよう
に思われますが、コンパイラ言語では、プログラムの実行時に変数のデータ型式を変える
ことは通常できません。これができるのは、インタプリタならではのことです。
次に、この身長値から適性体重を求めます。それが、次行の計算式になります。
weight = height * height * 22.0 / 10000;
この計算式では、掛け算を行なう演算子 * と、割り算を行なう演算子 / を使っています。
本言語の演算子は、他にもいろいろありますが、C 言語や C++ 言語の演算子と、機能が
相当する場合は、できるだけ、同じ表記になるようになっています。演算子に関しては、
「演算子」の章で詳しく述べています。
本言語では、数値のデータ型式に、整数型と浮動小数点型があります。これについては、
「基本データ型」の章で詳説します。上例では、現時点での height の中身と 10000 が
整数値で、22.0 が浮動小数点数値になります。整数型式と浮動小数点型式の演算結果は、
浮動小数点型式になります。そのため、変数 weight の中身は、浮動小数点型式の数値に
なります。
この計算式で求まった適正体重は、以下の最後の行でプリントされます。
print "あなたの適正体重は、" + weight'f(1) + " kg です";
ここで、weight'f(1) という表記がありますが、これは、前述の 'int と同じ関数コール
形式で、f が関数、weight がその主対象データ(第1引数)、1 が第2引数になります。
この関数コール形式でも、第2以降の引数がある場合、それらを丸括弧で囲う必要があり
ます。'f 関数は、システム組み込み関数で、対象の数値を文字列に変換します。第2引
数は、小数点以下の桁数を指定します。従って、weight'f(1) は、変数 weight に入って
いる(浮動小数点)数値を小数点以下1桁数で表わす文字列になります。
文字列どうしの連結は、本言語の場合、+ 演算子で行なうことができます。上例の
"あなたの適正体重は、" + weight'f(1) + " kg です"
は、3つの文字列を連結して、1つの文字列にしています。この文字列は、print の対象
になっているので、たとえば、weight'f(1) が "63.6" という文字列なら、
あなたの適正体重は、63.6 kg です
という文字列がコンソールに表示されます。
●簡単なプログラム(例3)の作成と実行
最後に、簡単なプログラムをもう1つ作ってみましょう。これは、100 以下の素数を列
挙するプログラムです。なお、このアルゴリズムは、単純さを優先しているため、最善で
はありません。
Prime[0] = 2; // 最初の素数を配列 Prime に登録
N = 1; // 今までに見つかった素数の個数( 配列 Prime 内の現要素数 )
for( v = 3 ; v <= 100 ; v += 2 ) // 3 から 100 までの奇数を順に調査する
{
for( i = 0 ; i < N ; i++ ) // 今までに見つかった各素数について
{
if( v % Prime[i] == 0 ) // 現調査数値は今までの素数で割り切れる?
goto NEXT; // そうなら素数ではないので次の数値へ
}
// 現調査数値が今までのどの素数でも割り切れない場合
Prime[ N++ ] = v; // 現調査数値を素数として配列 Prime に登録
NEXT: ;
}
// 今までに見つかった全素数をプリントする
for( i = 0 ; i < N ; i++ )
print Prime[i] : " " : -;
print ;
このプログラムを、前回と同じ要領で、適当なテキストエディタを使って打ち込めば、
良いのですが、こんどは、ちょっと長いので、全部打ち込むのは面倒です。そこで、この
プログラムのテキスト部をそのままクリップボードにコピーして、テキストエディタの新
規ファイル上でペーストします。こうすれば、簡単にこのプログラムのテキストが作成で
きます。このテキストを今回は primes.mc というテキストファイルに格納します。さて、
このプログラムの実行ですが、前回と同じ要領で、DOS/コマンドプロンプトから、以下の
コマンドを打ち込みます。
miko primes.mc
これを実行すると、コンソールには以下の素数列が表われます。
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
●簡単なプログラム(例3)の内容の説明
この例では、Prime という「配列」が使われています。この配列は、厳密には、「連想
配列」になります。連想配列では、インデックスを文字列にすることもよくありますが、
ここでは、整数のインデックスになっています。連想配列は、前述の変数と同様に、事前
に宣言しておく必要はありません。存在していない連想配列の要素が代入先になる場合、
その代入時点でその要素が自動的に生成されます。これで自動生成されるのは、あくまで
その要素だけで、未使用の要素が何らかの見込みで勝手に生成されることはありません。
一方、既存の連想配列の要素が代入先になる場合には、それが使われます。また、連想配
列の要素は、変数の場合と同様に、特定のデータ型に固定されてしまうのではなく、どの
ようなデータ型でも代入できます。連想配列については、「連想配列」の章で詳しく説明
します。
コメント(注釈)を、プログラムの随所に入れることができます。本言語のコメントは、
C++ 言語等と同じ表記で、// から改行までと、/* から */ までの間の2種類があります。
コメントは、プログラムの翻訳時には読み飛ばされるので、実行内容には影響しません。
上例では、多数のコメントが書いてあります。
for 文、if 文、goto 文が、この例で初めて登場します。これらは、制御の流れを変え
る構文で、C 言語での機能と基本的に同じです。for 文は、反復制御、if 文は、条件分
岐、goto 文は、ラベルジャンプを行ないます。この詳細は、「制御の流れ(構造化系)」
と「制御の流れ(ジャンプ系)」の章で述べています。
演算子も、以前の例にはないものが使われていますが、どれも、C 言語等ではお馴染み
のものです。演算子に関しては、「演算子」の章で詳しく説明しています。
print 文が、この例でも登場しますが、今までの使い方と若干違います。print 文では、
プリント対象の項目を複数記述できますが、各項目を、コンマ(,)で区切る場合と、コロ
ン(:)で区切る場合があります。コンマで区切った場合、各項目は、その間に、デフォー
ルトの区切り(コンマ+半角空白)が挿入されて、プリントされます。一方、コロンで区
切った場合、各項目は何の区切りもなしに連続してプリントされます。また、最後の項目
が - の場合、改行が付加されずにプリントされます。ちなみに、このような仕様になって
いるのは、print の用途を統計的にみてみると、この方が便利な場合が多いからです。
さて、上例の
print Prime[i] : " " : -;
では、素数値の後に続けて(デフォールトの区切りなしに)、半角空白が1個プリントさ
れます。この時、改行が付加されないので、各素数値が1行内にプリントされることにな
ります。なお、Prime[i] のデータ型は、文字列ではなく整数値ですが、print では、プ
リント対象が数値の場合、所定の書式の文字列に変換してプリントします。最後の
print ;
は、プリント項目がありませんが、改行が付加されるので,結局、この文の意図するとこ
ろは、改行のみをプリントすることです。
以上で、簡単なプログラムを3例示しました。これで、ある程度のプログラムの作成と
実行ができるようになったと思います。以降の章では、さらに高度な機能や便利な使い方
を紹介します。また、説明をもっと詳細かつ厳密にします。