[sample]$ ./hello
こんにちは、Mindです。
コンパイルの概念
解説が前後してしまいますが、ここで Mind で言うところの「コンパイル」の概念とその内容について詳しく説明します。
コンパイルとは
「コンパイル」とは、日本語で記述されたプログラム(中身はテキストファイル)をコンピュータが実行可能な機械語に翻訳する作業を指します。
翻訳元となるプログラムを「ソースプログラム」または「ソースコード」と言い、翻訳結果の機械語を「オブジェクトプログラム」または「オブジェクトコード」と言います。
ソースプログラム
- 翻訳前の日本語の文章
- ファイル拡張子は .src を用いる。ファイルの状態のものを特に「ソースファイル」と呼ぶ
- 文字コードの集まりなので、ソースファイルは目で見ることができる
オブジェクトプログラム
- 翻訳後の機械語が集まったもの。(コンピュータが実行可能な形態である)
- ファイルの拡張子は .exe(Linuxでは拡張子なし) と .mco を用いる。ファイルの状態のものを特に「オブジェクトファイル」と呼ぶ
- 1と0のランダムな集合なので、人が見て読める形にはなっていない
翻訳の方法
翻訳を行なう為には辞書が必要です。ソースコードに記述されている単語が何を表しているのかを認識するためです。Mindシステムに付属するファイルの中に(特に lib¥ 内) .sym という拡張子のファイルが幾つか入っていたはずです。これが辞書に相当するファイルです。
Mindでは次のような方法をとっています。
- コンパイラ自体としては少ない語彙しか持たない
- その代わり, 新しい単語を簡単に追加できる機構を用意する
- 次のコンパイル時には、以前のコンパイルで増殖した辞書の続きを使える
この考え方は、人間の成長の仕組みと似ています。産まれたばかりの赤ちゃんは殆ど知識を持っていませんが、大人が教育することでどんどん知識を身に付けて成長してゆきます。
Mindのプログラムミング
プログラマはコンピュータ(Mind)に新しい単語を覚えさせます。その覚えさせ方は「○○とは・・・・である」という体裁をとります。新しい単語を、既に知っている単語の集まりで判り易く説明するのです。
Mindでプログラムを記述することは、新しい語彙をコンピュータに教えることにほかなりません。その語彙の数だけコンピュータは利口になってゆきます。Mindは人間で言えば義務教育終了のレベルでユーザに届けられます。ユーザ側ではさらに独自の業務知識を覚え込ませてから実社会で使うものであると思って下さい。
ライブラリとは
我々は「プログラム」という言葉から、それ単独で何かの処理を行なうことができる独立した能力をイメージしがちです。しかし、先に述べたように、Mindではコンピュータに知識を与えることがプログラミングですから、それが完結したものでなく、ある業務の為の基礎知識というものも考えられます。
基礎知識ですから, 直ちにそれだけで特定の仕事ができるわけではありません。これらを「ライブラリ」と名付けることにします。ライブラリは何種類か付属していますが、たとえば、 lib¥ ディレクトリにある file.mco(sym) などはそれに相当します。
ライブラリは成長途中のある時点の知識であると言えます。ライブラリの上にまたライブラリをかぶせる(さらに知識を与える)というような階層構造になっています。
ライブラリも通常のプログラム(実行可能なもの)も、みかけは同じ形をしています。ソースプログラムの最後に「メイン」という単語が定義されているものが実行可能なもの(.exeファイルが付く)で、「メイン」が無いものがライブラリ(.exeファイルが付かない)であると理解してください。
プログラムの履歴
Mindで作成されたプログラムは、メインプログラム/ライブラリを問わず、 すべてに履歴書のようなものが付けられています(拡張子 .sym のファイルです)。この履歴書はMindの標準ツール mhist を実行すると見ることができます。
試しに、標準ライブラリの一つである file の履歴を見てみましょう。コマンドラインで次の操作を行ってみてください。
C:¥pmind¥sample>mhist file
"C:¥pmind¥lib¥file"の履歴 (対応するランタイム=mrunt010)
+------+----------------+----------------+-----------+----------+-----------+
|module|filename |compile date |total words|total code| total data|
+------+----------------+----------------+-----------+----------+-----------+
| 0|yoyakugoG |2016 12/ 2 16:49| 221| 0| 0|
| 1|asmword |2017 2/ 3 17:15| 621| 128| 0|
| 2|console |2017 2/ 3 17:15| 531| 11,424| 21,804|
| 3|file |2017 2/ 4 18:12| 878| 34,848| 615,388|
+------+----------------+----------------+-----------+----------+-----------+
Next code location=00008820 Next data location=000963DC
上記ではライブラリ file の存在場所を指定していませんが、mhistは環境変数から標準ライブラリの lib¥ のパスを知り、そこにある fileというライブラリの情報を表示しています。もちろん明に存在パスを指定しても構いません。この位置なら、mhist ..¥lib¥file あるいは mhist ../lib/fileとなります。
上図で、情報の1行目にあるyoyakugoG というモジュール0が新生児の知識に相当します。この行の「total words」という項目に注目してください。日本語に直せば「総単語数」となりますが、いわば語彙数に相当するものです。最初は220程度の語彙しか持ちませんが以降、ライブラリのモジュール番号(ライブラリのレベル)が1〜3に成長するに従って知識が増大してゆくのを見ることができます。
リンク
「リンク」はソフトウェア用語で言えば、別々のプログラムモジュールをつなげることの意味として使われていますが、それらが並列的に接続されるイメージで使われることが多いので、誤解の無いようにここで補足しておきます。
Mindでは、ある下位ライブラリに接続して新しいプログラムをコンパイルすること(関係性)をリンクと呼んでいます。別の見方で言えば、ある下位ライブラリの知識にかぶせて次のライブラリまたはメインプログラムの知識を与えることを指します。このリンクは
直列的に行なわれます。
┌───────────────┐
│ │
│ レベル2の知識 │
┌─→ (file) |知識の合計はL0+L1+L2
リ│ │ │
ン| |┌─────────────┐|
ク| ││ ││
└─── ││
││ レベル1の知識 ||知識の合計はL0+L1
┌──→ (console) ||
リ| ││ ││
ン| |│┌───────────┐|│
ク| ||│ ||│
└──── ||│
||│ レベル0の知識 |||知識の合計はL0
||│ (yoyakugo)|||
||│ ||│
||└───────────┘||
││ ││
|└─────────────┘│
│ │
└───────────────┘
一般的なアセンブラやコンパイラでいう明な「リンク」というフェーズ(実際、他の言語では「リンカー」というツールが存在することが多い)は Mindには存在しません。リンクはあくまでコンパイル作業の一つであり、コンパイルと同時に内部で自動的に行なわれます。従って Mindでのリンクという言葉は、リンクという作業段階を指すのではなく、モジュールの結合関係を指す目的に使われます。つまり、「・・にリンクして・・をコンパイルして下さい」というように使います。
単語の習得について
先の「プログラムの履歴」のセクションにもありましたが、Mindの標準的なライブラリであるfileモジュールで約800程の単語が入っています。
「800もの単語を覚えないとプログラムが書けないのか!」と思われるかも知れませんが、この点は心配ありません。この全てを知っていないとプログラムが書けないわけではないからです。とりあえずはこれから作るプログラムに関係しそうな語から覚えていけば良いのです。
たとえばですが、何万語と言われる日本語の語彙に比べれば、小学生の知っている語彙数など本当に僅かなものですが、彼等は日常会話をこなすことができます。−−−それに、あなたがこれから覚えなくてはならない単語というのは日本語なのですから−−−。
コンパイラが入出力するファイル
冒頭の「簡単なプログラムを実行してみる」において、hello.src というMindのソースプログラムをコンパイルしました。このとき、次のようなファイル群が入出力されています。
┌─────────┐ 実行ファイルはライブラリを
│ライブラリ │ 作る際は出力されません
│ file.mco │ ↓
│ file.sym │ ┌─────────┐
└─────────┘ │実行ファイル │
| ┌→ │ hello(.exe) │
入力| │ └─────────┘
┌─────────┐ | │ ┌─────────┐
│ソースファイル │入力 ↓ 出力 │Mコードファイル │
│ hello.src │─→[Mindコンパイラ]─┼→ │ hello.mco │
│ │ │ └─────────┘
└─────────┘ │ ┌─────────┐
│ │シンボルファイル │
├→ │ hello.sym │
│ └─────────┘
│ ┌─────────┐
│ │ヒストリファイル │
├→ │ hello.his │
│ └─────────┘
│ ┌ ─ ─ ─ ─ ┐
│ インフォメーション
└→ │ hello.inf │
└ ─ ─ ─ ─ ┘
↑
文法エラーがあった時のみ出力
メインを含み、それ自体で起動するプログラムでは、実際には .exe/.mco ファイルだけが得られれば良いのですが、mhistを使って履歴を見たり、mmakeを使って自動再コンパイルをおこなうといった目的のため、このようなたくさんのファイルを生成しています。
以下に個々のファイルについて解説します。
■exeファイル(実行ファイル)(Linuxでは拡張子なし)
「メイン」という単語を含むプログラムは単独で起動し実行することができますが、そのようなプログラムをコンパイルした場合に生成されます。メインの無い(=ライブラリとなる)プログラムのコンパイルでは出力されません。
一見すると、この実行ファイルがプログラム本体に見えますが、実はこれは本体プログラムを
キックするためのプログラムに過ぎません。本体プログラムのサイズにかかわらず、このファイルは常に固定サイズの、しかも小さなものです。
■mcoファイル(Mコードファイル)
実質的なプログラムの本体(オブジェクトコード)はこれです。Mindは Version 7 以降、コンパイラはMコードと呼ぶ中間コードを生成するようになりました。Mindのランタイム(mruntXXX.exeというファイル)がこれを解読・実行します。
これ自身はCPU命令を含まないため直接にはOSから起動することができませんが、代わりにキッカーとなるプログラム(前記のexeファイル)がその仲立ちをするので、最終的に普通にexeファイル形式(Linuxでは拡張子無しの実行ファイル)のプログラムを起動したかのようにふるまいます。
■symファイル(シンボルファイル)
「辞書」に相当します。これまで覚えた単語が全部入っいます。これはテキストファイルではないので目で見ることはできません。
■hisファイル(履歴ファイル)
ヒストリファイルという意味で .his になっています。これにはコンパイル手順の履歴‥‥それまでコンパイルしたすべてのソースファイルの名前やタイムスタンプ、そしてリンクしたライブラリの情報‥‥が記入されています。
これはテキストファイルなので見ることができます。たとえば、たびたび取り上げてきたサンプルプログラム hello.src をコンパイルした時の hisファイルは以下のような内容となります。
c:¥pmind¥sample>type hello.his
..........
hello.src 2004-05-08 18:38.04 file
hello.srcは簡単なプログラムなので履歴も小さいですが、コンパイル単位が何層にもなる大きなアプリケーションをコンパイルする時には、この1行を単位として何行も記入されます。
行内の内訳ですが、まず最初にソースファイル名が記入され、次いでそのファイルが更新された日時、その次に「file」とあるのは、リンク先のライブラリ名です(もし起動オプションもあれば続いて記入されます)。
もう少し大きなプログラムとして、tool¥ ディレクトリにある mmake の履歴ファイルを見てみます。
c:¥pmind¥sample>type ..¥tool¥obj¥mmake.his
..........
mmakeF.src 2017-01-06 13:41.01 ..¥lib¥file2 obj¥mmake
コンパイル convStamp.src 2017-01-06 13:48.58
コンパイル mmakeFsub.src 2017-01-06 13:48.22
上記では3行の情報が記入されています。
最初の行はメインソースとなる mmakeF.src に関するものです。コンパイラ起動時に第3引数でオブジェクトファイルの生成ディレクトリを指定している(obj¥mmake)のも分かります。
2行目には、同ソースファイルから副次的に読み出される(インクルードと呼んでいます)副ソースの1つである convStamp.src の情報が、3行目には同じく副ソースの mmakeFsub.src の情報が記入されています。
自動再コンパイルをおこなうツールである mmake(このプログラム自身ですが)は、このファイルに書かれている情報をもとに再コンパイルをおこないます。
結果的にmmakeの為だけにあるようなファイルですが、開発者が目で見ても有益です。これを読めば、そこまでコンパイルして来たすべてのソースファイルの名前と作られた日時、リンクした先のライブラリ名、そしてコンパイラ起動オプションまで知ることができるからです。
■.mco/.symファイルのペア
これらは, さらに上位のプログラムモジュールをコンパイルする際のリンクに用いられます。ライブラリ的なプログラム(上位のプログラムにリンクされる)の場合は、このペアのファイルは、言わば途中結果のような立場となります。
xxx.mco ──┐
├─→ 上位プログラムのコンパイル時にこれをライブラリ指定する
xxx.sym ──┘
■infファイル(インフォメーションファイル)
開発者向けのメッセージが入ります。通常はコンパイル時に文法エラーがあったとき、そのエラー情報が記入されます。開発者はこのファイル内容を見て、どこに間違いがあったかを知ることができます。
Mindで作ったプログラムを配布するには
Mindで作成したプログラムは簡単に配布することができます。配布されたプログラムを使う側でMindの開発システムが存在する必要はありません。
少し前の「簡単なプログラムを実行してみる」のセクションの中で、サンプルの hello.src をコンパイルし、さらに
Mindコンパイラが生成したオブジェクトファイルを確認する場面がありました。まずそちらを再度、確認願います。
hello.src を例にとれば、以下のファイルが実行に必要なものです。
hello.exe ←これが起動すべきプログラム(しかし実際はキッカーに過ぎない)
hello.mco ←Mコードファイル(実質的なプログラムの本体はこちら)
mrunt010(.exe) ←Mindのランタイムライブラリ(Linuxは拡張子無し)
↑mrunt010(.exe)は pmind/bin/ 内にあるので手動で複写する
(複数のMindプログラムがあってもmrunt010は1つあれば良い)
Mindのプログラムの実行には上記の3ファイルが必要であり、これをワンセットとして配布してください。ただ、複数のMindプログラムを1つのディレクトリ内に収容する場合、mrunt010(.exe)(Mindのランタイム)は1つあれば可です。
よくある間違いとして、mrunt010 を入れ忘れることがあります。MindシステムをインストールしているPCで、Mindのインストールディレクトリとはまったく別のディレクトリに(あるいは別のドライブに)作成したプログラムの.exeと.mcoの2ファイルだけを置いたとして、その2ファイルだけでも正常に動作します。
この理由は、開発機では pmind¥bin にPATHが通っているため、作成したプログラムを置いたディレクトリに mrunt010 が無くても、 pmind¥bin¥mrunt010 が自動的に起動できるからです。この状態をもって動作確認できたと思い、2ファイルだけを他人に配布しても、もらった側では動かないということになります。
配布とは直接関係がありませんが、少し補足します。
外目には、helloというプログラムの実行ファイルは hello.exe で、その通りなのですが、実際には、 hello.exe は起動されるとすぐ、mrunt010(.exe) を起動し、さらにそれが hello.mco をロードして実行が始まります。ただこの仕組みは外目にはまったく感じず、あくまでhello.exeが動作しているように感じます。
なお、
CGIの場合は必要なファイルが異なります。第7章「サンプルプログラムのコンパイルと実行(CGI編)」の
「Mindランタイムライブラリの複写」 のセクションをお読みください。