Implement distributivity in $scalar ~~ @array
Rafael Garcia-Suarez [Sat, 9 May 2009 13:09:39 +0000 (15:09 +0200)]
Note that undef ~~ @array is not distributive, it only tests for
definedness of array elements.

pp_ctl.c
t/op/smartmatch.t

index 6a5ea65..46636f7 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4303,28 +4303,19 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
            destroy_matcher(matcher);
            RETPUSHNO;
        }
-       else if (SvNIOK(d)) {
+       else if (!SvOK(d)) {
+           /* undef ~~ array */
+           const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
            I32 i;
 
-           for(i = 0; i <= AvFILL(MUTABLE_AV(SvRV(e))); ++i) {
+           for (i = 0; i <= this_len; ++i) {
                SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
-               if (!svp)
-                   continue;
-               
-               PUSHs(d);
-               PUSHs(*svp);
-               PUTBACK;
-               if (CopHINTS_get(PL_curcop) & HINT_INTEGER)
-                   (void) pp_i_eq();
-               else
-                   (void) pp_eq();
-               SPAGAIN;
-               if (SvTRUEx(POPs))
+               if (!svp || !SvOK(*svp))
                    RETPUSHYES;
            }
            RETPUSHNO;
        }
-       else if (SvPOK(d)) {
+       else {
            const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
            I32 i;
 
@@ -4332,11 +4323,12 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
                SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
                if (!svp)
                    continue;
-               
+
                PUSHs(d);
                PUSHs(*svp);
                PUTBACK;
-               (void) pp_seq();
+               /* infinite recursion isn't supposed to happen here */
+               (void) do_smartmatch(NULL, NULL);
                SPAGAIN;
                if (SvTRUEx(POPs))
                    RETPUSHYES;
index 8047451..2c6e5f1 100644 (file)
@@ -13,6 +13,7 @@ use Tie::Hash;
 # Predeclare vars used in the tests:
 my @empty;
 my %empty;
+my @sparse; $sparse[2] = 2;
 
 my $deep1 = []; push @$deep1, \$deep1;
 my $deep2 = []; push @$deep2, \$deep2;
@@ -331,7 +332,7 @@ __DATA__
 !      /bar/           @fooormore
 
 # - a number
-       2               [qw(1foo 2bar)]
+       2               [qw(1.00 2.00)]
        2               [qw(foo 2)]
        2.0_0e+0        [qw(foo 2)]
 !      2               [qw(1foo bar2)]
@@ -340,6 +341,18 @@ __DATA__
 !      "2"             [qw(1foo 2bar)]
        "2bar"          [qw(1foo 2bar)]
 
+# - undef
+       undef           [1, 2, undef, 4]
+!      undef           [1, 2, [undef], 4]
+!      undef           @fooormore
+       undef           @sparse
+
+# - nested arrays and ~~ distributivity
+       11              [[11]]
+!      11              [[12]]
+       "foo"           [{foo => "bar"}]
+!      "bar"           [{foo => "bar"}]
+
 # Number against number
        2               2
        20              2_0