Subject: | [PATCH] Fix for bleadperl and more |
The attached file contains four patches, which are self-explanatory. You should be able to feed the attachment straight to ‘git am’ to apply them all at once.
I have not tested these patches fully except in bleadperl.
Subject: | patches.txt |
From: Father Chrysostomos <sprout@cpan.org>
op_lastsib support
In bleadperl, ops now have a lastsib field and debugging builds will
fail assertions if it has the wrong value.
The new op_sibling_splice function takes care of setting op_lastsib,
so use it for op_sibling manipulation where appropriate.
(Some cases of op_sibling manipulation weren’t causing any assertion
failures, so I left them as they were.)
diff -rup Params-Lazy-0.005-fW8fCO-orig/Lazy.xs Params-Lazy-0.005-fW8fCO/Lazy.xs
--- Params-Lazy-0.005-fW8fCO-orig/Lazy.xs 2014-10-25 22:20:10.000000000 -0700
+++ Params-Lazy-0.005-fW8fCO/Lazy.xs 2014-10-25 23:20:48.000000000 -0700
@@ -779,21 +779,18 @@ use_caller_args_hint(pTHX)
}
STATIC OP *
-replace_with_delayed(pTHX_ OP* aop) {
+wrap_with_delayed(pTHX_ OP* aop) {
MAGIC *mg;
- OP* new_op;
OP* const kid = aop;
- OP* const sib = kid->op_sibling;
SV* magic_sv = newSVpvs("STATEMENT");
OP *listop;
delay_ctx *ctx;
Newx(ctx, 1, delay_ctx);
- /* Disconnect the op we're delaying, then wrap it in
+ /* Wrap the op we're delaying in
* a OP_LIST
*/
- kid->op_sibling = 0;
/* Make GIMME in the deferred op be OPf_WANT_LIST */
op_contextualize(kid, G_ARRAY);
@@ -846,9 +843,7 @@ replace_with_delayed(pTHX_ OP* aop) {
/* Then put that SV place of the OPs we removed, but wrap
* as a ref.
*/
- new_op = (OP*)newSVOP(OP_CONST, 0, newRV_noinc(magic_sv));
- new_op->op_sibling = sib;
- return new_op;
+ return (OP*)newSVOP(OP_CONST, 0, newRV_noinc(magic_sv));
}
static OP *
@@ -898,13 +893,24 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
STRLEN protolen, len = 0;
char * protopv = SvPV(proto, protolen);
OP *aop, *prev;
+#ifdef op_sibling_splice
+ OP *parent;
+#endif
PERL_UNUSED_ARG(namegv);
aop = cUNOPx(entersubop)->op_first;
- if (!aop->op_sibling)
+ if (!aop->op_sibling) {
+#ifdef op_sibling_splice
+ parent = aop;
+#endif
aop = cUNOPx(aop)->op_first;
+ }
+#ifdef op_sibling_splice
+ else
+ parent = entersubop;
+#endif
prev = aop;
@@ -919,8 +925,17 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
/* Fallthrough */
case '^':
{
- aop = replace_with_delayed(aTHX_ aop);
+#ifdef op_sibling_splice
+ op_sibling_splice(parent, prev, 1, NULL);
+ aop = wrap_with_delayed(aTHX_ aop);
+ op_sibling_splice(parent, prev, 0, aop);
+#else
+ OP * const sib = aop->op_sibling;
+ aop->op_sibling = NULL;
+ aop = wrap_with_delayed(aTHX_ aop);
prev->op_sibling = aop;
+ aop->op_sibling = sib;
+#endif
protopv[len] = '$';
break;
}
@@ -943,11 +958,22 @@ THX_ck_delay_caller_args(pTHX_ OP *enter
OP* op = THX_ck_delay(aTHX_ entersubop, namegv, ckobj);
UNOP *newop;
OP *aop;
+#ifdef op_sibling_splice
+ OP *parent;
+#endif
aop = cUNOPx(op)->op_first;
- if (!aop->op_sibling)
+ if (!aop->op_sibling) {
+#ifdef op_sibling_splice
+ parent = aop;
+#endif
aop = cUNOPx(aop)->op_first;
+ }
+#ifdef op_sibling_splice
+ else
+ parent = op;
+#endif
for (aop = aop->op_sibling; aop->op_sibling; aop = aop->op_sibling) {
}
@@ -957,7 +983,11 @@ THX_ck_delay_caller_args(pTHX_ OP *enter
newop->op_ppaddr = S_pp_delay;
newop->op_private = use_caller_args_hint();
+#ifdef op_sibling_splice
+ op_sibling_splice(parent, aop, 0, (OP *)newop);
+#else
aop->op_sibling = (OP*)newop;
+#endif
return op;
}
From: Father Chrysostomos <sprout@cpan.org>
List refgen support
diff -rup Params-Lazy-0.005-fW8fCO-orig/Lazy.xs Params-Lazy-0.005-9c4xOW/Lazy.xs
--- Params-Lazy-0.005-fW8fCO-orig/Lazy.xs 2014-10-25 22:20:10.000000000 -0700
+++ Params-Lazy-0.005-9c4xOW/Lazy.xs 2014-10-25 23:33:24.000000000 -0700
@@ -912,7 +912,9 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
if ( len < protolen ) {
switch ( protopv[len] ) {
case ':':
- if ( aop->op_type == OP_REFGEN ) {
+ if ( aop->op_type == OP_REFGEN
+ && cUNOPx(cUNOPx(aop)->op_first)->op_first
+ ->op_sibling->op_type == OP_ANONCODE ) {
protopv[len] = '&';
break;
}
diff -rup Params-Lazy-0.005-fW8fCO-orig/t/10-prototypes.t Params-Lazy-0.005-9c4xOW/t/10-prototypes.t
--- Params-Lazy-0.005-fW8fCO-orig/t/10-prototypes.t 2013-08-27 15:55:46.000000000 -0700
+++ Params-Lazy-0.005-9c4xOW/t/10-prototypes.t 2014-10-25 23:30:23.000000000 -0700
@@ -34,6 +34,12 @@ is_deeply(
'fakemap \"_${_}_"'
);
+is_deeply(
+ [fakemap \($_,$_), 1..10],
+ [ map \($_,$_), 1..10],
+ 'fakemap \($_,$_) (refgen, not srefgen)'
+);
+
TODO: {
local $TODO = "fakemap sub {}, 1; differs from map sub {}, 1";
is_deeply(
From: Father Chrysostomos <sprout@cpan.org>
perl 5.21.5 uses srefgen for anoncode
diff -rup Params-Lazy-0.005-fW8fCO/Lazy.xs Params-Lazy-0.005-fW8fCO-copy/Lazy.xs
--- Params-Lazy-0.005-fW8fCO/Lazy.xs 2014-10-25 23:36:26.000000000 -0700
+++ Params-Lazy-0.005-fW8fCO-copy/Lazy.xs 2014-10-25 23:41:54.000000000 -0700
@@ -918,11 +918,28 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
if ( len < protolen ) {
switch ( protopv[len] ) {
case ':':
+ /* Under perl 5.21.5:
+ *
+ * srefgen
+ * ex-list
+ * anoncode
+ *
+ * Under earlier perls:
+ *
+ * refgen
+ * ex-list
+ * pushmark
+ * anoncode
+ */
if ( aop->op_type == OP_REFGEN
- && cUNOPx(cUNOPx(aop)->op_first)->op_first
- ->op_sibling->op_type == OP_ANONCODE ) {
+ || aop->op_type == OP_SREFGEN ) {
+ OP *kid = cUNOPx(cUNOPx(aop)->op_first)->op_first;
+ if ( aop->op_type == OP_PUSHMARK )
+ kid = aop->op_sibling;
+ if (kid->op_type == OP_ANONCODE ) {
protopv[len] = '&';
break;
+ }
}
/* Fallthrough */
case '^':
From: Father Chrysostomos <sprout@cpan.org>
: sub{} support
This allows mymap sub {}, LIST to work just like map.
diff -rup Params-Lazy-0.005-fW8fCO-copy/Lazy.xs Params-Lazy-0.005-fW8fCO-copy2/Lazy.xs
--- Params-Lazy-0.005-fW8fCO-copy/Lazy.xs 2014-10-25 23:41:54.000000000 -0700
+++ Params-Lazy-0.005-fW8fCO-copy2/Lazy.xs 2014-10-25 23:54:25.000000000 -0700
@@ -893,24 +893,18 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
STRLEN protolen, len = 0;
char * protopv = SvPV(proto, protolen);
OP *aop, *prev;
-#ifdef op_sibling_splice
OP *parent;
-#endif
PERL_UNUSED_ARG(namegv);
aop = cUNOPx(entersubop)->op_first;
if (!aop->op_sibling) {
-#ifdef op_sibling_splice
parent = aop;
-#endif
aop = cUNOPx(aop)->op_first;
}
-#ifdef op_sibling_splice
else
parent = entersubop;
-#endif
prev = aop;
@@ -936,7 +930,15 @@ THX_ck_delay(pTHX_ OP *entersubop, GV *n
OP *kid = cUNOPx(cUNOPx(aop)->op_first)->op_first;
if ( aop->op_type == OP_PUSHMARK )
kid = aop->op_sibling;
- if (kid->op_type == OP_ANONCODE ) {
+ if ( kid->op_type == OP_ANONCODE
+ /* Evil hack.
+ mymap sub {} LIST puts ex-rv2cv is scalar cx
+ mymap {} LIST puts ex-rv2cv in no cx
+ That's true for 5.8.8 to 5.21.5. Let's hope
+ it stays that way.
+ */
+ && !(cLISTOPx(parent)->op_last->op_flags
+ & OPf_WANT) ) {
protopv[len] = '&';
break;
}
diff -rup Params-Lazy-0.005-fW8fCO-copy/lib/Params/Lazy.pm Params-Lazy-0.005-fW8fCO-copy2/lib/Params/Lazy.pm
--- Params-Lazy-0.005-fW8fCO-copy/lib/Params/Lazy.pm 2013-09-19 09:15:37.000000000 -0700
+++ Params-Lazy-0.005-fW8fCO-copy2/lib/Params/Lazy.pm 2014-10-25 23:45:14.000000000 -0700
@@ -185,16 +185,6 @@ Runs the delayed code.
=item *
-When using the C<:> prototype, these two cases are indistinguishable:
-
- myfunction { ... }
- myfunction sub { ... }
-
-Which means that C<mymap sub { ... }, 1..10> will work
-differently than the default map.
-
-=item *
-
It's important to note that delayed arguments are C<*not*> closures,
so storing them for later use will likely lead to crashes, segfaults,
and a general feeling of malignancy to descend upon you, your family,
diff -rup Params-Lazy-0.005-fW8fCO-copy/t/10-prototypes.t Params-Lazy-0.005-fW8fCO-copy2/t/10-prototypes.t
--- Params-Lazy-0.005-fW8fCO-copy/t/10-prototypes.t 2014-10-25 23:36:26.000000000 -0700
+++ Params-Lazy-0.005-fW8fCO-copy2/t/10-prototypes.t 2014-10-25 23:44:54.000000000 -0700
@@ -40,14 +40,11 @@ is_deeply(
'fakemap \($_,$_) (refgen, not srefgen)'
);
-TODO: {
- local $TODO = "fakemap sub {}, 1; differs from map sub {}, 1";
- is_deeply(
+is_deeply(
[map ref, fakemap sub { "_${_}_"}, 1..10],
[map ref, map sub { "_${_}_"}, 1..10],
'fakemap sub {}'
- );
-}
+);
is_deeply(
[fakemap [ "_${_}_" ], 1..10],