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 */
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;
RETPUSHNO;
}
else {
+ sm_any_sub:
ENTER;
SAVETMPS;
PUSHMARK(SP);
}
/* ~~ %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) {
RETPUSHNO;
}
else {
+ sm_any_hash:
if (hv_exists_ent(MUTABLE_HV(SvRV(e)), d, 0))
RETPUSHYES;
else
}
/* ~~ @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;
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// */
qr// \&bar
! [1] \&foo
! {a=>1} \&foo
- $obj sub { ref $_[0] =~ /NoOverload/ } TODO
- $ov_obj sub { ref $_[0] =~ /CopyOverload/ } TODO
+ $obj sub { ref($_[0]) =~ /NoOverload/ }
+ $ov_obj sub { ref($_[0]) =~ /CopyOverload/ }
# empty stuff matches, because the sub is never called:
[] \&foo
{} \&foo
# - an object
! $obj @fooormore
- $obj [sub{ref shift}] TODO
+ $obj [sub{ref shift}]
# - works with lists instead of arrays
"foo" qw(foo bar) TODO