summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-05-09 15:25:41 +0200
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-05-09 15:25:41 +0200
commit41e726ac827d803b499877b6a79913968b88cf46 (patch)
treeb5f3f5b68d01a5ff51f839847d9d698f4b8704f2 /pp_ctl.c
parent015eb7b967ac690ef0b530c0aa564f080ff0fa4b (diff)
downloadperl-41e726ac827d803b499877b6a79913968b88cf46.tar.gz
Treat blessed references on the left of C<~~> as scalars
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 46636f787f..c6bb46ab5e 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3997,6 +3997,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
dVAR;
dSP;
+ bool object_on_left = FALSE;
SV *e = TOPs; /* e is for 'expression' */
SV *d = TOPm1s; /* d is for 'default', as in PL_defgv */
@@ -4035,11 +4036,16 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
if (sv_isobject(e) && (SvTYPE(SvRV(e)) != SVt_REGEXP))
Perl_croak(aTHX_ "Smart matching a non-overloaded object breaks encapsulation");
+ if (sv_isobject(d) && (SvTYPE(SvRV(d)) != SVt_REGEXP))
+ object_on_left = TRUE;
/* ~~ sub */
if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVCV) {
I32 c;
- if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
+ if (object_on_left) {
+ goto sm_any_sub; /* Treat objects like scalars */
+ }
+ else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
/* Test sub truth for each key */
HE *he;
bool andedresults = TRUE;
@@ -4098,6 +4104,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
RETPUSHNO;
}
else {
+ sm_any_sub:
ENTER;
SAVETMPS;
PUSHMARK(SP);
@@ -4116,7 +4123,10 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
}
/* ~~ %hash */
else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVHV) {
- if (!SvOK(d)) {
+ if (object_on_left) {
+ goto sm_any_hash; /* Treat objects like scalars */
+ }
+ else if (!SvOK(d)) {
RETPUSHNO;
}
else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
@@ -4209,6 +4219,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
RETPUSHNO;
}
else {
+ sm_any_hash:
if (hv_exists_ent(MUTABLE_HV(SvRV(e)), d, 0))
RETPUSHYES;
else
@@ -4217,7 +4228,10 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
}
/* ~~ @array */
else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVAV) {
- if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
+ if (object_on_left) {
+ goto sm_any_array; /* Treat objects like scalars */
+ }
+ else 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;
I32 i;
@@ -4316,24 +4330,27 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
RETPUSHNO;
}
else {
- const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
- I32 i;
+ sm_any_array:
+ {
+ I32 i;
+ const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
- for(i = 0; i <= this_len; ++i) {
- SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
- if (!svp)
- continue;
+ 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;
- /* infinite recursion isn't supposed to happen here */
- (void) do_smartmatch(NULL, NULL);
- SPAGAIN;
- if (SvTRUEx(POPs))
- RETPUSHYES;
+ PUSHs(d);
+ PUSHs(*svp);
+ PUTBACK;
+ /* infinite recursion isn't supposed to happen here */
+ (void) do_smartmatch(NULL, NULL);
+ SPAGAIN;
+ if (SvTRUEx(POPs))
+ RETPUSHYES;
+ }
+ RETPUSHNO;
}
- RETPUSHNO;
}
}
/* ~~ qr// */