mruby命令セット

対応risv:00090000

OP_NOP (0x00)

OP_NOP --> No operation
3130292827262524232221201918171615141312111009080706050403020100
0000000

何もしない。

OP_MOVE (0x01)

OP_MOVE A, B --> R(A) := R(B)
3130292827262524232221201918171615141312111009080706050403020100
A B 0000001

R(B)をR(A)にコピーする。コピー後のR(B)も残ったまま。

OP_LOADL (0x02)

OP_LOADL A, Bx --> R(A) := Lit(Bx)
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0000010

Poolにあるリテラル値[Bx]をR(A)に代入する。

OP_LOADI (0x03)

OP_LOADI A, sBx --> R(A) := sBx
3130292827262524232221201918171615141312111009080706050403020100
A sBx(+32767オフセットされた整数値) 0000011

R(A)に整数値(-32767~+32768)を代入する。

OP_LOADSYM (0x04)

OP_LOADSYM A, Bx --> R(A) := Sym(Bx)
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0000100

R(A)にシンボルSym(Bx)を代入する。

OP_LOADNIL (0x05)

OP_LOADNIL A --> R(A) := nil
3130292827262524232221201918171615141312111009080706050403020100
A 0000101

R(A)にnilを代入する。

OP_LOADSELF (0x06)

OP_LOADSELF A --> R(A) := self
3130292827262524232221201918171615141312111009080706050403020100
A 0000110

R(A)にselfを代入する。selfはR(0)なので、OP_MOVE A,0と等価。

OP_LOADT (0x07)

OP_LOADT A --> R(A) := true
3130292827262524232221201918171615141312111009080706050403020100
A 0000111

R(A)にtrueを代入する。

OP_LOADF (0x08)

OP_LOADF A --> R(A) := false
3130292827262524232221201918171615141312111009080706050403020100
A 0001000

R(A)にfalseを代入する。

OP_GETGLOBAL (0x09)

OP_GETGLOBAL A, Bx --> R(A) := getglobal(Sym(Bx))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001001

グローバル変数Sym(Bx)を取得し、R(A)に代入する。存在しない場合はnilを代入する。

OP_SETGLOBAL (0x0a)

OP_SETGLOBAL A, Bx --> setglobal(Sym(Bx), R(A))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001010

グローバル変数Sym(Bx)にR(A)を代入する。(既にあれば上書き、なければ新規作成される)

OP_GETSPECIAL (0x0b)

OP_GETSPECIAL A, Bx --> R(A) := Special[Bx]
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001011

FIXME 現時点ではFixnumの0がR(A)に代入される。Bxは無視。

OP_SETSPECIAL (0x0c)

OP_SETSPECIAL A, Bx --> Special[Bx] := R(A)
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001100

現時点では何もしない。FIXME

OP_GETIV (0x0d)

OP_GETIV A, Bx --> R(A) := ivget(Sym(Bx))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001101

R(0)つまりselfのインスタンス変数リストから、シンボルSym(Bx)に対応する値を取得してR(A)に代入する。selfがオブジェクトでない場合or見つからない場合はnilを代入する。

OP_SETIV (0x0e)

OP_SETIV A, Bx --> ivset(Sym(Bx), R(A))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001110

R(0)つまりselfのインスタンス変数リストのシンボルSym(Bx)にR(A)を保存する。リストやシンボルが未生成の場合は作成する。 なお、selfがオブジェクトでは無い場合、ARGUMENT_ERRORでraiseする。

OP_GETCV (0x0f)

OP_GETCV A, Bx --> R(A) := cvget(Sym(Bx))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0001111

クラス変数Sym(Bx)を取得し、R(A)に代入する。変数が存在しない場合はNameError例外(uninitialized class variable)を発生する。 検索対象のクラスcはci→proc→target_class(NULLならばci→target_class)である。c→iv_tblから検索し、見つからなければ 上位(c→super)へと遡って検索する。

OP_SETCV (0x10)

OP_SETCV A, Bx --> cvset(Sym(Bx), R(A))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0010000

OP_GETCVと同じルールでクラスを遡り、クラス変数Sym(Bx)が存在すれば、その内容をR(A)で上書きする。なお、見つからなかった場合は、ci→target_class→iv_tblに新規登録する。

OP_GETCONST (0x11)

OP_GETCONST A, Bx --> R(A) := constget(Sym(Bx))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0010001

定数Sym(Bx)を取得し、R(A)に代入する。以下の順序で検索し、最初に見つかった値が利用される。

  1. c=ci→proc→target_classが非NULLならば、ci→proc→target_class→iv
  2. c=ci→target_classが非NULLならば、ci→target_class→iv
  3. cのouterモジュール(内側から外側に向かって遡る)
    • outerモジュールは ivから__outer__を参照すると得られる。
  4. cと、そのsuperクラス(サブクラスからスーパークラスに向かって遡る)
  5. (cがMODULEの場合のみ) Objectクラスのiv (Objectおよびそのsuperへ遡る)

見つからなかった場合、cからsuperに向かって遡りながら、const_missingというメソッドを検索する。メソッドが見つかった場合はそれを実行する。 メソッドが見つからなかった場合はNameError例外(uninitialized constant)を発生させる。

OP_SETCONST (0x12)

OP_SETCONST A, Bx --> constset(Sym(Bx), R(A))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0010010

定数Sym(Bx)を定義する。ci→proc→target_classまたはci→target_classのivにSym(Bx)の名前でR(A)の内容を登録する。FIXME 二重登録時の警告は?

OP_GETMCNST (0x13)

OP_GETMCNST A, Bx --> R(A) := R(A)::Sym(Bx)
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0010011

R(A)が指すクラス(またはモジュール)レベルの定数Sym(Bx)を取得し、R(A)に代入する。なお、命令実行前のR(A)がクラス/モジュールでは無い1)場合、TypeError例外(constant look-up for non class/module)を発生させる。定数検索のルールは、OP_GETCONSTの4,5と同じ。

OP_SETMCNST (0x14)

OP_SETMCNST A, Bx --> R(A+1)::Sym(Bx) := R(A)
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0010100

R(A+1)の指すクラス/モジュールに属する定数Sym(Bx)を定義する。OP_GETMCNSTと同じ方法でR(A+1)がクラス/モジュールであることを確認し、インスタンス変数としてSym(Bx)=R(A)を登録する。 R(A+1)がクラス/モジュールでない場合は、OP_GETMCNSTと同じく例外を発生させる。

OP_GETUPVAR (0x15)

OP_GETUPVAR A, B, C --> R(A) := uvget(B, C)
3130292827262524232221201918171615141312111009080706050403020100
A B C 0010101

C段分上位のメソッド/ブロックの変数R(B)を取得し、現在のブロックのR(A)に代入する。
なお、C=0はci→proc→env、C=1はci→proc→env→c、C=2は( (REnv*)Ci→proc→env→c)→c、以下同様。対応するenvが存在しない場合はR(A)にnilを代入する。

OP_SETUPVAR (0x16)

OP_SETUPVAR A, B, C --> uvset(B, C, R(A))
3130292827262524232221201918171615141312111009080706050403020100
A B C 0010110

C段分上位のメソッド/ブロックの変数R(B)に、R(A)の内容を代入する。C段の遡り方はOP_GETUPVARに同じ。 対応するenvが存在しない場合は、何もしない。(エラーにもならない)

OP_JMP (0x17)

OP_JMP sBx --> pc += sBx
3130292827262524232221201918171615141312111009080706050403020100
sBx(+32767オフセットされた整数値) 0010111

PCを変更し、現在のirep中でジャンプする。なお、変更前のPCはこのJMP命令がある場所そのものであり、PC++する前の値である。 また、JMP命令なのでPC++は実施されない。従って、-32767個前~JMP命令自身~+32768個後まで合計65536通りの場所にジャンプできる。

OP_JMPIF (0x18)

OP_JMPIF A, sBx --> if R(A) pc += sBx
3130292827262524232221201918171615141312111009080706050403020100
A sBx(+32767オフセットされた整数値) 0011000

R(A)がfalseまたはnilのときは、ジャンプしない(つまりPC++)。それ以外の時はJMP命令と同様にジャンプする。

OP_JMPNOT (0x19)

OP_JMPNOT A, sBx --> if !R(A) pc += sBx
3130292827262524232221201918171615141312111009080706050403020100
A sBx(+32767オフセットされた整数値) 0011001

R(A)がfalseまたはnilのとき、JMP命令と同様にジャンプする。それ以外の時はジャンプしない(つまりPC++)。

OP_ONERR (0x1a)

OP_ONERR sBx --> rescue_push(pc + sBx)
3130292827262524232221201918171615141312111009080706050403020100
sBx(+32767オフセットされた整数値) 0011010

rescue節を登録する。登録先のmrb→rescueが未生成の場合、サイズ16で作成。mrb→rescueのサイズ(mrb→rsize)が足りない場合、自動的に2倍に拡張する。 登録はPC+sBxの計算結果をrescueの現在位置(0から昇順)に記録する。mrb→ci→ridxは次のrescue保存位置を指す。

OP_RESCUE (0x1b)

OP_RESCUE A --> clear(exc); R(A) := exception (ignore when A=0)
3130292827262524232221201918171615141312111009080706050403020100
A 0011011

R(A)に現在のRObject* mrb→excの内容を設定する。mrb→excはNULLに設定される。

OP_POPERR (0x1c)

OP_POPERR A --> A.times { rescue_pop() }
3130292827262524232221201918171615141312111009080706050403020100
A 0011100

mrb→ci→ridxをAだけ減らす。ONERRで登録したrescue節を通らずに抜けるのに利用する。

OP_RAISE (0x1d)

OP_RAISE A --> raise(R(A))
3130292827262524232221201918171615141312111009080706050403020100
A 0011101

例外を投げる。投げる例外オブジェクトはR(A)。なお、これは例外オブジェクトでなければならない。つまり、 NilClass,TrueClass,FalseClass,Fixnumといった型は渡せず、内部表現が mrb_value.value.p を用いる型しか渡せない(これは言語仕様でも規定されている)。

OP_EPUSH (0x1e)

OP_EPUSH Bx --> ensure_push(SEQ[Bx])
3130292827262524232221201918171615141312111009080706050403020100
Bx 0011110

ensure節を登録する。(irep→idx+Bx)番目のirepのクロージャを新規作成し、それをmrb→ensureに登録する。 mrb→ensureバッファはrescueバッファ同様に、未作成ならサイズ16で作成、個数オーバーなら2倍拡張となる。 mrb→ci→eidxは次の登録番号(つまり現在の登録個数)を指す。

OP_EPOP (0x1f)

OP_EPOP A --> A.times { ensure_pop().call }
3130292827262524232221201918171615141312111009080706050403020100
A 0011111

ensureバッファの最後尾にあるクロージャをpopしてecallする作業をA回繰り返す。ensure付きのブロックを抜ける(つまりensure節が実行される)ときに利用する。

OP_SEND (0x20)

(1) OP_SEND A, B, C (C=0)     --> R(A) := call(R(A), mSym(B))
(3) OP_SEND A, B, C (0<C<127) --> R(A) := call(R(A), mSym(B), R(A+1), ..., R(A+C))
(2) OP_SEND A, B, C (C=127)   --> R(A) := call(R(A), mSym(B), *R(A+1))
3130292827262524232221201918171615141312111009080706050403020100
A B C 0100000

mSym(B)で指定された関数/メソッドを呼び出す。レシーバがR(A)、R(A+1)~R(A+C)が引数(C=0のときは無し)、 R(A+C+1)がブロック(SENDならnilを自動代入、SENDBならブロック)となる。ただしこれは引数が126個以下の場合で、 引数が127個以上の場合は、引数を収めたArrayをR(A+1)に、R(A+2)にブロックを格納し、C=127とする。

レシーバの型内でメソッド(シンボルmSym(B))の検索を行い、該当するものが存在しない場合は、method_missingというメソッドの 呼び出しにすり替えて実行する。すり替えを実施する場合、見つからなかったシンボルが第1引数となり、第2引数以降が元々の引数となる。

  1. callinfoバッファに1つpush。
    • これから呼ぶメソッドのシンボルをci→mid、そのprocをci→proc、現在のスタックトップをci→stackidx、引数の個数2)をci→argc、レシーバのクラスをci→target_class、現在のpc+1をci→pc、A値をci→accにそれぞれ代入する。
  2. スタックをAずらす。つまり、呼び出し先のR'(0)が現在のR(A)となる。(だから、R(A)にレシーバを入れると丁度いいわけだ。)
  3. 呼び出し自体は、呼び出し先の種類(C実装のfunction/Ruby実装のmethod)によって異なる。
    • 呼び出し先がC実装関数(function)である場合
      1. 引数の個数3)+2をci→nregsに記憶
      2. mrbとレシーバを渡して該当関数を呼ぶ
      3. スタック末尾(つまりR(A))に関数の戻り値を格納
      4. mrc→excが設定されていればOP_RAISE処理へジャンプ
      5. レジスタ先頭位置、スタック位置をci→stackidxを用いて元に戻す。
      6. callinfoバッファから1つpopする。
    • 呼び出し先がrubyのmethodである場合。
      1. 実行中proc、irep、pool、symsを呼び出し先メソッドの内容に変更する。
      2. irep→nregsをci→nregsに記憶
      3. スタックを拡張する
        • Array渡しの場合、[irep→nregs,3].max 個確保(room)し、そのうち3個をkeepする。
        • レジスタ渡しの場合、irep→nregs個確保(room)し、そのうち(ci→argc+2)個をkeepする。
      4. レジスタ先頭位置をスタック末尾(つまりR(A)==R'(0))の位置にする。
      5. PCをirepの先頭にする。

OP_SENDB (0x21)

(1) OP_SENDB A, B, C (C=0)     --> R(A) := call(R(A), mSym(B), &R(A+1))
(3) OP_SENDB A, B, C (0<C<127) --> R(A) := call(R(A), mSym(B), R(A+1), ..., R(A+C), &R(A+C+1))
(2) OP_SENDB A, B, C (C=127)   --> R(A) := call(R(A), mSym(B), *R(A+1), &R(A+2))
3130292827262524232221201918171615141312111009080706050403020100
A B C 0100001

説明は OP_SEND を参照。

OP_FSEND (0x22)

未実装。現時点ではNOPと同じ。

OP_CALL (0x23)

OP_CALL --> self.call(frame.argc, frame.argv)
3130292827262524232221201918171615141312111009080706050403020100
0100011

Proc#callの実装用命令。codegenで生成されることはなく、Proc#call(またはProc#[])の内部実装のみに使われている。 これの命令が実行された場合、selfつまりR(0)はProcのインスタンスを指しており、それが保持しているクロージャmへのcallにすり替える作業を行う。

  • ci→target_classにm→target_classを上書き
  • ci→procにmを上書き
  • (m→envが存在すれば) ci→midにm→env→midを上書き
  • (m→envが存在し、m→env→stackが存在しなければ) m→env→stackにmrb→stackを代入
  • あとはSENDと同じ。

OP_SUPER (0x24)

OP_SUPER A, C --> R(A) := super(R(A+1), ..., R(A+C+1))
3130292827262524232221201918171615141312111009080706050403020100
A C 0100100

self(==R(0))をレシーバとし、ci→target_class→superからci→midのシンボルを探して実行する。 呼び出し本体の挙動はSENDと同じ。

OP_ARGARY (0x25)

FIXME

OP_ENTER (0x26)

OP_ENTER Ax --> argument setup (m1:o:r:m2:k:kd:b)
3130292827262524232221201918171615141312111009080706050403020100
Ax 0100110
m1 o r m2 k kd b

メソッドやブロックの先頭で用いられ、スタックに積まれた引数を使用できるようにする命令。 各パラメータの意味は以下の通り。

  • m1 : 引数(省略不可)の個数
  • o : 引数(省略可)の個数
  • r : 可変長引数を受け取るとき1
  • m2 : 不明。0以外を使っているところを見たことがない…。
  • k : 未使用
  • kd : 未使用
  • b : ブロック引数(&block)を受け取るとき1

現在のproc(ci→proc)のフラグがMRB_PROC_STRICTを持っているときは、引数の個数チェックを行う。 逆に言うと、STRICTフラグがないのはeachなどのイテレータブロックを呼び出す場合。Hash#eachだと受け側ブロックの引数が一つだと [key, value]で受け取れるし、二つだと key, value となる。この曖昧さはSTRICTを外すことで得られている。

受け取り側の引数の数でci→argcを上書きしたあと、引数の個数差に応じて調整を行う。

  • 実際に与えられた個数(argc)が受け取り数(len)より少ない場合
    1. ブロック引数を適切な位置(regs[len+1])にコピーする
    2. (argc-m2)個を、argvからregs[1]にコピーする(配列渡しなど、argvとregs[1]が別領域の場合のみ)
    3. (m2)個をargv[argc-m2]からregs[len-m2-1]に移動する(m2>0の場合)
    4. regs[m1+o+1]に空の配列を作成する(r==1の場合)
    5. ジャンプする
      • o==0の場合、通常どおりpc++して次の命令へ
      • o!=0の場合、pc+=(argc-m1-m2+1)してその命令へ。
        • 省略可能引数がある場合、その省略値をロードする命令群が含まれる。それらへのJMP命令をENTER命令の直後に省略可能引数の個数(o)だけ並べるルール。
  • 実際に与えられた個数(argc)が受け取り数(len)以上の場合
    1. (m1+o)個を、argvからregs[1]にコピーする(配列渡しなど、argvとregs[1]が別領域の場合のみ)
    2. 可変長引数がある場合、regs[m1+o+1]に配列を作成する(配列の内容は(argv+m1+o)から、(argc-m1-o-m2)個)
    3. (m2)個をargv[argc-m2]からregs[m1+o+r+1]に移動する(m2>0の場合)
    4. ブロック引数を適切な位置(regs[len+1])にコピーする
    5. pc+=(o+1)して、その命令へ (省略可能引数のジャンプテーブル末端へ飛ばす)

OP_KARG (0x27)

未実装 FIXME

OP_KDICT (0x28)

未実装 FIXME

OP_RETURN (0x29)

OP_RETURN A --> retrun R(A)
3130292827262524232221201918171615141312111009080706050403020100
A B 0101001

* 例外(mrb→exc)がある場合【L_RAISE処理】

  1. 例外オブジェクト(以下exc)の@lastpcにpcを保存
  2. excの@ciidxに現在のciの位置(cibaseからのインデックス)を保存
  3. ciがcibaseと同じ(つまり最上位フレームに居る)場合、ci→ridxが非0であればL_RESCUE処理へ。ci→irdxが0であればL_STOPへ。
  4. 現在のridxと一つ上位(ci[-1])のridxが異なる値になるまで、以下を繰り返し
    1. callinfoバッファから1つpop
    2. popしたciのaccが-1かつmrb_run開始時のmrb→jmpが非NULLの場合、上位のmrb_runにてsetjmpが設定されている(≒擬似的なtryブロックの中にいる)とみなし、longjmp(1)でthrowする。
      • 上位mrb_runのcatch節はL_RAISEの先頭へ飛んでくる。
      • 要するに、mrb_runの再帰呼び出しで処理している間に起きた例外を、最上位のmrb_runで吸収するための機構と思われる。
    3. ensureバッファにある内容について、pop後の最下位ci→eidxより大きいものをすべてecall
    4. mrb→ciがmrb→cibaseに達していたら、ループ終了しL_RESCUE処理へ
      • このとき、ci→ridx==0の場合はregs、stackをスタック先頭に戻し、L_STOP処理へ。
  5. ここから【L_RESCUE処理】
    1. irepをci→procのirepに設定、pool,symsも新irepに合わせて変更する
    2. regs、stackをci[1].stackidxを用いて戻す。
    3. pcをrescueバッファの[–ci→ridx]番目に設定してそこから実行再開
  • 例外がない場合
  • B=OP_R_RETURN(2)の場合
    1. proc→envがNULL、または、現在いるprocがSTRICTの場合はOP_R_NOMRALの処理へ移動
    2. FIXME
  • B=OP_R_NORMAL(0)の場合
    1. mrb→ciがcallinfoバッファの先頭の場合、returnできない所にいるはずなので“LocalJumpError: unexpected return”を起こすためL_RAISEへ。
    2. ローカル変数ciをmrb→ciとする。
  • B=OP_R_BREAK(1)の場合
    1. proc→env→cioffが負の場合、breakするべきブロック内に居ないことになるので“LocalJumpError: unexpected break”を起こすためL_RAISEへ。
    2. ローカル変数ci、mrb→ciをcallinfoバッファの[proc→env→cioff+1]番目とする。
  1. callinfoバッファを1つpop

OP_TAILCALL (0x2a)

01/16現在、ディスアセンブリのみ対応。コード生成箇所無し。FIXME

OP_BLKPUSH (0x2b)

FIXME

OP_ADD (0x2c)

FIXME

OP_ADDI (0x2d)

FIXME

OP_SUB (0x2e)

FIXME

OP_SUBI (0x2f)

FIXME

OP_MUL (0x30)

FIXME

OP_DIV (0x31)

FIXME

OP_EQ (0x32)

OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
3130292827262524232221201918171615141312111009080706050403020100
A B (mSyms[B]=:==) C (0000001) 0110010

OP_LT (0x33)

OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
3130292827262524232221201918171615141312111009080706050403020100
A B (mSyms[B]=:<) C (0000001) 0110011

OP_LE (0x34)

OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
3130292827262524232221201918171615141312111009080706050403020100
A B (mSyms[B]=:<=) C (0000001) 0110100

OP_GT (0x35)

OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
3130292827262524232221201918171615141312111009080706050403020100
A B (mSyms[B]=:>) C (0000001) 0110101

OP_GE (0x36)

OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
3130292827262524232221201918171615141312111009080706050403020100
A B (mSyms[B]=:>=) C (0000001) 0110110

OP_ARRAY (0x37)

OP_ARRAY A, B, C (C>0) --> R(A) := ary_new(R(B), R(B+1), ..., R(B+C))
3130292827262524232221201918171615141312111009080706050403020100
A B C (0000001) 0110111

OP_ARYCAT (0x38)

OP_ARYCAT A, B --> ary_cat(R(A), R(B))
3130292827262524232221201918171615141312111009080706050403020100
A B 0111000

OP_ARYPUSH (0x39)

OP_ARYPUSH A, B --> ary_push(R(A), R(B))
3130292827262524232221201918171615141312111009080706050403020100
A B 0111001

OP_AREF (0x3a)

OP_AREF A, B, C --> R(A) := R(B)[C]
3130292827262524232221201918171615141312111009080706050403020100
A B C 0111010

配列の要素参照。ただし、言語仕様上で配列扱いとなる部分に対して使われる。なお、R(B)が配列では無い場合、エラーとはならずR(A)にnilが代入される。

# 次の例はOP_AREFではなく、ただの[]メソッド呼び出しである。
b = a[1]
# 000 OP_MOVE     R4      (a)
# 001 OP_LOADI    R5      1
# 002 OP_SEND     R4      :[]     1
 
# 次のように多重代入を行う場合は、a,b,cに代入すべき値の取り出しがOP_AREFで行われる。
a,b,c = foo
# 000 OP_MOVE     R4      (foo)
# 001 OP_AREF     R1      R4      0
# 002 OP_AREF     R2      R4      1
# 003 OP_AREF     R3      R4      2

OP_ASET (0x3b)

OP_ASET A, B, C --> R(B)[C] := R(A)
3130292827262524232221201918171615141312111009080706050403020100
A B C 0111011

OP_AREFの反対で、配列への代入。FIXME 現時点では使われている様子がない。

OP_APOST (0x3c)

OP_APOST A, B, C --> *R(A), R(A+1), ..., R(A+C) := R(A)
3130292827262524232221201918171615141312111009080706050403020100
A B C 0111100

OP_STRING (0x3d)

OP_STRING A, Bx --> R(A) := str_dup(Lit(Bx))
3130292827262524232221201918171615141312111009080706050403020100
A Bx 0111101

Lit(Bx)にある文字列をもつStringのインスタンスを生成し、R(A)に代入する。

OP_STRCAT (0x3e)

OP_STRCAT A, B --> str_cat(R(A), R(B))
3130292827262524232221201918171615141312111009080706050403020100
A B 0111110

文字列R(A)の末端に文字列R(B)を連結する。R(A)に対しては破壊的。R(B)は破壊されない。 FIXME R(A)やR(B)がStringでなかった場合は?

OP_HASH (0x3f)

OP_HASH A, B, C --> R(A) := hash_new(R(B), R(B+1), ..., R(B+C))
3130292827262524232221201918171615141312111009080706050403020100
A B C 0111111

OP_LAMBDA (0x40)

OP_LAMBDA A, b, c--> R(A) := lambda(SEQ[b], c)
3130292827262524232221201918171615141312111009080706050403020100
A b c 1000000

OP_RANGE (0x41)

OP_RANGE A, B, C --> R(A) := range_new(R(B), R(B+1), C)
3130292827262524232221201918171615141312111009080706050403020100
A B C 1000001

OP_OCLASS (0x42)

OP_OCLASS A --> R(A) := ::Object
3130292827262524232221201918171615141312111009080706050403020100
A 1000010

::ObjectをR(A)に代入する。

OP_CLASS (0x43)

OP_CLASS A, B --> R(A) := newclass(R(A), mSym(B), R(A+1))
3130292827262524232221201918171615141312111009080706050403020100
A B 1000011

クラスを定義する。R(A)はbase(たいていnil入れてるけど何これ?FIXME)、R(A+1)はsuper。

OP_MODULE (0x44)

OP_MODULE A, B --> R(A) := newmodule(R(A), mSym(B))
3130292827262524232221201918171615141312111009080706050403020100
A B 1000100

OP_EXEC (0x45)

OP_EXEC A, Bx --> R(A) := blockexec(R(A), SEQ[Bx])
3130292827262524232221201918171615141312111009080706050403020100
A Bx 1000101

OP_METHOD (0x46)

OP_METHOD A, B --> R(A).newmethod(mSym(B), R(A+1))
3130292827262524232221201918171615141312111009080706050403020100
A B 1000110

OP_SCLASS (0x47)

OP_SCLASS A, B --> R(A) := R(B).singleton_class
3130292827262524232221201918171615141312111009080706050403020100
A B 1000111

R(B)のクラスを元として、singletonクラスを作成する。singletonクラスとは、元のクラスと同じ機能を継承した上で、特異メソッドなどを持つインスタンス固有のクラス。 なお、singletonクラスに対して OP_SCLASS を実行すると、FIXME

OP_TCLASS (0x48)

OP_TCLASS A --> R(A) := target_class
3130292827262524232221201918171615141312111009080706050403020100
A 1001000

OP_DEBUG (0x49)

OP_DEBUG A --> print R(A)
3130292827262524232221201918171615141312111009080706050403020100
A 1001001

OP_STOP (0x4a)

OP_STOP --> Stop VM
3130292827262524232221201918171615141312111009080706050403020100
1001010

OP_ERR (0x4b)

OP_ERR Bx --> raise RuntimeError with message Lit(Bx)
3130292827262524232221201918171615141312111009080706050403020100
Bx 1001011

OP_RSVD1 (0x4c)

Reserved instruction #1
3130292827262524232221201918171615141312111009080706050403020100
1001100

OP_RSVD1 (0x4d)

Reserved instruction #2
3130292827262524232221201918171615141312111009080706050403020100
1001101

OP_RSVD1 (0x4e)

Reserved instruction #3
3130292827262524232221201918171615141312111009080706050403020100
1001110

OP_RSVD1 (0x4f)

Reserved instruction #4
3130292827262524232221201918171615141312111009080706050403020100
1001111

OP_RSVD1 (0x50)

Reserved instruction #5
3130292827262524232221201918171615141312111009080706050403020100
1010000
1)
MRB_TT_CLASS,MRB_TT_MODULE,MRB_TT_SCLASSのいずれでもない
2)
Array渡しのときは-1
3)
Array渡しの場合は1
ruby/mruby/instructions.txt · 最終更新: 2013/04/14 00:59 (外部編集)
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0