このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

JavaScriptで仮想機械の勉強をしましょう (その3)

JavaScriptで仮想機械の勉強をしましょう (その2)」で定義した命令セットを動くようにしてみました。ただし、NFCALL(ネイティブ関数の呼び出し)はまだやっていません。プログラムの終了命令を忘れていたので追加しました。

  • EXIT -- 正常終了
  • ERROR -- 異常終了

命令コード(OPコード)の定義は次のようになります。

/* == 命令コード一覧 == */

/* 定数の命令 */
var CONST   = 00; // 定数nをスタックに積む

/* 算術演算の命令 */
var ADD     = 10; // 足し算
var SUB     = 11; // 引き算
var MUL     = 12; // 掛け算
var DIV     = 13; // 割り算
var REM     = 15; // 割り算の余り

/* 述語/関係の命令 */
var EQ      = 20; // スタックトップと二番目が等しいかどうか
var LT      = 21; // スタックトップ < 二番目 かどう

/* 論理演算の命令 */
var AND     = 30; // 論理アンド
var OR      = 31; // 論理オア
var NOT     = 32; // 論理ノット

/* 流れ制御の命令 */
var $$$     = 40; // ラベルを付ける
var JMP     = 41; // ラベルの場所にジャンプ
var IFT     = 42; // スタックトップが真だったらラベルの場所にジャンプ
var EXIT    = 44; // プログラムの終了
var ERROR   = 45; // エラーによるプログラムの終了

/* ブロックスコープと変数の命令 */
var BOPEN   = 50; // 新しいブロックを作成 
var BCLOSE  = 51; // 現在のブロックを破棄 
var REF     = 52; // 変数値をスタックに積む
var ASSIGN  = 54; // 変数にスタックトップを代入、スタックトップはそのまま
var ALLOC   = 55; // 変数を確保(値は未定義)

/* スタック操作の命令 */
var DISCARD = 60; // スタックトップを捨てる
var DUP     = 61; // スタックトップをコピー
var XCHG    = 62; // スタックトップと二番目を入れ換える

/* ネイティブ関数呼び出しの命令 */
var NFCALL  = 70; // 名前で示される関数を呼ぶ

この命令セットによって、簡単なプログラムを書いてみました。


// 2 + 3 を計算する。
[
CONST, 2,
CONST, 3,
ADD,
EXIT
],

// x^2 + y^2 を計算する。
[
REF, "x",
DUP,
MUL,
REF, "y",
DUP,
MUL,
ADD,
EXIT
],

// スタックトップの絶対値を求める。
[
DUP,
CONST, 0,
LT,
IFT, "Neg",
EXIT,

$$$, "Neg",
CONST, 0,
XCHG,
SUB,
EXIT
],

// スタックトップの階乗を計算する。
[
DUP,
CONST, 1,
LT,
IFT, "Error",
// 準備
ASSIGN, "k",

// 計算開始
$$$, "Start",
REF, "k",
CONST, 1,
SUB,
DUP,
CONST, 0,
// N, k-1, k-1, 0
EQ,
IFT, "End",
// N, k-1
ASSIGN, "k", // k := k - 1
MUL, // N*(k-1),
JMP, "Start",

$$$, "Error",
ERROR, "NonPositiveArgument",

$$$, "End",
DISCARD,
EXIT
],

// 変数n, m(ただし、n ≦ m)に対して、
// その最大公約数を求める。
[
$$$, "ConfirmArgs",
REF, "m",
REF, "n",
LT,
NOT,
IFT, "Check",
ERROR, "BadArgument",

$$$, "Check",
REF, "n",
CONST, 0,
EQ,
IFT, "End",

$$$, "DoStep",
REF, "m",
REF, "n",
ASSIGN, "x",
REM,
ASSIGN, "n",
DISCARD,
REF, "x",
ASSIGN, "m",
DISCARD,
JMP, "Check",

$$$, "End",
REF, "m",

EXIT
],


次のURL(冒頭にも示した)で、上記のサンプルプログラムを実行できます。