I am returning to the topic of search_lex. I ask to be excused because
this is another "I need this op" mail, but I think the feature I request
here has merit for other languages as well...
In my case my "problem" (challenge) is that I want to generate some
parrot code that is capable of searching the lexical pads for the
existence of a lexical. In my particular case this code executes
frequently.
My current code generator generates code to trap the LEX_NOT_FOUND
exception. However, the "set_eh" instruction is *terribly* slow...
I hacked around var.ops a bit to introduce a set of ops called
'search_lex' which just return a null PMC if the lexical is not found
(see the bottom of this mail for the implementation. It is quite
trivial).
With these ops, detection of a non-existing lexical is orders of
magnitude faster and easier, so I would like to plead the gods of parrot
to contemplate them for inclusion in the basic operation set... (please!
please! :-)
++Jos.nl
P.S. There is a strong NLP case for this op as well, since the verb
"search" implies the possibility of failure, whereas "find" does
not. When asked what I am doing (while scurrying around the
room) I like to say that I am finding my sandwich instead of
searching it.... :-)
###############################################################################
=item B<search_lex>(out PMC, in STR)
Search the lexical variable named $2 (at any depth) and store it in $1.
Returns null if the lexical is not found.
=item B<search_lex>(out PMC, in INT, in STR)
Search the lexical variable named $3 at depth $2 and store it in $1.
If $2 is negative the, count out from the current lexical scope;
otherwise, count up from the outermost scope.
Returns null if the lexical is not found.
=item B<search_lex>(out PMC, in INT, in INT)
Search the lexical variable at position $3 at depth $2 and store it in
$1. If $2 is negative the, count out from the current lexical scope;
otherwise, count up from the outermost scope.
Returns null if the lexical is not found.
=cut
op search_lex(out PMC, in STR) {
PMC * pad = scratchpad_get_current(interpreter);
$1 = scratchpad_get(interpreter, pad, $2, 0);
goto NEXT();
}
op search_lex(out PMC, in INT) {
PMC * pad = scratchpad_get_current(interpreter);
$1 = scratchpad_get(interpreter, pad, NULL, $2);
goto NEXT();
}
op search_lex(out PMC, in INT, in STR) {
PMC * pad = scratchpad_get_current(interpreter);
$1 = scratchpad_get_index(interpreter, pad, $2, $3, 0);
goto NEXT();
}
op search_lex(out PMC, in INT, in INT) {
PMC * pad = scratchpad_get_current(interpreter);
$1 = scratchpad_get_index(interpreter, pad, $2, NULL, $3);
goto NEXT();
}
=back
=cut
--
ek is so lug jy vlieg deur my
sonder jou is ek sonder patroon
"Breyten Breytenbach"
> My current code generator generates code to trap the LEX_NOT_FOUND
> exception. However, the "set_eh" instruction is *terribly* slow...
All my answers to that (and other threads) seem to be missing currently.
Anyway I have put in an intermediate hack to speed this up a bit.
A real solution will follow - probably in some steps and later.
leo
> In my case my "problem" (challenge) is that I want to generate some
> parrot code that is capable of searching the lexical pads for the
> existence of a lexical. In my particular case this code executes
> frequently.
I would implement the proposed OrderedHash (HashArray) PMC, base
lexicals on these and then iterate over these aggregates in the lexical
pad. Trying to search for non existent lexicals doesn't seem to be a
good idea.
> My current code generator generates code to trap the LEX_NOT_FOUND
> exception. However, the "set_eh" instruction is *terribly* slow...
The C<set_eh> is a stack_push and shouldn't be that slow. But your are
right. Something is fishy here. I'll try to find int.
> I hacked around var.ops a bit to introduce a set of ops called
> 'search_lex' which just return a null PMC if the lexical is not found
While I'm not strictly against these, a new C<error> flag (like the
current C<warns>) in the interpreter->ctx to toggle some exception would
be better.
> ++Jos.nl
leo
> My current code generator generates code to trap the LEX_NOT_FOUND
> exception. However, the "set_eh" instruction is *terribly* slow...
After having a closer look at this, I can describe what's happening:
- the exception handler is a continuation
- these have COWed copies of the interpreter's stacks
- the C<set_eh> pushes an exception handler onto the control stack
this unCOWes the interpreter's control stack
- when the exception is resumable, a return continuation is built
again setting the control stack as COWed
- so resuming after the exception puts a saved copy of the original
control_stack in place, which has the COW flag set.
- this causes a chunk_copy (effectively constructing a new stack) at
the next set_eh :-(
The COW logic for stacks is wrong.
Test program follows:
new_pad 0
new P0, .PerlInt
set P0, 42
store_lex -1, "yep", P0
set I0, 10000
time N0
lp1:
find_lex P1, "yep"
dec I0
if I0, lp1
time N1
sub N2, N1, N0
print N2
print "\n"
newsub P3, .Exception_Handler, _failed
set_eh P3
set I0, 10000
time N0
lp2:
find_lex P1, "no"
ret:
set_eh P3
dec I0
if I0, lp2
time N1
sub N2, N1, N0
print N2
print "\n"
end
_failed:
set P0, P5["_invoke_cc"]
invoke # resume at ret: