summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro Matsumoto <[email protected]>2012-06-11 15:55:04 +0900
committerYukihiro Matsumoto <[email protected]>2012-06-11 15:55:04 +0900
commit13a542d48d5d86b866dbc4d6a4f0ec17bee49c12 (patch)
treeb73deac37c7cedb7f1b718a92ff71f21f97263dc /src
parent8f020f28c6b5b9c64cbd66db8369f89809b20d0a (diff)
downloadmruby-13a542d48d5d86b866dbc4d6a4f0ec17bee49c12.tar.gz
mruby-13a542d48d5d86b866dbc4d6a4f0ec17bee49c12.zip
zsuper should respect block given; close #185
Diffstat (limited to 'src')
-rw-r--r--src/codegen.c9
-rw-r--r--src/parse.y16
-rw-r--r--src/vm.c7
3 files changed, 24 insertions, 8 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 117588b6e..105a27cef 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1280,7 +1280,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
int n = 0;
- push();
+ push(); /* room for receiver */
if (tree) {
node *args = tree->car;
while (args) {
@@ -1307,14 +1307,19 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_scope *s2 = s;
int lv = 0, ainfo = 0;
+ push(); /* room for receiver */
while (s2->ainfo < 0) {
lv++;
s2 = s2->prev;
if (!s2) break;
}
if (s2) ainfo = s2->ainfo;
- push();
genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ if (tree && tree->cdr) {
+ push();
+ codegen(s, tree->cdr, VAL);
+ pop_n(2);
+ }
pop();
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
if (val) push();
diff --git a/src/parse.y b/src/parse.y
index 3f542a3b3..d31711b68 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -754,11 +754,21 @@ args_with_block(parser_state *p, node *a, node *b)
static void
call_with_block(parser_state *p, node *a, node *b)
{
- node *n = a->cdr->cdr->cdr;
+ node *n;
- if (!n->car) n->car = cons(0, b);
+ if (a->car == (node*)NODE_SUPER ||
+ a->car == (node*)NODE_ZSUPER) {
+ if (!a->cdr) a->cdr = cons(0, b);
+ else {
+ args_with_block(p, a->cdr, b);
+ }
+ }
else {
- args_with_block(p, n->car, b);
+ n = a->cdr->cdr->cdr;
+ if (!n->car) n->car = cons(0, b);
+ else {
+ args_with_block(p, n->car, b);
+ }
}
}
diff --git a/src/vm.c b/src/vm.c
index 508d8fe77..5a521c357 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -933,12 +933,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int argc = mrb->ci->argc;
mrb_value *argv = regs+1;
int len = m1 + o + r + m2;
+ mrb_value *blk = &argv[argc < 0 ? 1 : argc];
if (argc < 0) {
struct RArray *ary = mrb_ary_ptr(regs[1]);
argv = ary->ptr;
argc = ary->len;
- regs[len+2] = regs[1]; /* save argary in register */
+ mrb_gc_protect(mrb, regs[1]);
}
if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) {
if (argc >= 0) {
@@ -954,7 +955,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
mrb->ci->argc = len;
if (argc < len) {
- regs[len+1] = argv[argc]; /* move block */
+ regs[len+1] = *blk; /* move block */
memmove(&regs[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */
memmove(&regs[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */
if (r) { /* r */
@@ -968,7 +969,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o);
}
memmove(&regs[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2);
- regs[len+1] = argv[argc]; /* move block */
+ regs[len+1] = *blk; /* move block */
pc += o + 1;
}
JUMP;