4

I have been playing with the new parse_block feature in bleadperl,

I can parse several statements into a listop, which would generate the tree below:

LISTOP (0x1002a00c0) leave [1] 
    OP (0x1002d6220) enter 
    COP (0x1002a0b80) nextstate 
    OP (0x10028c0f0) null 
    LISTOP (0x1002a0170) print 
        OP (0x1002b1a90) pushmark 
        SVOP (0x100327ee0) const  PV (0x100826ec0) "hello\n" 
    COP (0x1002a0c50) nextstate 
    LISTOP (0x100324ee0) print 
        OP (0x100327880) pushmark 
        SVOP (0x100324eb0) const  PV (0x100897688) "world\n"

I need to return a pointer to an optree structure from my keyword plugin, which at the moment just contains the bare list of ops. I want to wrap these ops inside a subroutine and assign it to a symbol within a stash.

So I guess I want to do something like this:

$ perl  -MO=Terse -e "*foo = sub { print 'my listops here' }"

LISTOP (0x10022b5e0) leave [1] 
    OP (0x10022b620) enter 
    COP (0x10022b590) nextstate 
    BINOP (0x100202090) sassign 
        UNOP (0x1002083d0) refgen 
            UNOP (0x100208360) null [146] 
                OP (0x1002083a0) pushmark 
                SVOP (0x100208330) anoncode [1] CV (0x100826d40) 
        UNOP (0x1002085a0) rv2gv 
            SVOP (0x100208550) gv  GV (0x100826d28) *foo 

Presumably I need to add entersub, leavesub at the beginning and end of my listops but I am not sure how I would go about constructing this in XS? Nor do I know how to turn the resulting optree in to a CV?

I can find examples of generating a CV for xsubs but not from optrees.

Thanks for your help.

rob
  • 41
  • 1

1 Answers1

0

I'd have a look at what eval does internally, as this is essentially what it does. In particular, op.c and Perl_newPROG( OP *o) might be a good place to start:

void
Perl_newPROG(pTHX_ OP *o)
{
    ...
    PL_eval_root = newUNOP(OP_LEAVEEVAL,
                   ((PL_in_eval & EVAL_KEEPERR)
                ? OPf_SPECIAL : 0), o);
    PL_eval_start = op_linklist(PL_eval_root);
    PL_eval_root->op_private |= OPpREFCOUNTED;
    OpREFCNT_set(PL_eval_root, 1);
    PL_eval_root->op_next = 0;
    CALL_PEEP(PL_eval_start);
    ...
Alex
  • 5,863
  • 2
  • 29
  • 46