2009年9月3日木曜日

Flash Lite 1.1 で関数

言語で関数を定義することはできないけれど
通常は再生されないフレームにアクションを書いて
call(フレーム名) とする方法が使われる。

しかし、これは関数と言うよりはサブルーチンだ。
普通は再帰呼び出しすることはできない。

「それじゃ、引数や返り値の受け渡しのためにスタックを実装すれば、関数になるのでは?」

と思って作ってみた。

いろいろな実装方法が考えられるけれど、とりあえず次のようなルールとする。
  • 関数への引数は、関数を呼び出す側でスタックに積む。
  • 関数はスタックを参照して引数を得る。
  • 関数は返り値をスタックに積む。
  • 関数呼び出しの後に引数と返り値をスタックから取り除くのは、関数を呼び出す側の責任。

ルートムービークリップのフレーム1のアクション
sp = -1; // スタックポインタの初期化

// 引数をスタックに積む
++sp;
eval( "s" add sp ) = 12;

call ( "fact" ); // 関数呼び出し

// 答えをスタックから取り除く
r = eval ( "s" add sp );
--sp;

trace ( r ); // 確認

stop();

ルートムービークリップのフレーム2のアクション
// 階乗を計算する関数
n = eval ( "s" add sp );
if ( n == 0 ) {
eval ( "s" add sp ) = 1; // 引数をスタックから取り除き、答えをスタックに積む。つまりspは変化しない。
} else {
// 引数をスタックに積む
++sp;
eval ( "s" add sp ) = n - 1;
call ( "fact" );
r = eval ( "s" add sp ); // 関数の答えを取得する。
--sp; // スタックポインタを戻す
n = eval ( "s" add sp ); // n は再帰呼び出しで変化してるので復帰させる。
eval ( "s" add sp ) = r * n; // 引数をスタックから取り除き、答えをスタックに積む。つまりspは変化しない。
}

最後にルートムービークリップのフレーム2に名前"fact"をつけてプレビュー。

479001600

12!(12の階乗)を計算できた。
関数できた。
・・・かなり面倒だな。

0 件のコメント:

コメントを投稿