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

Flailing randomly at ops

Thread Next
From:
Paul "LeoNerd" Evans
Date:
August 8, 2016 21:53
Subject:
Flailing randomly at ops
Message ID:
20160808225325.79944d95@shy.leonerd.org.uk
Who can tell me where there's more (any?) documentation about optrees.

In particular, the ops I'm interested in learning more about are
ENTERTRY and LEAVETRY. The limit of my knowledge so far is that, from
what I can tell reading source OP_ENTERTRY is a LOGOP, and LEAVETRY is
a LISTOP.

From poking at B::Concise, I find that

$ perl -MO=Concise,f -ce 'sub f { eval { A(); B() }; C(); D() }'
main::f:
c  <1> leavesub[1 ref] K/REFC,1 ->(end)
-     <@> lineseq KP ->c
1        <;> nextstate(main 2 -e:1) v:{ ->2
3        <@> leavetry vKP ->4
2           <|> entertry(other->3) vK ->d
d           <;> nextstate(main 3 -e:1) v ->e
g           <1> entersub[t2] vKS/TARG ->h
-              <1> ex-list K ->g
e                 <0> pushmark s ->f
-                 <1> ex-rv2cv sK/1 ->-
f                    <#> gv[*A] s/EARLYCV ->g
h           <;> nextstate(main 3 -e:1) v ->i
k           <1> entersub[t4] vKS/TARG ->3
-              <1> ex-list K ->k
i                 <0> pushmark s ->j
-                 <1> ex-rv2cv sK/1 ->-
j                    <#> gv[*B] s/EARLYCV ->k
4        <;> nextstate(main 4 -e:1) v:{ ->5
7        <1> entersub[t6] vKS/TARG ->8
-           <1> ex-list K ->7
5              <0> pushmark s ->6
-              <1> ex-rv2cv sK/1 ->-
6                 <#> gv[*C] s/EARLYCV ->7
8        <;> nextstate(main 4 -e:1) v:{ ->9
b        <1> entersub[t8] KS/TARG ->c
-           <1> ex-list K ->b
9              <0> pushmark s ->a
-              <1> ex-rv2cv sK/1 ->-
a                 <#> gv[*D] s/EARLYCV ->b

It appears that OP_ENTERTRY's op_other is the OP_LEAVETRY which is its
own parent. It further seems that the code that is the contents of the
eval {} block appears as siblings of the ENTERTRY, and the entire
ENTERTRY+body list is the child list contained within the LEAVETRY.

Armed with this observation (or elsewhere), 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?

  OP *wrap_eval(OP *body) { ... }

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.

As a final item: if there's anywhere that these subjects are
documented, could someone point me at it? If there isn't and it's not
written, then I guess I'll be submitting a patch to write such docs, so
any more snippets of information people have to hand would be much
appreciated.

Thanks,

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

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