From: Rafael Garcia-Suarez Date: Mon, 23 Mar 2009 23:27:32 +0000 (+0100) Subject: Implement "~~ $scalar" for numbers and strings X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=33ed63a220e7fd3d10f2504723eeeef68371efe8;p=p5sagit%2Fp5-mst-13.2.git Implement "~~ $scalar" for numbers and strings Make documentation more precise about the different cases, and add tests. --- diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index 5b1af05..a51a67d 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -705,9 +705,8 @@ entries apply in those cases. undef Range[4] always false Any Range[4] in string range - Num numish[5] numeric equality $a == $b - Any Str string equality $a eq $b Any Num numeric equality $a == $b + Num numish[5] numeric equality $a == $b Any Any string equality $a eq $b diff --git a/pp_ctl.c b/pp_ctl.c index 74881c0..8908850 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -4026,7 +4026,6 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) SV *e = TOPs; /* e is for 'expression' */ SV *d = TOPm1s; /* d is for 'default', as in PL_defgv */ - SV *This, *Other; /* 'This' (and Other to match) to play with C++ */ # define SM_SEEN_THIS(sv) hv_exists_ent(seen_this, \ sv_2mortal(newSViv(PTR2IV(sv))), 0) @@ -4154,35 +4153,35 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) bool other_tied = FALSE; U32 this_key_count = 0, other_key_count = 0; - This = SvRV(e); + HV *hv = MUTABLE_HV(SvRV(e)); /* Tied hashes don't know how many keys they have. */ - if (SvTIED_mg(This, PERL_MAGIC_tied)) { + if (SvTIED_mg((SV*)hv, PERL_MAGIC_tied)) { tied = TRUE; } else if (SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied)) { HV * const temp = other_hv; - other_hv = MUTABLE_HV(This); - This = MUTABLE_SV(temp); + other_hv = hv; + hv = temp; tied = TRUE; } if (SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied)) other_tied = TRUE; - if (!tied && HvUSEDKEYS((const HV *) This) != HvUSEDKEYS(other_hv)) + if (!tied && HvUSEDKEYS((const HV *) hv) != HvUSEDKEYS(other_hv)) RETPUSHNO; /* The hashes have the same number of keys, so it suffices to check that one is a subset of the other. */ - (void) hv_iterinit(MUTABLE_HV(This)); - while ( (he = hv_iternext(MUTABLE_HV(This))) ) { + (void) hv_iterinit(hv); + while ( (he = hv_iternext(hv)) ) { I32 key_len; char * const key = hv_iterkey(he, &key_len); ++ this_key_count; if(!hv_exists(other_hv, key, key_len)) { - (void) hv_iterinit(MUTABLE_HV(This)); /* reset iterator */ + (void) hv_iterinit(hv); /* reset iterator */ RETPUSHNO; } } @@ -4204,7 +4203,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) AV * const other_av = MUTABLE_AV(SvRV(d)); const I32 other_len = av_len(other_av) + 1; I32 i; - This = SvRV(e); + HV *hv = MUTABLE_HV(SvRV(e)); for (i = 0; i < other_len; ++i) { SV ** const svp = av_fetch(other_av, i, FALSE); @@ -4213,7 +4212,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) if (svp) { /* ??? When can this not happen? */ key = SvPV(*svp, key_len); - if (hv_exists(MUTABLE_HV(This), key, key_len)) + if (hv_exists(hv, key, key_len)) RETPUSHYES; } } @@ -4222,12 +4221,12 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_REGEXP) { PMOP * const matcher = make_matcher((REGEXP*) SvRV(d)); HE *he; - This = SvRV(e); + HV *hv = MUTABLE_HV(SvRV(e)); - (void) hv_iterinit(MUTABLE_HV(This)); - while ( (he = hv_iternext(MUTABLE_HV(This))) ) { + (void) hv_iterinit(hv); + while ( (he = hv_iternext(hv)) ) { if (matcher_matches_sv(matcher, hv_iterkeysv(he))) { - (void) hv_iterinit(MUTABLE_HV(This)); + (void) hv_iterinit(hv); destroy_matcher(matcher); RETPUSHYES; } @@ -4244,7 +4243,6 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) } /* ~~ @array */ else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVAV) { - This = SvRV(e); if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) { AV * const other_av = MUTABLE_AV(SvRV(e)); const I32 other_len = av_len(other_av) + 1; @@ -4329,7 +4327,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) destroy_matcher(matcher); RETPUSHNO; } - else if (SvIOK(d) || SvNOK(d)) { + else if (SvNIOK(d)) { I32 i; for(i = 0; i <= AvFILL(MUTABLE_AV(SvRV(e))); ++i) { @@ -4383,16 +4381,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) } /* ~~ X..Y TODO */ /* ~~ scalar */ - else if ( ((SvIOK(d) || SvNOK(d)) && (This = d) && (Other = e)) - || ((SvIOK(e) || SvNOK(e)) && (This = e) && (Other = d)) ) - { - if (SvPOK(Other) && !looks_like_number(Other)) { - /* String comparison */ - PUSHs(d); PUSHs(e); - PUTBACK; - return pp_seq(); - } - /* Otherwise, numeric comparison */ + else if (SvNIOK(e) || (SvPOK(e) && looks_like_number(e) && SvNIOK(d))) { + /* numeric comparison */ PUSHs(d); PUSHs(e); PUTBACK; if (CopHINTS_get(PL_curcop) & HINT_INTEGER) diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t index 8123246..adf1c50 100644 --- a/t/op/smartmatch.t +++ b/t/op/smartmatch.t @@ -302,15 +302,17 @@ __DATA__ # Number against number 2 2 + 20 2_0 ! 2 3 0 FALSE 3-2 TRUE + undef 0 # Number against string - 2 "2" - 2 "2.0" += 2 "2" += 2 "2.0" ! 2 "2bananas" -! 2_3 "2_3" +!= 2_3 "2_3" FALSE "0" # Regex against string