summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2014-03-05 14:19:33 +0000
committerDavid Mitchell <davem@iabyn.com>2014-03-16 18:34:37 +0000
commit22240f589eab50022218e3541b91a487c29a729b (patch)
treed3556abef8cd6b5c4f32d4d64c63d83c3fd8bff3 /op.c
parent61eef0f5eac901e462178b0556cbaacb988b8a58 (diff)
downloadperl-22240f589eab50022218e3541b91a487c29a729b.tar.gz
rpeep(): OP_SORT with code block has OPf_SPECIAL
In rpeep(), we check whether the OP_SORT has a code block as the first arg (e.g. sort {BLOCK} ...) by testing for OPf_STACKED, then looking for an OP_SCOPE or ex-OP_LEAVE. However, ck_sort() has already checked for this situation and set the OPf_SPECIAL flag. So just just check for this flag in rpeep(); leave in the OP_SCOPE/ex-OP_LEAVE checks as just assertions. Also, add some commentary to ck_sort() and S_simplify_sort().
Diffstat (limited to 'op.c')
-rw-r--r--op.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/op.c b/op.c
index a6488b065a..10d7da0121 100644
--- a/op.c
+++ b/op.c
@@ -9962,9 +9962,12 @@ Perl_ck_sort(pTHX_ OP *o)
if (o->op_flags & OPf_STACKED)
simplify_sort(o);
firstkid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
+
if ((stacked = o->op_flags & OPf_STACKED)) { /* may have been cleared */
OP *kid = cUNOPx(firstkid)->op_first; /* get past null */
+ /* if the first arg is a code block, process it and mark sort as
+ * OPf_SPECIAL */
if (kid->op_type == OP_SCOPE || kid->op_type == OP_LEAVE) {
LINKLIST(kid);
if (kid->op_type == OP_LEAVE)
@@ -9991,6 +9994,16 @@ Perl_ck_sort(pTHX_ OP *o)
return o;
}
+/* for sort { X } ..., where X is one of
+ * $a <=> $b, $b <= $a, $a cmp $b, $b cmp $a
+ * elide the second child of the sort (the one containing X),
+ * and set these flags as appropriate
+ OPpSORT_NUMERIC;
+ OPpSORT_INTEGER;
+ OPpSORT_DESCEND;
+ * Also, check and warn on lexical $a, $b.
+ */
+
STATIC void
S_simplify_sort(pTHX_ OP *o)
{
@@ -11883,12 +11896,14 @@ Perl_rpeep(pTHX_ OP *o)
case OP_SORT: {
OP *oright;
- if (o->op_flags & OPf_STACKED) {
- OP * const kid =
- cUNOPx(cLISTOP->op_first->op_sibling)->op_first;
- if (kid->op_type == OP_SCOPE
- || (kid->op_type == OP_NULL && kid->op_targ == OP_LEAVE))
- DEFER(kLISTOP->op_first);
+ if (o->op_flags & OPf_SPECIAL) {
+ /* first arg is a code block */
+ OP * const nullop = cLISTOP->op_first->op_sibling;
+ OP * const kid = cUNOPx(nullop)->op_first;
+ assert(nullop->op_type == OP_NULL);
+ assert(kid->op_type == OP_SCOPE
+ || (kid->op_type == OP_NULL && kid->op_targ == OP_LEAVE));
+ DEFER(kLISTOP->op_first);
}
/* check that RHS of sort is a single plain array */