minosys script を作ろう (11)
関数の実装
関数にはパッケージ関数とメンバー関数がありますが、
パッケージ関数の実装から考えてみます。
パッケージにはバイナリパッケージと minosys script パッケージが
定義されているのでした。
minosys.hateblo.jp
両者を統一的に扱うために PackageBase というクラスを導入し、
Ptr<Var> start(const string &fname, vector<Var> args);
という純粋仮想関数を導入します。
バイナリパッケージ(PackageDlopen) ではこの関数の実装は start と
いうシンボルを持つ関数が呼び出されて解決しますが、この関数の
「真の定義」は以下のようになっています。
extern "C" int start(Ptr<Var> *rval, Engine *eng, const char *fname, vector<Ptr<Var> > *parg);
実行環境 eng の元で関数名 fname である関数を引数並び parg で呼び出す
という構造になっています。戻り値は rval に返されます。
(もちろん、同時にパラメータスタックトップにも返すことになっています。)
関数呼び出しに成功した場合は 0 を、失敗した場合は -1 を返すことを
想定しています。(失敗した場合は minosys script では NULL 変数に変換
されます。)
minosys script パッケージ(PackageMinosys)ではスクリプト解析木
top が定義されます。minosys script における start 関数の仕事は以下のように
なります。
- 引数リストから引数マップを作成し、引数スタックに積む
- 3つのスタックのスタックトップの位置を xxxmark 変数に退避する
- top->funcs.find(fname) を実行し、関数名に対応する解析木を取り出す
- 解析木を実行する
- 退避しておいたスタックトップ位置を元に戻し、関数の戻り値を構成する
- 関数呼び出しに失敗した場合は NULL 変数を返す
関数の解釈は
Ptr<Var> callfunc(const string &fname, Content *c);
で行われます。実際はこの関数には制御構造が実装されているのみで、
評価式は
Ptr<Var> evalute(Content *c);
で解釈されます(まだメソッド定義を書いていません...)
ビルトイン関数
4つのビルトイン関数を用意しました。
関数名 | 内容 |
---|---|
type | 変数の型に対応する数値を返します。数値には VT_NULL, VT_INT などが定義されています。 |
convert | 変数の型変換を行います。VT_INT, VT_DNUM, VT_STRING の相互変換が可能です。変換元の変数と変換先の型を指定します。 |
変数値を文字列出力します。引数は不定数とります。 | |
exit | ExitException 例外を投げます。引数はプログラム戻り値です。 |
次回はメンバー関数の発見と実行、パッケージ関数とメンバー関数の微妙な
違いについて考えてみます。