Skip to content

Commit 11ee9dd

Browse files
committed
Macro for common OP checks: "is this X or was it before NULLing?"
For example, if (OP_TYPE_IS_OR_WAS(o, OP_LIST)) ... is now available instead of either of the following: if ( o && ( o->op_type == OP_LIST || (o->op_type == OP_NULL && o->op_targ == OP_LIST) ) ) ... if ( o && (o->op_type == OP_NULL ? o->op_targ ? o->op_type) == OP_LIST ) ... In case the above logic is a bit unclear: It checks whether that OP is an OP_LIST or used to be one before being NULLed using op_null. (FTR, the resulting OP_NULLs have their op_targ set to the old OP type). This sort of check (and it's reverse "isn't and didn't use to be") are a relatively common pattern in the part of op.c that tries to intuit structures from optimization-mangled OP trees. Hopefully, using these macros will make some code a fair amount clearer.
1 parent 1472fa3 commit 11ee9dd

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

op.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5777,8 +5777,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
57775777
o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop);
57785778
o->op_private = (U8)(0 | (flags >> 8));
57795779

5780-
if ((left->op_type == OP_LIST
5781-
|| (left->op_type == OP_NULL && left->op_targ == OP_LIST)))
5780+
if (OP_TYPE_IS_OR_WAS(left, OP_LIST))
57825781
{
57835782
OP* lop = ((LISTOP*)left)->op_first;
57845783
maybe_common_vars = FALSE;

op.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,8 +1006,23 @@ to the registree to ensure it is accurate. The value returned will be
10061006
one of the OA_* constants from op.h.
10071007
10081008
=for apidoc Am|bool|OP_TYPE_IS|OP *o, Optype type
1009-
Returns true if the given OP is not NULL and if it is of the given
1010-
type.
1009+
Returns true if the given OP is not a NULL pointer
1010+
and if it is of the given type.
1011+
1012+
The negation of this macro, C<OP_TYPE_ISNT> is also available
1013+
as well as C<OP_TYPE_IS_NN> and C<OP_TYPE_ISNT_NN> which elide
1014+
the NULL pointer check.
1015+
1016+
=for apidoc Am|bool|OP_TYPE_IS_OR_WAS|OP *o, Optype type
1017+
Returns true if the given OP is not a NULL pointer and
1018+
if it is of the given type or used to be before being
1019+
replaced by an OP of type OP_NULL.
1020+
1021+
The negation of this macro, C<OP_TYPE_ISNT_AND_WASNT>
1022+
is also available as well as C<OP_TYPE_IS_OR_WAS_NN>
1023+
and C<OP_TYPE_ISNT_AND_WASNT_NN> which elide
1024+
the NULL pointer check.
1025+
10111026
=cut
10121027
*/
10131028

@@ -1022,7 +1037,27 @@ type.
10221037
: (PL_opargs[(o)->op_type] & OA_CLASS_MASK))
10231038

10241039
#define OP_TYPE_IS(o, type) ((o) && (o)->op_type == (type))
1025-
1040+
#define OP_TYPE_IS_NN(o, type) ((o)->op_type == (type))
1041+
#define OP_TYPE_ISNT(o, type) ((o) && (o)->op_type != (type))
1042+
#define OP_TYPE_ISNT_NN(o, type) ((o)->op_type != (type))
1043+
1044+
#define OP_TYPE_IS_OR_WAS_NN(o, type) \
1045+
( ((o)->op_type == OP_NULL \
1046+
? (o)->op_targ \
1047+
: (o)->op_type) \
1048+
== (type) )
1049+
1050+
#define OP_TYPE_IS_OR_WAS(o, type) \
1051+
( (o) && OP_TYPE_IS_OR_WAS_NN(o, type) )
1052+
1053+
#define OP_TYPE_ISNT_AND_WASNT_NN(o, type) \
1054+
( ((o)->op_type == OP_NULL \
1055+
? (o)->op_targ \
1056+
: (o)->op_type) \
1057+
!= (type) )
1058+
1059+
#define OP_TYPE_ISNT_AND_WASNT(o, type) \
1060+
( (o) && OP_TYPE_ISNT_AND_WASNT_NN(o, type) )
10261061

10271062
#define newATTRSUB(f, o, p, a, b) Perl_newATTRSUB_x(aTHX_ f, o, p, a, b, FALSE)
10281063
#define newSUB(f, o, p, b) newATTRSUB((f), (o), (p), NULL, (b))

0 commit comments

Comments
 (0)