diff --git a/kernel/bootstrap/context.rb b/kernel/bootstrap/context.rb index f91d5bb..e9501b1 100644 --- a/kernel/bootstrap/context.rb +++ b/kernel/bootstrap/context.rb @@ -110,6 +110,11 @@ class BlockContext end class BlockEnvironment + def prepare + Ruby.primitive :block_prepare + raise PrimitiveFailure, "primitive failed" + end + def call(*args) Ruby.primitive :block_call raise PrimitiveFailure, "primitive failed" diff --git a/kernel/core/kernel.rb b/kernel/core/kernel.rb index 4de46ff..cc88879 100644 --- a/kernel/core/kernel.rb +++ b/kernel/core/kernel.rb @@ -287,7 +287,9 @@ module Kernel module_function :proc def caller(start=1) - return MethodContext.current.sender.calling_hierarchy(start) + ctx = MethodContext.current.sender + ctx = ctx.sender if ctx.__kind_of__(BlockContext) + return ctx.calling_hierarchy(start) end module_function :caller diff --git a/kernel/core/proc.rb b/kernel/core/proc.rb index 7e56905..d1369a9 100644 --- a/kernel/core/proc.rb +++ b/kernel/core/proc.rb @@ -15,7 +15,7 @@ class Proc end def binding - Binding.setup @block.home + Binding.setup @block.prepare end #-- diff --git a/shotgun/lib/methctx.c b/shotgun/lib/methctx.c index c912e57..4c5d7ce 100644 --- a/shotgun/lib/methctx.c +++ b/shotgun/lib/methctx.c @@ -106,6 +106,16 @@ void blokenv_call(STATE, cpu c, OBJECT self, int num_args) { } +/* Prepares a block context like blockenv_call, but + * does not activate it. */ +OBJECT blokenv_prepare(STATE, cpu c, OBJECT self) { + OBJECT ctx; + cpu_flush_sp(c); + cpu_create_block_context(state, c, self, c->sp); + ctx = blokenv_get_home(self); + return ctx; +} + void methctx_reference(STATE, OBJECT ctx) { struct fast_context *fc; diff --git a/shotgun/lib/methctx.h b/shotgun/lib/methctx.h index 89fd237..47da1a2 100644 --- a/shotgun/lib/methctx.h +++ b/shotgun/lib/methctx.h @@ -4,6 +4,7 @@ OBJECT blokctx_s_under_context(STATE, OBJECT ctx); OBJECT blokenv_s_under_context2(STATE, OBJECT cmethod, OBJECT ctx, OBJECT ctx_block); void blokenv_call(STATE, cpu c, OBJECT self, int num_args); +OBJECT blokenv_prepare(STATE, cpu c, OBJECT self); OBJECT methctx_dup(STATE, OBJECT self); OBJECT methctx_dup_chain(STATE, OBJECT ctx, OBJECT *also); diff --git a/shotgun/lib/primitives.rb b/shotgun/lib/primitives.rb index b0760ca..16be067 100644 --- a/shotgun/lib/primitives.rb +++ b/shotgun/lib/primitives.rb @@ -584,6 +584,18 @@ class ShotgunPrimitives CODE end + defprim :block_prepare + def block_prepare + <<-CODE + ARITY(0); + OBJECT t1; + GUARD(BLOCKENV_P(msg->recv)); + + t1 = blokenv_prepare(state, c, msg->recv); + RET(t1); + CODE + end + defprim :io_write def io_write <<-CODE