From: Rafael Garcia-Suarez <rgarciasuarez@gmail.com>
Date: Wed, 18 Mar 2009 19:20:17 +0000 (+0100)
Subject: Smart match when a hash is on the RHS
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=61a621c635b84b53e4eb7d27f7e28c7cd3bdf7e6;p=p5sagit%2Fp5-mst-13.2.git

Smart match when a hash is on the RHS

This implement the new semantics of C<~~ HASH> smart matching.
This also reveals that overloading actually does not work at all.
Add also tests for C<undef ~~ %hash>.
---

diff --git a/pp_ctl.c b/pp_ctl.c
index 1b4bbf5..3977953 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4161,15 +4161,19 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
 	    RETURN;
 	}
     }
-    else if (SM_REF(PVHV)) {
-	if (SM_OTHER_REF(PVHV)) {
+    else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVHV) {
+	if (!SvOK(d)) {
+	    RETPUSHNO;
+	}
+	else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
 	    /* Check that the key-sets are identical */
 	    HE *he;
-	    HV *other_hv = MUTABLE_HV(SvRV(Other));
+	    HV *other_hv = MUTABLE_HV(SvRV(d));
 	    bool tied = FALSE;
 	    bool other_tied = FALSE;
 	    U32 this_key_count  = 0,
 	        other_key_count = 0;
+	    This = SvRV(e);
 	    
 	    /* Tied hashes don't know how many keys they have. */
 	    if (SvTIED_mg(This, PERL_MAGIC_tied)) {
@@ -4215,10 +4219,11 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
 	    else
 		RETPUSHYES;
 	}
-	else if (SM_OTHER_REF(PVAV)) {
-	    AV * const other_av = MUTABLE_AV(SvRV(Other));
+	else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
+	    AV * const other_av = MUTABLE_AV(SvRV(d));
 	    const I32 other_len = av_len(other_av) + 1;
 	    I32 i;
+	    This = SvRV(e);
 
 	    for (i = 0; i < other_len; ++i) {
 		SV ** const svp = av_fetch(other_av, i, FALSE);
@@ -4233,9 +4238,12 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
 	    }
 	    RETPUSHNO;
 	}
-	else if (SM_OTHER_REGEX) {
+	else if (SvROK(d)
+		&& (SvTYPE(SvRV(d)) == SVt_REGEXP)
+		&& (other_regex = (REGEXP*) SvRV(d))) {
 	    PMOP * const matcher = make_matcher(other_regex);
 	    HE *he;
+	    This = SvRV(e);
 
 	    (void) hv_iterinit(MUTABLE_HV(This));
 	    while ( (he = hv_iternext(MUTABLE_HV(This))) ) {
@@ -4249,7 +4257,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
 	    RETPUSHNO;
 	}
 	else {
-	    if (hv_exists_ent(MUTABLE_HV(This), Other, 0))
+	    if (hv_exists_ent(MUTABLE_HV(SvRV(e)), d, 0))
 		RETPUSHYES;
 	    else
 		RETPUSHNO;
diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t
index 71e565a..a8b387b 100644
--- a/t/op/smartmatch.t
+++ b/t/op/smartmatch.t
@@ -153,15 +153,15 @@ __DATA__
 =	$ov_obj		{"key" => 1}
 =	$ov_obj		{"key" => 1, bar => 2}		TODO
 =!	$ov_obj		{"foo" => 1}
-=	$ov_obj		@keyandmore
+=	$ov_obj		@keyandmore			TODO
 =!	$ov_obj		@fooormore
-=	$ov_obj		["key" => 1]
+=	$ov_obj		["key" => 1]			TODO
 =!	$ov_obj		["foo" => 1]
-=	$ov_obj		/key/
+=	$ov_obj		/key/				TODO
 =!	$ov_obj		/foo/
-=	$ov_obj		qr/Key/i
+=	$ov_obj		qr/Key/i			TODO
 =!	$ov_obj		qr/foo/
-=	$ov_obj		"key"
+=	$ov_obj		"key"				TODO
 =!	$ov_obj		"foo"
 =!	$ov_obj		FALSE
 =!	$ov_obj		TRUE
@@ -261,6 +261,9 @@ __DATA__
 	"foo"		+{foo => 1, bar => 2}
 !	"baz"		+{foo => 1, bar => 2}
 
+#  - undef
+!	undef		%hash
+!	undef		+{"" => "empty key"}
 
 # ARRAY ref against:
 #  - another array ref