handle return from blocks, especially from lambda blocks; close #561

parent 1b2257c8
...@@ -151,14 +151,27 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v) ...@@ -151,14 +151,27 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v)
mrb_write_barrier(mrb, (struct RBasic*)e); mrb_write_barrier(mrb, (struct RBasic*)e);
} }
static inline int
is_strict(mrb_state *mrb, struct REnv *e)
{
int cioff = e->cioff;
if (cioff >= 0 && mrb->cibase[cioff].proc &&
MRB_PROC_STRICT_P(mrb->cibase[cioff].proc)) {
return 1;
}
return 0;
}
struct REnv* struct REnv*
top_env(struct RProc *proc) top_env(mrb_state *mrb, struct RProc *proc)
{ {
struct REnv *e = proc->env; struct REnv *e = proc->env;
if (is_strict(mrb, e)) return e;
while (e->c) { while (e->c) {
if (!e) return 0;
e = (struct REnv*)e->c; e = (struct REnv*)e->c;
if (is_strict(mrb, e)) return e;
} }
return e; return e;
} }
...@@ -1165,8 +1178,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ...@@ -1165,8 +1178,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
break; break;
case OP_R_RETURN: case OP_R_RETURN:
if (!proc->env) goto NORMAL_RETURN; if (!proc->env) goto NORMAL_RETURN;
if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
else { else {
struct REnv *e = top_env(proc); struct REnv *e = top_env(mrb, proc);
if (e->cioff < 0) { if (e->cioff < 0) {
localjump_error(mrb, "return"); localjump_error(mrb, "return");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment