diff options
-rw-r--r-- | mathoms.c | 14 | ||||
-rw-r--r-- | op.c | 15 | ||||
-rw-r--r-- | op.h | 46 | ||||
-rw-r--r-- | pod/perlguts.pod | 77 |
4 files changed, 148 insertions, 4 deletions
@@ -1555,6 +1555,20 @@ Perl_sv_2bool(pTHX_ register SV *const sv) } +/* +=for apidoc custom_op_name +Return the name for a given custom op. This was once used by the OP_NAME +macro, but is no longer: it has only been kept for compatibility, and +should not be used. + +=for apidoc custom_op_desc +Return the description of a given custom op. This was once used by the +OP_DESC macro, but is no longer: it has only been kept for +compatibility, and should not be used. + +=cut +*/ + const char* Perl_custom_op_name(pTHX_ const OP* o) { @@ -10041,6 +10041,16 @@ Perl_peep(pTHX_ register OP *o) CALL_RPEEP(o); } +/* +=head1 Custom Operators + +=for apidoc Ao||custom_op_xop +Return the XOP structure for a given custom op. This function should be +considered internal to OP_NAME and the other access macros: use them instead. + +=cut +*/ + const XOP * Perl_custom_op_xop(pTHX_ const OP *o) { @@ -10091,7 +10101,12 @@ Perl_custom_op_xop(pTHX_ const OP *o) return xop; } +/* +=for apidoc Ao||custom_op_register +Register a custom op. See L<perlguts/"Custom Operators">. +=cut +*/ void Perl_custom_op_register(pTHX_ Perl_ppaddr_t ppaddr, const XOP *xop) @@ -760,6 +760,31 @@ preprocessing token; the type of I<arg> depends on I<which>. #define RV2CVOPCV_MARK_EARLY 0x00000001 #define RV2CVOPCV_RETURN_NAME_GV 0x00000002 +/* +=head1 Custom Operators + +=for apidoc Am|U32|XopFLAGS|XOP *xop +Return the XOP's flags. + +=for apidoc Am||XopENTRY|XOP *xop|which +Return a member of the XOP structure. I<which> is a cpp token indicating +which entry to return. If the member is not set this will return a +default value. The return type depends on I<which>. + +=for apidoc Am|void|XopENTRY_set|XOP *xop|which|value +Set a member of the XOP structure. I<which> is a cpp token indicating +which entry to set. See L<perlguts/"Custom Operators"> for details about +the available members and how they are used. + +=for apidoc Am|void|XopDISABLE|XOP *xop|which +Temporarily disable a member of the XOP, by clearing the appropriate flag. + +=for apidoc Am|void|XopENABLE|XOP *xop|which +Reenable a member of the XOP which has been disabled. + +=cut +*/ + struct custom_op { U32 xop_flags; const char *xop_name; @@ -796,6 +821,27 @@ struct custom_op { assert(XopENTRY(xop, which)); \ } STMT_END +/* +=head1 Optree Manipulation Functions + +=for apidoc Am|const char *|OP_NAME|OP *o +Return the name of the provided OP. For core ops this looks up the name +from the op_type; for custom ops from the op_ppaddr. + +=for apidoc Am|const char *|OP_DESC|OP *o +Return a short description of the provided OP. + +=for apidoc Am|U32|OP_CLASS|OP *o +Return the class of the provided OP: that is, which of the *OP +structures it uses. For core ops this currently gets the information out +of PL_opargs, which does not always accurately reflect the type used. +For custom ops the type is returned from the registration, and it is up +to the registree to ensure it is accurate. The value returned will be +one of the OA_* constants from op.h. + +=cut +*/ + #define OP_NAME(o) ((o)->op_type == OP_CUSTOM \ ? XopENTRY(Perl_custom_op_xop(aTHX_ o), xop_name) \ : PL_op_name[(o)->op_type]) diff --git a/pod/perlguts.pod b/pod/perlguts.pod index 078eb68af0..b56811ccf0 100644 --- a/pod/perlguts.pod +++ b/pod/perlguts.pod @@ -2765,10 +2765,79 @@ responsible for adding stack marks if necessary. You should also "register" your op with the Perl interpreter so that it can produce sensible error and warning messages. Since it is possible to have multiple custom ops within the one "logical" op type C<OP_CUSTOM>, -Perl uses the value of C<< o->op_ppaddr >> as a key into the -C<PL_custom_op_descs> and C<PL_custom_op_names> hashes. This means you -need to enter a name and description for your op at the appropriate -place in the C<PL_custom_op_names> and C<PL_custom_op_descs> hashes. +Perl uses the value of C<< o->op_ppaddr >> to determine which custom op +it is dealing with. You should create an C<XOP> structure for each +ppaddr you use, set the properties of the custom op with +C<XopENTRY_set>, and register the structure against the ppaddr using +C<Perl_custom_op_register>. A trivial example might look like: + + static XOP my_xop; + static OP *my_pp(pTHX); + + BOOT: + XopENTRY_set(&my_xop, xop_name, "myxop"); + XopENTRY_set(&my_xop, xop_desc, "Useless custom op"); + Perl_custom_op_register(aTHX_ my_pp, &my_xop); + +The available fields in the structure are: + +=over 4 + +=item xop_name + +A short name for your op. This will be included in some error messages, +and will also be returned as C<< $op->name >> by the L<B|B> module, so +it will appear in the output of module like L<B::Concise|B::Concise>. + +=item xop_desc + +A short description of the function of the op. + +=item xop_class + +Which of the various C<*OP> structures this op uses. This should be one of +the C<OA_*> constants from F<op.h>, namely + +=over 4 + +=item OA_BASEOP + +=item OA_UNOP + +=item OA_BINOP + +=item OA_LOGOP + +=item OA_LISTOP + +=item OA_PMOP + +=item OA_SVOP + +=item OA_PADOP + +=item OA_PVOP_OR_SVOP + +This should be interpreted as 'C<PVOP>' only. The C<_OR_SVOP> is because +the only core C<PVOP>, C<OP_TRANS>, can sometimes be a C<SVOP> instead. + +=item OA_LOOP + +=item OA_COP + +=back + +The other C<OA_*> constants should not be used. + +=item xop_peep + +This member is of type C<Perl_cpeep_t>, which expands to C<void +(*Perl_cpeep_t)(aTHX_ OP *o, OP *oldop)>. If it is set, this function +will be called from C<Perl_rpeep> when ops of this type are encountered +by the peephole optimizer. I<o> is the OP that needs optimizing; +I<oldop> is the previous OP optimized, whose C<op_next> points to I<o>. + +=back C<B::Generate> directly supports the creation of custom ops by name. |