diff options
author | David Mitchell <davem@iabyn.com> | 2014-03-05 14:19:33 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-03-16 18:34:37 +0000 |
commit | 22240f589eab50022218e3541b91a487c29a729b (patch) | |
tree | d3556abef8cd6b5c4f32d4d64c63d83c3fd8bff3 /op.c | |
parent | 61eef0f5eac901e462178b0556cbaacb988b8a58 (diff) | |
download | perl-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.c | 27 |
1 files changed, 21 insertions, 6 deletions
@@ -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 */ |