combine regex concat overload loops
authorDavid Mitchell <davem@iabyn.com>
Tue, 16 Apr 2013 10:34:54 +0000 (11:34 +0100)
committerDavid Mitchell <davem@iabyn.com>
Sat, 20 Apr 2013 16:23:12 +0000 (17:23 +0100)
Currently when the components of a runtime regex (e.g. the "a", $x, "-"
in /a$x-/) are concatenated into a single pattern string, the handling of
magic and various types of overloading is done within two separate loops:
(in perlish pseudocode):

    foreach (@arg) {
        SvGETMAGIC($_);
        apply 'qr' overloading to $_;
    }
    foreach (@arg) {
        $pat .= $_, allowing for '.' and '""' overloading;
    }

This commit changes it to:

    foreach (@arg) {
        SvGETMAGIC($_);
        apply 'qr' overloading to $_;
        $pat .= $_, allowing for '.' and '""' overloading;
    }

Note that this is in theory a user-visible change in behaviour, since
the order in which various perl-level tie and overload functions get
called may change. But that was just a quirk of the current
implementation, rather than a documented feature.

regcomp.c

index 5af9f2b..41fe970 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -4986,6 +4986,20 @@ S_concat_pat(pTHX_ RExC_state_t * const pRExC_state,
             oplist = oplist->op_sibling;;
         }
 
+       /* apply magic and QR overloading to arg */
+
+        SvGETMAGIC(msv);
+        if (SvROK(msv) && SvAMAGIC(msv)) {
+            SV *sv = AMG_CALLunary(msv, regexp_amg);
+            if (sv) {
+                if (SvROK(sv))
+                    sv = SvRV(sv);
+                if (SvTYPE(sv) != SVt_REGEXP)
+                    Perl_croak(aTHX_ "Overloaded qr did not return a REGEXP");
+                msv = sv;
+            }
+        }
+
         /* try concatenation overload ... */
         if (pat && (SvAMAGIC(pat) || SvAMAGIC(msv)) &&
                 (sv = amagic_call(pat, msv, concat_amg, AMGf_assign)))
@@ -5552,29 +5566,12 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
     {
        /* concat args, handling magic, overloading etc */
 
-       SV **svp;
         OP *o = NULL;
 
         DEBUG_PARSE_r(PerlIO_printf(Perl_debug_log,
             "Assembling pattern from %d elements%s\n", pat_count,
                 orig_rx_flags & RXf_SPLIT ? " for split" : ""));
 
-       /* apply magic and RE overloading to each arg */
-       for (svp = new_patternp; svp < new_patternp + pat_count; svp++) {
-           SV *rx = *svp;
-           SvGETMAGIC(rx);
-           if (SvROK(rx) && SvAMAGIC(rx)) {
-               SV *sv = AMG_CALLunary(rx, regexp_amg);
-               if (sv) {
-                   if (SvROK(sv))
-                       sv = SvRV(sv);
-                   if (SvTYPE(sv) != SVt_REGEXP)
-                       Perl_croak(aTHX_ "Overloaded qr did not return a REGEXP");
-                   *svp = sv;
-               }
-           }
-       }
-
         if (pRExC_state->num_code_blocks) {
             if (expr->op_type == OP_CONST)
                 o = expr;