summaryrefslogtreecommitdiff
path: root/op.h
diff options
context:
space:
mode:
authorSteffen Mueller <smueller@cpan.org>2014-02-21 18:58:04 +0100
committerSteffen Mueller <smueller@cpan.org>2014-02-26 21:05:27 +0100
commit11ee9dd668c24ff655cfec47610c8939e74a8506 (patch)
tree03d1c62d215de5ed152f0baee1cfe8219e1329a8 /op.h
parent1472fa3142752a63cd8ba4fe348df51f378213e6 (diff)
downloadperl-11ee9dd668c24ff655cfec47610c8939e74a8506.tar.gz
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.
Diffstat (limited to 'op.h')
-rw-r--r--op.h41
1 files changed, 38 insertions, 3 deletions
diff --git a/op.h b/op.h
index ed9609dddf..a1c3c59340 100644
--- a/op.h
+++ b/op.h
@@ -1006,8 +1006,23 @@ to the registree to ensure it is accurate. The value returned will be
one of the OA_* constants from op.h.
=for apidoc Am|bool|OP_TYPE_IS|OP *o, Optype type
-Returns true if the given OP is not NULL and if it is of the given
-type.
+Returns true if the given OP is not a NULL pointer
+and if it is of the given type.
+
+The negation of this macro, C<OP_TYPE_ISNT> is also available
+as well as C<OP_TYPE_IS_NN> and C<OP_TYPE_ISNT_NN> which elide
+the NULL pointer check.
+
+=for apidoc Am|bool|OP_TYPE_IS_OR_WAS|OP *o, Optype type
+Returns true if the given OP is not a NULL pointer and
+if it is of the given type or used to be before being
+replaced by an OP of type OP_NULL.
+
+The negation of this macro, C<OP_TYPE_ISNT_AND_WASNT>
+is also available as well as C<OP_TYPE_IS_OR_WAS_NN>
+and C<OP_TYPE_ISNT_AND_WASNT_NN> which elide
+the NULL pointer check.
+
=cut
*/
@@ -1022,7 +1037,27 @@ type.
: (PL_opargs[(o)->op_type] & OA_CLASS_MASK))
#define OP_TYPE_IS(o, type) ((o) && (o)->op_type == (type))
-
+#define OP_TYPE_IS_NN(o, type) ((o)->op_type == (type))
+#define OP_TYPE_ISNT(o, type) ((o) && (o)->op_type != (type))
+#define OP_TYPE_ISNT_NN(o, type) ((o)->op_type != (type))
+
+#define OP_TYPE_IS_OR_WAS_NN(o, type) \
+ ( ((o)->op_type == OP_NULL \
+ ? (o)->op_targ \
+ : (o)->op_type) \
+ == (type) )
+
+#define OP_TYPE_IS_OR_WAS(o, type) \
+ ( (o) && OP_TYPE_IS_OR_WAS_NN(o, type) )
+
+#define OP_TYPE_ISNT_AND_WASNT_NN(o, type) \
+ ( ((o)->op_type == OP_NULL \
+ ? (o)->op_targ \
+ : (o)->op_type) \
+ != (type) )
+
+#define OP_TYPE_ISNT_AND_WASNT(o, type) \
+ ( (o) && OP_TYPE_ISNT_AND_WASNT_NN(o, type) )
#define newATTRSUB(f, o, p, a, b) Perl_newATTRSUB_x(aTHX_ f, o, p, a, b, FALSE)
#define newSUB(f, o, p, b) newATTRSUB((f), (o), (p), NULL, (b))