develooper Front page | perl.perl5.porters | Postings from August 2016

Re: Flailing randomly at ops

Thread Previous | Thread Next
From:
Father Chrysostomos
Date:
August 9, 2016 01:20
Subject:
Re: Flailing randomly at ops
Message ID:
20160809011959.2489.qmail@lists-nntp.develooper.com
Paul Evans wrote:
> can anyone explain to me
> how I can write a function that takes an OP tree representing the body
> of the eval block (the calls to A() and B() in the above), and return a
> new OP tree that invokes the given one inside an eval{} scope?


I will show you how to look up things like this in the perl source.

Under KEY_eval, toke.c has:

    UNIBRACK(OP_ENTERTRY);

UNIBRACK is defined in terms of UNI3, which ultimately results in the equivalent of:

    pl_yylval.ival = OP_ENTERTRY;
    return UNIOP;

So yylex returns a UNIOP with OP_ENTERTRY as the value, and we need to
look in perly.y to see how it handles UNIOP.

I see this:

        |        UNIOP block                          /* eval { foo }* */
                          { $$ = newUNOP($1, 0, $2); }

I already know that newUNOP will create a simply uniary op with
'block' as its argument.  It also calls a check function, so we look
in regen/opcodes to find out which one:

entertry        eval {block}            ck_eval         d|

OK, so it is ck_eval.  No surprises there.  If you look at ck_eval in
op.c, you can see that it does quite a bit of op tree munging, includ-
ing freeing the original op that newUNOP just created.

So it seems that you can just use:

    newUNOP(OP_ENTERTRY, 0, your_ops);

> For bonus points, I'll be wanting to inspect the success-or-failure of
> the eval{} operation, and interact with the perl stack afterwards based
> on this. I can probably implement all of my behaviour inside a single
> (custom) OP, so if someone can suggest how to (perhaps) PUSHMARK before
> the eval body, so I can find the length of the successfully returned
> list, and otherwise interact with the stack in the next OPs after the
> eval block returns, that would be useful too.

You could probably take what newUNOP ultimately returns (affected by
ck_eval) and change the OP_LEAVETRY into an OP_CUSTOM.

That custom op can call PL_ppaddr[OP_LEAVETRY] and then inspect the
stack when it returns.  As for distinguishing between an empty list
resulting from an error and an empty list return by a successful eval,
I do not know the details off the top of my head, but you could proba-
bly check ERRSV ($@).  If you want more details about how eval works at
run time, the only advice I can give you is to study pp_ctl.c.

> As a final item: if there's anywhere that these subjects are
> documented, could someone point me at it?

As you see, I use the source code as documentation of sorts.  I do not
know how much detail is in the various documents that perlhack links
to, since I rarely use them, having never found them nearly as helpful
as the source code itself.


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About