Skip to content

Commit a215a77

Browse files
tonycozap
authored andcommitted
Revert "switch removal: remove smartmatch"
This reverts commit cb2167d.
1 parent 9a10079 commit a215a77

32 files changed

+1994
-338
lines changed

MANIFEST

+1
Original file line numberDiff line numberDiff line change
@@ -6432,6 +6432,7 @@ t/op/signatures.t See if sub signatures work
64326432
t/op/sigsystem.t See if system and SIGCHLD handlers play together nicely
64336433
t/op/sleep.t See if sleep works
64346434
t/op/smartkve.t See if smart deref for keys/values/each works
6435+
t/op/smartmatch.t See if the ~~ operator works
64356436
t/op/sort.t See if sort works
64366437
t/op/splice.t See if splice works
64376438
t/op/split.t See if split works

embed.fnc

+10
Original file line numberDiff line numberDiff line change
@@ -4893,6 +4893,8 @@ S |bool |process_special_blocks \
48934893
|NN const char * const fullname \
48944894
|NN GV * const gv \
48954895
|NN CV * const cv
4896+
S |OP * |ref_array_or_hash \
4897+
|NULLOK OP *cond
48964898
S |OP * |refkids |NULLOK OP *o \
48974899
|I32 type
48984900
S |OP * |scalarboolean |NN OP *o
@@ -5071,6 +5073,7 @@ p |UV |_to_upper_title_latin1 \
50715073
#if defined(PERL_IN_PP_CTL_C)
50725074
RS |PerlIO *|check_type_and_open \
50735075
|NN SV *name
5076+
S |void |destroy_matcher|NN PMOP *matcher
50745077
RSd |OP * |docatch |Perl_ppaddr_t firstpp
50755078
S |bool |doeval_compile |U8 gimme \
50765079
|NULLOK CV *outside \
@@ -5090,6 +5093,13 @@ RS |I32 |dopoptolabel |NN const char *label \
50905093
RS |I32 |dopoptoloop |I32 startingblock
50915094
RS |I32 |dopoptosub_at |NN const PERL_CONTEXT *cxstk \
50925095
|I32 startingblock
5096+
S |OP * |do_smartmatch |NULLOK HV *seen_this \
5097+
|NULLOK HV *seen_other \
5098+
|const bool copied
5099+
RS |PMOP * |make_matcher |NN REGEXP *re
5100+
RS |bool |matcher_matches_sv \
5101+
|NN PMOP *matcher \
5102+
|NN SV *sv
50935103
RST |bool |num_overflow |NV value \
50945104
|I32 fldsize \
50955105
|I32 frcsize

embed.h

+6
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,7 @@
13511351
# define ck_scmp(a) Perl_ck_scmp(aTHX_ a)
13521352
# define ck_select(a) Perl_ck_select(aTHX_ a)
13531353
# define ck_shift(a) Perl_ck_shift(aTHX_ a)
1354+
# define ck_smartmatch(a) Perl_ck_smartmatch(aTHX_ a)
13541355
# define ck_sort(a) Perl_ck_sort(aTHX_ a)
13551356
# define ck_spair(a) Perl_ck_spair(aTHX_ a)
13561357
# define ck_split(a) Perl_ck_split(aTHX_ a)
@@ -1556,6 +1557,7 @@
15561557
# define opslab_slot_offset S_opslab_slot_offset
15571558
# define pmtrans(a,b,c) S_pmtrans(aTHX_ a,b,c)
15581559
# define process_special_blocks(a,b,c,d) S_process_special_blocks(aTHX_ a,b,c,d)
1560+
# define ref_array_or_hash(a) S_ref_array_or_hash(aTHX_ a)
15591561
# define refkids(a,b) S_refkids(aTHX_ a,b)
15601562
# define scalar_mod_type S_scalar_mod_type
15611563
# define scalarboolean(a) S_scalarboolean(aTHX_ a)
@@ -1631,6 +1633,8 @@
16311633
# endif
16321634
# if defined(PERL_IN_PP_CTL_C)
16331635
# define check_type_and_open(a) S_check_type_and_open(aTHX_ a)
1636+
# define destroy_matcher(a) S_destroy_matcher(aTHX_ a)
1637+
# define do_smartmatch(a,b,c) S_do_smartmatch(aTHX_ a,b,c)
16341638
# define docatch(a) S_docatch(aTHX_ a)
16351639
# define doeval_compile(a,b,c,d) S_doeval_compile(aTHX_ a,b,c,d)
16361640
# define dofindlabel(a,b,c,d,e,f) S_dofindlabel(aTHX_ a,b,c,d,e,f)
@@ -1639,6 +1643,8 @@
16391643
# define dopoptolabel(a,b,c) S_dopoptolabel(aTHX_ a,b,c)
16401644
# define dopoptoloop(a) S_dopoptoloop(aTHX_ a)
16411645
# define dopoptosub_at(a,b) S_dopoptosub_at(aTHX_ a,b)
1646+
# define make_matcher(a) S_make_matcher(aTHX_ a)
1647+
# define matcher_matches_sv(a,b) S_matcher_matches_sv(aTHX_ a,b)
16421648
# define num_overflow S_num_overflow
16431649
# define path_is_searchable S_path_is_searchable
16441650
# define run_user_filter(a,b,c) S_run_user_filter(aTHX_ a,b,c)

ext/Opcode/Opcode.pm

+2
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ These are a hotchpotch of opcodes still waiting to be considered
436436
entertry leavetry -- can be used to 'hide' fatal errors
437437
entertrycatch poptry catch leavetrycatch -- similar
438438
439+
smartmatch
440+
439441
pushdefer
440442
441443
custom -- where should this go

lib/B/Deparse.pm

+11-1
Original file line numberDiff line numberDiff line change
@@ -3169,6 +3169,16 @@ sub pp_padsv_store {
31693169
return $self->maybe_parens("$var = $val", $cx, 7);
31703170
}
31713171

3172+
sub pp_smartmatch {
3173+
my ($self, $op, $cx) = @_;
3174+
if (($op->flags & OPf_SPECIAL) && $self->{expand} < 2) {
3175+
return $self->deparse($op->last, $cx);
3176+
}
3177+
else {
3178+
binop(@_, "~~", 14);
3179+
}
3180+
}
3181+
31723182
# '.' is special because concats-of-concats are optimized to save copying
31733183
# by making all but the first concat stacked. The effect is as if the
31743184
# programmer had written '($a . $b) .= $c', except legal.
@@ -5194,7 +5204,7 @@ sub retscalar {
51945204
|i_subtract|concat|multiconcat|stringify|left_shift|right_shift|lt
51955205
|i_lt|gt|i_gt|le|i_le|ge|i_ge|eq|i_eq|ne|i_ne|ncmp|i_ncmp
51965206
|slt|sgt|sle|sge|seq|sne|scmp|[sn]?bit_(?:and|x?or)|negate
5197-
|i_negate|not|[sn]?complement|atan2|sin|cos
5207+
|i_negate|not|[sn]?complement|smartmatch|atan2|sin|cos
51985208
|rand|srand|exp|log|sqrt|int|hex|oct|abs|length|substr
51995209
|vec|index|rindex|sprintf|formline|ord|chr|crypt|ucfirst
52005210
|lcfirst|uc|lc|quotemeta|aelemfast|aelem|exists|helem

lib/B/Op_private.pm

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/overload.pm

+36-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package overload;
33
use strict;
44
no strict 'refs';
55

6-
our $VERSION = '1.39';
6+
our $VERSION = '1.40';
77

88
our %ops = (
99
with_assign => "+ - * / % ** << >> x .",
@@ -376,6 +376,7 @@ hash C<%overload::ops>:
376376
iterators => '<>',
377377
filetest => '-X',
378378
dereferencing => '${} @{} %{} &{} *{}',
379+
matching => '~~',
379380
special => 'nomethod fallback =',
380381
381382
Most of the overloadable operators map one-to-one to these keys.
@@ -519,6 +520,37 @@ result of the last C<stat>, C<lstat> or unoverloaded filetest.
519520
520521
This overload was introduced in Perl 5.12.
521522
523+
=item * I<Matching>
524+
525+
The key C<"~~"> allows you to override the smart matching logic used by
526+
the C<~~> operator and the switch construct (C<given>/C<when>). See
527+
L<perlsyn/Switch Statements> and L<feature>.
528+
529+
Unusually, the overloaded implementation of the smart match operator
530+
does not get full control of the smart match behaviour.
531+
In particular, in the following code:
532+
533+
package Foo;
534+
use overload '~~' => 'match';
535+
536+
my $obj = Foo->new();
537+
$obj ~~ [ 1,2,3 ];
538+
539+
the smart match does I<not> invoke the method call like this:
540+
541+
$obj->match([1,2,3],0);
542+
543+
rather, the smart match distributive rule takes precedence, so $obj is
544+
smart matched against each array element in turn until a match is found,
545+
so you may see between one and three of these calls instead:
546+
547+
$obj->match(1,0);
548+
$obj->match(2,0);
549+
$obj->match(3,0);
550+
551+
Consult the match table in L<perlop/"Smartmatch Operator"> for
552+
details of when overloading is invoked.
553+
522554
=item * I<Dereferencing>
523555
524556
${} @{} %{} &{} *{}
@@ -647,6 +679,7 @@ expects. The minimal set is:
647679
& | ^ ~ &. |. ^. ~.
648680
atan2 cos sin exp log sqrt int
649681
"" 0+ bool
682+
~~
650683
651684
Of the conversions, only one of string, boolean or numeric is
652685
needed because each can be generated from either of the other two.
@@ -849,7 +882,8 @@ skipped.
849882
850883
There are exceptions to the above rules for dereference operations
851884
(which, if Step 1 fails, always fall back to the normal, built-in
852-
implementations - see Dereferencing) under L</Overloadable Operations>
885+
implementations - see Dereferencing), and for C<~~> (which has its
886+
own set of rules - see C<Matching> under L</Overloadable Operations>
853887
above).
854888
855889
Note on Step 7: some operators have a different semantic depending

lib/overload.t

+30-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ package main;
7171

7272
$| = 1;
7373
BEGIN { require './test.pl'; require './charset_tools.pl' }
74-
plan tests => 5309;
74+
plan tests => 5367;
7575

7676
use Scalar::Util qw(tainted);
7777

@@ -1857,6 +1857,10 @@ foreach my $op (qw(<=> == != < <= > >=)) {
18571857
push @tests, [ chr 256, 'chr(256) =~ (%s)', '(qr)', '("")',
18581858
[ 1, 2, 0 ], 0 ];
18591859
1860+
$e = '"abc" ~~ (%s)';
1861+
$subs{'~~'} = $e;
1862+
push @tests, [ "abc", $e, '(~~)', '(NM:~~)', [ 1, 1, 0 ], 0 ];
1863+
18601864
$subs{'-X'} = 'do { my $f = (%s);'
18611865
. '$_[1] eq "r" ? (-r ($f)) :'
18621866
. '$_[1] eq "e" ? (-e ($f)) :'
@@ -3225,3 +3229,28 @@ package RT33789 {
32253229
::is($destroy, 1, "RT #133789: delayed destroy");
32263230
}
32273231

3232+
# GH #21477: with an overloaded object $obj, ($obj ~~ $scalar) wasn't
3233+
# popping the original args off the stack. So in list context, rather than
3234+
# returning (Y/N), it was returning ($obj, $scalar, Y/N)
3235+
3236+
3237+
package GH21477 {
3238+
use overload
3239+
'""' => sub { $_[0][0]; },
3240+
'~~' => sub { $_[0][0] eq $_[1] },
3241+
'eq' => sub { $_[0][0] eq $_[1] },
3242+
;
3243+
3244+
my $o = bless ['cat'];
3245+
3246+
# smartmatch is deprecated and will be removed in 5.042
3247+
no warnings 'deprecated';
3248+
3249+
my @result = ($o ~~ 'cat');
3250+
::is(scalar(@result), 1, "GH #21477: return one result");
3251+
::is($result[0], 1, "GH #21477: return true");
3252+
3253+
@result = ($o ~~ 'dog');
3254+
::is(scalar(@result), 1, "GH #21477: return one result - part 2");
3255+
::is($result[0], "", "GH #21477: return false");
3256+
}

lib/overload/numbers.pm

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ our @names = qw#
8686
(x=
8787
(.
8888
(.=
89+
(~~
8990
(-X
9091
(qr
9192
#;
@@ -163,6 +164,7 @@ our @enums = qw#
163164
repeat_ass
164165
concat
165166
concat_ass
167+
smart
166168
ftest
167169
regexp
168170
#;

op.c

+65
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,7 @@ Perl_scalarvoid(pTHX_ OP *arg)
21742174
/* FALLTHROUGH */
21752175
case OP_WANTARRAY:
21762176
case OP_GV:
2177+
case OP_SMARTMATCH:
21772178
case OP_AV2ARYLEN:
21782179
case OP_REF:
21792180
case OP_REFGEN:
@@ -10009,6 +10010,38 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
1000910010
return o;
1001010011
}
1001110012

10013+
/* if the condition is a literal array or hash
10014+
(or @{ ... } etc), make a reference to it.
10015+
*/
10016+
STATIC OP *
10017+
S_ref_array_or_hash(pTHX_ OP *cond)
10018+
{
10019+
if (cond
10020+
&& (cond->op_type == OP_RV2AV
10021+
|| cond->op_type == OP_PADAV
10022+
|| cond->op_type == OP_RV2HV
10023+
|| cond->op_type == OP_PADHV))
10024+
10025+
return newUNOP(OP_REFGEN, 0, op_lvalue(cond, OP_REFGEN));
10026+
10027+
else if(cond
10028+
&& (cond->op_type == OP_ASLICE
10029+
|| cond->op_type == OP_KVASLICE
10030+
|| cond->op_type == OP_HSLICE
10031+
|| cond->op_type == OP_KVHSLICE)) {
10032+
10033+
/* anonlist now needs a list from this op, was previously used in
10034+
* scalar context */
10035+
cond->op_flags &= ~(OPf_WANT_SCALAR | OPf_REF);
10036+
cond->op_flags |= OPf_WANT_LIST;
10037+
10038+
return newANONLIST(op_lvalue(cond, OP_ANONLIST));
10039+
}
10040+
10041+
else
10042+
return cond;
10043+
}
10044+
1001210045

1001310046
/*
1001410047
=for apidoc newDEFEROP
@@ -13418,6 +13451,38 @@ Perl_ck_listiob(pTHX_ OP *o)
1341813451
return listkids(o);
1341913452
}
1342013453

13454+
OP *
13455+
Perl_ck_smartmatch(pTHX_ OP *o)
13456+
{
13457+
PERL_ARGS_ASSERT_CK_SMARTMATCH;
13458+
if (0 == (o->op_flags & OPf_SPECIAL)) {
13459+
OP *first = cBINOPo->op_first;
13460+
OP *second = OpSIBLING(first);
13461+
13462+
/* Implicitly take a reference to an array or hash */
13463+
13464+
/* remove the original two siblings, then add back the
13465+
* (possibly different) first and second sibs.
13466+
*/
13467+
op_sibling_splice(o, NULL, 1, NULL);
13468+
op_sibling_splice(o, NULL, 1, NULL);
13469+
first = ref_array_or_hash(first);
13470+
second = ref_array_or_hash(second);
13471+
op_sibling_splice(o, NULL, 0, second);
13472+
op_sibling_splice(o, NULL, 0, first);
13473+
13474+
/* Implicitly take a reference to a regular expression */
13475+
if (first->op_type == OP_MATCH && !(first->op_flags & OPf_STACKED)) {
13476+
OpTYPE_set(first, OP_QR);
13477+
}
13478+
if (second->op_type == OP_MATCH && !(second->op_flags & OPf_STACKED)) {
13479+
OpTYPE_set(second, OP_QR);
13480+
}
13481+
}
13482+
13483+
return o;
13484+
}
13485+
1342113486

1342213487
static OP *
1342313488
S_maybe_targlex(pTHX_ OP *o)

0 commit comments

Comments
 (0)