On Mon, 19 May 2008, Parrot via RT wrote:
while converting mod_perl6 from PIR to pure perl6, i encountered the
following error when running a handler:
No such caller depth
current instr.: 'parrot;ModParrot;HLL;perl6;handler' pc 62 (EVAL_13:46)
i tracked down the error to this block in perl6's actions.pm:
unless $?BLOCK.symbol('$/') {
$init.push( PAST::Var.new( :name('$/'), :isdecl(1) ) );
$?BLOCK.symbol( '$/', :scope('lexical') );
$init.push(
PAST::Op.new(
:inline(
" %r = getinterp\n"
~ " %r = %r['lexpad';1]\n"
~ " if null %r goto no_match_to_copy\n"
~ " %r = %r['$/']\n"
~ " store_lex '$/', %r\n"
~ " no_match_to_copy:\n"
)
)
);
}
this code assumes there is a previous call frame which might contain a
lexpad, which is always true when called from PIR or the PCT command line.
however, in a pure perl mod_perl6, a perl6 sub is called directly from C,
and therefore lives in the top level call frame. any reference to the
nonexistent previous frame using the interpreter object bombs out.
you can reproduce this problem in pure PIR with this:
.sub main :main
$P0 = getinterp
$P1 = $P0['lexpad';1]
.end
if we want perl6 subs to be directly invokable from an embedded
environemnt, we either need to teach perl6 to be smarter about this or
change how parrot handles this kind of exception.
-jeff
After further investigation, it looks like the parrotinterpreter PMC is
validating caller depth before looking up the keyed item. So for
$P0['lexpad';1] it verifies there's a call frame 1 level up before doing
anything else. A backtrace reveals that the exception occurs at
parrotinterpreter.pmc:426:
if (!ctx->current_sub)
real_exception(interp, NULL, E_ValueError,
"No such caller depth");
So it *does* find a valid context one level up, but no current_sub since
we're calling from C. Is it necessary for this to be fatal? Should we
return NULL here instead of bombing out?