summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro Matz Matsumoto <[email protected]>2012-11-21 17:00:06 +0900
committerYukihiro Matz Matsumoto <[email protected]>2012-11-21 17:00:06 +0900
commit76f0e755e92d845b4b4bac1d77aa5eeb42bbbec9 (patch)
tree37e2b0b0dbe4dbbef3959e7661e483fab67b3bbf /src
parent1b2257c8ff212d1069b00e11a6b91672c9636ecb (diff)
downloadmruby-76f0e755e92d845b4b4bac1d77aa5eeb42bbbec9.tar.gz
mruby-76f0e755e92d845b4b4bac1d77aa5eeb42bbbec9.zip
handle return from blocks, especially from lambda blocks; close #561
Diffstat (limited to 'src')
-rw-r--r--src/vm.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/vm.c b/src/vm.c
index ebd505366..61274e374 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -151,14 +151,27 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v)
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*
-top_env(struct RProc *proc)
+top_env(mrb_state *mrb, struct RProc *proc)
{
struct REnv *e = proc->env;
+ if (is_strict(mrb, e)) return e;
while (e->c) {
- if (!e) return 0;
e = (struct REnv*)e->c;
+ if (is_strict(mrb, e)) return e;
}
return e;
}
@@ -1165,8 +1178,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
break;
case OP_R_RETURN:
if (!proc->env) goto NORMAL_RETURN;
+ if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
else {
- struct REnv *e = top_env(proc);
+ struct REnv *e = top_env(mrb, proc);
if (e->cioff < 0) {
localjump_error(mrb, "return");