mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Generate new OP_RESCUE; fix #3487
The old OP_RESCUE took one operand A, which specifies a class to match with the exception. The new OP_RESCUE takes tree operands: A: the register to hold exception B: the matching exception; the match result will be stored here. C: the continuation; if C is zero, the exception will be stored to R(A) otherwise, the value from R(A) is used as a exception. Thus, ```ruby begin raise "a" rescue TypeError p 1 rescue RuntimeError p 2 end ``` will be compiled as ``` irep 0x557a06667aa0 nregs=4 nlocals=1 pools=1 syms=4 reps=0 file: /tmp/e.rb 2 000 OP_ONERR 005 2 001 OP_LOADSELF R1 2 002 OP_STRING R2 L(0) ; "a" 2 003 OP_SEND R1 :raise 1 2 004 OP_JMP 022 3 005 OP_GETCONST R2 :TypeError 3 006 OP_RESCUE R1 R2 3 007 OP_JMPIF R2 009 3 008 OP_JMP 013 4 009 OP_LOADSELF R1 4 010 OP_LOADI R2 1 4 011 OP_SEND R1 :p 1 4 012 OP_JMP 023 5 013 OP_GETCONST R2 :RuntimeError 5 014 OP_RESCUE R1 R2 cont 5 015 OP_JMPIF R2 017 5 016 OP_JMP 021 6 017 OP_LOADSELF R1 6 018 OP_LOADI R2 2 6 019 OP_SEND R1 :p 1 6 020 OP_JMP 023 6 021 OP_RAISE R1 6 022 OP_POPERR 1 6 023 OP_STOP ``` The new VM can accept old OP_RESCUE. The mruby compatible VM (namely mruby/c) should be updated to support the new OP_RESCUE behavior.
This commit is contained in:
@@ -1293,8 +1293,8 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (tree->car) {
|
||||
node *n2 = tree->car;
|
||||
int exc = cursp();
|
||||
int cnt = 0;
|
||||
|
||||
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
|
||||
push();
|
||||
while (n2) {
|
||||
node *n3 = n2->car;
|
||||
@@ -1303,20 +1303,26 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (pos1) dispatch(s, pos1);
|
||||
pos2 = 0;
|
||||
do {
|
||||
if (n4) {
|
||||
codegen(s, n4->car, VAL);
|
||||
}
|
||||
else {
|
||||
genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
|
||||
push();
|
||||
}
|
||||
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
|
||||
pop();
|
||||
if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
|
||||
if (cnt == 0) {
|
||||
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, cnt)); cnt = 1;
|
||||
}
|
||||
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
|
||||
push();
|
||||
codegen(s, n4->car, VAL);
|
||||
pop_n(2);
|
||||
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
|
||||
}
|
||||
else {
|
||||
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
|
||||
if (n4) {
|
||||
codegen(s, n4->car, VAL);
|
||||
}
|
||||
else {
|
||||
genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
|
||||
push();
|
||||
}
|
||||
pop();
|
||||
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), cnt)); cnt = 1;
|
||||
}
|
||||
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
|
||||
pos2 = tmp;
|
||||
@@ -1788,11 +1794,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
genop(s, MKOP_A(OP_POPERR, 1));
|
||||
noexc = genop(s, MKOP_Bx(OP_JMP, 0));
|
||||
dispatch(s, onerr);
|
||||
<<<<<<< HEAD
|
||||
genop(s, MKOP_AB(OP_RESCUE, exc, 0));
|
||||
=======
|
||||
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
|
||||
>>>>>>> 55d89bd... Enhance OP_RESCUE to take B operand fas matching exception; ref #3487
|
||||
genop(s, MKOP_A(OP_LOADF, exc));
|
||||
dispatch(s, noexc);
|
||||
loop_pop(s, NOVAL);
|
||||
|
||||
Reference in New Issue
Block a user