From 8ca5e8b024faf626a391b87d3e36e3191e953ee8 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:29:59 +1100 Subject: [PATCH 01/12] Revert "switch removal: Safe t/safeops.t" This reverts commit 23f3171141d7fdb4b1fc8639eeabd2770eb82f5c. --- dist/Safe/Safe.pm | 2 +- dist/Safe/t/safeops.t | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dist/Safe/Safe.pm b/dist/Safe/Safe.pm index 791fa5750bac..1e1587c8bb91 100644 --- a/dist/Safe/Safe.pm +++ b/dist/Safe/Safe.pm @@ -3,7 +3,7 @@ package Safe; use 5.003_11; use Scalar::Util qw(reftype refaddr); -$Safe::VERSION = "2.47"; +$Safe::VERSION = "2.46"; # *** Don't declare any lexicals above this point *** # diff --git a/dist/Safe/t/safeops.t b/dist/Safe/t/safeops.t index 74fb58f413c7..57c46b62c3ee 100644 --- a/dist/Safe/t/safeops.t +++ b/dist/Safe/t/safeops.t @@ -45,7 +45,7 @@ plan(tests => scalar @op + 3); sub testop { my ($op, $opname, $code) = @_; pass("$op : skipped") and return if $code =~ /^SKIP/; - pass("$op : skipped") and return if $code eq "//" && $] < 5.010; + pass("$op : skipped") and return if $code =~ m://|~~: && $] < 5.010; my $c = new Safe; $c->deny_only($op); $c->reval($code); @@ -453,6 +453,7 @@ dor $x // $y dorassign $x //= $y once SKIP {use feature 'state'; state $foo = 42;} say SKIP {use feature 'say'; say "foo";} +smartmatch no warnings 'deprecated'; $x ~~ $y aeach SKIP each @t akeys SKIP keys @t avalues SKIP values @t From 8c9c74c4abd82250d4a4798e4979b55e075a531d Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:30:16 +1100 Subject: [PATCH 02/12] Revert "switch removal: ~~ no longer an op, so it still cannot chain" This reverts commit 51238ec1e6c1aa1f9aeba63bc4883f5c992963a7. --- t/op/cmpchain.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/op/cmpchain.t b/t/op/cmpchain.t index 89030993cd17..13672b836c09 100644 --- a/t/op/cmpchain.t +++ b/t/op/cmpchain.t @@ -9,7 +9,7 @@ BEGIN { use feature "isa"; my @cheqop = qw(== != eq ne); -my @nceqop = qw(<=> cmp); +my @nceqop = qw(<=> cmp ~~); my @chrelop = qw(< > <= >= lt gt le ge); my @ncrelop = qw(isa); From 2bff1ee1cdfe5c1dde6b81fa582b84046deed891 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:30:33 +1100 Subject: [PATCH 03/12] Revert "switch removal: no need for -DM anymore" This reverts commit 18b5dc4c09792eca002cbf4567e66c621c33f214. --- perl.c | 2 +- perl.h | 9 +++++++-- pod/perlrun.pod | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/perl.c b/perl.c index 15127adc50fe..698e07252867 100644 --- a/perl.c +++ b/perl.c @@ -3640,7 +3640,7 @@ Perl_get_debug_opts(pTHX_ const char **s, bool givehelp) * impacting the definitions of all the other flags in perl.h * However because the logic is guarded by isWORDCHAR we can * fill in holes with non-wordchar characters instead. */ - static const char debopts[] = "psltocPmfrxuUhXDSTRJvCAq BLiy"; + static const char debopts[] = "psltocPmfrxuUhXDSTRJvCAqMBLiy"; for (; isWORDCHAR(**s); (*s)++) { const char * const d = strchr(debopts,**s); diff --git a/perl.h b/perl.h index 572ff5df6f25..06217e903549 100644 --- a/perl.h +++ b/perl.h @@ -4822,12 +4822,12 @@ Gid_t getegid (void); #define DEBUG_C_FLAG 0x00200000 /*2097152 */ #define DEBUG_A_FLAG 0x00400000 /*4194304 */ #define DEBUG_q_FLAG 0x00800000 /*8388608 */ -/* was smartmatch, now free 0x01000000 16777216 */ +#define DEBUG_M_FLAG 0x01000000 /*16777216*/ #define DEBUG_B_FLAG 0x02000000 /*33554432*/ #define DEBUG_L_FLAG 0x04000000 /*67108864*/ #define DEBUG_i_FLAG 0x08000000 /*134217728*/ #define DEBUG_y_FLAG 0x10000000 /*268435456*/ -#define DEBUG_MASK 0x1EFFEFFF /* mask of all the standard flags */ +#define DEBUG_MASK 0x1FFFEFFF /* mask of all the standard flags */ #define DEBUG_DB_RECURSE_FLAG 0x40000000 #define DEBUG_TOP_FLAG 0x80000000 /* -D was given --> PL_debug |= FLAG */ @@ -4861,6 +4861,7 @@ Gid_t getegid (void); # define DEBUG_C_TEST_ UNLIKELY(PL_debug & DEBUG_C_FLAG) # define DEBUG_A_TEST_ UNLIKELY(PL_debug & DEBUG_A_FLAG) # define DEBUG_q_TEST_ UNLIKELY(PL_debug & DEBUG_q_FLAG) +# define DEBUG_M_TEST_ UNLIKELY(PL_debug & DEBUG_M_FLAG) # define DEBUG_B_TEST_ UNLIKELY(PL_debug & DEBUG_B_FLAG) /* Locale initialization comes earlier than PL_debug gets set, @@ -4907,6 +4908,7 @@ Gid_t getegid (void); # define DEBUG_C_TEST DEBUG_C_TEST_ # define DEBUG_A_TEST DEBUG_A_TEST_ # define DEBUG_q_TEST DEBUG_q_TEST_ +# define DEBUG_M_TEST DEBUG_M_TEST_ # define DEBUG_B_TEST DEBUG_B_TEST_ # define DEBUG_L_TEST DEBUG_L_TEST_ # define DEBUG_i_TEST DEBUG_i_TEST_ @@ -5005,6 +5007,7 @@ Gid_t getegid (void); # define DEBUG_C(a) DEBUG__(DEBUG_C_TEST, a) # define DEBUG_A(a) DEBUG__(DEBUG_A_TEST, a) # define DEBUG_q(a) DEBUG__(DEBUG_q_TEST, a) +# define DEBUG_M(a) DEBUG__(DEBUG_M_TEST, a) # define DEBUG_B(a) DEBUG__(DEBUG_B_TEST, a) # define DEBUG_L(a) DEBUG__(DEBUG_L_TEST, a) # define DEBUG_i(a) DEBUG__(DEBUG_i_TEST, a) @@ -5036,6 +5039,7 @@ Gid_t getegid (void); # define DEBUG_C_TEST (0) # define DEBUG_A_TEST (0) # define DEBUG_q_TEST (0) +# define DEBUG_M_TEST (0) # define DEBUG_B_TEST (0) # define DEBUG_L_TEST (0) # define DEBUG_i_TEST (0) @@ -5071,6 +5075,7 @@ Gid_t getegid (void); # define DEBUG_C(a) # define DEBUG_A(a) # define DEBUG_q(a) +# define DEBUG_M(a) # define DEBUG_B(a) # define DEBUG_L(a) # define DEBUG_i(a) diff --git a/pod/perlrun.pod b/pod/perlrun.pod index 748695d53050..e880d70d99c3 100644 --- a/pod/perlrun.pod +++ b/pod/perlrun.pod @@ -432,6 +432,7 @@ B<-D14> is equivalent to B<-Dtls>): 4194304 A Consistency checks on internal structures 8388608 q quiet - currently only suppresses the "EXECUTING" message + 16777216 M trace smart match resolution 33554432 B dump suBroutine definitions, including special Blocks like BEGIN 67108864 L trace Locale-related info; what gets output is very From 5b9917b0d4e1836776a0dd09be88d71f6fcaa4fd Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:30:55 +1100 Subject: [PATCH 04/12] Revert "switch removal: a completed experiment" This reverts commit 901bf8b75b37e48ff4ef383ec7fa55fe3bd42242. --- pod/perlexperiment.pod | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pod/perlexperiment.pod b/pod/perlexperiment.pod index 6a0a0d1d0d8d..18a52a767fce 100644 --- a/pod/perlexperiment.pod +++ b/pod/perlexperiment.pod @@ -18,6 +18,22 @@ their inception, versions, etc. There's a lot of speculation here. =over 8 +=item Smart match (C<~~>) + +Introduced in Perl 5.10.0 + +Modified in Perl 5.10.1, 5.12.0 + +Deprecated in 5.38.0 + +Will be removed in 5.42.0 + +Using this feature triggers warnings in the category +C. + +The ticket for this experiment is +L<[perl #13173]|https://github.com/Perl/perl5/issues/13173>. + =item Pluggable keywords Introduced in Perl 5.11.2 @@ -438,16 +454,6 @@ Introduced in Perl 5.8.0 (or before) Removed in Perl 5.36.0 -=item Smart match (C<~~>) - -Introduced in Perl 5.10.0 - -Modified in Perl 5.10.1, 5.12.0 - -Deprecated in 5.38.0 - -Has been removed for 5.42.0 - =back =head1 SEE ALSO From b996c519a06d8a2b2005b8a19d25c39d86f7b11f Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:31:34 +1100 Subject: [PATCH 05/12] Revert "switch removal: no longer deprecated, but removed" This reverts commit ffb20d96685800c313481edc0b8823a934ee010f. --- pod/perldeprecation.pod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pod/perldeprecation.pod b/pod/perldeprecation.pod index b06797d82b58..207f4974e234 100644 --- a/pod/perldeprecation.pod +++ b/pod/perldeprecation.pod @@ -75,8 +75,8 @@ Category: "deprecated::subsequent_use_version" Smartmatch is now seen as a failed experiment and was marked as deprecated in Perl 5.37.10. This includes the C and C keywords, as well -as the smartmatch operator C<~~>. The feature has been removed entirely for -the Perl 5.42.0 production release. +as the smartmatch operator C<~~>. The feature will be removed entirely in the +Perl 5.42.0 production release. Category: "deprecated::smartmatch" From b80ff73e206dd90e02d84ea9b76660598061ff08 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:45:21 +1100 Subject: [PATCH 06/12] Revert "switch removal: remove the feature from feature.pm" This reverts commit 149bea6edf8c49a1faf4fac124567101172d96bd. --- feature.h | 26 +++++++++++++++--- lib/B/Deparse.t | 4 +-- lib/feature.pm | 61 +++++++++++++++++++++++++++---------------- regen/feature.pl | 25 +++++++++++++----- t/lib/feature/api | 2 +- t/lib/feature/removed | 9 ------- 6 files changed, 83 insertions(+), 44 deletions(-) diff --git a/feature.h b/feature.h index c5e85c5d2a8b..19702d06a28e 100644 --- a/feature.h +++ b/feature.h @@ -31,9 +31,10 @@ #define FEATURE_SAY_BIT 0x10000 #define FEATURE_SIGNATURES_BIT 0x20000 #define FEATURE_STATE_BIT 0x40000 -#define FEATURE_TRY_BIT 0x80000 -#define FEATURE_UNIEVAL_BIT 0x100000 -#define FEATURE_UNICODE_BIT 0x200000 +#define FEATURE_SWITCH_BIT 0x80000 +#define FEATURE_TRY_BIT 0x100000 +#define FEATURE_UNIEVAL_BIT 0x200000 +#define FEATURE_UNICODE_BIT 0x400000 #define FEATURE_BUNDLE_DEFAULT 0 #define FEATURE_BUNDLE_510 1 @@ -116,6 +117,14 @@ FEATURE_IS_ENABLED_MASK(FEATURE_STATE_BIT)) \ ) +#define FEATURE_SWITCH_IS_ENABLED \ + ( \ + (CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_510 && \ + CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \ + || (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \ + FEATURE_IS_ENABLED_MASK(FEATURE_SWITCH_BIT)) \ + ) + #define FEATURE_BITWISE_IS_ENABLED \ ( \ (CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_527 && \ @@ -421,6 +430,11 @@ S_magic_sethint_feature(pTHX_ SV *keysv, const char *keypv, STRLEN keylen, mask = FEATURE_STATE_BIT; break; } + else if (keylen == sizeof("feature_switch")-1 + && memcmp(subf+1, "witch", keylen - sizeof("feature_")) == 0) { + mask = FEATURE_SWITCH_BIT; + break; + } return; case 't': @@ -580,6 +594,12 @@ PL_feature_bits[] = { STRLENs("feature_state"), FEATURE_STATE_BIT }, + { + /* feature switch */ + "feature_switch", + STRLENs("feature_switch"), + FEATURE_SWITCH_BIT + }, { /* feature try */ "feature_try", diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t index 59f937dcc52d..41b3691df065 100644 --- a/lib/B/Deparse.t +++ b/lib/B/Deparse.t @@ -965,7 +965,7 @@ say 'foo'; use feature ':5.10'; say 'foo'; >>>> -use feature 'say', 'state'; +use feature 'say', 'state', 'switch'; say 'foo'; #### # SKIP ?$] < 5.010 && "say not implemented on this Perl version" @@ -1010,7 +1010,7 @@ __SUB__; use feature ':5.15'; __SUB__; >>>> -use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'unicode_strings', 'unicode_eval'; +use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; __SUB__; #### # SKIP ?$] < 5.015 && "__SUB__ not implemented on this Perl version" diff --git a/lib/feature.pm b/lib/feature.pm index 8d1c930ca542..fa9ed5ed2b2f 100644 --- a/lib/feature.pm +++ b/lib/feature.pm @@ -4,7 +4,7 @@ # Any changes made here will be lost! package feature; -our $VERSION = '1.92'; +our $VERSION = '1.93'; our %feature = ( fc => 'feature_fc', @@ -14,6 +14,7 @@ our %feature = ( class => 'feature_class', defer => 'feature_defer', state => 'feature_state', + switch => 'feature_switch', bitwise => 'feature_bitwise', indirect => 'feature_indirect', evalbytes => 'feature_evalbytes', @@ -32,16 +33,16 @@ our %feature = ( ); our %feature_bundle = ( - "5.10" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state)], - "5.11" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state unicode_strings)], - "5.15" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state unicode_eval unicode_strings)], - "5.23" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state unicode_eval unicode_strings)], - "5.27" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state unicode_eval unicode_strings)], + "5.10" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch)], + "5.11" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch unicode_strings)], + "5.15" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state switch unicode_eval unicode_strings)], + "5.23" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)], + "5.27" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)], "5.35" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc isa postderef_qq say signatures state unicode_eval unicode_strings)], "5.37" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state unicode_eval unicode_strings)], "5.39" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state try unicode_eval unicode_strings)], "5.41" => [qw(bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state try unicode_eval unicode_strings)], - "all" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise class current_sub declared_refs defer evalbytes extra_paired_delimiters fc indirect isa module_true multidimensional postderef_qq refaliasing say signatures state try unicode_eval unicode_strings)], + "all" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise class current_sub declared_refs defer evalbytes extra_paired_delimiters fc indirect isa module_true multidimensional postderef_qq refaliasing say signatures state switch try unicode_eval unicode_strings)], "default" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional)], ); @@ -76,7 +77,6 @@ my %noops = ( ); my %removed = ( array_base => 1, - switch => 1, ); our $hint_shift = 26; @@ -176,10 +176,21 @@ This feature is available starting with Perl 5.10. =head2 The 'switch' feature -C told the compiler to enable the Raku +B: This feature is still experimental and the implementation may +change or be removed in future versions of Perl. For this reason, Perl will +warn when you use the feature, unless you have explicitly disabled the warning: + + no warnings "experimental::smartmatch"; + +C tells the compiler to enable the Raku given/when construct. -This feature was removed in Perl 5.42. +See L for details. + +This feature is available starting with Perl 5.10. +It is deprecated starting with Perl 5.38, and using +C, C or smartmatch will throw a warning. +It will be removed in Perl 5.42. =head2 The 'unicode_strings' feature @@ -537,68 +548,72 @@ The following feature bundles are available: :5.10 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state + multidimensional say state switch :5.12 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state unicode_strings + multidimensional say state switch + unicode_strings :5.14 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state unicode_strings + multidimensional say state switch + unicode_strings :5.16 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state - unicode_eval unicode_strings + switch unicode_eval unicode_strings :5.18 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state - unicode_eval unicode_strings + switch unicode_eval unicode_strings :5.20 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state - unicode_eval unicode_strings + switch unicode_eval unicode_strings :5.22 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state - unicode_eval unicode_strings + switch unicode_eval unicode_strings :5.24 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq - say state unicode_eval unicode_strings + say state switch unicode_eval + unicode_strings :5.26 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq - say state unicode_eval unicode_strings + say state switch unicode_eval + unicode_strings :5.28 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state unicode_eval + postderef_qq say state switch unicode_eval unicode_strings :5.30 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state unicode_eval + postderef_qq say state switch unicode_eval unicode_strings :5.32 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state unicode_eval + postderef_qq say state switch unicode_eval unicode_strings :5.34 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state unicode_eval + postderef_qq say state switch unicode_eval unicode_strings :5.36 apostrophe_as_package_separator diff --git a/regen/feature.pl b/regen/feature.pl index 9ff19fbfca1a..0528f0109aba 100755 --- a/regen/feature.pl +++ b/regen/feature.pl @@ -26,6 +26,7 @@ BEGIN my %feature = ( say => 'say', state => 'state', + switch => 'switch', bitwise => 'bitwise', evalbytes => 'evalbytes', current_sub => '__SUB__', @@ -55,13 +56,14 @@ BEGIN # 5.odd implies the next 5.even, but an explicit 5.even can override it. # features bundles -use constant V5_9_5 => sort qw{say state indirect multidimensional bareword_filehandles apostrophe_as_package_separator}; +use constant V5_9_5 => sort qw{say state switch indirect multidimensional bareword_filehandles apostrophe_as_package_separator}; use constant V5_11 => sort ( +V5_9_5, qw{unicode_strings} ); use constant V5_15 => sort ( +V5_11, qw{unicode_eval evalbytes current_sub fc} ); use constant V5_23 => sort ( +V5_15, qw{postderef_qq} ); use constant V5_27 => sort ( +V5_23, qw{bitwise} ); -use constant V5_35 => sort grep {; $_ ne 'indirect' +use constant V5_35 => sort grep {; $_ ne 'switch' + && $_ ne 'indirect' && $_ ne 'multidimensional' } +V5_27, qw{isa signatures}; use constant V5_37 => sort grep {; $_ ne 'bareword_filehandles' } +V5_35, qw{module_true}; @@ -108,7 +110,7 @@ BEGIN ); my @noops = qw( postderef lexical_subs ); -my @removed = qw( array_base switch ); +my @removed = qw( array_base ); ########################################################################### @@ -546,7 +548,7 @@ sub longest { __END__ package feature; -our $VERSION = '1.92'; +our $VERSION = '1.93'; FEATURES @@ -638,10 +640,21 @@ =head2 The 'state' feature =head2 The 'switch' feature -C told the compiler to enable the Raku +B: This feature is still experimental and the implementation may +change or be removed in future versions of Perl. For this reason, Perl will +warn when you use the feature, unless you have explicitly disabled the warning: + + no warnings "experimental::smartmatch"; + +C tells the compiler to enable the Raku given/when construct. -This feature was removed in Perl 5.42. +See L for details. + +This feature is available starting with Perl 5.10. +It is deprecated starting with Perl 5.38, and using +C, C or smartmatch will throw a warning. +It will be removed in Perl 5.42. =head2 The 'unicode_strings' feature diff --git a/t/lib/feature/api b/t/lib/feature/api index 1635e3e60207..1b67edd1cb9d 100644 --- a/t/lib/feature/api +++ b/t/lib/feature/api @@ -20,7 +20,7 @@ EXPECT default: apostrophe_as_package_separator bareword_filehandles indirect multidimensional unicode_strings is not enabled bundle: default -5.12: apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state unicode_strings +5.12: apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch unicode_strings unicode_strings is enabled bundle: 5.11 ######## diff --git a/t/lib/feature/removed b/t/lib/feature/removed index a3320019ce47..f2805eecd86a 100644 --- a/t/lib/feature/removed +++ b/t/lib/feature/removed @@ -8,12 +8,3 @@ OPTIONS regex ######## no feature "array_base"; EXPECT -######## -# NAME switch feature removed -use feature "switch"; -EXPECT -OPTIONS regex -^Feature "switch" is not supported by Perl [v0-9.]+ at - line 1. -######## -no feature "switch"; -EXPECT From 25f3eccdf1187f57216f71b955f76eb5b77d309f Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 14:47:33 +1100 Subject: [PATCH 07/12] Revert "switch removal: remove smartmatch" This reverts commit cb2167d3785e61e23819ca2c58ac1e89d5e4bf3b. --- MANIFEST | 1 + embed.fnc | 10 + embed.h | 6 + ext/Opcode/Opcode.pm | 2 + lib/B/Deparse.pm | 12 +- lib/B/Op_private.pm | 1 + lib/overload.pm | 38 ++- lib/overload.t | 31 +- lib/overload/numbers.pm | 2 + op.c | 65 +++++ opcode.h | 9 +- opnames.h | 617 ++++++++++++++++++++-------------------- overload.h | 5 +- overload.inc | 2 + pod/perlcheat.pod | 4 +- pod/perldiag.pod | 14 + pod/perlop.pod | 295 ++++++++++++++++++- pp_ctl.c | 514 +++++++++++++++++++++++++++++++++ pp_proto.h | 1 + proto.h | 32 +++ regen/opcodes | 2 + regen/overload.pl | 1 + sv.c | 1 + t/comp/parser.t | 6 + t/lib/warnings/9uninit | 7 + t/lib/warnings/op | 14 +- t/lib/warnings/utf8 | 2 +- t/op/smartmatch.t | 592 ++++++++++++++++++++++++++++++++++++++ t/op/svleak.t | 9 +- t/op/taint.t | 10 +- t/op/tie_fetch_count.t | 6 +- toke.c | 9 + 32 files changed, 1988 insertions(+), 332 deletions(-) create mode 100644 t/op/smartmatch.t diff --git a/MANIFEST b/MANIFEST index cc59d64bbd2d..e3ca90d7d2f9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -6417,6 +6417,7 @@ t/op/signatures.t See if sub signatures work t/op/sigsystem.t See if system and SIGCHLD handlers play together nicely t/op/sleep.t See if sleep works t/op/smartkve.t See if smart deref for keys/values/each works +t/op/smartmatch.t See if the ~~ operator works t/op/sort.t See if sort works t/op/splice.t See if splice works t/op/split.t See if split works diff --git a/embed.fnc b/embed.fnc index 5f48566133b9..ec3058f86e4c 100644 --- a/embed.fnc +++ b/embed.fnc @@ -4797,6 +4797,8 @@ S |bool |process_special_blocks \ |NN const char * const fullname \ |NN GV * const gv \ |NN CV * const cv +S |OP * |ref_array_or_hash \ + |NULLOK OP *cond S |OP * |refkids |NULLOK OP *o \ |I32 type S |OP * |scalarboolean |NN OP *o @@ -4975,6 +4977,7 @@ p |UV |_to_upper_title_latin1 \ #if defined(PERL_IN_PP_CTL_C) RS |PerlIO *|check_type_and_open \ |NN SV *name +S |void |destroy_matcher|NN PMOP *matcher RSd |OP * |docatch |Perl_ppaddr_t firstpp S |bool |doeval_compile |U8 gimme \ |NULLOK CV *outside \ @@ -4994,6 +4997,13 @@ RS |I32 |dopoptolabel |NN const char *label \ RS |I32 |dopoptoloop |I32 startingblock RS |I32 |dopoptosub_at |NN const PERL_CONTEXT *cxstk \ |I32 startingblock +S |OP * |do_smartmatch |NULLOK HV *seen_this \ + |NULLOK HV *seen_other \ + |const bool copied +RS |PMOP * |make_matcher |NN REGEXP *re +RS |bool |matcher_matches_sv \ + |NN PMOP *matcher \ + |NN SV *sv RST |bool |num_overflow |NV value \ |I32 fldsize \ |I32 frcsize diff --git a/embed.h b/embed.h index 86804dee2694..dae6e35efeb0 100644 --- a/embed.h +++ b/embed.h @@ -1323,6 +1323,7 @@ # define ck_scmp(a) Perl_ck_scmp(aTHX_ a) # define ck_select(a) Perl_ck_select(aTHX_ a) # define ck_shift(a) Perl_ck_shift(aTHX_ a) +# define ck_smartmatch(a) Perl_ck_smartmatch(aTHX_ a) # define ck_sort(a) Perl_ck_sort(aTHX_ a) # define ck_spair(a) Perl_ck_spair(aTHX_ a) # define ck_split(a) Perl_ck_split(aTHX_ a) @@ -1528,6 +1529,7 @@ # define opslab_slot_offset S_opslab_slot_offset # define pmtrans(a,b,c) S_pmtrans(aTHX_ a,b,c) # define process_special_blocks(a,b,c,d) S_process_special_blocks(aTHX_ a,b,c,d) +# define ref_array_or_hash(a) S_ref_array_or_hash(aTHX_ a) # define refkids(a,b) S_refkids(aTHX_ a,b) # define scalar_mod_type S_scalar_mod_type # define scalarboolean(a) S_scalarboolean(aTHX_ a) @@ -1603,6 +1605,8 @@ # endif # if defined(PERL_IN_PP_CTL_C) # define check_type_and_open(a) S_check_type_and_open(aTHX_ a) +# define destroy_matcher(a) S_destroy_matcher(aTHX_ a) +# define do_smartmatch(a,b,c) S_do_smartmatch(aTHX_ a,b,c) # define docatch(a) S_docatch(aTHX_ a) # define doeval_compile(a,b,c,d) S_doeval_compile(aTHX_ a,b,c,d) # define dofindlabel(a,b,c,d,e,f) S_dofindlabel(aTHX_ a,b,c,d,e,f) @@ -1611,6 +1615,8 @@ # define dopoptolabel(a,b,c) S_dopoptolabel(aTHX_ a,b,c) # define dopoptoloop(a) S_dopoptoloop(aTHX_ a) # define dopoptosub_at(a,b) S_dopoptosub_at(aTHX_ a,b) +# define make_matcher(a) S_make_matcher(aTHX_ a) +# define matcher_matches_sv(a,b) S_matcher_matches_sv(aTHX_ a,b) # define num_overflow S_num_overflow # define path_is_searchable S_path_is_searchable # define run_user_filter(a,b,c) S_run_user_filter(aTHX_ a,b,c) diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index baacf3c677ea..4168b46ecd0a 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -434,6 +434,8 @@ These are a hotchpotch of opcodes still waiting to be considered entertry leavetry -- can be used to 'hide' fatal errors entertrycatch poptry catch leavetrycatch -- similar + smartmatch + pushdefer custom -- where should this go diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 6e3389373695..6b309ca74eda 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -3152,6 +3152,16 @@ sub pp_padsv_store { return $self->maybe_parens("$var = $val", $cx, 7); } +sub pp_smartmatch { + my ($self, $op, $cx) = @_; + if (($op->flags & OPf_SPECIAL) && $self->{expand} < 2) { + return $self->deparse($op->last, $cx); + } + else { + binop(@_, "~~", 14); + } +} + # '.' is special because concats-of-concats are optimized to save copying # by making all but the first concat stacked. The effect is as if the # programmer had written '($a . $b) .= $c', except legal. @@ -5156,7 +5166,7 @@ sub retscalar { |i_subtract|concat|multiconcat|stringify|left_shift|right_shift|lt |i_lt|gt|i_gt|le|i_le|ge|i_ge|eq|i_eq|ne|i_ne|ncmp|i_ncmp |slt|sgt|sle|sge|seq|sne|scmp|[sn]?bit_(?:and|x?or)|negate - |i_negate|not|[sn]?complement|atan2|sin|cos + |i_negate|not|[sn]?complement|smartmatch|atan2|sin|cos |rand|srand|exp|log|sqrt|int|hex|oct|abs|length|substr |vec|index|rindex|sprintf|formline|ord|chr|crypt|ucfirst |lcfirst|uc|lc|quotemeta|aelemfast|aelem|exists|helem diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm index 255817c85fc1..329106fc0a8f 100644 --- a/lib/B/Op_private.pm +++ b/lib/B/Op_private.pm @@ -565,6 +565,7 @@ $bits{sin}{0} = $bf[0]; @{$bits{sle}}{1,0} = ($bf[1], $bf[1]); @{$bits{sleep}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); @{$bits{slt}}{1,0} = ($bf[1], $bf[1]); +@{$bits{smartmatch}}{1,0} = ($bf[1], $bf[1]); @{$bits{sne}}{1,0} = ($bf[1], $bf[1]); $bits{snetent}{0} = $bf[0]; @{$bits{socket}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); diff --git a/lib/overload.pm b/lib/overload.pm index cb699a16d453..03ad240a9cbb 100644 --- a/lib/overload.pm +++ b/lib/overload.pm @@ -3,7 +3,7 @@ package overload; use strict; no strict 'refs'; -our $VERSION = '1.39'; +our $VERSION = '1.40'; our %ops = ( with_assign => "+ - * / % ** << >> x .", @@ -376,6 +376,7 @@ hash C<%overload::ops>: iterators => '<>', filetest => '-X', dereferencing => '${} @{} %{} &{} *{}', + matching => '~~', special => 'nomethod fallback =', Most of the overloadable operators map one-to-one to these keys. @@ -519,6 +520,37 @@ result of the last C, C or unoverloaded filetest. This overload was introduced in Perl 5.12. +=item * I + +The key C<"~~"> allows you to override the smart matching logic used by +the C<~~> operator and the switch construct (C/C). See +L and L. + +Unusually, the overloaded implementation of the smart match operator +does not get full control of the smart match behaviour. +In particular, in the following code: + + package Foo; + use overload '~~' => 'match'; + + my $obj = Foo->new(); + $obj ~~ [ 1,2,3 ]; + +the smart match does I invoke the method call like this: + + $obj->match([1,2,3],0); + +rather, the smart match distributive rule takes precedence, so $obj is +smart matched against each array element in turn until a match is found, +so you may see between one and three of these calls instead: + + $obj->match(1,0); + $obj->match(2,0); + $obj->match(3,0); + +Consult the match table in L for +details of when overloading is invoked. + =item * I ${} @{} %{} &{} *{} @@ -647,6 +679,7 @@ expects. The minimal set is: & | ^ ~ &. |. ^. ~. atan2 cos sin exp log sqrt int "" 0+ bool + ~~ Of the conversions, only one of string, boolean or numeric is needed because each can be generated from either of the other two. @@ -849,7 +882,8 @@ skipped. There are exceptions to the above rules for dereference operations (which, if Step 1 fails, always fall back to the normal, built-in -implementations - see Dereferencing) under L +implementations - see Dereferencing), and for C<~~> (which has its +own set of rules - see C under L above). Note on Step 7: some operators have a different semantic depending diff --git a/lib/overload.t b/lib/overload.t index afe76d707cf8..7f8cb48a7d78 100644 --- a/lib/overload.t +++ b/lib/overload.t @@ -71,7 +71,7 @@ package main; $| = 1; BEGIN { require './test.pl'; require './charset_tools.pl' } -plan tests => 5309; +plan tests => 5367; use Scalar::Util qw(tainted); @@ -1857,6 +1857,10 @@ foreach my $op (qw(<=> == != < <= > >=)) { push @tests, [ chr 256, 'chr(256) =~ (%s)', '(qr)', '("")', [ 1, 2, 0 ], 0 ]; + $e = '"abc" ~~ (%s)'; + $subs{'~~'} = $e; + push @tests, [ "abc", $e, '(~~)', '(NM:~~)', [ 1, 1, 0 ], 0 ]; + $subs{'-X'} = 'do { my $f = (%s);' . '$_[1] eq "r" ? (-r ($f)) :' . '$_[1] eq "e" ? (-e ($f)) :' @@ -3225,3 +3229,28 @@ package RT33789 { ::is($destroy, 1, "RT #133789: delayed destroy"); } +# GH #21477: with an overloaded object $obj, ($obj ~~ $scalar) wasn't +# popping the original args off the stack. So in list context, rather than +# returning (Y/N), it was returning ($obj, $scalar, Y/N) + + +package GH21477 { + use overload + '""' => sub { $_[0][0]; }, + '~~' => sub { $_[0][0] eq $_[1] }, + 'eq' => sub { $_[0][0] eq $_[1] }, + ; + + my $o = bless ['cat']; + + # smartmatch is deprecated and will be removed in 5.042 + no warnings 'deprecated'; + + my @result = ($o ~~ 'cat'); + ::is(scalar(@result), 1, "GH #21477: return one result"); + ::is($result[0], 1, "GH #21477: return true"); + + @result = ($o ~~ 'dog'); + ::is(scalar(@result), 1, "GH #21477: return one result - part 2"); + ::is($result[0], "", "GH #21477: return false"); +} diff --git a/lib/overload/numbers.pm b/lib/overload/numbers.pm index bc1ffb4251f3..9a6f457e529e 100644 --- a/lib/overload/numbers.pm +++ b/lib/overload/numbers.pm @@ -86,6 +86,7 @@ our @names = qw# (x= (. (.= + (~~ (-X (qr #; @@ -163,6 +164,7 @@ our @enums = qw# repeat_ass concat concat_ass + smart ftest regexp #; diff --git a/op.c b/op.c index c3e3d8958452..a55bf94a88ac 100644 --- a/op.c +++ b/op.c @@ -2175,6 +2175,7 @@ Perl_scalarvoid(pTHX_ OP *arg) /* FALLTHROUGH */ case OP_WANTARRAY: case OP_GV: + case OP_SMARTMATCH: case OP_AV2ARYLEN: case OP_REF: case OP_REFGEN: @@ -9972,6 +9973,38 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label) return o; } +/* if the condition is a literal array or hash + (or @{ ... } etc), make a reference to it. + */ +STATIC OP * +S_ref_array_or_hash(pTHX_ OP *cond) +{ + if (cond + && (cond->op_type == OP_RV2AV + || cond->op_type == OP_PADAV + || cond->op_type == OP_RV2HV + || cond->op_type == OP_PADHV)) + + return newUNOP(OP_REFGEN, 0, op_lvalue(cond, OP_REFGEN)); + + else if(cond + && (cond->op_type == OP_ASLICE + || cond->op_type == OP_KVASLICE + || cond->op_type == OP_HSLICE + || cond->op_type == OP_KVHSLICE)) { + + /* anonlist now needs a list from this op, was previously used in + * scalar context */ + cond->op_flags &= ~(OPf_WANT_SCALAR | OPf_REF); + cond->op_flags |= OPf_WANT_LIST; + + return newANONLIST(op_lvalue(cond, OP_ANONLIST)); + } + + else + return cond; +} + /* =for apidoc newDEFEROP @@ -13369,6 +13402,38 @@ Perl_ck_listiob(pTHX_ OP *o) return listkids(o); } +OP * +Perl_ck_smartmatch(pTHX_ OP *o) +{ + PERL_ARGS_ASSERT_CK_SMARTMATCH; + if (0 == (o->op_flags & OPf_SPECIAL)) { + OP *first = cBINOPo->op_first; + OP *second = OpSIBLING(first); + + /* Implicitly take a reference to an array or hash */ + + /* remove the original two siblings, then add back the + * (possibly different) first and second sibs. + */ + op_sibling_splice(o, NULL, 1, NULL); + op_sibling_splice(o, NULL, 1, NULL); + first = ref_array_or_hash(first); + second = ref_array_or_hash(second); + op_sibling_splice(o, NULL, 0, second); + op_sibling_splice(o, NULL, 0, first); + + /* Implicitly take a reference to a regular expression */ + if (first->op_type == OP_MATCH && !(first->op_flags & OPf_STACKED)) { + OpTYPE_set(first, OP_QR); + } + if (second->op_type == OP_MATCH && !(second->op_flags & OPf_STACKED)) { + OpTYPE_set(second, OP_QR); + } + } + + return o; +} + static OP * S_maybe_targlex(pTHX_ OP *o) diff --git a/opcode.h b/opcode.h index ab62fa16ccc6..7cb1a93f7a88 100644 --- a/opcode.h +++ b/opcode.h @@ -254,6 +254,7 @@ EXTCONST char* const PL_op_name[] INIT({ "complement", "ncomplement", "scomplement", + "smartmatch", "atan2", "sin", "cos", @@ -673,6 +674,7 @@ EXTCONST char* const PL_op_desc[] INIT({ "1's complement (~)", "numeric 1's complement (~)", "string 1's complement (~)", + "smart match", "atan2", "sin", "cos", @@ -1097,6 +1099,7 @@ INIT({ Perl_pp_complement, Perl_pp_ncomplement, Perl_pp_scomplement, + Perl_pp_smartmatch, Perl_pp_atan2, Perl_pp_sin, Perl_pp_cos, /* implemented by Perl_pp_sin */ @@ -1516,6 +1519,7 @@ INIT({ Perl_ck_bitop, /* complement */ Perl_ck_bitop, /* ncomplement */ Perl_ck_null, /* scomplement */ + Perl_ck_smartmatch, /* smartmatch */ Perl_ck_fun, /* atan2 */ Perl_ck_fun, /* sin */ Perl_ck_fun, /* cos */ @@ -1934,6 +1938,7 @@ EXTCONST U32 PL_opargs[] INIT({ 0x0000110e, /* complement */ 0x0000111e, /* ncomplement */ 0x0000111e, /* scomplement */ + 0x00000204, /* smartmatch */ 0x0001141e, /* atan2 */ 0x00009b9e, /* sin */ 0x00009b9e, /* cos */ @@ -2654,6 +2659,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 105, /* complement */ 103, /* ncomplement */ 78, /* scomplement */ + 13, /* smartmatch */ 101, /* atan2 */ 78, /* sin */ 78, /* cos */ @@ -2985,7 +2991,7 @@ EXTCONST U16 PL_op_private_bitdefs[] = { 0x077e, 0x0554, 0x1b70, 0x542c, 0x4fc8, 0x4225, /* const */ 0x3cfc, 0x47f9, /* gvsv */ 0x19d5, /* gv */ - 0x0067, /* gelem, lt, i_lt, gt, i_gt, le, i_le, ge, i_ge, eq, i_eq, ne, i_ne, ncmp, i_ncmp, slt, sgt, sle, sge, seq, sne, scmp, lslice, xor, isa */ + 0x0067, /* gelem, lt, i_lt, gt, i_gt, le, i_le, ge, i_ge, eq, i_eq, ne, i_ne, ncmp, i_ncmp, slt, sgt, sle, sge, seq, sne, scmp, smartmatch, lslice, xor, isa */ 0x3cfc, 0x5378, 0x04f7, /* padsv */ 0x3cfc, 0x5378, 0x0003, /* padsv_store, lvavref */ 0x3cfc, 0x5378, 0x06d4, 0x3dec, 0x5149, /* padav */ @@ -3177,6 +3183,7 @@ EXTCONST U8 PL_op_private_valid[] = { /* COMPLEMENT */ (OPpUSEINT), /* NCOMPLEMENT */ (OPpUSEINT|OPpTARGET_MY), /* SCOMPLEMENT */ (OPpARG1_MASK|OPpTARGET_MY), + /* SMARTMATCH */ (OPpARG2_MASK), /* ATAN2 */ (OPpARG4_MASK|OPpTARGET_MY), /* SIN */ (OPpARG1_MASK|OPpTARGET_MY), /* COS */ (OPpARG1_MASK|OPpTARGET_MY), diff --git a/opnames.h b/opnames.h index 4fb9f5d12d7d..7e1f2dfa2358 100644 --- a/opnames.h +++ b/opnames.h @@ -122,313 +122,314 @@ typedef enum opcode { OP_COMPLEMENT = 105, OP_NCOMPLEMENT = 106, OP_SCOMPLEMENT = 107, - OP_ATAN2 = 108, - OP_SIN = 109, - OP_COS = 110, - OP_RAND = 111, - OP_SRAND = 112, - OP_EXP = 113, - OP_LOG = 114, - OP_SQRT = 115, - OP_INT = 116, - OP_HEX = 117, - OP_OCT = 118, - OP_ABS = 119, - OP_LENGTH = 120, - OP_SUBSTR = 121, - OP_VEC = 122, - OP_INDEX = 123, - OP_RINDEX = 124, - OP_SPRINTF = 125, - OP_FORMLINE = 126, - OP_ORD = 127, - OP_CHR = 128, - OP_CRYPT = 129, - OP_UCFIRST = 130, - OP_LCFIRST = 131, - OP_UC = 132, - OP_LC = 133, - OP_QUOTEMETA = 134, - OP_RV2AV = 135, - OP_AELEMFAST = 136, - OP_AELEMFAST_LEX = 137, - OP_AELEMFASTLEX_STORE = 138, - OP_AELEM = 139, - OP_ASLICE = 140, - OP_KVASLICE = 141, - OP_AEACH = 142, - OP_AVALUES = 143, - OP_AKEYS = 144, - OP_EACH = 145, - OP_VALUES = 146, - OP_KEYS = 147, - OP_DELETE = 148, - OP_EXISTS = 149, - OP_RV2HV = 150, - OP_HELEM = 151, - OP_HSLICE = 152, - OP_KVHSLICE = 153, - OP_MULTIDEREF = 154, - OP_UNPACK = 155, - OP_PACK = 156, - OP_SPLIT = 157, - OP_JOIN = 158, - OP_LIST = 159, - OP_LSLICE = 160, - OP_ANONLIST = 161, - OP_ANONHASH = 162, - OP_EMPTYAVHV = 163, - OP_SPLICE = 164, - OP_PUSH = 165, - OP_POP = 166, - OP_SHIFT = 167, - OP_UNSHIFT = 168, - OP_SORT = 169, - OP_REVERSE = 170, - OP_GREPSTART = 171, - OP_GREPWHILE = 172, - OP_MAPSTART = 173, - OP_MAPWHILE = 174, - OP_RANGE = 175, - OP_FLIP = 176, - OP_FLOP = 177, - OP_AND = 178, - OP_OR = 179, - OP_XOR = 180, - OP_DOR = 181, - OP_COND_EXPR = 182, - OP_ANDASSIGN = 183, - OP_ORASSIGN = 184, - OP_DORASSIGN = 185, - OP_ENTERSUB = 186, - OP_LEAVESUB = 187, - OP_LEAVESUBLV = 188, - OP_ARGCHECK = 189, - OP_ARGELEM = 190, - OP_ARGDEFELEM = 191, - OP_CALLER = 192, - OP_WARN = 193, - OP_DIE = 194, - OP_RESET = 195, - OP_LINESEQ = 196, - OP_NEXTSTATE = 197, - OP_DBSTATE = 198, - OP_UNSTACK = 199, - OP_ENTER = 200, - OP_LEAVE = 201, - OP_SCOPE = 202, - OP_ENTERITER = 203, - OP_ITER = 204, - OP_ENTERLOOP = 205, - OP_LEAVELOOP = 206, - OP_RETURN = 207, - OP_LAST = 208, - OP_NEXT = 209, - OP_REDO = 210, - OP_DUMP = 211, - OP_GOTO = 212, - OP_EXIT = 213, - OP_METHOD = 214, - OP_METHOD_NAMED = 215, - OP_METHOD_SUPER = 216, - OP_METHOD_REDIR = 217, - OP_METHOD_REDIR_SUPER = 218, - OP_OPEN = 219, - OP_CLOSE = 220, - OP_PIPE_OP = 221, - OP_FILENO = 222, - OP_UMASK = 223, - OP_BINMODE = 224, - OP_TIE = 225, - OP_UNTIE = 226, - OP_TIED = 227, - OP_DBMOPEN = 228, - OP_DBMCLOSE = 229, - OP_SSELECT = 230, - OP_SELECT = 231, - OP_GETC = 232, - OP_READ = 233, - OP_ENTERWRITE = 234, - OP_LEAVEWRITE = 235, - OP_PRTF = 236, - OP_PRINT = 237, - OP_SAY = 238, - OP_SYSOPEN = 239, - OP_SYSSEEK = 240, - OP_SYSREAD = 241, - OP_SYSWRITE = 242, - OP_EOF = 243, - OP_TELL = 244, - OP_SEEK = 245, - OP_TRUNCATE = 246, - OP_FCNTL = 247, - OP_IOCTL = 248, - OP_FLOCK = 249, - OP_SEND = 250, - OP_RECV = 251, - OP_SOCKET = 252, - OP_SOCKPAIR = 253, - OP_BIND = 254, - OP_CONNECT = 255, - OP_LISTEN = 256, - OP_ACCEPT = 257, - OP_SHUTDOWN = 258, - OP_GSOCKOPT = 259, - OP_SSOCKOPT = 260, - OP_GETSOCKNAME = 261, - OP_GETPEERNAME = 262, - OP_LSTAT = 263, - OP_STAT = 264, - OP_FTRREAD = 265, - OP_FTRWRITE = 266, - OP_FTREXEC = 267, - OP_FTEREAD = 268, - OP_FTEWRITE = 269, - OP_FTEEXEC = 270, - OP_FTIS = 271, - OP_FTSIZE = 272, - OP_FTMTIME = 273, - OP_FTATIME = 274, - OP_FTCTIME = 275, - OP_FTROWNED = 276, - OP_FTEOWNED = 277, - OP_FTZERO = 278, - OP_FTSOCK = 279, - OP_FTCHR = 280, - OP_FTBLK = 281, - OP_FTFILE = 282, - OP_FTDIR = 283, - OP_FTPIPE = 284, - OP_FTSUID = 285, - OP_FTSGID = 286, - OP_FTSVTX = 287, - OP_FTLINK = 288, - OP_FTTTY = 289, - OP_FTTEXT = 290, - OP_FTBINARY = 291, - OP_CHDIR = 292, - OP_CHOWN = 293, - OP_CHROOT = 294, - OP_UNLINK = 295, - OP_CHMOD = 296, - OP_UTIME = 297, - OP_RENAME = 298, - OP_LINK = 299, - OP_SYMLINK = 300, - OP_READLINK = 301, - OP_MKDIR = 302, - OP_RMDIR = 303, - OP_OPEN_DIR = 304, - OP_READDIR = 305, - OP_TELLDIR = 306, - OP_SEEKDIR = 307, - OP_REWINDDIR = 308, - OP_CLOSEDIR = 309, - OP_FORK = 310, - OP_WAIT = 311, - OP_WAITPID = 312, - OP_SYSTEM = 313, - OP_EXEC = 314, - OP_KILL = 315, - OP_GETPPID = 316, - OP_GETPGRP = 317, - OP_SETPGRP = 318, - OP_GETPRIORITY = 319, - OP_SETPRIORITY = 320, - OP_TIME = 321, - OP_TMS = 322, - OP_LOCALTIME = 323, - OP_GMTIME = 324, - OP_ALARM = 325, - OP_SLEEP = 326, - OP_SHMGET = 327, - OP_SHMCTL = 328, - OP_SHMREAD = 329, - OP_SHMWRITE = 330, - OP_MSGGET = 331, - OP_MSGCTL = 332, - OP_MSGSND = 333, - OP_MSGRCV = 334, - OP_SEMOP = 335, - OP_SEMGET = 336, - OP_SEMCTL = 337, - OP_REQUIRE = 338, - OP_DOFILE = 339, - OP_HINTSEVAL = 340, - OP_ENTEREVAL = 341, - OP_LEAVEEVAL = 342, - OP_ENTERTRY = 343, - OP_LEAVETRY = 344, - OP_GHBYNAME = 345, - OP_GHBYADDR = 346, - OP_GHOSTENT = 347, - OP_GNBYNAME = 348, - OP_GNBYADDR = 349, - OP_GNETENT = 350, - OP_GPBYNAME = 351, - OP_GPBYNUMBER = 352, - OP_GPROTOENT = 353, - OP_GSBYNAME = 354, - OP_GSBYPORT = 355, - OP_GSERVENT = 356, - OP_SHOSTENT = 357, - OP_SNETENT = 358, - OP_SPROTOENT = 359, - OP_SSERVENT = 360, - OP_EHOSTENT = 361, - OP_ENETENT = 362, - OP_EPROTOENT = 363, - OP_ESERVENT = 364, - OP_GPWNAM = 365, - OP_GPWUID = 366, - OP_GPWENT = 367, - OP_SPWENT = 368, - OP_EPWENT = 369, - OP_GGRNAM = 370, - OP_GGRGID = 371, - OP_GGRENT = 372, - OP_SGRENT = 373, - OP_EGRENT = 374, - OP_GETLOGIN = 375, - OP_SYSCALL = 376, - OP_LOCK = 377, - OP_ONCE = 378, - OP_CUSTOM = 379, - OP_COREARGS = 380, - OP_AVHVSWITCH = 381, - OP_RUNCV = 382, - OP_FC = 383, - OP_PADCV = 384, - OP_INTROCV = 385, - OP_CLONECV = 386, - OP_PADRANGE = 387, - OP_REFASSIGN = 388, - OP_LVREF = 389, - OP_LVREFSLICE = 390, - OP_LVAVREF = 391, - OP_ANONCONST = 392, - OP_ISA = 393, - OP_CMPCHAIN_AND = 394, - OP_CMPCHAIN_DUP = 395, - OP_ENTERTRYCATCH = 396, - OP_LEAVETRYCATCH = 397, - OP_POPTRY = 398, - OP_CATCH = 399, - OP_PUSHDEFER = 400, - OP_IS_BOOL = 401, - OP_IS_WEAK = 402, - OP_WEAKEN = 403, - OP_UNWEAKEN = 404, - OP_BLESSED = 405, - OP_REFADDR = 406, - OP_REFTYPE = 407, - OP_CEIL = 408, - OP_FLOOR = 409, - OP_IS_TAINTED = 410, - OP_HELEMEXISTSOR = 411, - OP_METHSTART = 412, - OP_INITFIELD = 413, - OP_CLASSNAME = 414, + OP_SMARTMATCH = 108, + OP_ATAN2 = 109, + OP_SIN = 110, + OP_COS = 111, + OP_RAND = 112, + OP_SRAND = 113, + OP_EXP = 114, + OP_LOG = 115, + OP_SQRT = 116, + OP_INT = 117, + OP_HEX = 118, + OP_OCT = 119, + OP_ABS = 120, + OP_LENGTH = 121, + OP_SUBSTR = 122, + OP_VEC = 123, + OP_INDEX = 124, + OP_RINDEX = 125, + OP_SPRINTF = 126, + OP_FORMLINE = 127, + OP_ORD = 128, + OP_CHR = 129, + OP_CRYPT = 130, + OP_UCFIRST = 131, + OP_LCFIRST = 132, + OP_UC = 133, + OP_LC = 134, + OP_QUOTEMETA = 135, + OP_RV2AV = 136, + OP_AELEMFAST = 137, + OP_AELEMFAST_LEX = 138, + OP_AELEMFASTLEX_STORE = 139, + OP_AELEM = 140, + OP_ASLICE = 141, + OP_KVASLICE = 142, + OP_AEACH = 143, + OP_AVALUES = 144, + OP_AKEYS = 145, + OP_EACH = 146, + OP_VALUES = 147, + OP_KEYS = 148, + OP_DELETE = 149, + OP_EXISTS = 150, + OP_RV2HV = 151, + OP_HELEM = 152, + OP_HSLICE = 153, + OP_KVHSLICE = 154, + OP_MULTIDEREF = 155, + OP_UNPACK = 156, + OP_PACK = 157, + OP_SPLIT = 158, + OP_JOIN = 159, + OP_LIST = 160, + OP_LSLICE = 161, + OP_ANONLIST = 162, + OP_ANONHASH = 163, + OP_EMPTYAVHV = 164, + OP_SPLICE = 165, + OP_PUSH = 166, + OP_POP = 167, + OP_SHIFT = 168, + OP_UNSHIFT = 169, + OP_SORT = 170, + OP_REVERSE = 171, + OP_GREPSTART = 172, + OP_GREPWHILE = 173, + OP_MAPSTART = 174, + OP_MAPWHILE = 175, + OP_RANGE = 176, + OP_FLIP = 177, + OP_FLOP = 178, + OP_AND = 179, + OP_OR = 180, + OP_XOR = 181, + OP_DOR = 182, + OP_COND_EXPR = 183, + OP_ANDASSIGN = 184, + OP_ORASSIGN = 185, + OP_DORASSIGN = 186, + OP_ENTERSUB = 187, + OP_LEAVESUB = 188, + OP_LEAVESUBLV = 189, + OP_ARGCHECK = 190, + OP_ARGELEM = 191, + OP_ARGDEFELEM = 192, + OP_CALLER = 193, + OP_WARN = 194, + OP_DIE = 195, + OP_RESET = 196, + OP_LINESEQ = 197, + OP_NEXTSTATE = 198, + OP_DBSTATE = 199, + OP_UNSTACK = 200, + OP_ENTER = 201, + OP_LEAVE = 202, + OP_SCOPE = 203, + OP_ENTERITER = 204, + OP_ITER = 205, + OP_ENTERLOOP = 206, + OP_LEAVELOOP = 207, + OP_RETURN = 208, + OP_LAST = 209, + OP_NEXT = 210, + OP_REDO = 211, + OP_DUMP = 212, + OP_GOTO = 213, + OP_EXIT = 214, + OP_METHOD = 215, + OP_METHOD_NAMED = 216, + OP_METHOD_SUPER = 217, + OP_METHOD_REDIR = 218, + OP_METHOD_REDIR_SUPER = 219, + OP_OPEN = 220, + OP_CLOSE = 221, + OP_PIPE_OP = 222, + OP_FILENO = 223, + OP_UMASK = 224, + OP_BINMODE = 225, + OP_TIE = 226, + OP_UNTIE = 227, + OP_TIED = 228, + OP_DBMOPEN = 229, + OP_DBMCLOSE = 230, + OP_SSELECT = 231, + OP_SELECT = 232, + OP_GETC = 233, + OP_READ = 234, + OP_ENTERWRITE = 235, + OP_LEAVEWRITE = 236, + OP_PRTF = 237, + OP_PRINT = 238, + OP_SAY = 239, + OP_SYSOPEN = 240, + OP_SYSSEEK = 241, + OP_SYSREAD = 242, + OP_SYSWRITE = 243, + OP_EOF = 244, + OP_TELL = 245, + OP_SEEK = 246, + OP_TRUNCATE = 247, + OP_FCNTL = 248, + OP_IOCTL = 249, + OP_FLOCK = 250, + OP_SEND = 251, + OP_RECV = 252, + OP_SOCKET = 253, + OP_SOCKPAIR = 254, + OP_BIND = 255, + OP_CONNECT = 256, + OP_LISTEN = 257, + OP_ACCEPT = 258, + OP_SHUTDOWN = 259, + OP_GSOCKOPT = 260, + OP_SSOCKOPT = 261, + OP_GETSOCKNAME = 262, + OP_GETPEERNAME = 263, + OP_LSTAT = 264, + OP_STAT = 265, + OP_FTRREAD = 266, + OP_FTRWRITE = 267, + OP_FTREXEC = 268, + OP_FTEREAD = 269, + OP_FTEWRITE = 270, + OP_FTEEXEC = 271, + OP_FTIS = 272, + OP_FTSIZE = 273, + OP_FTMTIME = 274, + OP_FTATIME = 275, + OP_FTCTIME = 276, + OP_FTROWNED = 277, + OP_FTEOWNED = 278, + OP_FTZERO = 279, + OP_FTSOCK = 280, + OP_FTCHR = 281, + OP_FTBLK = 282, + OP_FTFILE = 283, + OP_FTDIR = 284, + OP_FTPIPE = 285, + OP_FTSUID = 286, + OP_FTSGID = 287, + OP_FTSVTX = 288, + OP_FTLINK = 289, + OP_FTTTY = 290, + OP_FTTEXT = 291, + OP_FTBINARY = 292, + OP_CHDIR = 293, + OP_CHOWN = 294, + OP_CHROOT = 295, + OP_UNLINK = 296, + OP_CHMOD = 297, + OP_UTIME = 298, + OP_RENAME = 299, + OP_LINK = 300, + OP_SYMLINK = 301, + OP_READLINK = 302, + OP_MKDIR = 303, + OP_RMDIR = 304, + OP_OPEN_DIR = 305, + OP_READDIR = 306, + OP_TELLDIR = 307, + OP_SEEKDIR = 308, + OP_REWINDDIR = 309, + OP_CLOSEDIR = 310, + OP_FORK = 311, + OP_WAIT = 312, + OP_WAITPID = 313, + OP_SYSTEM = 314, + OP_EXEC = 315, + OP_KILL = 316, + OP_GETPPID = 317, + OP_GETPGRP = 318, + OP_SETPGRP = 319, + OP_GETPRIORITY = 320, + OP_SETPRIORITY = 321, + OP_TIME = 322, + OP_TMS = 323, + OP_LOCALTIME = 324, + OP_GMTIME = 325, + OP_ALARM = 326, + OP_SLEEP = 327, + OP_SHMGET = 328, + OP_SHMCTL = 329, + OP_SHMREAD = 330, + OP_SHMWRITE = 331, + OP_MSGGET = 332, + OP_MSGCTL = 333, + OP_MSGSND = 334, + OP_MSGRCV = 335, + OP_SEMOP = 336, + OP_SEMGET = 337, + OP_SEMCTL = 338, + OP_REQUIRE = 339, + OP_DOFILE = 340, + OP_HINTSEVAL = 341, + OP_ENTEREVAL = 342, + OP_LEAVEEVAL = 343, + OP_ENTERTRY = 344, + OP_LEAVETRY = 345, + OP_GHBYNAME = 346, + OP_GHBYADDR = 347, + OP_GHOSTENT = 348, + OP_GNBYNAME = 349, + OP_GNBYADDR = 350, + OP_GNETENT = 351, + OP_GPBYNAME = 352, + OP_GPBYNUMBER = 353, + OP_GPROTOENT = 354, + OP_GSBYNAME = 355, + OP_GSBYPORT = 356, + OP_GSERVENT = 357, + OP_SHOSTENT = 358, + OP_SNETENT = 359, + OP_SPROTOENT = 360, + OP_SSERVENT = 361, + OP_EHOSTENT = 362, + OP_ENETENT = 363, + OP_EPROTOENT = 364, + OP_ESERVENT = 365, + OP_GPWNAM = 366, + OP_GPWUID = 367, + OP_GPWENT = 368, + OP_SPWENT = 369, + OP_EPWENT = 370, + OP_GGRNAM = 371, + OP_GGRGID = 372, + OP_GGRENT = 373, + OP_SGRENT = 374, + OP_EGRENT = 375, + OP_GETLOGIN = 376, + OP_SYSCALL = 377, + OP_LOCK = 378, + OP_ONCE = 379, + OP_CUSTOM = 380, + OP_COREARGS = 381, + OP_AVHVSWITCH = 382, + OP_RUNCV = 383, + OP_FC = 384, + OP_PADCV = 385, + OP_INTROCV = 386, + OP_CLONECV = 387, + OP_PADRANGE = 388, + OP_REFASSIGN = 389, + OP_LVREF = 390, + OP_LVREFSLICE = 391, + OP_LVAVREF = 392, + OP_ANONCONST = 393, + OP_ISA = 394, + OP_CMPCHAIN_AND = 395, + OP_CMPCHAIN_DUP = 396, + OP_ENTERTRYCATCH = 397, + OP_LEAVETRYCATCH = 398, + OP_POPTRY = 399, + OP_CATCH = 400, + OP_PUSHDEFER = 401, + OP_IS_BOOL = 402, + OP_IS_WEAK = 403, + OP_WEAKEN = 404, + OP_UNWEAKEN = 405, + OP_BLESSED = 406, + OP_REFADDR = 407, + OP_REFTYPE = 408, + OP_CEIL = 409, + OP_FLOOR = 410, + OP_IS_TAINTED = 411, + OP_HELEMEXISTSOR = 412, + OP_METHSTART = 413, + OP_INITFIELD = 414, + OP_CLASSNAME = 415, OP_max } opcode; @@ -439,7 +440,7 @@ An enum of all the legal Perl opcodes, defined in F =cut */ -#define MAXO 415 +#define MAXO 416 #define OP_FREED MAXO /* the OP_IS_* macros are optimized to a simple range check because diff --git a/overload.h b/overload.h index a9d6bfbe7f50..cb2e9f1d022b 100644 --- a/overload.h +++ b/overload.h @@ -86,8 +86,9 @@ enum { repeat_ass_amg, /* 0x45 x= */ concat_amg, /* 0x46 . */ concat_ass_amg, /* 0x47 .= */ - ftest_amg, /* 0x48 -X */ - regexp_amg, /* 0x49 qr */ + smart_amg, /* 0x48 ~~ */ + ftest_amg, /* 0x49 -X */ + regexp_amg, /* 0x4a qr */ max_amg_code /* Do not leave a trailing comma here. C9X allows it, C89 doesn't. */ }; diff --git a/overload.inc b/overload.inc index 64d8022bae70..34c3fc0010e8 100644 --- a/overload.inc +++ b/overload.inc @@ -90,6 +90,7 @@ static const U8 PL_AMG_namelens[NofAMmeth] = { 2, 3, 3, + 3, 3 }; @@ -171,6 +172,7 @@ static const char * const PL_AMG_names[NofAMmeth] = { "(x=", /* repeat_ass */ "(.", /* concat */ "(.=", /* concat_ass */ + "(~~", /* smart */ "(-X", /* ftest */ "(qr" }; diff --git a/pod/perlcheat.pod b/pod/perlcheat.pod index b7e0f903ea02..797e333b62ec 100644 --- a/pod/perlcheat.pod +++ b/pod/perlcheat.pod @@ -28,14 +28,14 @@ already be overwhelming. -> while (e) { } until (e) { } ++ -- if (e) { } elsif (e) { } else { } ** unless (e) { } elsif (e) { } else { } - ! ~ \ u+ u- + ! ~ \ u+ u- given (e) { when (e) {} default {} } =~ !~ * / % x NUMBERS vs STRINGS FALSE vs TRUE + - . = = undef, "", 0, "0" << >> + . anything else named uops == != eq ne < > <= >= lt gt le ge < > <= >= lt gt le ge - == != <=> eq ne cmp <=> cmp + == != <=> eq ne cmp ~~ <=> cmp & | ^ REGEX MODIFIERS REGEX METACHARS && /i case insensitive ^ string begin diff --git a/pod/perldiag.pod b/pod/perldiag.pod index ab08994aa0a4..a48ddff5931b 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -6156,6 +6156,20 @@ requested. hash) parameter. The slurpy parameter takes all the available arguments, so there can't be any left to fill later parameters. +=item Smart matching a non-overloaded object breaks encapsulation + +(F) You should not use the C<~~> operator on an object that does not +overload it: Perl refuses to use the object's underlying structure +for the smart match. + +=item Smartmatch is deprecated + +(D deprecated::smartmatch) This warning is emitted if you +use the smartmatch (C<~~>) operator. This is a deprecated +feature. Particularly, its behavior is noticed for being +unnecessarily complex and unintuitive, and it will be removed +in Perl 5.42. + =item Sorry, hash keys must be smaller than 2**31 bytes (F) You tried to create a hash containing a very large key, where "very diff --git a/pod/perlop.pod b/pod/perlop.pod index 36edd23f633c..28e6e9ad8e08 100644 --- a/pod/perlop.pod +++ b/pod/perlop.pod @@ -138,7 +138,7 @@ values only, not array values. nonassoc named unary operators nonassoc isa chained < > <= >= lt gt le ge - chain/na == != eq ne <=> cmp + chain/na == != eq ne <=> cmp ~~ left & &. left | |. ^ ^. left && @@ -638,9 +638,13 @@ Here we can see the difference between <=> and cmp, (likewise between gt and >, lt and <, etc.) X -The two-sided ordering operators C<"E=E"> and C<"cmp"> are -non-associative with respect to each other and with respect to the -equality operators of the same precedence. +Binary C<"~~"> does a smartmatch between its arguments. Smart matching +is described in the next section. +X<~~> + +The two-sided ordering operators C<"E=E"> and C<"cmp">, and the +smartmatch operator C<"~~">, are non-associative with respect to each +other and with respect to the equality operators of the same precedence. C<"lt">, C<"le">, C<"ge">, C<"gt"> and C<"cmp"> use the collation (sort) order specified by the current C locale if a S (or higher) declaration in the current scope. =head2 Smartmatch Operator -The smartmatch operator C<~~> was removed in Perl 5.42. +First available in Perl 5.10.1 (the 5.10.0 version behaved differently), +binary C<~~> does a "smartmatch" between its arguments. This is mostly +used implicitly in the C construct described in L, although +not all C clauses call the smartmatch operator. Unique among all of +Perl's operators, the smartmatch operator can recurse. The smartmatch +operator is L and its behavior is +subject to change. + +It is also unique in that all other Perl operators impose a context +(usually string or numeric context) on their operands, autoconverting +those operands to those imposed contexts. In contrast, smartmatch +I contexts from the actual types of its operands and uses that +type information to select a suitable comparison mechanism. + +The C<~~> operator compares its operands "polymorphically", determining how +to compare them according to their actual types (numeric, string, array, +hash, etc.). Like the equality operators with which it shares the same +precedence, C<~~> returns 1 for true and C<""> for false. It is often best +read aloud as "in", "inside of", or "is contained in", because the left +operand is often looked for I the right operand. That makes the +order of the operands to the smartmatch operand often opposite that of +the regular match operator. In other words, the "smaller" thing is usually +placed in the left operand and the larger one in the right. + +The behavior of a smartmatch depends on what type of things its arguments +are, as determined by the following table. The first row of the table +whose types apply determines the smartmatch behavior. Because what +actually happens is mostly determined by the type of the second operand, +the table is sorted on the right operand instead of on the left. + + Left Right Description and pseudocode + =============================================================== + Any undef check whether Any is undefined + like: !defined Any + + Any Object invoke ~~ overloading on Object, or die + + Right operand is an ARRAY: + + Left Right Description and pseudocode + =============================================================== + ARRAY1 ARRAY2 recurse on paired elements of ARRAY1 and ARRAY2[2] + like: (ARRAY1[0] ~~ ARRAY2[0]) + && (ARRAY1[1] ~~ ARRAY2[1]) && ... + HASH ARRAY any ARRAY elements exist as HASH keys + like: grep { exists HASH->{$_} } ARRAY + Regexp ARRAY any ARRAY elements pattern match Regexp + like: grep { /Regexp/ } ARRAY + undef ARRAY undef in ARRAY + like: grep { !defined } ARRAY + Any ARRAY smartmatch each ARRAY element[3] + like: grep { Any ~~ $_ } ARRAY + + Right operand is a HASH: + + Left Right Description and pseudocode + =============================================================== + HASH1 HASH2 all same keys in both HASHes + like: keys HASH1 == + grep { exists HASH2->{$_} } keys HASH1 + ARRAY HASH any ARRAY elements exist as HASH keys + like: grep { exists HASH->{$_} } ARRAY + Regexp HASH any HASH keys pattern match Regexp + like: grep { /Regexp/ } keys HASH + undef HASH always false (undef cannot be a key) + like: 0 == 1 + Any HASH HASH key existence + like: exists HASH->{Any} + + Right operand is CODE: + + Left Right Description and pseudocode + =============================================================== + ARRAY CODE sub returns true on all ARRAY elements[1] + like: !grep { !CODE->($_) } ARRAY + HASH CODE sub returns true on all HASH keys[1] + like: !grep { !CODE->($_) } keys HASH + Any CODE sub passed Any returns true + like: CODE->(Any) + + Right operand is a Regexp: + + Left Right Description and pseudocode + =============================================================== + ARRAY Regexp any ARRAY elements match Regexp + like: grep { /Regexp/ } ARRAY + HASH Regexp any HASH keys match Regexp + like: grep { /Regexp/ } keys HASH + Any Regexp pattern match + like: Any =~ /Regexp/ + + Other: + + Left Right Description and pseudocode + =============================================================== + Object Any invoke ~~ overloading on Object, + or fall back to... + + Any Num numeric equality + like: Any == Num + Num nummy[4] numeric equality + like: Num == nummy + undef Any check whether undefined + like: !defined(Any) + Any Any string equality + like: Any eq Any + + +Notes: + +=over + +=item 1. +Empty hashes or arrays match. + +=item 2. +That is, each element smartmatches the element of the same index in the other array.[3] + +=item 3. +If a circular reference is found, fall back to referential equality. + +=item 4. +Either an actual number, or a string that looks like one. + +=back + +The smartmatch implicitly dereferences any non-blessed hash or array +reference, so the C> and C> entries apply in those cases. +For blessed references, the C> entries apply. Smartmatches +involving hashes only consider hash keys, never hash values. + +The "like" code entry is not always an exact rendition. For example, the +smartmatch operator short-circuits whenever possible, but C does +not. Also, C in scalar context returns the number of matches, but +C<~~> returns only true or false. + +Unlike most operators, the smartmatch operator knows to treat C +specially: + + use v5.10.1; + @array = (1, 2, 3, undef, 4, 5); + say "some elements undefined" if undef ~~ @array; + +Each operand is considered in a modified scalar context, the modification +being that array and hash variables are passed by reference to the +operator, which implicitly dereferences them. Both elements +of each pair are the same: + + use v5.10.1; + + my %hash = (red => 1, blue => 2, green => 3, + orange => 4, yellow => 5, purple => 6, + black => 7, grey => 8, white => 9); + + my @array = qw(red blue green); + + say "some array elements in hash keys" if @array ~~ %hash; + say "some array elements in hash keys" if \@array ~~ \%hash; + + say "red in array" if "red" ~~ @array; + say "red in array" if "red" ~~ \@array; + + say "some keys end in e" if /e$/ ~~ %hash; + say "some keys end in e" if /e$/ ~~ \%hash; + +Two arrays smartmatch if each element in the first array smartmatches +(that is, is "in") the corresponding element in the second array, +recursively. + + use v5.10.1; + my @little = qw(red blue green); + my @bigger = ("red", "blue", [ "orange", "green" ] ); + if (@little ~~ @bigger) { # true! + say "little is contained in bigger"; + } + +Because the smartmatch operator recurses on nested arrays, this +will still report that "red" is in the array. + + use v5.10.1; + my @array = qw(red blue green); + my $nested_array = [[[[[[[ @array ]]]]]]]; + say "red in array" if "red" ~~ $nested_array; + +If two arrays smartmatch each other, then they are deep +copies of each others' values, as this example reports: + + use v5.12.0; + my @a = (0, 1, 2, [3, [4, 5], 6], 7); + my @b = (0, 1, 2, [3, [4, 5], 6], 7); + + if (@a ~~ @b && @b ~~ @a) { + say "a and b are deep copies of each other"; + } + elsif (@a ~~ @b) { + say "a smartmatches in b"; + } + elsif (@b ~~ @a) { + say "b smartmatches in a"; + } + else { + say "a and b don't smartmatch each other at all"; + } + + +If you were to set S>, then instead of reporting that "a and b +are deep copies of each other", it now reports that C<"b smartmatches in a">. +That's because the corresponding position in C<@a> contains an array that +(eventually) has a 4 in it. + +Smartmatching one hash against another reports whether both contain the +same keys, no more and no less. This could be used to see whether two +records have the same field names, without caring what values those fields +might have. For example: + + use v5.10.1; + sub make_dogtag { + state $REQUIRED_FIELDS = { name=>1, rank=>1, serial_num=>1 }; + + my ($class, $init_fields) = @_; + + die "Must supply (only) name, rank, and serial number" + unless $init_fields ~~ $REQUIRED_FIELDS; + + ... + } + +However, this only does what you mean if C<$init_fields> is indeed a hash +reference. The condition C<$init_fields ~~ $REQUIRED_FIELDS> also allows the +strings C<"name">, C<"rank">, C<"serial_num"> as well as any array reference +that contains C<"name"> or C<"rank"> or C<"serial_num"> anywhere to pass +through. + +The smartmatch operator is most often used as the implicit operator of a +C clause. See the section on "Switch Statements" in L. + +=head3 Smartmatching of Objects + +To avoid relying on an object's underlying representation, if the +smartmatch's right operand is an object that doesn't overload C<~~>, +it raises the exception "C". That's because one has no business digging +around to see whether something is "in" an object. These are all +illegal on objects without a C<~~> overload: + + %hash ~~ $object + 42 ~~ $object + "fred" ~~ $object + +However, you can change the way an object is smartmatched by overloading +the C<~~> operator. This is allowed to +extend the usual smartmatch semantics. +For objects that do have an C<~~> overload, see L. + +Using an object as the left operand is allowed, although not very useful. +Smartmatching rules take precedence over overloading, so even if the +object in the left operand has smartmatch overloading, this will be +ignored. A left operand that is a non-overloaded object falls back on a +string or numeric comparison of whatever the C operator returns. That +means that + + $object ~~ X + +does I invoke the overload method with C> as an argument. +Instead the above table is consulted as normal, and based on the type of +C>, overloading may or may not be invoked. For simple strings or +numbers, "in" becomes equivalent to this: + + $object ~~ $number ref($object) == $number + $object ~~ $string ref($object) eq $string + +For example, this reports that the handle smells IOish +(but please don't really do this!): + + use IO::Handle; + my $fh = IO::Handle->new(); + if ($fh ~~ /\bIO\b/) { + say "handle smells IOish"; + } + +That's because it treats C<$fh> as a string like +C<"IO::Handle=GLOB(0x8039e0)">, then pattern matches against that. =head2 Bitwise And X X X<&> diff --git a/pp_ctl.c b/pp_ctl.c index f7d81c349d50..acc56cf6eb38 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -5645,6 +5645,520 @@ PP(pp_leavetry) return retop; } +/* Helper routines used by pp_smartmatch */ +STATIC PMOP * +S_make_matcher(pTHX_ REGEXP *re) +{ + PMOP *matcher = cPMOPx(newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED)); + + PERL_ARGS_ASSERT_MAKE_MATCHER; + + PM_SETRE(matcher, ReREFCNT_inc(re)); + + SAVEFREEOP((OP *) matcher); + ENTER_with_name("matcher"); SAVETMPS; + SAVEOP(); + return matcher; +} + +STATIC bool +S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv) +{ + bool result; + + PERL_ARGS_ASSERT_MATCHER_MATCHES_SV; + + PL_op = (OP *) matcher; + rpp_xpush_1(sv); + (void) Perl_pp_match(aTHX); + result = SvTRUEx(*PL_stack_sp); + rpp_popfree_1_NN(); + return result; +} + +STATIC void +S_destroy_matcher(pTHX_ PMOP *matcher) +{ + PERL_ARGS_ASSERT_DESTROY_MATCHER; + PERL_UNUSED_ARG(matcher); + + FREETMPS; + LEAVE_with_name("matcher"); +} + + +/* Do a smart match */ +PP(pp_smartmatch) +{ + DEBUG_M(Perl_deb(aTHX_ "Starting smart match resolution\n")); + return do_smartmatch(NULL, NULL, 0); +} + + +/* This version of do_smartmatch() implements the + * table of smart matches that is found in perlsyn. + */ +STATIC OP * +S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) +{ + bool object_on_left = FALSE; + SV *e = PL_stack_sp[0]; /* e is for 'expression' */ + SV *d = PL_stack_sp[-1]; /* d is for 'default', as in PL_defgv */ + + /* Take care only to invoke mg_get() once for each argument. + * Currently we do this by copying the SV if it's magical. */ + if (d) { + if (!copied && SvGMAGICAL(d)) + d = sv_mortalcopy(d); + } + else + d = &PL_sv_undef; + + assert(e); + if (SvGMAGICAL(e)) + e = sv_mortalcopy(e); + + /* First of all, handle overload magic of the rightmost argument */ + if (SvAMAGIC(e)) { + SV * tmpsv; + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Object\n")); + DEBUG_M(Perl_deb(aTHX_ " attempting overload\n")); + + tmpsv = amagic_call(d, e, smart_amg, AMGf_noleft); + if (tmpsv) { + rpp_replace_2_1_NN(tmpsv); + return NORMAL; + } + DEBUG_M(Perl_deb(aTHX_ " failed to run overload method; continuing...\n")); + } + + /* ~~ undef */ + if (!SvOK(e)) { + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-undef\n")); + if (SvOK(d)) + goto ret_no; + else + goto ret_yes; + } + + if (SvROK(e) && SvOBJECT(SvRV(e)) && (SvTYPE(SvRV(e)) != SVt_REGEXP)) { + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Object\n")); + Perl_croak(aTHX_ "Smart matching a non-overloaded object breaks encapsulation"); + } + if (SvROK(d) && SvOBJECT(SvRV(d)) && (SvTYPE(SvRV(d)) != SVt_REGEXP)) + object_on_left = TRUE; + + /* ~~ sub */ + if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVCV) { + 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; + HV *hv = (HV*) SvRV(d); + I32 numkeys = hv_iterinit(hv); + DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-CodeRef\n")); + if (numkeys == 0) + goto ret_yes; + while ( (he = hv_iternext(hv)) ) { + DEBUG_M(Perl_deb(aTHX_ " testing hash key...\n")); + ENTER_with_name("smartmatch_hash_key_test"); + SAVETMPS; + PUSHMARK(PL_stack_sp); + rpp_xpush_1(hv_iterkeysv(he)); + (void)call_sv(e, G_SCALAR); + andedresults = SvTRUEx(PL_stack_sp[0]) && andedresults; + rpp_popfree_1_NN(); + FREETMPS; + LEAVE_with_name("smartmatch_hash_key_test"); + } + if (andedresults) + goto ret_yes; + else + goto ret_no; + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { + /* Test sub truth for each element */ + Size_t i; + bool andedresults = TRUE; + AV *av = (AV*) SvRV(d); + const Size_t len = av_count(av); + DEBUG_M(Perl_deb(aTHX_ " applying rule Array-CodeRef\n")); + if (len == 0) + goto ret_yes; + for (i = 0; i < len; ++i) { + SV * const * const svp = av_fetch(av, i, FALSE); + DEBUG_M(Perl_deb(aTHX_ " testing array element...\n")); + ENTER_with_name("smartmatch_array_elem_test"); + SAVETMPS; + PUSHMARK(PL_stack_sp); + if (svp) + rpp_xpush_1(*svp); + (void)call_sv(e, G_SCALAR); + andedresults = SvTRUEx(PL_stack_sp[0]) && andedresults; + rpp_popfree_1_NN(); + FREETMPS; + LEAVE_with_name("smartmatch_array_elem_test"); + } + if (andedresults) + goto ret_yes; + else + goto ret_no; + } + else { + sm_any_sub: + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-CodeRef\n")); + ENTER_with_name("smartmatch_coderef"); + PUSHMARK(PL_stack_sp); + rpp_xpush_1(d); + (void)call_sv(e, G_SCALAR); + LEAVE_with_name("smartmatch_coderef"); + SV *retsv = *PL_stack_sp--; + rpp_replace_2_1(retsv); +#ifdef PERL_RC_STACK + SvREFCNT_dec(retsv); +#endif + return NORMAL; + } + } + /* ~~ %hash */ + else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVHV) { + if (object_on_left) { + goto sm_any_hash; /* Treat objects like scalars */ + } + else if (!SvOK(d)) { + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Hash ($a undef)\n")); + goto ret_no; + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) { + /* Check that the key-sets are identical */ + HE *he; + HV *other_hv = HV_FROM_REF(d); + bool tied; + bool other_tied; + U32 this_key_count = 0, + other_key_count = 0; + HV *hv = HV_FROM_REF(e); + + DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Hash\n")); + /* Tied hashes don't know how many keys they have. */ + tied = cBOOL(SvTIED_mg((SV*)hv, PERL_MAGIC_tied)); + other_tied = cBOOL(SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied)); + if (!tied ) { + if(other_tied) { + /* swap HV sides */ + HV * const temp = other_hv; + other_hv = hv; + hv = temp; + tied = TRUE; + other_tied = FALSE; + } + else if(HvUSEDKEYS((const HV *) hv) != HvUSEDKEYS(other_hv)) + goto ret_no; + } + + /* The hashes have the same number of keys, so it suffices + to check that one is a subset of the other. */ + (void) hv_iterinit(hv); + while ( (he = hv_iternext(hv)) ) { + SV *key = hv_iterkeysv(he); + + DEBUG_M(Perl_deb(aTHX_ " comparing hash key...\n")); + ++ this_key_count; + + if(!hv_exists_ent(other_hv, key, 0)) { + (void) hv_iterinit(hv); /* reset iterator */ + goto ret_no; + } + } + + if (other_tied) { + (void) hv_iterinit(other_hv); + while ( hv_iternext(other_hv) ) + ++other_key_count; + } + else + other_key_count = HvUSEDKEYS(other_hv); + + if (this_key_count != other_key_count) + goto ret_no; + else + goto ret_yes; + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { + AV * const other_av = AV_FROM_REF(d); + const Size_t other_len = av_count(other_av); + Size_t i; + HV *hv = HV_FROM_REF(e); + + DEBUG_M(Perl_deb(aTHX_ " applying rule Array-Hash\n")); + for (i = 0; i < other_len; ++i) { + SV ** const svp = av_fetch(other_av, i, FALSE); + DEBUG_M(Perl_deb(aTHX_ " checking for key existence...\n")); + if (svp) { /* ??? When can this not happen? */ + if (hv_exists_ent(hv, *svp, 0)) + goto ret_yes; + } + } + goto ret_no; + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_REGEXP) { + DEBUG_M(Perl_deb(aTHX_ " applying rule Regex-Hash\n")); + sm_regex_hash: + { + PMOP * const matcher = make_matcher((REGEXP*) SvRV(d)); + HE *he; + HV *hv = HV_FROM_REF(e); + + (void) hv_iterinit(hv); + while ( (he = hv_iternext(hv)) ) { + DEBUG_M(Perl_deb(aTHX_ " testing key against pattern...\n")); + if (matcher_matches_sv(matcher, hv_iterkeysv(he))) { + (void) hv_iterinit(hv); + destroy_matcher(matcher); + goto ret_yes; + } + } + destroy_matcher(matcher); + goto ret_no; + } + } + else { + sm_any_hash: + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Hash\n")); + if (hv_exists_ent(HV_FROM_REF(e), d, 0)) + goto ret_yes; + else + goto ret_no; + } + } + /* ~~ @array */ + else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVAV) { + 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 = AV_FROM_REF(e); + const Size_t other_len = av_count(other_av); + Size_t i; + + DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Array\n")); + for (i = 0; i < other_len; ++i) { + SV ** const svp = av_fetch(other_av, i, FALSE); + + DEBUG_M(Perl_deb(aTHX_ " testing for key existence...\n")); + if (svp) { /* ??? When can this not happen? */ + if (hv_exists_ent(HV_FROM_REF(d), *svp, 0)) + goto ret_yes; + } + } + goto ret_no; + } + if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { + AV *other_av = AV_FROM_REF(d); + DEBUG_M(Perl_deb(aTHX_ " applying rule Array-Array\n")); + if (av_count(AV_FROM_REF(e)) != av_count(other_av)) + goto ret_no; + else { + Size_t i; + const Size_t other_len = av_count(other_av); + + if (NULL == seen_this) { + seen_this = (HV*)newSV_type_mortal(SVt_PVHV); + } + if (NULL == seen_other) { + seen_other = (HV*)newSV_type_mortal(SVt_PVHV); + } + for(i = 0; i < other_len; ++i) { + SV * const * const this_elem = av_fetch(AV_FROM_REF(e), i, FALSE); + SV * const * const other_elem = av_fetch(other_av, i, FALSE); + + if (!this_elem || !other_elem) { + if ((this_elem && SvOK(*this_elem)) + || (other_elem && SvOK(*other_elem))) + goto ret_no; + } + else if (hv_exists_ent(seen_this, + sv_2mortal(newSViv(PTR2IV(*this_elem))), 0) || + hv_exists_ent(seen_other, + sv_2mortal(newSViv(PTR2IV(*other_elem))), 0)) + { + if (*this_elem != *other_elem) + goto ret_no; + } + else { + (void)hv_store_ent(seen_this, + sv_2mortal(newSViv(PTR2IV(*this_elem))), + &PL_sv_undef, 0); + (void)hv_store_ent(seen_other, + sv_2mortal(newSViv(PTR2IV(*other_elem))), + &PL_sv_undef, 0); + rpp_xpush_2(*other_elem, *this_elem); + DEBUG_M(Perl_deb(aTHX_ " recursively comparing array element...\n")); + (void) do_smartmatch(seen_this, seen_other, 0); + DEBUG_M(Perl_deb(aTHX_ " recursion finished\n")); + + bool ok = SvTRUEx(PL_stack_sp[0]); + rpp_popfree_1_NN(); + if (!ok) + goto ret_no; + } + } + goto ret_yes; + } + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_REGEXP) { + DEBUG_M(Perl_deb(aTHX_ " applying rule Regex-Array\n")); + sm_regex_array: + { + PMOP * const matcher = make_matcher((REGEXP*) SvRV(d)); + const Size_t this_len = av_count(AV_FROM_REF(e)); + Size_t i; + + for(i = 0; i < this_len; ++i) { + SV * const * const svp = av_fetch(AV_FROM_REF(e), i, FALSE); + DEBUG_M(Perl_deb(aTHX_ " testing element against pattern...\n")); + if (svp && matcher_matches_sv(matcher, *svp)) { + destroy_matcher(matcher); + goto ret_yes; + } + } + destroy_matcher(matcher); + goto ret_no; + } + } + else if (!SvOK(d)) { + /* undef ~~ array */ + const Size_t this_len = av_count(AV_FROM_REF(e)); + Size_t i; + + DEBUG_M(Perl_deb(aTHX_ " applying rule Undef-Array\n")); + for (i = 0; i < this_len; ++i) { + SV * const * const svp = av_fetch(AV_FROM_REF(e), i, FALSE); + DEBUG_M(Perl_deb(aTHX_ " testing for undef element...\n")); + if (!svp || !SvOK(*svp)) + goto ret_yes; + } + goto ret_no; + } + else { + sm_any_array: + { + Size_t i; + const Size_t this_len = av_count(AV_FROM_REF(e)); + + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Array\n")); + for (i = 0; i < this_len; ++i) { + SV * const * const svp = av_fetch(AV_FROM_REF(e), i, FALSE); + if (!svp) + continue; + + rpp_xpush_2(d, *svp); + /* infinite recursion isn't supposed to happen here */ + DEBUG_M(Perl_deb(aTHX_ " recursively testing array element...\n")); + (void) do_smartmatch(NULL, NULL, 1); + DEBUG_M(Perl_deb(aTHX_ " recursion finished\n")); + bool ok = SvTRUEx(PL_stack_sp[0]); + rpp_popfree_1_NN(); + if (ok) + goto ret_yes; + } + goto ret_no; + } + } + } + /* ~~ qr// */ + else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_REGEXP) { + if (!object_on_left && SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) { + SV *t = d; d = e; e = t; + DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Regex\n")); + goto sm_regex_hash; + } + else if (!object_on_left && SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { + SV *t = d; d = e; e = t; + DEBUG_M(Perl_deb(aTHX_ " applying rule Array-Regex\n")); + goto sm_regex_array; + } + else { + PMOP * const matcher = make_matcher((REGEXP*) SvRV(e)); + bool result; + + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Regex\n")); + result = matcher_matches_sv(matcher, d); + destroy_matcher(matcher); + if (result) + goto ret_yes; + else + goto ret_no; + } + } + /* ~~ scalar */ + /* See if there is overload magic on left */ + else if (object_on_left && SvAMAGIC(d)) { + SV *tmpsv; + DEBUG_M(Perl_deb(aTHX_ " applying rule Object-Any\n")); + DEBUG_M(Perl_deb(aTHX_ " attempting overload\n")); + tmpsv = amagic_call(d, e, smart_amg, AMGf_noright); + if (tmpsv) { + rpp_replace_2_1_NN(tmpsv); + return NORMAL; + } + + DEBUG_M(Perl_deb(aTHX_ " failed to run overload method; falling back...\n")); + goto sm_any_scalar; + } + else if (!SvOK(d)) { + /* undef ~~ scalar ; we already know that the scalar is SvOK */ + DEBUG_M(Perl_deb(aTHX_ " applying rule undef-Any\n")); + goto ret_no; + } + else + sm_any_scalar: + if (SvNIOK(e) || (SvPOK(e) && looks_like_number(e) && SvNIOK(d))) { + DEBUG_M(if (SvNIOK(e)) + Perl_deb(aTHX_ " applying rule Any-Num\n"); + else + Perl_deb(aTHX_ " applying rule Num-numish\n"); + ); + /* numeric comparison */ + rpp_xpush_2(d, e); + if (CopHINTS_get(PL_curcop) & HINT_INTEGER) + (void) Perl_pp_i_eq(aTHX); + else + (void) Perl_pp_eq(aTHX); + bool ok = SvTRUEx(PL_stack_sp[0]); + rpp_popfree_1_NN(); + if (ok) + goto ret_yes; + else + goto ret_no; + } + + /* As a last resort, use string comparison */ + DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Any\n")); + rpp_xpush_2(d, e); + Perl_pp_seq(aTHX); + { + bool ok = SvTRUEx(PL_stack_sp[0]); + rpp_popfree_1_NN(); + if (ok) + goto ret_yes; + else + goto ret_no; + } + + ret_no: + rpp_replace_2_IMM_NN(&PL_sv_no); + return NORMAL; + + ret_yes: + rpp_replace_2_IMM_NN(&PL_sv_yes); + return NORMAL; +} + + static void _invoke_defer_block(pTHX_ U8 type, void *_arg) { diff --git a/pp_proto.h b/pp_proto.h index 02754995f4f2..1b9544163e99 100644 --- a/pp_proto.h +++ b/pp_proto.h @@ -264,6 +264,7 @@ PERL_CALLCONV PP(pp_shutdown) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_sin) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_sle) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_sleep) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_smartmatch) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_sne) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_socket) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_sockpair) __attribute__visibility__("hidden"); diff --git a/proto.h b/proto.h index 61327e70349d..ddac2c71f5fd 100644 --- a/proto.h +++ b/proto.h @@ -6395,6 +6395,13 @@ Perl_ck_shift(pTHX_ OP *o) # define PERL_ARGS_ASSERT_CK_SHIFT \ assert(o) +PERL_CALLCONV OP * +Perl_ck_smartmatch(pTHX_ OP *o) + __attribute__warn_unused_result__ + __attribute__visibility__("hidden"); +# define PERL_ARGS_ASSERT_CK_SMARTMATCH \ + assert(o) + PERL_CALLCONV OP * Perl_ck_sort(pTHX_ OP *o) __attribute__warn_unused_result__ @@ -7350,6 +7357,10 @@ S_process_special_blocks(pTHX_ I32 floor, const char * const fullname, GV * cons assert(fullname); assert(gv); assert(cv); \ assert(SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM) +STATIC OP * +S_ref_array_or_hash(pTHX_ OP *cond); +# define PERL_ARGS_ASSERT_REF_ARRAY_OR_HASH + STATIC OP * S_refkids(pTHX_ OP *o, I32 type); # define PERL_ARGS_ASSERT_REFKIDS @@ -7672,6 +7683,15 @@ S_check_type_and_open(pTHX_ SV *name) # define PERL_ARGS_ASSERT_CHECK_TYPE_AND_OPEN \ assert(name) +STATIC void +S_destroy_matcher(pTHX_ PMOP *matcher); +# define PERL_ARGS_ASSERT_DESTROY_MATCHER \ + assert(matcher) + +STATIC OP * +S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied); +# define PERL_ARGS_ASSERT_DO_SMARTMATCH + STATIC OP * S_docatch(pTHX_ Perl_ppaddr_t firstpp) __attribute__warn_unused_result__; @@ -7714,6 +7734,18 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) # define PERL_ARGS_ASSERT_DOPOPTOSUB_AT \ assert(cxstk) +STATIC PMOP * +S_make_matcher(pTHX_ REGEXP *re) + __attribute__warn_unused_result__; +# define PERL_ARGS_ASSERT_MAKE_MATCHER \ + assert(re) + +STATIC bool +S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv) + __attribute__warn_unused_result__; +# define PERL_ARGS_ASSERT_MATCHER_MATCHES_SV \ + assert(matcher); assert(sv) + STATIC bool S_num_overflow(NV value, I32 fldsize, I32 frcsize) __attribute__warn_unused_result__; diff --git a/regen/opcodes b/regen/opcodes index f93a7a0635b3..1757742fba89 100644 --- a/regen/opcodes +++ b/regen/opcodes @@ -178,6 +178,8 @@ complement 1's complement (~) ck_bitop fst1 S ncomplement numeric 1's complement (~) ck_bitop fsT1 S scomplement string 1's complement (~) ck_null fsT1 S +smartmatch smart match ck_smartmatch s2 + # High falutin' math. atan2 atan2 ck_fun fsT@ S S diff --git a/regen/overload.pl b/regen/overload.pl index 9496b7d369c6..cbd01b5d1b54 100644 --- a/regen/overload.pl +++ b/regen/overload.pl @@ -202,5 +202,6 @@ package overload::numbers; repeat_ass (x= concat (. concat_ass (.= +smart (~~ ftest (-X regexp (qr diff --git a/sv.c b/sv.c index f0b0b006d4b8..0cfea4571a5e 100644 --- a/sv.c +++ b/sv.c @@ -17543,6 +17543,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, case OP_DOFILE: case OP_PROTOTYPE: case OP_NCMP: + case OP_SMARTMATCH: case OP_UNPACK: case OP_SYSOPEN: case OP_SYSSEEK: diff --git a/t/comp/parser.t b/t/comp/parser.t index 20ecc7ac11c5..dbd5ecc842bc 100644 --- a/t/comp/parser.t +++ b/t/comp/parser.t @@ -558,6 +558,12 @@ eval{$1=eval{a:}}; eval "map+map"; eval "grep+grep"; +# ALso failed an assertion [perl #123848] +{ + local $SIG{__WARN__} = sub{}; + eval 'my $_; m// ~~ 0'; +} + # Used to crash [perl #125679] eval 'BEGIN {$^H=-1} \eval=time'; diff --git a/t/lib/warnings/9uninit b/t/lib/warnings/9uninit index 53e05e8a50dc..949e0b755aff 100644 --- a/t/lib/warnings/9uninit +++ b/t/lib/warnings/9uninit @@ -1950,6 +1950,13 @@ $v = 1 + prototype $fn; EXPECT Use of uninitialized value in addition (+) at - line 4. ######## +use warnings 'uninitialized'; no warnings 'deprecated'; +my $v; +my $fn = sub {}; +$v = 1 + (1 ~~ $fn); +EXPECT +Use of uninitialized value in addition (+) at - line 4. +######## use warnings 'uninitialized'; my $v; my $f = ""; diff --git a/t/lib/warnings/op b/t/lib/warnings/op index cf067d9e5378..995e54c98650 100644 --- a/t/lib/warnings/op +++ b/t/lib/warnings/op @@ -418,6 +418,7 @@ eval { getgrgid 1 }; # OP_GGRGID eval { getpwnam 1 }; # OP_GPWNAM eval { getpwuid 1 }; # OP_GPWUID prototype "foo"; # OP_PROTOTYPE +$a ~~ $b; # OP_SMARTMATCH $a <=> $b; # OP_NCMP "dsatrewq"; "diatrewq"; @@ -466,12 +467,13 @@ Useless use of getgrgid in void context at - line 51. Useless use of getpwnam in void context at - line 52. Useless use of getpwuid in void context at - line 53. Useless use of subroutine prototype in void context at - line 54. -Useless use of numeric comparison (<=>) in void context at - line 55. -Useless use of a constant ("dsatrewq") in void context at - line 56. -Useless use of a constant ("diatrewq") in void context at - line 57. -Useless use of a constant ("igatrewq") in void context at - line 58. -Useless use of __SUB__ in void context at - line 60. -Useless use of anonymous array ([]) in void context at - line 61. +Useless use of smart match in void context at - line 55. +Useless use of numeric comparison (<=>) in void context at - line 56. +Useless use of a constant ("dsatrewq") in void context at - line 57. +Useless use of a constant ("diatrewq") in void context at - line 58. +Useless use of a constant ("igatrewq") in void context at - line 59. +Useless use of __SUB__ in void context at - line 61. +Useless use of anonymous array ([]) in void context at - line 62. ######## # op.c use warnings 'scalar' ; close STDIN ; diff --git a/t/lib/warnings/utf8 b/t/lib/warnings/utf8 index 67d36ada6f30..49fa4e404f4d 100644 --- a/t/lib/warnings/utf8 +++ b/t/lib/warnings/utf8 @@ -779,7 +779,7 @@ BEGIN{ } no warnings; use warnings 'utf8'; -for(uc 0..t){pack("UXc",exp) == 0} +for(uc 0..t){0~~pack"UXc",exp} EXPECT OPTIONS regex Malformed UTF-8 character: \\x([[:xdigit:]]{2})\\x([[:xdigit:]]{2}) \(unexpected non-continuation byte 0x\2, immediately after start byte 0x\1; need 2 bytes, got 1\) in pack at - line 9. diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t new file mode 100644 index 000000000000..ca85d15785c2 --- /dev/null +++ b/t/op/smartmatch.t @@ -0,0 +1,592 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + require './test.pl'; + set_up_inc('../lib'); +} +use strict; +use warnings; +no warnings 'uninitialized'; +no warnings 'deprecated'; # smartmatch is deprecated and will be removed in 5.042 + +++$|; + +use Tie::Array; +use Tie::Hash; + +# Predeclare vars used in the tests: +my @empty; +my %empty; +my @sparse; $sparse[2] = 2; + +my $deep1 = []; push @$deep1, $deep1; +my $deep2 = []; push @$deep2, $deep2; + +my @nums = (1..10); +tie my @tied_nums, 'Tie::StdArray'; +@tied_nums = (1..10); + +my %hash = (foo => 17, bar => 23); +tie my %tied_hash, 'Tie::StdHash'; +%tied_hash = %hash; + +{ + package Test::Object::NoOverload; + sub new { bless { key => 1 } } +} + +{ + package Test::Object::StringOverload; + use overload '""' => sub { "object" }, fallback => 1; + sub new { bless { key => 1 } } +} + +{ + package Test::Object::WithOverload; + sub new { bless { key => ($_[1] // 'magic') } } + use overload '~~' => sub { + my %hash = %{ $_[0] }; + if ($_[2]) { # arguments reversed ? + return $_[1] eq reverse $hash{key}; + } + else { + return $_[1] eq $hash{key}; + } + }; + use overload '""' => sub { "stringified" }; + use overload 'eq' => sub {"$_[0]" eq "$_[1]"}; +} + +our $ov_obj = Test::Object::WithOverload->new; +our $ov_obj_2 = Test::Object::WithOverload->new("object"); +our $obj = Test::Object::NoOverload->new; +our $str_obj = Test::Object::StringOverload->new; + +my %refh; +unless (is_miniperl()) { + require Tie::RefHash; + tie %refh, 'Tie::RefHash'; + $refh{$ov_obj} = 1; +} + +my @keyandmore = qw(key and more); +my @fooormore = qw(foo or more); +my %keyandmore = map { $_ => 0 } @keyandmore; +my %fooormore = map { $_ => 0 } @fooormore; + +# Load and run the tests +plan tests => 349+4; + +while () { + SKIP: { + next if /^#/ || !/\S/; + chomp; + my ($yn, $left, $right, $note) = split /\t+/; + + local $::TODO = $note =~ /TODO/; + + die "Bad test spec: ($yn, $left, $right)" if $yn =~ /[^!@=]/; + + my $tstr = "$left ~~ $right"; + + test_again: + my $res; + if ($note =~ /NOWARNINGS/) { + $res = eval "no warnings; $tstr"; + } + else { + skip_if_miniperl("Doesn't work with miniperl", $yn =~ /=/ ? 2 : 1) + if $note =~ /MINISKIP/; + $res = eval $tstr; + } + + chomp $@; + + if ( $yn =~ /@/ ) { + ok( $@ ne '', "$tstr dies" ) + and print "# \$\@ was: $@\n"; + } else { + my $test_name = $tstr . ($yn =~ /!/ ? " does not match" : " matches"); + if ( $@ ne '' ) { + fail($test_name); + print "# \$\@ was: $@\n"; + } else { + ok( ($yn =~ /!/ xor $res), $test_name ); + } + } + + if ( $yn =~ s/=// ) { + $tstr = "$right ~~ $left"; + goto test_again; + } + } +} + +sub foo {} +sub bar {42} +sub gorch {42} +sub fatal {die "fatal sub\n"} + +# to test constant folding +sub FALSE() { 0 } +sub TRUE() { 1 } +sub NOT_DEF() { undef } + +{ + # [perl #123860] + # this can but might not crash + # This can but might not crash + # + # The second smartmatch would leave a &PL_sv_no on the stack for + # each key it checked in %!, this could then cause various types of + # crash or assertion failure. + # + # This isn't guaranteed to crash, but if the stack issue is + # re-introduced it will probably crash in one of the many smoke + # builds. + fresh_perl_is('print (q(x) ~~ q(x)) | (/x/ ~~ %!)', "1", + { switches => [ "-MErrno", "-M-warnings=deprecated" ] }, + "don't fill the stack with rubbish"); +} + +{ + # [perl #123860] continued; + # smartmatch was failing to SPAGAIN after pushing an SV and calling + # pp_match, which may have resulted in the stack being realloced + # in the meantime. Test this by filling the stack with pregressively + # larger amounts of data. At some point the stack will get realloced. + my @a = qw(x); + my %h = qw(x 1); + my @args; + my $x = 1; + my $bad = -1; + for (1..1000) { + push @args, $_; + my $exp_n = join '-', (@args, $x == 0); + my $exp_y = join '-', (@args, $x == 1); + + my $got_an = join '-', (@args, (/X/ ~~ @a)); + my $got_ay = join '-', (@args, (/x/ ~~ @a)); + my $got_hn = join '-', (@args, (/X/ ~~ %h)); + my $got_hy = join '-', (@args, (/x/ ~~ %h)); + + if ( $exp_n ne $got_an || $exp_n ne $got_hn + || $exp_y ne $got_ay || $exp_y ne $got_hy + ) { + $bad = $_; + last; + } + } + is($bad, -1, "RT 123860: stack realloc"); +} + + +{ + # [perl #130705] + # Perl_ck_smartmatch would turn the match in: + # 0 =~ qr/1/ ~~ 0 # parsed as (0 =~ qr/1/) ~~ 0 + # into a qr, leaving the initial 0 on the stack after execution + # + # Similarly for: 0 ~~ (0 =~ qr/1/) + # + # Either caused an assertion failure in the context of warn (or print) + # if there was some other operator's arguments left on the stack, as with + # the test cases. + fresh_perl_is('print(0->[0 =~ qr/1/ ~~ 0])', '', + { switches => [ "-M-warnings=deprecated" ] }, + "don't qr-ify left-side match against a stacked argument"); + fresh_perl_is('print(0->[0 ~~ (0 =~ qr/1/)])', '', + { switches => [ "-M-warnings=deprecated" ] }, + "don't qr-ify right-side match against a stacked argument"); +} + +# Prefix character : +# - expected to match +# ! - expected to not match +# @ - expected to be a compilation failure +# = - expected to match symmetrically (runs test twice) +# Data types to test : +# undef +# Object-overloaded +# Object +# Coderef +# Hash +# Hashref +# Array +# Arrayref +# Tied arrays and hashes +# Arrays that reference themselves +# Regex (// and qr//) +# Range +# Num +# Str +# Other syntactic items of interest: +# Constants +# Values returned by a sub call +__DATA__ +# Any ~~ undef +! $ov_obj undef +! $obj undef +! sub {} undef +! %hash undef +! \%hash undef +! {} undef +! @nums undef +! \@nums undef +! [] undef +! %tied_hash undef +! @tied_nums undef +! $deep1 undef +! /foo/ undef +! qr/foo/ undef +! 21..30 undef +! 189 undef +! "foo" undef +! "" undef +! !1 undef + undef undef + (my $u) undef + NOT_DEF undef + &NOT_DEF undef + +# Any ~~ object overloaded +! \&fatal $ov_obj + 'cigam' $ov_obj +! 'cigam on' $ov_obj +! ['cigam'] $ov_obj +! ['stringified'] $ov_obj +! { cigam => 1 } $ov_obj +! { stringified => 1 } $ov_obj +! $obj $ov_obj +! undef $ov_obj + +# regular object +@ $obj $obj +@ $ov_obj $obj +=@ \&fatal $obj +@ \&FALSE $obj +@ \&foo $obj +@ sub { 1 } $obj +@ sub { 0 } $obj +@ %keyandmore $obj +@ {"key" => 1} $obj +@ @fooormore $obj +@ ["key" => 1] $obj +@ /key/ $obj +@ qr/key/ $obj +@ "key" $obj +@ FALSE $obj + +# regular object with "" overload +@ $obj $str_obj +=@ \&fatal $str_obj +@ \&FALSE $str_obj +@ \&foo $str_obj +@ sub { 1 } $str_obj +@ sub { 0 } $str_obj +@ %keyandmore $str_obj +@ {"object" => 1} $str_obj +@ @fooormore $str_obj +@ ["object" => 1] $str_obj +@ /object/ $str_obj +@ qr/object/ $str_obj +@ "object" $str_obj +@ FALSE $str_obj +# Those will treat the $str_obj as a string because of fallback: + +# object (overloaded or not) ~~ Any + $obj qr/NoOverload/ + $ov_obj qr/^stringified$/ += "$ov_obj" "stringified" += "$str_obj" "object" +!= $ov_obj "stringified" + $str_obj "object" + $ov_obj 'magic' +! $ov_obj 'not magic' + +# ~~ Coderef + sub{0} sub { ref $_[0] eq "CODE" } + %fooormore sub { $_[0] =~ /^(foo|or|more)$/ } +! %fooormore sub { $_[0] =~ /^(foo|or|less)$/ } + \%fooormore sub { $_[0] =~ /^(foo|or|more)$/ } +! \%fooormore sub { $_[0] =~ /^(foo|or|less)$/ } + +{%fooormore} sub { $_[0] =~ /^(foo|or|more)$/ } +! +{%fooormore} sub { $_[0] =~ /^(foo|or|less)$/ } + @fooormore sub { $_[0] =~ /^(foo|or|more)$/ } +! @fooormore sub { $_[0] =~ /^(foo|or|less)$/ } + \@fooormore sub { $_[0] =~ /^(foo|or|more)$/ } +! \@fooormore sub { $_[0] =~ /^(foo|or|less)$/ } + [@fooormore] sub { $_[0] =~ /^(foo|or|more)$/ } +! [@fooormore] sub { $_[0] =~ /^(foo|or|less)$/ } + %fooormore sub{@_==1} + @fooormore sub{@_==1} + "foo" sub { $_[0] =~ /^(foo|or|more)$/ } +! "more" sub { $_[0] =~ /^(foo|or|less)$/ } + /fooormore/ sub{ref $_[0] eq 'Regexp'} + qr/fooormore/ sub{ref $_[0] eq 'Regexp'} + 1 sub{shift} +! 0 sub{shift} +! undef sub{shift} + undef sub{not shift} + NOT_DEF sub{not shift} + &NOT_DEF sub{not shift} + FALSE sub{not shift} + [1] \&bar + {a=>1} \&bar + qr// \&bar +! [1] \&foo +! {a=>1} \&foo + $obj sub { ref($_[0]) =~ /NoOverload/ } + $ov_obj sub { ref($_[0]) =~ /WithOverload/ } +# empty stuff matches, because the sub is never called: + [] \&foo + {} \&foo + @empty \&foo + %empty \&foo +! qr// \&foo +! undef \&foo + undef \&bar +@ undef \&fatal +@ 1 \&fatal +@ [1] \&fatal +@ {a=>1} \&fatal +@ "foo" \&fatal +@ qr// \&fatal +# sub is not called on empty hashes / arrays + [] \&fatal + +{} \&fatal + @empty \&fatal + %empty \&fatal +# sub is not special on the left + sub {0} qr/^CODE/ + sub {0} sub { ref shift eq "CODE" } + +# HASH ref against: +# - another hash ref + {} {} +=! {} {1 => 2} + {1 => 2} {1 => 2} + {1 => 2} {1 => 3} +=! {1 => 2} {2 => 3} += \%main:: {map {$_ => 'x'} keys %main::} + +# - tied hash ref += \%hash \%tied_hash + \%tied_hash \%tied_hash +!= {"a"=>"b"} \%tied_hash += %hash %tied_hash + %tied_hash %tied_hash +!= {"a"=>"b"} %tied_hash + $ov_obj %refh MINISKIP +! "$ov_obj" %refh MINISKIP + [$ov_obj] %refh MINISKIP +! ["$ov_obj"] %refh MINISKIP + %refh %refh MINISKIP + +# - an array ref +# (since this is symmetrical, tests as well hash~~array) += [keys %main::] \%:: += [qw[STDIN STDOUT]] \%:: +=! [] \%:: +=! [""] {} +=! [] {} +=! @empty {} += [undef] {"" => 1} += [""] {"" => 1} += ["foo"] { foo => 1 } += ["foo", "bar"] { foo => 1 } += ["foo", "bar"] \%hash += ["foo"] \%hash +=! ["quux"] \%hash += [qw(foo quux)] \%hash += @fooormore { foo => 1, or => 2, more => 3 } += @fooormore %fooormore += @fooormore \%fooormore += \@fooormore %fooormore + +# - a regex += qr/^(fo[ox])$/ {foo => 1} += /^(fo[ox])$/ %fooormore +=! qr/[13579]$/ +{0..99} +=! qr/a*/ {} += qr/a*/ {b=>2} += qr/B/i {b=>2} += /B/i {b=>2} +=! qr/a+/ {b=>2} += qr/^à/ {"à"=>2} + +# - a scalar + "foo" +{foo => 1, bar => 2} + "foo" %fooormore +! "baz" +{foo => 1, bar => 2} +! "boz" %fooormore +! 1 +{foo => 1, bar => 2} +! 1 %fooormore + 1 { 1 => 3 } + 1.0 { 1 => 3 } +! "1.0" { 1 => 3 } +! "1.0" { 1.0 => 3 } + "1.0" { "1.0" => 3 } + "à" { "à" => "À" } + +# - undef +! undef { hop => 'zouu' } +! undef %hash +! undef +{"" => "empty key"} +! undef {} + +# ARRAY ref against: +# - another array ref + [] [] +=! [] [1] + [["foo"], ["bar"]] [qr/o/, qr/a/] +! [["foo"], ["bar"]] [qr/ARRAY/, qr/ARRAY/] + ["foo", "bar"] [qr/o/, qr/a/] +! [qr/o/, qr/a/] ["foo", "bar"] + ["foo", "bar"] [["foo"], ["bar"]] +! ["foo", "bar"] [qr/o/, "foo"] + ["foo", undef, "bar"] [qr/o/, undef, "bar"] +! ["foo", undef, "bar"] [qr/o/, "", "bar"] +! ["foo", "", "bar"] [qr/o/, undef, "bar"] + $deep1 $deep1 + @$deep1 @$deep1 +! $deep1 $deep2 + += \@nums \@tied_nums += @nums \@tied_nums += \@nums @tied_nums += @nums @tied_nums + +# - an object +! $obj @fooormore + $obj [sub{ref shift}] + +# - a regex += qr/x/ [qw(foo bar baz quux)] +=! qr/y/ [qw(foo bar baz quux)] += /x/ [qw(foo bar baz quux)] +=! /y/ [qw(foo bar baz quux)] += /FOO/i @fooormore +=! /bar/ @fooormore + +# - a number + 2 [qw(1.00 2.00)] + 2 [qw(foo 2)] + 2.0_0e+0 [qw(foo 2)] +! 2 [qw(1foo bar2)] + +# - a string +! "2" [qw(1foo 2bar)] + "2bar" [qw(1foo 2bar)] + +# - undef + undef [1, 2, undef, 4] +! undef [1, 2, [undef], 4] +! undef @fooormore + undef @sparse + undef [undef] +! 0 [undef] +! "" [undef] +! undef [0] +! undef [""] + +# - nested arrays and ~~ distributivity + 11 [[11]] +! 11 [[12]] + "foo" [{foo => "bar"}] +! "bar" [{foo => "bar"}] + +# Number against number + 2 2 + 20 2_0 +! 2 3 + 0 FALSE + 3-2 TRUE +! undef 0 +! (my $u) 0 + +# Number against string += 2 "2" += 2 "2.0" +! 2 "2bananas" +!= 2_3 "2_3" NOWARNINGS + FALSE "0" +! undef "0" +! undef "" + +# Regex against string + "x" qr/x/ +! "x" qr/y/ + +# Regex against number + 12345 qr/3/ +! 12345 qr/7/ + +# array/hash against string + @fooormore "".\@fooormore +! @keyandmore "".\@fooormore + %fooormore "".\%fooormore +! %keyandmore "".\%fooormore + +# Test the implicit referencing + 7 @nums + @nums \@nums +! @nums \\@nums + @nums [1..10] +! @nums [0..9] + + "foo" %hash + /bar/ %hash + [qw(bar)] %hash +! [qw(a b c)] %hash + %hash %hash + %hash +{%hash} + %hash \%hash + %hash %tied_hash + %tied_hash %tied_hash + %hash { foo => 5, bar => 10 } +! %hash { foo => 5, bar => 10, quux => 15 } + + @nums { 1, '', 2, '' } + @nums { 1, '', 12, '' } +! @nums { 11, '', 12, '' } + +# array slices + @nums[0..-1] [] + @nums[0..0] [1] +! @nums[0..1] [0..2] + @nums[0..4] [1..5] + +! undef @nums[0..-1] + 1 @nums[0..0] + 2 @nums[0..1] +! @nums[0..1] 2 + + @nums[0..1] @nums[0..1] + +# hash slices + @keyandmore{qw(not)} [undef] + @keyandmore{qw(key)} [0] + + undef @keyandmore{qw(not)} + 0 @keyandmore{qw(key and more)} +! 2 @keyandmore{qw(key and)} + + @fooormore{qw(foo)} @keyandmore{qw(key)} + @fooormore{qw(foo or more)} @keyandmore{qw(key and more)} + +# UNDEF +! 3 undef +! 1 undef +! [] undef +! {} undef +! \%::main undef +! [1,2] undef +! %hash undef +! @nums undef +! "foo" undef +! "" undef +! !1 undef +! \&foo undef +! sub { } undef diff --git a/t/op/svleak.t b/t/op/svleak.t index 8b2a35c08533..da7bd6e2b052 100644 --- a/t/op/svleak.t +++ b/t/op/svleak.t @@ -15,7 +15,7 @@ BEGIN { use Config; -plan tests => 156; +plan tests => 157; # run some code N times. If the number of SVs at the end of loop N is # greater than (N-1)*delta at the end of loop 1, we've got a leak @@ -646,6 +646,13 @@ my $refcount; PERL } +{ + # smartmatch is deprecated and will be removed in 5.042 + no warnings 'deprecated'; + my $one = 1; + leak 2, 0, sub { 1 ~~ sub { 1 + $one } }, 'Smartmatch doesn\'t leak'; +} + # the initial implementation of the require hook had some leaks sub hook::before { $_[0] = "NoSuchFile2" if $_[0] =~/ NoSuch/; diff --git a/t/op/taint.t b/t/op/taint.t index 1e7a3e47de46..a884a3e47721 100644 --- a/t/op/taint.t +++ b/t/op/taint.t @@ -25,7 +25,7 @@ if ($NoTaintSupport) { exit 0; } -plan tests => 1057; +plan tests => 1059; $| = 1; @@ -2454,6 +2454,14 @@ EOF ok(!tainted "", "tainting still works after index() of the constant"); } +# Tainted values with smartmatch +# [perl #93590] S_do_smartmatch stealing its own string buffers +{ +no warnings 'deprecated'; +ok "M$TAINT" ~~ ['m', 'M'], '$tainted ~~ ["whatever", "match"]'; +ok !("M$TAINT" ~~ ['m', undef]), '$tainted ~~ ["whatever", undef]'; +} + # Tainted values and ref() for(1,2) { my $x = bless \"M$TAINT", ref(bless[], "main"); diff --git a/t/op/tie_fetch_count.t b/t/op/tie_fetch_count.t index 2b79f34e5eae..86505f6eba85 100644 --- a/t/op/tie_fetch_count.t +++ b/t/op/tie_fetch_count.t @@ -9,7 +9,7 @@ BEGIN { set_up_inc('../lib'); } -plan (tests => 342); +plan (tests => 343); use strict; use warnings; @@ -164,6 +164,10 @@ $dummy = -e -e -e $var ; check_count '-e -e'; $_ = "foo"; $dummy = $var =~ m/ / ; check_count 'm//'; $dummy = $var =~ s/ //; check_count 's///'; +{ + no warnings 'deprecated'; + $dummy = $var ~~ 1 ; check_count '~~'; +} $dummy = $var =~ y/ //; check_count 'y///'; $var = \1; $dummy = $var =~y/ /-/; check_count '$ref =~ y///'; diff --git a/toke.c b/toke.c index 22ba91f6cffb..a6c8b2603f07 100644 --- a/toke.c +++ b/toke.c @@ -6813,6 +6813,15 @@ static int yyl_tilde(pTHX_ char *s) { bool bof; + if (s[1] == '~' && (PL_expect == XOPERATOR || PL_expect == XTERMORDORDOR)) { + if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE) + TOKEN(0); + s += 2; + Perl_ck_warner_d(aTHX_ + packWARN(WARN_DEPRECATED__SMARTMATCH), + "Smartmatch is deprecated"); + NCEop(OP_SMARTMATCH); + } s++; if ((bof = FEATURE_BITWISE_IS_ENABLED) && *s == '.') { s++; From 74a8eae3fde75e4fac344071530c87f27a590856 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 18 Nov 2024 15:40:50 +1100 Subject: [PATCH 08/12] Revert "switch removal: remove given/when/break/continue" This reverts commit dff5181acc0f5386556522c0ae4e59f672162f6e. --- MANIFEST | 2 + cop.h | 28 +- dump.c | 2 + embed.fnc | 18 + embed.h | 10 + ext/Opcode/Opcode.pm | 5 +- gv.c | 8 +- inline.h | 46 + keywords.c | 136 ++- keywords.h | 480 ++++----- lib/B/Deparse-core.t | 9 +- lib/B/Deparse.pm | 34 +- lib/B/Deparse.t | 57 +- lib/B/Op_private.pm | 4 + op.c | 215 +++- opcode.h | 44 +- opnames.h | 400 +++---- perl.h | 2 + perly.act | 1067 ++++++++++--------- perly.h | 181 ++-- perly.tab | 2412 +++++++++++++++++++++--------------------- perly.y | 12 + pod/perldiag.pod | 47 + pod/perlguts.pod | 2 + pod/perlsyn.pod | 444 +++++++- pp_ctl.c | 227 +++- pp_proto.h | 6 + proto.h | 52 + regen/keywords.pl | 8 + regen/opcodes | 7 + sv.c | 5 + t/lib/croak/pp_ctl | 11 +- t/lib/feature/switch | 142 +++ t/op/coreamp.t | 27 +- t/op/coresubs.t | 6 +- t/op/cproto.t | 7 +- t/op/state.t | 14 +- t/op/switch.t | 1384 ++++++++++++++++++++++++ t/op/taint.t | 28 +- toke.c | 35 +- 40 files changed, 5296 insertions(+), 2328 deletions(-) create mode 100644 t/lib/feature/switch create mode 100644 t/op/switch.t diff --git a/MANIFEST b/MANIFEST index e3ca90d7d2f9..68d330820920 100644 --- a/MANIFEST +++ b/MANIFEST @@ -6118,6 +6118,7 @@ t/lib/feature/multidimensional Tests for enabling/disabling $foo{$x, $y} => $fo t/lib/feature/nonesuch Tests for enabling/disabling nonexistent feature t/lib/feature/removed Tests for enabling/disabling removed feature t/lib/feature/say Tests for enabling/disabling say feature +t/lib/feature/switch Tests for enabling/disabling switch feature t/lib/h2ph.h Test header file for h2ph t/lib/h2ph.pht Generated output from h2ph.h by h2ph, for comparison t/lib/locale/latin1 Part of locale.t in Latin 1 @@ -6440,6 +6441,7 @@ t/op/substr_thr.t See if substr works in another thread t/op/svflags.t See if POK is set as expected. t/op/svleak.pl Test file for svleak.t t/op/svleak.t See if stuff leaks SVs +t/op/switch.t See if switches (given/when) work t/op/symbolcache.t See if undef/delete works on stashes with functions t/op/sysio.t See if sysread and syswrite work t/op/taint.t See if tainting works diff --git a/cop.h b/cop.h index 1b868be9f723..c9d36ca44bf2 100644 --- a/cop.h +++ b/cop.h @@ -1119,21 +1119,27 @@ struct context { and a static array of context names in pp_ctl.c */ #define CXTYPEMASK 0xf #define CXt_NULL 0 /* currently only used for sort BLOCK */ -#define CXt_BLOCK 1 +#define CXt_WHEN 1 +#define CXt_BLOCK 2 +/* When micro-optimising :-) keep GIVEN next to the LOOPs, as these 5 share a + jump table in pp_ctl.c + The first 4 don't have a 'case' in at least one switch statement in pp_ctl.c +*/ +#define CXt_GIVEN 3 /* be careful of the ordering of these five. Macros like CxTYPE_is_LOOP, * CxFOREACH compare ranges */ -#define CXt_LOOP_ARY 2 /* for (@ary) { ...; } */ -#define CXt_LOOP_LAZYSV 3 /* for ('a'..'z') { ...; } */ -#define CXt_LOOP_LAZYIV 4 /* for (1..9) { ...; } */ -#define CXt_LOOP_LIST 5 /* for (1,2,3) { ...; } */ -#define CXt_LOOP_PLAIN 6 /* while (...) { ...; } +#define CXt_LOOP_ARY 4 /* for (@ary) { ...; } */ +#define CXt_LOOP_LAZYSV 5 /* for ('a'..'z') { ...; } */ +#define CXt_LOOP_LAZYIV 6 /* for (1..9) { ...; } */ +#define CXt_LOOP_LIST 7 /* for (1,2,3) { ...; } */ +#define CXt_LOOP_PLAIN 8 /* while (...) { ...; } or plain block { ...; } */ -#define CXt_SUB 7 -#define CXt_FORMAT 8 -#define CXt_EVAL 9 /* eval'', eval{}, try{} */ -#define CXt_SUBST 10 -#define CXt_DEFER 11 +#define CXt_SUB 9 +#define CXt_FORMAT 10 +#define CXt_EVAL 11 /* eval'', eval{}, try{} */ +#define CXt_SUBST 12 +#define CXt_DEFER 13 /* SUBST doesn't feature in all switch statements. */ /* private flags for CXt_SUB and CXt_FORMAT */ diff --git a/dump.c b/dump.c index cdbbb0e2819d..4b72ada8b973 100644 --- a/dump.c +++ b/dump.c @@ -1444,6 +1444,8 @@ S_do_op_dump_bar(pTHX_ I32 level, UV bar, PerlIO *file, const OP *o) case OP_DORASSIGN: case OP_ANDASSIGN: case OP_ARGDEFELEM: + case OP_ENTERGIVEN: + case OP_ENTERWHEN: case OP_ENTERTRY: case OP_ONCE: S_opdump_indent(aTHX_ o, level, bar, file, "OTHER"); diff --git a/embed.fnc b/embed.fnc index ec3058f86e4c..744f7ef55847 100644 --- a/embed.fnc +++ b/embed.fnc @@ -2196,6 +2196,9 @@ ARdp |OP * |newFOROP |I32 flags \ |NN OP *expr \ |NULLOK OP *block \ |NULLOK OP *cont +ARdp |OP * |newGIVENOP |NN OP *cond \ + |NN OP *block \ + |PADOFFSET defsv_off : Used in scope.c eopx |GP * |newGP |NN GV * const gv Adm |GV * |newGVgen |NN const char *pack @@ -2340,6 +2343,8 @@ ERXopx |char * |new_warnings_bitfield \ |NULLOK char *buffer \ |NN const char * const bits \ |STRLEN size +ARdp |OP * |newWHENOP |NULLOK OP *cond \ + |NN OP *block ARdp |OP * |newWHILEOP |I32 flags \ |I32 debuggable \ |NULLOK LOOP *loop \ @@ -4765,6 +4770,7 @@ RST |bool |is_handle_constructor \ Ti |bool |is_standard_filehandle_name \ |NN const char *fhname S |OP * |listkids |NULLOK OP *o +S |bool |looks_like_bool|NN const OP *o S |OP * |modkids |NULLOK OP *o \ |I32 type S |void |move_proto_attr|NN OP **proto \ @@ -4774,6 +4780,11 @@ S |void |move_proto_attr|NN OP **proto \ S |OP * |my_kid |NULLOK OP *o \ |NULLOK OP *attrs \ |NN OP **imopsp +S |OP * |newGIVWHENOP |NULLOK OP *cond \ + |NN OP *block \ + |I32 enter_opcode \ + |I32 leave_opcode \ + |PADOFFSET entertarg RS |OP * |new_logop |I32 type \ |I32 flags \ |NN OP **firstp \ @@ -4991,12 +5002,14 @@ RS |OP * |dofindlabel |NN OP *o \ |NN OP **oplimit S |MAGIC *|doparseform |NN SV *sv RS |I32 |dopoptoeval |I32 startingblock +RS |I32 |dopoptogivenfor|I32 startingblock RS |I32 |dopoptolabel |NN const char *label \ |STRLEN len \ |U32 flags RS |I32 |dopoptoloop |I32 startingblock RS |I32 |dopoptosub_at |NN const PERL_CONTEXT *cxstk \ |I32 startingblock +RS |I32 |dopoptowhen |I32 startingblock S |OP * |do_smartmatch |NULLOK HV *seen_this \ |NULLOK HV *seen_other \ |const bool copied @@ -6115,11 +6128,13 @@ CTp |Malloc_t|mem_log_realloc \ Cipx |void |cx_popblock |NN PERL_CONTEXT *cx Cipx |void |cx_popeval |NN PERL_CONTEXT *cx Cipx |void |cx_popformat |NN PERL_CONTEXT *cx +Cipx |void |cx_popgiven |NN PERL_CONTEXT *cx Cipx |void |cx_poploop |NN PERL_CONTEXT *cx Cipx |void |cx_popsub |NN PERL_CONTEXT *cx Cipx |void |cx_popsub_args |NN PERL_CONTEXT *cx Cipx |void |cx_popsub_common \ |NN PERL_CONTEXT *cx +Cipx |void |cx_popwhen |NN PERL_CONTEXT *cx Cipx |PERL_CONTEXT *|cx_pushblock \ |U8 type \ |U8 gimme \ @@ -6132,6 +6147,8 @@ Cipx |void |cx_pushformat |NN PERL_CONTEXT *cx \ |NN CV *cv \ |NULLOK OP *retop \ |NULLOK GV *gv +Cipx |void |cx_pushgiven |NN PERL_CONTEXT *cx \ + |NULLOK SV *orig_defsv Cipx |void |cx_pushloop_for|NN PERL_CONTEXT *cx \ |NN void *itervarp \ |NULLOK SV *itersave @@ -6143,6 +6160,7 @@ Cipx |void |cx_pushsub |NN PERL_CONTEXT *cx \ |bool hasargs Cipx |void |cx_pushtry |NN PERL_CONTEXT *cx \ |NULLOK OP *retop +Cipx |void |cx_pushwhen |NN PERL_CONTEXT *cx Cipx |void |cx_topblock |NN PERL_CONTEXT *cx Cipx |U8 |gimme_V #endif /* !defined(PERL_NO_INLINE_FUNCTIONS) */ diff --git a/embed.h b/embed.h index dae6e35efeb0..c33d983d2028 100644 --- a/embed.h +++ b/embed.h @@ -420,6 +420,7 @@ # define newDEFSVOP() Perl_newDEFSVOP(aTHX) # define newFORM(a,b,c) Perl_newFORM(aTHX_ a,b,c) # define newFOROP(a,b,c,d,e) Perl_newFOROP(aTHX_ a,b,c,d,e) +# define newGIVENOP(a,b,c) Perl_newGIVENOP(aTHX_ a,b,c) # define newGVOP(a,b,c) Perl_newGVOP(aTHX_ a,b,c) # define newGVREF(a,b) Perl_newGVREF(aTHX_ a,b) # define newGVgen_flags(a,b) Perl_newGVgen_flags(aTHX_ a,b) @@ -475,6 +476,7 @@ # define newTRYCATCHOP(a,b,c,d) Perl_newTRYCATCHOP(aTHX_ a,b,c,d) # define newUNOP(a,b,c) Perl_newUNOP(aTHX_ a,b,c) # define newUNOP_AUX(a,b,c,d) Perl_newUNOP_AUX(aTHX_ a,b,c,d) +# define newWHENOP(a,b) Perl_newWHENOP(aTHX_ a,b) # define newWHILEOP(a,b,c,d,e,f,g) Perl_newWHILEOP(aTHX_ a,b,c,d,e,f,g) # define newXS(a,b,c) Perl_newXS(aTHX_ a,b,c) # define newXS_flags(a,b,c,d,e) Perl_newXS_flags(aTHX_ a,b,c,d,e) @@ -1518,9 +1520,11 @@ # define is_handle_constructor S_is_handle_constructor # define is_standard_filehandle_name S_is_standard_filehandle_name # define listkids(a) S_listkids(aTHX_ a) +# define looks_like_bool(a) S_looks_like_bool(aTHX_ a) # define modkids(a,b) S_modkids(aTHX_ a,b) # define move_proto_attr(a,b,c,d) S_move_proto_attr(aTHX_ a,b,c,d) # define my_kid(a,b,c) S_my_kid(aTHX_ a,b,c) +# define newGIVWHENOP(a,b,c,d,e) S_newGIVWHENOP(aTHX_ a,b,c,d,e) # define newMETHOP_internal(a,b,c,d) S_newMETHOP_internal(aTHX_ a,b,c,d) # define new_logop(a,b,c,d) S_new_logop(aTHX_ a,b,c,d) # define no_fh_allowed(a) S_no_fh_allowed(aTHX_ a) @@ -1612,9 +1616,11 @@ # define dofindlabel(a,b,c,d,e,f) S_dofindlabel(aTHX_ a,b,c,d,e,f) # define doparseform(a) S_doparseform(aTHX_ a) # define dopoptoeval(a) S_dopoptoeval(aTHX_ a) +# define dopoptogivenfor(a) S_dopoptogivenfor(aTHX_ a) # define dopoptolabel(a,b,c) S_dopoptolabel(aTHX_ a,b,c) # define dopoptoloop(a) S_dopoptoloop(aTHX_ a) # define dopoptosub_at(a,b) S_dopoptosub_at(aTHX_ a,b) +# define dopoptowhen(a) S_dopoptowhen(aTHX_ a) # define make_matcher(a) S_make_matcher(aTHX_ a) # define matcher_matches_sv(a,b) S_matcher_matches_sv(aTHX_ a,b) # define num_overflow S_num_overflow @@ -2205,17 +2211,21 @@ # define cx_popblock(a) Perl_cx_popblock(aTHX_ a) # define cx_popeval(a) Perl_cx_popeval(aTHX_ a) # define cx_popformat(a) Perl_cx_popformat(aTHX_ a) +# define cx_popgiven(a) Perl_cx_popgiven(aTHX_ a) # define cx_poploop(a) Perl_cx_poploop(aTHX_ a) # define cx_popsub(a) Perl_cx_popsub(aTHX_ a) # define cx_popsub_args(a) Perl_cx_popsub_args(aTHX_ a) # define cx_popsub_common(a) Perl_cx_popsub_common(aTHX_ a) +# define cx_popwhen(a) Perl_cx_popwhen(aTHX_ a) # define cx_pushblock(a,b,c,d) Perl_cx_pushblock(aTHX_ a,b,c,d) # define cx_pusheval(a,b,c) Perl_cx_pusheval(aTHX_ a,b,c) # define cx_pushformat(a,b,c,d) Perl_cx_pushformat(aTHX_ a,b,c,d) +# define cx_pushgiven(a,b) Perl_cx_pushgiven(aTHX_ a,b) # define cx_pushloop_for(a,b,c) Perl_cx_pushloop_for(aTHX_ a,b,c) # define cx_pushloop_plain(a) Perl_cx_pushloop_plain(aTHX_ a) # define cx_pushsub(a,b,c,d) Perl_cx_pushsub(aTHX_ a,b,c,d) # define cx_pushtry(a,b) Perl_cx_pushtry(aTHX_ a,b) +# define cx_pushwhen(a) Perl_cx_pushwhen(aTHX_ a) # define cx_topblock(a) Perl_cx_topblock(aTHX_ a) # define gimme_V() Perl_gimme_V(aTHX) # endif /* !defined(PERL_NO_INLINE_FUNCTIONS) */ diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index 4168b46ecd0a..c7820c172873 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -1,4 +1,4 @@ -package Opcode 1.66; +package Opcode 1.65; use strict; @@ -434,6 +434,9 @@ These are a hotchpotch of opcodes still waiting to be considered entertry leavetry -- can be used to 'hide' fatal errors entertrycatch poptry catch leavetrycatch -- similar + entergiven leavegiven + enterwhen leavewhen + break continue smartmatch pushdefer diff --git a/gv.c b/gv.c index bfd5f30fefae..417c689f66a7 100644 --- a/gv.c +++ b/gv.c @@ -611,13 +611,13 @@ S_maybe_add_coresub(pTHX_ HV * const stash, GV *gv, case KEY___DATA__: case KEY___END__ : case KEY_ADJUST : case KEY_AUTOLOAD: case KEY_BEGIN : case KEY_CHECK : case KEY_DESTROY : case KEY_END : case KEY_INIT : case KEY_UNITCHECK: - case KEY_and : case KEY_catch : case KEY_class : - case KEY_continue: case KEY_cmp : case KEY_defer : + case KEY_and : case KEY_catch : case KEY_class : + case KEY_cmp : case KEY_default: case KEY_defer : case KEY_do : case KEY_dump : case KEY_else : case KEY_elsif : case KEY_eq : case KEY_eval : case KEY_field : case KEY_finally: case KEY_for : case KEY_foreach: case KEY_format: case KEY_ge : - case KEY_goto : case KEY_grep : case KEY_gt : + case KEY_given : case KEY_goto : case KEY_grep : case KEY_gt : case KEY_if : case KEY_isa : case KEY_last : case KEY_le : case KEY_local : case KEY_lt : case KEY_m : @@ -630,7 +630,7 @@ S_maybe_add_coresub(pTHX_ HV * const stash, GV *gv, case KEY_state: case KEY_sub : case KEY_tr : case KEY_try : case KEY_unless: - case KEY_until: case KEY_use : case KEY_while : + case KEY_until: case KEY_use : case KEY_when : case KEY_while : case KEY_x : case KEY_xor : case KEY_y : return NULL; case KEY_chomp: case KEY_chop: case KEY_defined: case KEY_delete: diff --git a/inline.h b/inline.h index 11e59be414a4..a4c70fc95187 100644 --- a/inline.h +++ b/inline.h @@ -3695,6 +3695,52 @@ Perl_cx_poploop(pTHX_ PERL_CONTEXT *cx) } +PERL_STATIC_INLINE void +Perl_cx_pushwhen(pTHX_ PERL_CONTEXT *cx) +{ + PERL_ARGS_ASSERT_CX_PUSHWHEN; + + cx->blk_givwhen.leave_op = cLOGOP->op_other; +} + + +PERL_STATIC_INLINE void +Perl_cx_popwhen(pTHX_ PERL_CONTEXT *cx) +{ + PERL_ARGS_ASSERT_CX_POPWHEN; + assert(CxTYPE(cx) == CXt_WHEN); + + PERL_UNUSED_ARG(cx); + PERL_UNUSED_CONTEXT; + /* currently NOOP */ +} + + +PERL_STATIC_INLINE void +Perl_cx_pushgiven(pTHX_ PERL_CONTEXT *cx, SV *orig_defsv) +{ + PERL_ARGS_ASSERT_CX_PUSHGIVEN; + + cx->blk_givwhen.leave_op = cLOGOP->op_other; + cx->blk_givwhen.defsv_save = orig_defsv; +} + + +PERL_STATIC_INLINE void +Perl_cx_popgiven(pTHX_ PERL_CONTEXT *cx) +{ + SV *sv; + + PERL_ARGS_ASSERT_CX_POPGIVEN; + assert(CxTYPE(cx) == CXt_GIVEN); + + sv = GvSV(PL_defgv); + GvSV(PL_defgv) = cx->blk_givwhen.defsv_save; + cx->blk_givwhen.defsv_save = NULL; + SvREFCNT_dec(sv); +} + + /* Make @_ empty in-place in simple cases: a cheap av_clear(). * See Perl_clear_defarray() for non-simple cases */ diff --git a/keywords.c b/keywords.c index cae22c9ac7f9..50870579b8e3 100644 --- a/keywords.c +++ b/keywords.c @@ -516,7 +516,7 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) goto unknown; } - case 4: /* 39 tokens of length 4 */ + case 4: /* 40 tokens of length 4 */ switch (name[0]) { case 'I': @@ -936,38 +936,49 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) } case 'w': - if (name[1] == 'a') + switch (name[1]) { - switch (name[2]) - { - case 'i': - if (name[3] == 't') - { /* wait */ - return -KEY_wait; - } + case 'a': + switch (name[2]) + { + case 'i': + if (name[3] == 't') + { /* wait */ + return -KEY_wait; + } - goto unknown; + goto unknown; - case 'r': - if (name[3] == 'n') - { /* warn */ - return -KEY_warn; - } + case 'r': + if (name[3] == 'n') + { /* warn */ + return -KEY_warn; + } - goto unknown; + goto unknown; - default: - goto unknown; - } - } + default: + goto unknown; + } - goto unknown; + case 'h': + if (name[2] == 'e' && + name[3] == 'n') + { /* when */ + return (all_keywords || FEATURE_SWITCH_IS_ENABLED ? KEY_when : 0); + } + + goto unknown; + + default: + goto unknown; + } default: goto unknown; } - case 5: /* 41 tokens of length 5 */ + case 5: /* 43 tokens of length 5 */ switch (name[0]) { case 'B': @@ -1020,15 +1031,31 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) } case 'b': - if (name[1] == 'l' && - name[2] == 'e' && - name[3] == 's' && - name[4] == 's') - { /* bless */ - return -KEY_bless; - } + switch (name[1]) + { + case 'l': + if (name[2] == 'e' && + name[3] == 's' && + name[4] == 's') + { /* bless */ + return -KEY_bless; + } - goto unknown; + goto unknown; + + case 'r': + if (name[2] == 'e' && + name[3] == 'a' && + name[4] == 'k') + { /* break */ + return (all_keywords || FEATURE_SWITCH_IS_ENABLED ? -KEY_break : 0); + } + + goto unknown; + + default: + goto unknown; + } case 'c': switch (name[1]) @@ -1189,6 +1216,17 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) goto unknown; } + case 'g': + if (name[1] == 'i' && + name[2] == 'v' && + name[3] == 'e' && + name[4] == 'n') + { /* given */ + return (all_keywords || FEATURE_SWITCH_IS_ENABLED ? KEY_given : 0); + } + + goto unknown; + case 'i': switch (name[1]) { @@ -1968,7 +2006,7 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) goto unknown; } - case 7: /* 30 tokens of length 7 */ + case 7: /* 31 tokens of length 7 */ switch (name[0]) { case 'D': @@ -2060,13 +2098,33 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) goto unknown; case 'e': - if (name[2] == 'f' && - name[3] == 'i' && - name[4] == 'n' && - name[5] == 'e' && - name[6] == 'd') - { /* defined */ - return KEY_defined; + if (name[2] == 'f') + { + switch (name[3]) + { + case 'a': + if (name[4] == 'u' && + name[5] == 'l' && + name[6] == 't') + { /* default */ + return (all_keywords || FEATURE_SWITCH_IS_ENABLED ? KEY_default : 0); + } + + goto unknown; + + case 'i': + if (name[4] == 'n' && + name[5] == 'e' && + name[6] == 'd') + { /* defined */ + return KEY_defined; + } + + goto unknown; + + default: + goto unknown; + } } goto unknown; @@ -3515,5 +3573,5 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) } /* Generated from: - * 7960cd8dbcd65990506e4c222c8d32119ef37cacb444a2031cf2ea7cc723ccdc regen/keywords.pl + * c8b75109fa56ce3ea3f30503a3b398f02e49036dc60d5fb36ea5ba9ffd6c596e regen/keywords.pl * ex: set ro ft=c: */ diff --git a/keywords.h b/keywords.h index c4ef7730a373..72c6d874c90b 100644 --- a/keywords.h +++ b/keywords.h @@ -37,244 +37,248 @@ #define KEY_bind 21 #define KEY_binmode 22 #define KEY_bless 23 -#define KEY_caller 24 -#define KEY_catch 25 -#define KEY_chdir 26 -#define KEY_chmod 27 -#define KEY_chomp 28 -#define KEY_chop 29 -#define KEY_chown 30 -#define KEY_chr 31 -#define KEY_chroot 32 -#define KEY_class 33 -#define KEY_close 34 -#define KEY_closedir 35 -#define KEY_cmp 36 -#define KEY_connect 37 -#define KEY_continue 38 -#define KEY_cos 39 -#define KEY_crypt 40 -#define KEY_dbmclose 41 -#define KEY_dbmopen 42 -#define KEY_defer 43 -#define KEY_defined 44 -#define KEY_delete 45 -#define KEY_die 46 -#define KEY_do 47 -#define KEY_dump 48 -#define KEY_each 49 -#define KEY_else 50 -#define KEY_elsif 51 -#define KEY_endgrent 52 -#define KEY_endhostent 53 -#define KEY_endnetent 54 -#define KEY_endprotoent 55 -#define KEY_endpwent 56 -#define KEY_endservent 57 -#define KEY_eof 58 -#define KEY_eq 59 -#define KEY_eval 60 -#define KEY_evalbytes 61 -#define KEY_exec 62 -#define KEY_exists 63 -#define KEY_exit 64 -#define KEY_exp 65 -#define KEY_fc 66 -#define KEY_fcntl 67 -#define KEY_field 68 -#define KEY_fileno 69 -#define KEY_finally 70 -#define KEY_flock 71 -#define KEY_for 72 -#define KEY_foreach 73 -#define KEY_fork 74 -#define KEY_format 75 -#define KEY_formline 76 -#define KEY_ge 77 -#define KEY_getc 78 -#define KEY_getgrent 79 -#define KEY_getgrgid 80 -#define KEY_getgrnam 81 -#define KEY_gethostbyaddr 82 -#define KEY_gethostbyname 83 -#define KEY_gethostent 84 -#define KEY_getlogin 85 -#define KEY_getnetbyaddr 86 -#define KEY_getnetbyname 87 -#define KEY_getnetent 88 -#define KEY_getpeername 89 -#define KEY_getpgrp 90 -#define KEY_getppid 91 -#define KEY_getpriority 92 -#define KEY_getprotobyname 93 -#define KEY_getprotobynumber 94 -#define KEY_getprotoent 95 -#define KEY_getpwent 96 -#define KEY_getpwnam 97 -#define KEY_getpwuid 98 -#define KEY_getservbyname 99 -#define KEY_getservbyport 100 -#define KEY_getservent 101 -#define KEY_getsockname 102 -#define KEY_getsockopt 103 -#define KEY_glob 104 -#define KEY_gmtime 105 -#define KEY_goto 106 -#define KEY_grep 107 -#define KEY_gt 108 -#define KEY_hex 109 -#define KEY_if 110 -#define KEY_index 111 -#define KEY_int 112 -#define KEY_ioctl 113 -#define KEY_isa 114 -#define KEY_join 115 -#define KEY_keys 116 -#define KEY_kill 117 -#define KEY_last 118 -#define KEY_lc 119 -#define KEY_lcfirst 120 -#define KEY_le 121 -#define KEY_length 122 -#define KEY_link 123 -#define KEY_listen 124 -#define KEY_local 125 -#define KEY_localtime 126 -#define KEY_lock 127 -#define KEY_log 128 -#define KEY_lstat 129 -#define KEY_lt 130 -#define KEY_m 131 -#define KEY_map 132 -#define KEY_method 133 -#define KEY_mkdir 134 -#define KEY_msgctl 135 -#define KEY_msgget 136 -#define KEY_msgrcv 137 -#define KEY_msgsnd 138 -#define KEY_my 139 -#define KEY_ne 140 -#define KEY_next 141 -#define KEY_no 142 -#define KEY_not 143 -#define KEY_oct 144 -#define KEY_open 145 -#define KEY_opendir 146 -#define KEY_or 147 -#define KEY_ord 148 -#define KEY_our 149 -#define KEY_pack 150 -#define KEY_package 151 -#define KEY_pipe 152 -#define KEY_pop 153 -#define KEY_pos 154 -#define KEY_print 155 -#define KEY_printf 156 -#define KEY_prototype 157 -#define KEY_push 158 -#define KEY_q 159 -#define KEY_qq 160 -#define KEY_qr 161 -#define KEY_quotemeta 162 -#define KEY_qw 163 -#define KEY_qx 164 -#define KEY_rand 165 -#define KEY_read 166 -#define KEY_readdir 167 -#define KEY_readline 168 -#define KEY_readlink 169 -#define KEY_readpipe 170 -#define KEY_recv 171 -#define KEY_redo 172 -#define KEY_ref 173 -#define KEY_rename 174 -#define KEY_require 175 -#define KEY_reset 176 -#define KEY_return 177 -#define KEY_reverse 178 -#define KEY_rewinddir 179 -#define KEY_rindex 180 -#define KEY_rmdir 181 -#define KEY_s 182 -#define KEY_say 183 -#define KEY_scalar 184 -#define KEY_seek 185 -#define KEY_seekdir 186 -#define KEY_select 187 -#define KEY_semctl 188 -#define KEY_semget 189 -#define KEY_semop 190 -#define KEY_send 191 -#define KEY_setgrent 192 -#define KEY_sethostent 193 -#define KEY_setnetent 194 -#define KEY_setpgrp 195 -#define KEY_setpriority 196 -#define KEY_setprotoent 197 -#define KEY_setpwent 198 -#define KEY_setservent 199 -#define KEY_setsockopt 200 -#define KEY_shift 201 -#define KEY_shmctl 202 -#define KEY_shmget 203 -#define KEY_shmread 204 -#define KEY_shmwrite 205 -#define KEY_shutdown 206 -#define KEY_sin 207 -#define KEY_sleep 208 -#define KEY_socket 209 -#define KEY_socketpair 210 -#define KEY_sort 211 -#define KEY_splice 212 -#define KEY_split 213 -#define KEY_sprintf 214 -#define KEY_sqrt 215 -#define KEY_srand 216 -#define KEY_stat 217 -#define KEY_state 218 -#define KEY_study 219 -#define KEY_sub 220 -#define KEY_substr 221 -#define KEY_symlink 222 -#define KEY_syscall 223 -#define KEY_sysopen 224 -#define KEY_sysread 225 -#define KEY_sysseek 226 -#define KEY_system 227 -#define KEY_syswrite 228 -#define KEY_tell 229 -#define KEY_telldir 230 -#define KEY_tie 231 -#define KEY_tied 232 -#define KEY_time 233 -#define KEY_times 234 -#define KEY_tr 235 -#define KEY_try 236 -#define KEY_truncate 237 -#define KEY_uc 238 -#define KEY_ucfirst 239 -#define KEY_umask 240 -#define KEY_undef 241 -#define KEY_unless 242 -#define KEY_unlink 243 -#define KEY_unpack 244 -#define KEY_unshift 245 -#define KEY_untie 246 -#define KEY_until 247 -#define KEY_use 248 -#define KEY_utime 249 -#define KEY_values 250 -#define KEY_vec 251 -#define KEY_wait 252 -#define KEY_waitpid 253 -#define KEY_wantarray 254 -#define KEY_warn 255 -#define KEY_while 256 -#define KEY_write 257 -#define KEY_x 258 -#define KEY_xor 259 -#define KEY_y 260 +#define KEY_break 24 +#define KEY_caller 25 +#define KEY_catch 26 +#define KEY_chdir 27 +#define KEY_chmod 28 +#define KEY_chomp 29 +#define KEY_chop 30 +#define KEY_chown 31 +#define KEY_chr 32 +#define KEY_chroot 33 +#define KEY_class 34 +#define KEY_close 35 +#define KEY_closedir 36 +#define KEY_cmp 37 +#define KEY_connect 38 +#define KEY_continue 39 +#define KEY_cos 40 +#define KEY_crypt 41 +#define KEY_dbmclose 42 +#define KEY_dbmopen 43 +#define KEY_default 44 +#define KEY_defer 45 +#define KEY_defined 46 +#define KEY_delete 47 +#define KEY_die 48 +#define KEY_do 49 +#define KEY_dump 50 +#define KEY_each 51 +#define KEY_else 52 +#define KEY_elsif 53 +#define KEY_endgrent 54 +#define KEY_endhostent 55 +#define KEY_endnetent 56 +#define KEY_endprotoent 57 +#define KEY_endpwent 58 +#define KEY_endservent 59 +#define KEY_eof 60 +#define KEY_eq 61 +#define KEY_eval 62 +#define KEY_evalbytes 63 +#define KEY_exec 64 +#define KEY_exists 65 +#define KEY_exit 66 +#define KEY_exp 67 +#define KEY_fc 68 +#define KEY_fcntl 69 +#define KEY_field 70 +#define KEY_fileno 71 +#define KEY_finally 72 +#define KEY_flock 73 +#define KEY_for 74 +#define KEY_foreach 75 +#define KEY_fork 76 +#define KEY_format 77 +#define KEY_formline 78 +#define KEY_ge 79 +#define KEY_getc 80 +#define KEY_getgrent 81 +#define KEY_getgrgid 82 +#define KEY_getgrnam 83 +#define KEY_gethostbyaddr 84 +#define KEY_gethostbyname 85 +#define KEY_gethostent 86 +#define KEY_getlogin 87 +#define KEY_getnetbyaddr 88 +#define KEY_getnetbyname 89 +#define KEY_getnetent 90 +#define KEY_getpeername 91 +#define KEY_getpgrp 92 +#define KEY_getppid 93 +#define KEY_getpriority 94 +#define KEY_getprotobyname 95 +#define KEY_getprotobynumber 96 +#define KEY_getprotoent 97 +#define KEY_getpwent 98 +#define KEY_getpwnam 99 +#define KEY_getpwuid 100 +#define KEY_getservbyname 101 +#define KEY_getservbyport 102 +#define KEY_getservent 103 +#define KEY_getsockname 104 +#define KEY_getsockopt 105 +#define KEY_given 106 +#define KEY_glob 107 +#define KEY_gmtime 108 +#define KEY_goto 109 +#define KEY_grep 110 +#define KEY_gt 111 +#define KEY_hex 112 +#define KEY_if 113 +#define KEY_index 114 +#define KEY_int 115 +#define KEY_ioctl 116 +#define KEY_isa 117 +#define KEY_join 118 +#define KEY_keys 119 +#define KEY_kill 120 +#define KEY_last 121 +#define KEY_lc 122 +#define KEY_lcfirst 123 +#define KEY_le 124 +#define KEY_length 125 +#define KEY_link 126 +#define KEY_listen 127 +#define KEY_local 128 +#define KEY_localtime 129 +#define KEY_lock 130 +#define KEY_log 131 +#define KEY_lstat 132 +#define KEY_lt 133 +#define KEY_m 134 +#define KEY_map 135 +#define KEY_method 136 +#define KEY_mkdir 137 +#define KEY_msgctl 138 +#define KEY_msgget 139 +#define KEY_msgrcv 140 +#define KEY_msgsnd 141 +#define KEY_my 142 +#define KEY_ne 143 +#define KEY_next 144 +#define KEY_no 145 +#define KEY_not 146 +#define KEY_oct 147 +#define KEY_open 148 +#define KEY_opendir 149 +#define KEY_or 150 +#define KEY_ord 151 +#define KEY_our 152 +#define KEY_pack 153 +#define KEY_package 154 +#define KEY_pipe 155 +#define KEY_pop 156 +#define KEY_pos 157 +#define KEY_print 158 +#define KEY_printf 159 +#define KEY_prototype 160 +#define KEY_push 161 +#define KEY_q 162 +#define KEY_qq 163 +#define KEY_qr 164 +#define KEY_quotemeta 165 +#define KEY_qw 166 +#define KEY_qx 167 +#define KEY_rand 168 +#define KEY_read 169 +#define KEY_readdir 170 +#define KEY_readline 171 +#define KEY_readlink 172 +#define KEY_readpipe 173 +#define KEY_recv 174 +#define KEY_redo 175 +#define KEY_ref 176 +#define KEY_rename 177 +#define KEY_require 178 +#define KEY_reset 179 +#define KEY_return 180 +#define KEY_reverse 181 +#define KEY_rewinddir 182 +#define KEY_rindex 183 +#define KEY_rmdir 184 +#define KEY_s 185 +#define KEY_say 186 +#define KEY_scalar 187 +#define KEY_seek 188 +#define KEY_seekdir 189 +#define KEY_select 190 +#define KEY_semctl 191 +#define KEY_semget 192 +#define KEY_semop 193 +#define KEY_send 194 +#define KEY_setgrent 195 +#define KEY_sethostent 196 +#define KEY_setnetent 197 +#define KEY_setpgrp 198 +#define KEY_setpriority 199 +#define KEY_setprotoent 200 +#define KEY_setpwent 201 +#define KEY_setservent 202 +#define KEY_setsockopt 203 +#define KEY_shift 204 +#define KEY_shmctl 205 +#define KEY_shmget 206 +#define KEY_shmread 207 +#define KEY_shmwrite 208 +#define KEY_shutdown 209 +#define KEY_sin 210 +#define KEY_sleep 211 +#define KEY_socket 212 +#define KEY_socketpair 213 +#define KEY_sort 214 +#define KEY_splice 215 +#define KEY_split 216 +#define KEY_sprintf 217 +#define KEY_sqrt 218 +#define KEY_srand 219 +#define KEY_stat 220 +#define KEY_state 221 +#define KEY_study 222 +#define KEY_sub 223 +#define KEY_substr 224 +#define KEY_symlink 225 +#define KEY_syscall 226 +#define KEY_sysopen 227 +#define KEY_sysread 228 +#define KEY_sysseek 229 +#define KEY_system 230 +#define KEY_syswrite 231 +#define KEY_tell 232 +#define KEY_telldir 233 +#define KEY_tie 234 +#define KEY_tied 235 +#define KEY_time 236 +#define KEY_times 237 +#define KEY_tr 238 +#define KEY_try 239 +#define KEY_truncate 240 +#define KEY_uc 241 +#define KEY_ucfirst 242 +#define KEY_umask 243 +#define KEY_undef 244 +#define KEY_unless 245 +#define KEY_unlink 246 +#define KEY_unpack 247 +#define KEY_unshift 248 +#define KEY_untie 249 +#define KEY_until 250 +#define KEY_use 251 +#define KEY_utime 252 +#define KEY_values 253 +#define KEY_vec 254 +#define KEY_wait 255 +#define KEY_waitpid 256 +#define KEY_wantarray 257 +#define KEY_warn 258 +#define KEY_when 259 +#define KEY_while 260 +#define KEY_write 261 +#define KEY_x 262 +#define KEY_xor 263 +#define KEY_y 264 /* Generated from: - * 7960cd8dbcd65990506e4c222c8d32119ef37cacb444a2031cf2ea7cc723ccdc regen/keywords.pl + * c8b75109fa56ce3ea3f30503a3b398f02e49036dc60d5fb36ea5ba9ffd6c596e regen/keywords.pl * ex: set ro ft=c: */ diff --git a/lib/B/Deparse-core.t b/lib/B/Deparse-core.t index 539ad5361b77..a898cf60bc13 100644 --- a/lib/B/Deparse-core.t +++ b/lib/B/Deparse-core.t @@ -86,6 +86,7 @@ sub testit { use feature 'lexical_subs'; $code = "no warnings 'syntax'; no strict 'vars'; sub { state sub $keyword; ${vars}() = $expr }"; $code = "use feature 'isa';\n$code" if $keyword eq "isa"; + $code = "use feature 'switch';\n$code" if $keyword eq "break"; $code_ref = eval $code or die "$@ in $expr"; } else { @@ -94,6 +95,7 @@ sub testit { import subs $keyword; $code = "no warnings 'syntax'; no strict 'vars'; sub { ${vars}() = $expr }"; $code = "use feature 'isa';\n$code" if $keyword eq "isa"; + $code = "use feature 'switch';\n$code" if $keyword eq "break"; $code_ref = eval $code or die "$@ in $expr"; } @@ -362,7 +364,7 @@ my %not_tested = map { $_ => 1} qw( UNITCHECK catch class - continue + default defer else elsif @@ -371,6 +373,7 @@ my %not_tested = map { $_ => 1} qw( for foreach format + given if m method @@ -388,6 +391,7 @@ my %not_tested = map { $_ => 1} qw( unless until use + when while y ); @@ -468,6 +472,7 @@ atan2 2 p bind 2 p binmode 12 p bless 1 p +break 0 - caller 0 - chdir 01 - chmod @ p1 @@ -480,6 +485,7 @@ close 01 - closedir 1 - cmp B - connect 2 p +continue 0 - cos 01 $ crypt 2 p # dbmopen handled specially @@ -537,6 +543,7 @@ getservbyport 2 p getservent 0 - getsockname 1 - getsockopt 3 p +# given handled specially grep 123 p+ # also tested specially # glob handled specially # goto handled specially diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 6b309ca74eda..d19097a65ab6 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -7,7 +7,7 @@ # This is based on the module of the same name by Malcolm Beattie, # but essentially none of his code remains. -package B::Deparse 1.80; +package B::Deparse 1.81; use strict; use Carp; use B qw(class main_root main_start main_cv svref_2object opnumber perlstring @@ -2326,6 +2326,10 @@ my %feature_keywords = ( # keyword => 'feature', state => 'state', say => 'say', + given => 'switch', + when => 'switch', + default => 'switch', + break => 'switch', evalbytes=>'evalbytes', __SUB__ => '__SUB__', fc => 'fc', @@ -2635,6 +2639,34 @@ sub pp_ggrgid { unop(@_, "getgrgid") } sub pp_lock { unop(@_, "lock") } +sub pp_continue { unop(@_, "continue"); } +sub pp_break { unop(@_, "break"); } + +sub givwhen { + my $self = shift; + my($op, $cx, $givwhen) = @_; + + my $enterop = $op->first; + my ($head, $block); + if ($enterop->flags & OPf_SPECIAL) { + $head = $self->keyword("default"); + $block = $self->deparse($enterop->first, 0); + } + else { + my $cond = $enterop->first; + my $cond_str = $self->deparse($cond, 1); + $head = "$givwhen ($cond_str)"; + $block = $self->deparse($cond->sibling, 0); + } + + return "$head {\n". + "\t$block\n". + "\b}\cK"; +} + +sub pp_leavegiven { givwhen(@_, $_[0]->keyword("given")); } +sub pp_leavewhen { givwhen(@_, $_[0]->keyword("when")); } + sub pp_exists { my $self = shift; my($op, $cx) = @_; diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t index 41b3691df065..c7a69135236d 100644 --- a/lib/B/Deparse.t +++ b/lib/B/Deparse.t @@ -1068,6 +1068,15 @@ my $b = \{}; my $c = []; my $d = \[]; #### +# SKIP ?$] < 5.010 && "smartmatch and given/when not implemented on this Perl version" +# CONTEXT use feature ':5.10'; no warnings 'deprecated'; +# implicit smartmatch in given/when +given ('foo') { + when ('bar') { continue; } + when ($_ ~~ 'quux') { continue; } + default { 0; } +} +#### # conditions in elsifs (regression in change #33710 which fixed bug #37302) if ($a) { x(); } elsif ($b) { x(); } @@ -1626,6 +1635,14 @@ $a[0] = 1; # CONTEXT no warnings 'deprecated'; CORE::state $x; CORE::say $x; +CORE::given ($x) { + CORE::when (3) { + continue; + } + CORE::default { + CORE::break; + } +} CORE::evalbytes ''; () = CORE::__SUB__; () = CORE::fc $x; @@ -1636,11 +1653,27 @@ use feature (sprintf(":%vd", $^V)); use 1; CORE::say $_; CORE::state $x; +CORE::given ($x) { + CORE::when (3) { + continue; + } + CORE::default { + CORE::break; + } +} CORE::evalbytes ''; () = CORE::__SUB__; >>>> CORE::say $_; CORE::state $x; +CORE::given ($x) { + CORE::when (3) { + continue; + } + CORE::default { + CORE::break; + } +} CORE::evalbytes ''; () = CORE::__SUB__; #### @@ -1651,6 +1684,14 @@ use feature (sprintf(":%vd", $^V)); use 1; CORE::say $_; CORE::state $x; +CORE::given ($x) { + CORE::when (3) { + continue; + } + CORE::default { + CORE::break; + } +} CORE::evalbytes ''; () = CORE::__SUB__; >>>> @@ -1658,16 +1699,26 @@ no feature ':all'; use feature ':default'; CORE::say $_; CORE::state $x; +CORE::given ($x) { + CORE::when (3) { + continue; + } + CORE::default { + CORE::break; + } +} CORE::evalbytes ''; () = CORE::__SUB__; #### # SKIP ?$] < 5.017004 && "lexical subs not implemented on this Perl version" # lexical subroutines and keywords of the same name -# CONTEXT use feature 'lexical_subs'; no warnings 'experimental'; no warnings 'deprecated'; +# CONTEXT use feature 'lexical_subs', 'switch'; no warnings 'experimental'; no warnings 'deprecated'; +my sub default; my sub else; my sub elsif; my sub for; my sub foreach; +my sub given; my sub if; my sub m; my sub no; @@ -1683,7 +1734,9 @@ my sub tr; my sub unless; my sub until; my sub use; +my sub when; my sub while; +CORE::default { die; } CORE::if ($1) { die; } CORE::if ($1) { die; } CORE::elsif ($1) { die; } @@ -1691,6 +1744,7 @@ CORE::else { die; } CORE::for (die; $1; die) { die; } CORE::foreach $_ (1 .. 10) { die; } die CORE::foreach (1); +CORE::given ($1) { die; } CORE::m[/]; CORE::m?/?; CORE::package foo; @@ -1704,6 +1758,7 @@ CORE::unless ($1) { die; } CORE::until ($1) { die; } die CORE::until $1; CORE::use strict; +CORE::when ($1 ~~ $2) { die; } CORE::while ($1) { die; } die CORE::while $1; #### diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm index 329106fc0a8f..1240b74d4ccf 100644 --- a/lib/B/Op_private.pm +++ b/lib/B/Op_private.pm @@ -335,10 +335,12 @@ $bits{dump}{0} = $bf[0]; $bits{each}{0} = $bf[0]; @{$bits{emptyavhv}}{5,3,2,1,0} = ('OPpEMPTYAVHV_IS_HV', $bf[5], $bf[5], $bf[5], $bf[5]); @{$bits{entereval}}{6,5,4,3,2,1,0} = ('OPpEVAL_EVALSV', 'OPpEVAL_RE_REPARSING', 'OPpEVAL_COPHH', 'OPpEVAL_BYTES', 'OPpEVAL_UNICODE', 'OPpEVAL_HAS_HH', $bf[0]); +$bits{entergiven}{0} = $bf[0]; $bits{enteriter}{3} = 'OPpITER_DEF'; @{$bits{entersub}}{5,4,0} = ($bf[9], $bf[9], 'OPpENTERSUB_INARGS'); $bits{entertry}{0} = $bf[0]; $bits{entertrycatch}{0} = $bf[0]; +$bits{enterwhen}{0} = $bf[0]; @{$bits{enterwrite}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); @{$bits{eof}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); @{$bits{eq}}{1,0} = ($bf[1], $bf[1]); @@ -445,9 +447,11 @@ $bits{lc}{0} = $bf[0]; $bits{lcfirst}{0} = $bf[0]; @{$bits{le}}{1,0} = ($bf[1], $bf[1]); $bits{leaveeval}{0} = $bf[0]; +$bits{leavegiven}{0} = $bf[0]; @{$bits{leaveloop}}{1,0} = ($bf[1], $bf[1]); $bits{leavesub}{0} = $bf[0]; $bits{leavesublv}{0} = $bf[0]; +$bits{leavewhen}{0} = $bf[0]; $bits{leavewrite}{0} = $bf[0]; $bits{length}{0} = $bf[0]; @{$bits{link}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); diff --git a/op.c b/op.c index a55bf94a88ac..25a17f99c2c0 100644 --- a/op.c +++ b/op.c @@ -2058,6 +2058,8 @@ Perl_scalar(pTHX_ OP *o) next_kid = kid; goto do_next; } + else if (kid->op_type == OP_LEAVEWHEN) + scalar(kid); else scalarvoid(kid); kid = sib; @@ -2146,7 +2148,7 @@ Perl_scalarvoid(pTHX_ OP *arg) want = o->op_flags & OPf_WANT; if ((want && want != OPf_WANT_SCALAR) || (PL_parser && PL_parser->error_count) - || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE) + || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE || o->op_type == OP_LEAVEWHEN) { goto get_next_op; } @@ -2414,6 +2416,8 @@ Perl_scalarvoid(pTHX_ OP *arg) case OP_DOR: case OP_COND_EXPR: + case OP_ENTERGIVEN: + case OP_ENTERWHEN: next_kid = OpSIBLING(cUNOPo->op_first); break; @@ -2433,6 +2437,8 @@ Perl_scalarvoid(pTHX_ OP *arg) case OP_LEAVETRY: case OP_LEAVELOOP: case OP_LINESEQ: + case OP_LEAVEGIVEN: + case OP_LEAVEWHEN: case OP_ONCE: kids: next_kid = cLISTOPo->op_first; @@ -2619,6 +2625,8 @@ Perl_list(pTHX_ OP *o) next_kid = kid; goto do_next; } + else if (kid->op_type == OP_LEAVEWHEN) + list(kid); else scalarvoid(kid); kid = sib; @@ -10005,6 +10013,207 @@ S_ref_array_or_hash(pTHX_ OP *cond) return cond; } +/* These construct the optree fragments representing given() + and when() blocks. + + entergiven and enterwhen are LOGOPs; the op_other pointer + points up to the associated leave op. We need this so we + can put it in the context and make break/continue work. + (Also, of course, pp_enterwhen will jump straight to + op_other if the match fails.) + */ + +STATIC OP * +S_newGIVWHENOP(pTHX_ OP *cond, OP *block, + I32 enter_opcode, I32 leave_opcode, + PADOFFSET entertarg) +{ + LOGOP *enterop; + OP *o; + + PERL_ARGS_ASSERT_NEWGIVWHENOP; + PERL_UNUSED_ARG(entertarg); /* used to indicate targ of lexical $_ */ + + enterop = alloc_LOGOP(enter_opcode, block, NULL); + enterop->op_targ = 0; + enterop->op_private = 0; + + o = newUNOP(leave_opcode, 0, (OP *) enterop); + + if (cond) { + /* prepend cond if we have one */ + op_sibling_splice((OP*)enterop, NULL, 0, scalar(cond)); + + o->op_next = LINKLIST(cond); + cond->op_next = (OP *) enterop; + } + else { + /* This is a default {} block */ + enterop->op_flags |= OPf_SPECIAL; + o ->op_flags |= OPf_SPECIAL; + + o->op_next = (OP *) enterop; + } + + CHECKOP(enter_opcode, enterop); /* Currently does nothing, since + entergiven and enterwhen both + use ck_null() */ + + enterop->op_next = LINKLIST(block); + block->op_next = enterop->op_other = o; + + return o; +} + + +/* For the purposes of 'when(implied_smartmatch)' + * versus 'when(boolean_expression)', + * does this look like a boolean operation? For these purposes + a boolean operation is: + - a subroutine call [*] + - a logical connective + - a comparison operator + - a filetest operator, with the exception of -s -M -A -C + - defined(), exists() or eof() + - /$re/ or $foo =~ /$re/ + + [*] possibly surprising + */ +STATIC bool +S_looks_like_bool(pTHX_ const OP *o) +{ + PERL_ARGS_ASSERT_LOOKS_LIKE_BOOL; + + switch(o->op_type) { + case OP_OR: + case OP_DOR: + return looks_like_bool(cLOGOPo->op_first); + + case OP_AND: + { + OP* sibl = OpSIBLING(cLOGOPo->op_first); + ASSUME(sibl); + return ( + looks_like_bool(cLOGOPo->op_first) + && looks_like_bool(sibl)); + } + + case OP_NULL: + case OP_SCALAR: + return ( + o->op_flags & OPf_KIDS + && looks_like_bool(cUNOPo->op_first)); + + case OP_ENTERSUB: + + case OP_NOT: case OP_XOR: + + case OP_EQ: case OP_NE: case OP_LT: + case OP_GT: case OP_LE: case OP_GE: + + case OP_I_EQ: case OP_I_NE: case OP_I_LT: + case OP_I_GT: case OP_I_LE: case OP_I_GE: + + case OP_SEQ: case OP_SNE: case OP_SLT: + case OP_SGT: case OP_SLE: case OP_SGE: + + case OP_SMARTMATCH: + + case OP_FTRREAD: case OP_FTRWRITE: case OP_FTREXEC: + case OP_FTEREAD: case OP_FTEWRITE: case OP_FTEEXEC: + case OP_FTIS: case OP_FTEOWNED: case OP_FTROWNED: + case OP_FTZERO: case OP_FTSOCK: case OP_FTCHR: + case OP_FTBLK: case OP_FTFILE: case OP_FTDIR: + case OP_FTPIPE: case OP_FTLINK: case OP_FTSUID: + case OP_FTSGID: case OP_FTSVTX: case OP_FTTTY: + case OP_FTTEXT: case OP_FTBINARY: + + case OP_DEFINED: case OP_EXISTS: + case OP_MATCH: case OP_EOF: + + case OP_FLOP: + + return TRUE; + + case OP_INDEX: + case OP_RINDEX: + /* optimised-away (index() != -1) or similar comparison */ + if (o->op_private & OPpTRUEBOOL) + return TRUE; + return FALSE; + + case OP_CONST: + /* Detect comparisons that have been optimized away */ + if (cSVOPo->op_sv == &PL_sv_yes + || cSVOPo->op_sv == &PL_sv_no) + + return TRUE; + else + return FALSE; + /* FALLTHROUGH */ + default: + return FALSE; + } +} + + +/* +=for apidoc newGIVENOP + +Constructs, checks, and returns an op tree expressing a C block. +C supplies the expression to whose value C<$_> will be locally +aliased, and C supplies the body of the C construct; they +are consumed by this function and become part of the constructed op tree. +C must be zero (it used to identity the pad slot of lexical $_). + +=cut +*/ + +OP * +Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off) +{ + PERL_ARGS_ASSERT_NEWGIVENOP; + PERL_UNUSED_ARG(defsv_off); + + assert(!defsv_off); + return newGIVWHENOP( + ref_array_or_hash(cond), + block, + OP_ENTERGIVEN, OP_LEAVEGIVEN, + 0); +} + +/* +=for apidoc newWHENOP + +Constructs, checks, and returns an op tree expressing a C block. +C supplies the test expression, and C supplies the block +that will be executed if the test evaluates to true; they are consumed +by this function and become part of the constructed op tree. C +will be interpreted DWIMically, often as a comparison against C<$_>, +and may be null to generate a C block. + +=cut +*/ + +OP * +Perl_newWHENOP(pTHX_ OP *cond, OP *block) +{ + const bool cond_llb = (!cond || looks_like_bool(cond)); + OP *cond_op; + + PERL_ARGS_ASSERT_NEWWHENOP; + + if (cond_llb) + cond_op = cond; + else { + cond_op = newBINOP(OP_SMARTMATCH, OPf_SPECIAL, + newDEFSVOP(), + scalar(ref_array_or_hash(cond))); + } + + return newGIVWHENOP(cond_op, block, OP_ENTERWHEN, OP_LEAVEWHEN, 0); +} /* =for apidoc newDEFEROP @@ -15715,8 +15924,8 @@ Perl_core_prototype(pTHX_ SV *sv, const char *name, const int code, #define retsetpvs(x,y) sv_setpvs(sv, x); if(opnum) *opnum=(y); return sv switch (code < 0 ? -code : code) { - case KEY_and : case KEY_chop: case KEY_chomp : case KEY_cmp : - case KEY_continue: case KEY_defined: case KEY_delete: case KEY_exec : + case KEY_and : case KEY_chop: case KEY_chomp: + case KEY_cmp : case KEY_defined: case KEY_delete: case KEY_exec : case KEY_exists: case KEY_eq : case KEY_ge : case KEY_goto : case KEY_grep : case KEY_gt : case KEY_last : case KEY_le : case KEY_lt : case KEY_map : case KEY_ne : case KEY_next : diff --git a/opcode.h b/opcode.h index 7cb1a93f7a88..fdb13eee95cc 100644 --- a/opcode.h +++ b/opcode.h @@ -366,6 +366,12 @@ EXTCONST char* const PL_op_name[] INIT({ "method_super", "method_redir", "method_redir_super", + "entergiven", + "leavegiven", + "enterwhen", + "leavewhen", + "break", + "continue", "open", "close", "pipe_op", @@ -786,6 +792,12 @@ EXTCONST char* const PL_op_desc[] INIT({ "super with known name", "redirect method with known name", "redirect super method with known name", + "given()", + "leave given block", + "when()", + "leave when block", + "break", + "continue", "open", "close", "pipe", @@ -1211,6 +1223,12 @@ INIT({ Perl_pp_method_super, Perl_pp_method_redir, Perl_pp_method_redir_super, + Perl_pp_entergiven, + Perl_pp_leavegiven, + Perl_pp_enterwhen, + Perl_pp_leavewhen, + Perl_pp_break, + Perl_pp_continue, Perl_pp_open, Perl_pp_close, Perl_pp_pipe_op, @@ -1631,6 +1649,12 @@ INIT({ Perl_ck_null, /* method_super */ Perl_ck_null, /* method_redir */ Perl_ck_null, /* method_redir_super */ + Perl_ck_null, /* entergiven */ + Perl_ck_null, /* leavegiven */ + Perl_ck_null, /* enterwhen */ + Perl_ck_null, /* leavewhen */ + Perl_ck_null, /* break */ + Perl_ck_null, /* continue */ Perl_ck_open, /* open */ Perl_ck_fun, /* close */ Perl_ck_fun, /* pipe_op */ @@ -2050,6 +2074,12 @@ EXTCONST U32 PL_opargs[] INIT({ 0x00000e40, /* method_super */ 0x00000e40, /* method_redir */ 0x00000e40, /* method_redir_super */ + 0x00000340, /* entergiven */ + 0x00000100, /* leavegiven */ + 0x00000340, /* enterwhen */ + 0x00000100, /* leavewhen */ + 0x00000000, /* break */ + 0x00000000, /* continue */ 0x0029640d, /* open */ 0x0000eb04, /* close */ 0x00066404, /* pipe_op */ @@ -2771,6 +2801,12 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 213, /* method_super */ 213, /* method_redir */ 213, /* method_redir_super */ + 0, /* entergiven */ + 0, /* leavegiven */ + 0, /* enterwhen */ + 0, /* leavewhen */ + -1, /* break */ + -1, /* continue */ 215, /* open */ 56, /* close */ 56, /* pipe_op */ @@ -2985,7 +3021,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { */ EXTCONST U16 PL_op_private_bitdefs[] = { - 0x0003, /* scalar, prototype, refgen, srefgen, readline, regcmaybe, regcreset, regcomp, substcont, chop, schop, defined, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, not, ucfirst, lcfirst, uc, lc, quotemeta, aeach, avalues, each, pop, shift, grepstart, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, argcheck, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, fc, anonconst, cmpchain_and, cmpchain_dup, entertrycatch, catch, is_bool, is_weak, weaken, unweaken, is_tainted */ + 0x0003, /* scalar, prototype, refgen, srefgen, readline, regcmaybe, regcreset, regcomp, substcont, chop, schop, defined, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, not, ucfirst, lcfirst, uc, lc, quotemeta, aeach, avalues, each, pop, shift, grepstart, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, argcheck, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, fc, anonconst, cmpchain_and, cmpchain_dup, entertrycatch, catch, is_bool, is_weak, weaken, unweaken, is_tainted */ 0x3cfc, 0x5379, /* pushmark */ 0x00bd, /* wantarray, runcv */ 0x077e, 0x0554, 0x1b70, 0x542c, 0x4fc8, 0x4225, /* const */ @@ -3295,6 +3331,12 @@ EXTCONST U8 PL_op_private_valid[] = { /* METHOD_SUPER */ (OPpARG1_MASK|OPpMETH_NO_BAREWORD_IO), /* METHOD_REDIR */ (OPpARG1_MASK|OPpMETH_NO_BAREWORD_IO), /* METHOD_REDIR_SUPER */ (OPpARG1_MASK|OPpMETH_NO_BAREWORD_IO), + /* ENTERGIVEN */ (OPpARG1_MASK), + /* LEAVEGIVEN */ (OPpARG1_MASK), + /* ENTERWHEN */ (OPpARG1_MASK), + /* LEAVEWHEN */ (OPpARG1_MASK), + /* BREAK */ (0), + /* CONTINUE */ (0), /* OPEN */ (OPpARG4_MASK|OPpOPEN_IN_RAW|OPpOPEN_IN_CRLF|OPpOPEN_OUT_RAW|OPpOPEN_OUT_CRLF), /* CLOSE */ (OPpARG4_MASK), /* PIPE_OP */ (OPpARG4_MASK), diff --git a/opnames.h b/opnames.h index 7e1f2dfa2358..0ac7b0b6c4a3 100644 --- a/opnames.h +++ b/opnames.h @@ -234,202 +234,208 @@ typedef enum opcode { OP_METHOD_SUPER = 217, OP_METHOD_REDIR = 218, OP_METHOD_REDIR_SUPER = 219, - OP_OPEN = 220, - OP_CLOSE = 221, - OP_PIPE_OP = 222, - OP_FILENO = 223, - OP_UMASK = 224, - OP_BINMODE = 225, - OP_TIE = 226, - OP_UNTIE = 227, - OP_TIED = 228, - OP_DBMOPEN = 229, - OP_DBMCLOSE = 230, - OP_SSELECT = 231, - OP_SELECT = 232, - OP_GETC = 233, - OP_READ = 234, - OP_ENTERWRITE = 235, - OP_LEAVEWRITE = 236, - OP_PRTF = 237, - OP_PRINT = 238, - OP_SAY = 239, - OP_SYSOPEN = 240, - OP_SYSSEEK = 241, - OP_SYSREAD = 242, - OP_SYSWRITE = 243, - OP_EOF = 244, - OP_TELL = 245, - OP_SEEK = 246, - OP_TRUNCATE = 247, - OP_FCNTL = 248, - OP_IOCTL = 249, - OP_FLOCK = 250, - OP_SEND = 251, - OP_RECV = 252, - OP_SOCKET = 253, - OP_SOCKPAIR = 254, - OP_BIND = 255, - OP_CONNECT = 256, - OP_LISTEN = 257, - OP_ACCEPT = 258, - OP_SHUTDOWN = 259, - OP_GSOCKOPT = 260, - OP_SSOCKOPT = 261, - OP_GETSOCKNAME = 262, - OP_GETPEERNAME = 263, - OP_LSTAT = 264, - OP_STAT = 265, - OP_FTRREAD = 266, - OP_FTRWRITE = 267, - OP_FTREXEC = 268, - OP_FTEREAD = 269, - OP_FTEWRITE = 270, - OP_FTEEXEC = 271, - OP_FTIS = 272, - OP_FTSIZE = 273, - OP_FTMTIME = 274, - OP_FTATIME = 275, - OP_FTCTIME = 276, - OP_FTROWNED = 277, - OP_FTEOWNED = 278, - OP_FTZERO = 279, - OP_FTSOCK = 280, - OP_FTCHR = 281, - OP_FTBLK = 282, - OP_FTFILE = 283, - OP_FTDIR = 284, - OP_FTPIPE = 285, - OP_FTSUID = 286, - OP_FTSGID = 287, - OP_FTSVTX = 288, - OP_FTLINK = 289, - OP_FTTTY = 290, - OP_FTTEXT = 291, - OP_FTBINARY = 292, - OP_CHDIR = 293, - OP_CHOWN = 294, - OP_CHROOT = 295, - OP_UNLINK = 296, - OP_CHMOD = 297, - OP_UTIME = 298, - OP_RENAME = 299, - OP_LINK = 300, - OP_SYMLINK = 301, - OP_READLINK = 302, - OP_MKDIR = 303, - OP_RMDIR = 304, - OP_OPEN_DIR = 305, - OP_READDIR = 306, - OP_TELLDIR = 307, - OP_SEEKDIR = 308, - OP_REWINDDIR = 309, - OP_CLOSEDIR = 310, - OP_FORK = 311, - OP_WAIT = 312, - OP_WAITPID = 313, - OP_SYSTEM = 314, - OP_EXEC = 315, - OP_KILL = 316, - OP_GETPPID = 317, - OP_GETPGRP = 318, - OP_SETPGRP = 319, - OP_GETPRIORITY = 320, - OP_SETPRIORITY = 321, - OP_TIME = 322, - OP_TMS = 323, - OP_LOCALTIME = 324, - OP_GMTIME = 325, - OP_ALARM = 326, - OP_SLEEP = 327, - OP_SHMGET = 328, - OP_SHMCTL = 329, - OP_SHMREAD = 330, - OP_SHMWRITE = 331, - OP_MSGGET = 332, - OP_MSGCTL = 333, - OP_MSGSND = 334, - OP_MSGRCV = 335, - OP_SEMOP = 336, - OP_SEMGET = 337, - OP_SEMCTL = 338, - OP_REQUIRE = 339, - OP_DOFILE = 340, - OP_HINTSEVAL = 341, - OP_ENTEREVAL = 342, - OP_LEAVEEVAL = 343, - OP_ENTERTRY = 344, - OP_LEAVETRY = 345, - OP_GHBYNAME = 346, - OP_GHBYADDR = 347, - OP_GHOSTENT = 348, - OP_GNBYNAME = 349, - OP_GNBYADDR = 350, - OP_GNETENT = 351, - OP_GPBYNAME = 352, - OP_GPBYNUMBER = 353, - OP_GPROTOENT = 354, - OP_GSBYNAME = 355, - OP_GSBYPORT = 356, - OP_GSERVENT = 357, - OP_SHOSTENT = 358, - OP_SNETENT = 359, - OP_SPROTOENT = 360, - OP_SSERVENT = 361, - OP_EHOSTENT = 362, - OP_ENETENT = 363, - OP_EPROTOENT = 364, - OP_ESERVENT = 365, - OP_GPWNAM = 366, - OP_GPWUID = 367, - OP_GPWENT = 368, - OP_SPWENT = 369, - OP_EPWENT = 370, - OP_GGRNAM = 371, - OP_GGRGID = 372, - OP_GGRENT = 373, - OP_SGRENT = 374, - OP_EGRENT = 375, - OP_GETLOGIN = 376, - OP_SYSCALL = 377, - OP_LOCK = 378, - OP_ONCE = 379, - OP_CUSTOM = 380, - OP_COREARGS = 381, - OP_AVHVSWITCH = 382, - OP_RUNCV = 383, - OP_FC = 384, - OP_PADCV = 385, - OP_INTROCV = 386, - OP_CLONECV = 387, - OP_PADRANGE = 388, - OP_REFASSIGN = 389, - OP_LVREF = 390, - OP_LVREFSLICE = 391, - OP_LVAVREF = 392, - OP_ANONCONST = 393, - OP_ISA = 394, - OP_CMPCHAIN_AND = 395, - OP_CMPCHAIN_DUP = 396, - OP_ENTERTRYCATCH = 397, - OP_LEAVETRYCATCH = 398, - OP_POPTRY = 399, - OP_CATCH = 400, - OP_PUSHDEFER = 401, - OP_IS_BOOL = 402, - OP_IS_WEAK = 403, - OP_WEAKEN = 404, - OP_UNWEAKEN = 405, - OP_BLESSED = 406, - OP_REFADDR = 407, - OP_REFTYPE = 408, - OP_CEIL = 409, - OP_FLOOR = 410, - OP_IS_TAINTED = 411, - OP_HELEMEXISTSOR = 412, - OP_METHSTART = 413, - OP_INITFIELD = 414, - OP_CLASSNAME = 415, + OP_ENTERGIVEN = 220, + OP_LEAVEGIVEN = 221, + OP_ENTERWHEN = 222, + OP_LEAVEWHEN = 223, + OP_BREAK = 224, + OP_CONTINUE = 225, + OP_OPEN = 226, + OP_CLOSE = 227, + OP_PIPE_OP = 228, + OP_FILENO = 229, + OP_UMASK = 230, + OP_BINMODE = 231, + OP_TIE = 232, + OP_UNTIE = 233, + OP_TIED = 234, + OP_DBMOPEN = 235, + OP_DBMCLOSE = 236, + OP_SSELECT = 237, + OP_SELECT = 238, + OP_GETC = 239, + OP_READ = 240, + OP_ENTERWRITE = 241, + OP_LEAVEWRITE = 242, + OP_PRTF = 243, + OP_PRINT = 244, + OP_SAY = 245, + OP_SYSOPEN = 246, + OP_SYSSEEK = 247, + OP_SYSREAD = 248, + OP_SYSWRITE = 249, + OP_EOF = 250, + OP_TELL = 251, + OP_SEEK = 252, + OP_TRUNCATE = 253, + OP_FCNTL = 254, + OP_IOCTL = 255, + OP_FLOCK = 256, + OP_SEND = 257, + OP_RECV = 258, + OP_SOCKET = 259, + OP_SOCKPAIR = 260, + OP_BIND = 261, + OP_CONNECT = 262, + OP_LISTEN = 263, + OP_ACCEPT = 264, + OP_SHUTDOWN = 265, + OP_GSOCKOPT = 266, + OP_SSOCKOPT = 267, + OP_GETSOCKNAME = 268, + OP_GETPEERNAME = 269, + OP_LSTAT = 270, + OP_STAT = 271, + OP_FTRREAD = 272, + OP_FTRWRITE = 273, + OP_FTREXEC = 274, + OP_FTEREAD = 275, + OP_FTEWRITE = 276, + OP_FTEEXEC = 277, + OP_FTIS = 278, + OP_FTSIZE = 279, + OP_FTMTIME = 280, + OP_FTATIME = 281, + OP_FTCTIME = 282, + OP_FTROWNED = 283, + OP_FTEOWNED = 284, + OP_FTZERO = 285, + OP_FTSOCK = 286, + OP_FTCHR = 287, + OP_FTBLK = 288, + OP_FTFILE = 289, + OP_FTDIR = 290, + OP_FTPIPE = 291, + OP_FTSUID = 292, + OP_FTSGID = 293, + OP_FTSVTX = 294, + OP_FTLINK = 295, + OP_FTTTY = 296, + OP_FTTEXT = 297, + OP_FTBINARY = 298, + OP_CHDIR = 299, + OP_CHOWN = 300, + OP_CHROOT = 301, + OP_UNLINK = 302, + OP_CHMOD = 303, + OP_UTIME = 304, + OP_RENAME = 305, + OP_LINK = 306, + OP_SYMLINK = 307, + OP_READLINK = 308, + OP_MKDIR = 309, + OP_RMDIR = 310, + OP_OPEN_DIR = 311, + OP_READDIR = 312, + OP_TELLDIR = 313, + OP_SEEKDIR = 314, + OP_REWINDDIR = 315, + OP_CLOSEDIR = 316, + OP_FORK = 317, + OP_WAIT = 318, + OP_WAITPID = 319, + OP_SYSTEM = 320, + OP_EXEC = 321, + OP_KILL = 322, + OP_GETPPID = 323, + OP_GETPGRP = 324, + OP_SETPGRP = 325, + OP_GETPRIORITY = 326, + OP_SETPRIORITY = 327, + OP_TIME = 328, + OP_TMS = 329, + OP_LOCALTIME = 330, + OP_GMTIME = 331, + OP_ALARM = 332, + OP_SLEEP = 333, + OP_SHMGET = 334, + OP_SHMCTL = 335, + OP_SHMREAD = 336, + OP_SHMWRITE = 337, + OP_MSGGET = 338, + OP_MSGCTL = 339, + OP_MSGSND = 340, + OP_MSGRCV = 341, + OP_SEMOP = 342, + OP_SEMGET = 343, + OP_SEMCTL = 344, + OP_REQUIRE = 345, + OP_DOFILE = 346, + OP_HINTSEVAL = 347, + OP_ENTEREVAL = 348, + OP_LEAVEEVAL = 349, + OP_ENTERTRY = 350, + OP_LEAVETRY = 351, + OP_GHBYNAME = 352, + OP_GHBYADDR = 353, + OP_GHOSTENT = 354, + OP_GNBYNAME = 355, + OP_GNBYADDR = 356, + OP_GNETENT = 357, + OP_GPBYNAME = 358, + OP_GPBYNUMBER = 359, + OP_GPROTOENT = 360, + OP_GSBYNAME = 361, + OP_GSBYPORT = 362, + OP_GSERVENT = 363, + OP_SHOSTENT = 364, + OP_SNETENT = 365, + OP_SPROTOENT = 366, + OP_SSERVENT = 367, + OP_EHOSTENT = 368, + OP_ENETENT = 369, + OP_EPROTOENT = 370, + OP_ESERVENT = 371, + OP_GPWNAM = 372, + OP_GPWUID = 373, + OP_GPWENT = 374, + OP_SPWENT = 375, + OP_EPWENT = 376, + OP_GGRNAM = 377, + OP_GGRGID = 378, + OP_GGRENT = 379, + OP_SGRENT = 380, + OP_EGRENT = 381, + OP_GETLOGIN = 382, + OP_SYSCALL = 383, + OP_LOCK = 384, + OP_ONCE = 385, + OP_CUSTOM = 386, + OP_COREARGS = 387, + OP_AVHVSWITCH = 388, + OP_RUNCV = 389, + OP_FC = 390, + OP_PADCV = 391, + OP_INTROCV = 392, + OP_CLONECV = 393, + OP_PADRANGE = 394, + OP_REFASSIGN = 395, + OP_LVREF = 396, + OP_LVREFSLICE = 397, + OP_LVAVREF = 398, + OP_ANONCONST = 399, + OP_ISA = 400, + OP_CMPCHAIN_AND = 401, + OP_CMPCHAIN_DUP = 402, + OP_ENTERTRYCATCH = 403, + OP_LEAVETRYCATCH = 404, + OP_POPTRY = 405, + OP_CATCH = 406, + OP_PUSHDEFER = 407, + OP_IS_BOOL = 408, + OP_IS_WEAK = 409, + OP_WEAKEN = 410, + OP_UNWEAKEN = 411, + OP_BLESSED = 412, + OP_REFADDR = 413, + OP_REFTYPE = 414, + OP_CEIL = 415, + OP_FLOOR = 416, + OP_IS_TAINTED = 417, + OP_HELEMEXISTSOR = 418, + OP_METHSTART = 419, + OP_INITFIELD = 420, + OP_CLASSNAME = 421, OP_max } opcode; @@ -440,7 +446,7 @@ An enum of all the legal Perl opcodes, defined in F =cut */ -#define MAXO 416 +#define MAXO 422 #define OP_FREED MAXO /* the OP_IS_* macros are optimized to a simple range check because diff --git a/perl.h b/perl.h index 06217e903549..116fc7959e0a 100644 --- a/perl.h +++ b/perl.h @@ -5674,7 +5674,9 @@ EXTCONST unsigned char PL_latin1_lc[]; #ifdef DOINIT EXTCONST char* const PL_block_type[] = { "NULL", + "WHEN", "BLOCK", + "GIVEN", "LOOP_ARY", "LOOP_LAZYSV", "LOOP_LAZYIV", diff --git a/perly.act b/perly.act index 386cf3aefe16..fb7480f6cad5 100644 --- a/perly.act +++ b/perly.act @@ -5,7 +5,7 @@ */ case 2: /* @1: %empty */ -#line 160 "perly.y" +#line 161 "perly.y" { parser->expect = XSTATE; (yyval.ival) = 0; @@ -14,7 +14,7 @@ case 2: /* @1: %empty */ break; case 3: /* grammar: GRAMPROG @1 remember stmtseq */ -#line 165 "perly.y" +#line 166 "perly.y" { newPROG(block_end((ps[-1].val.ival),(ps[0].val.opval))); PL_compiling.cop_seq = 0; @@ -24,7 +24,7 @@ case 2: /* @1: %empty */ break; case 4: /* @2: %empty */ -#line 171 "perly.y" +#line 172 "perly.y" { parser->expect = XTERM; (yyval.ival) = 0; @@ -33,7 +33,7 @@ case 2: /* @1: %empty */ break; case 5: /* grammar: GRAMEXPR @2 optexpr */ -#line 176 "perly.y" +#line 177 "perly.y" { PL_eval_root = (ps[0].val.opval); (yyval.ival) = 0; @@ -42,7 +42,7 @@ case 2: /* @1: %empty */ break; case 6: /* @3: %empty */ -#line 181 "perly.y" +#line 182 "perly.y" { parser->expect = XBLOCK; (yyval.ival) = 0; @@ -51,7 +51,7 @@ case 2: /* @1: %empty */ break; case 7: /* grammar: GRAMBLOCK @3 block */ -#line 186 "perly.y" +#line 187 "perly.y" { PL_pad_reset_pending = TRUE; PL_eval_root = (ps[0].val.opval); @@ -63,7 +63,7 @@ case 2: /* @1: %empty */ break; case 8: /* @4: %empty */ -#line 194 "perly.y" +#line 195 "perly.y" { parser->expect = XSTATE; (yyval.ival) = 0; @@ -72,7 +72,7 @@ case 2: /* @1: %empty */ break; case 9: /* grammar: GRAMBARESTMT @4 barestmt */ -#line 199 "perly.y" +#line 200 "perly.y" { PL_pad_reset_pending = TRUE; PL_eval_root = (ps[0].val.opval); @@ -84,7 +84,7 @@ case 2: /* @1: %empty */ break; case 10: /* @5: %empty */ -#line 207 "perly.y" +#line 208 "perly.y" { parser->expect = XSTATE; (yyval.ival) = 0; @@ -93,7 +93,7 @@ case 2: /* @1: %empty */ break; case 11: /* grammar: GRAMFULLSTMT @5 fullstmt */ -#line 212 "perly.y" +#line 213 "perly.y" { PL_pad_reset_pending = TRUE; PL_eval_root = (ps[0].val.opval); @@ -105,7 +105,7 @@ case 2: /* @1: %empty */ break; case 12: /* @6: %empty */ -#line 220 "perly.y" +#line 221 "perly.y" { parser->expect = XSTATE; (yyval.ival) = 0; @@ -114,7 +114,7 @@ case 2: /* @1: %empty */ break; case 13: /* grammar: GRAMSTMTSEQ @6 stmtseq */ -#line 225 "perly.y" +#line 226 "perly.y" { PL_eval_root = (ps[0].val.opval); (yyval.ival) = 0; @@ -123,7 +123,7 @@ case 2: /* @1: %empty */ break; case 14: /* @7: %empty */ -#line 230 "perly.y" +#line 231 "perly.y" { parser->expect = XSTATE; (yyval.ival) = 0; @@ -132,7 +132,7 @@ case 2: /* @1: %empty */ break; case 15: /* grammar: GRAMSUBSIGNATURE @7 subsigguts */ -#line 235 "perly.y" +#line 236 "perly.y" { PL_eval_root = (ps[0].val.opval); (yyval.ival) = 0; @@ -141,19 +141,19 @@ case 2: /* @1: %empty */ break; case 16: /* sigsub_or_method_named: KW_SUB_named_sig */ -#line 244 "perly.y" +#line 245 "perly.y" { (yyval.ival) = KW_SUB_named_sig; } break; case 17: /* sigsub_or_method_named: KW_METHOD_named */ -#line 246 "perly.y" +#line 247 "perly.y" { (yyval.ival) = KW_METHOD_named; } break; case 18: /* block: PERLY_BRACE_OPEN remember stmtseq PERLY_BRACE_CLOSE */ -#line 251 "perly.y" +#line 252 "perly.y" { if (parser->copline > (line_t)(ps[-3].val.ival)) parser->copline = (line_t)(ps[-3].val.ival); (yyval.opval) = block_end((ps[-2].val.ival), (ps[-1].val.opval)); @@ -162,13 +162,13 @@ case 2: /* @1: %empty */ break; case 19: /* empty: %empty */ -#line 258 "perly.y" +#line 259 "perly.y" { (yyval.opval) = NULL; } break; case 20: /* formblock: PERLY_EQUAL_SIGN remember PERLY_SEMICOLON FORMRBRACK formstmtseq PERLY_SEMICOLON PERLY_DOT */ -#line 263 "perly.y" +#line 264 "perly.y" { if (parser->copline > (line_t)(ps[-6].val.ival)) parser->copline = (line_t)(ps[-6].val.ival); (yyval.opval) = block_end((ps[-5].val.ival), (ps[-2].val.opval)); @@ -177,14 +177,14 @@ case 2: /* @1: %empty */ break; case 21: /* remember: %empty */ -#line 270 "perly.y" +#line 271 "perly.y" { (yyval.ival) = block_start(TRUE); parser->parsed_sub = 0; } break; case 22: /* mblock: PERLY_BRACE_OPEN mremember stmtseq PERLY_BRACE_CLOSE */ -#line 275 "perly.y" +#line 276 "perly.y" { if (parser->copline > (line_t)(ps[-3].val.ival)) parser->copline = (line_t)(ps[-3].val.ival); (yyval.opval) = block_end((ps[-2].val.ival), (ps[-1].val.opval)); @@ -193,32 +193,32 @@ case 2: /* @1: %empty */ break; case 23: /* mremember: %empty */ -#line 282 "perly.y" +#line 283 "perly.y" { (yyval.ival) = block_start(FALSE); parser->parsed_sub = 0; } break; case 25: /* $@8: %empty */ -#line 291 "perly.y" +#line 292 "perly.y" { parser->in_my = 1; } break; case 26: /* $@9: %empty */ -#line 293 "perly.y" +#line 294 "perly.y" { parser->in_my = 0; intro_my(); } break; case 27: /* catch_paren: PERLY_PAREN_OPEN $@8 scalar $@9 PERLY_PAREN_CLOSE */ -#line 295 "perly.y" +#line 296 "perly.y" { (yyval.opval) = (ps[-2].val.opval); } break; case 29: /* stmtseq: stmtseq fullstmt */ -#line 302 "perly.y" +#line 303 "perly.y" { (yyval.opval) = op_append_list(OP_LINESEQ, (ps[-1].val.opval), (ps[0].val.opval)); PL_pad_reset_pending = TRUE; if ((ps[-1].val.opval) && (ps[0].val.opval)) @@ -228,7 +228,7 @@ case 2: /* @1: %empty */ break; case 31: /* formstmtseq: formstmtseq formline */ -#line 313 "perly.y" +#line 314 "perly.y" { (yyval.opval) = op_append_list(OP_LINESEQ, (ps[-1].val.opval), (ps[0].val.opval)); PL_pad_reset_pending = TRUE; if ((ps[-1].val.opval) && (ps[0].val.opval)) @@ -238,7 +238,7 @@ case 2: /* @1: %empty */ break; case 32: /* fullstmt: barestmt */ -#line 322 "perly.y" +#line 323 "perly.y" { (yyval.opval) = (ps[0].val.opval) ? newSTATEOP(0, NULL, (ps[0].val.opval)) : NULL; } @@ -246,13 +246,13 @@ case 2: /* @1: %empty */ break; case 33: /* fullstmt: labfullstmt */ -#line 326 "perly.y" +#line 327 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 34: /* labfullstmt: LABEL barestmt */ -#line 330 "perly.y" +#line 331 "perly.y" { SV *label = cSVOPx_sv((ps[-1].val.opval)); (yyval.opval) = newSTATEOP(SvFLAGS(label) & SVf_UTF8, @@ -263,7 +263,7 @@ case 2: /* @1: %empty */ break; case 35: /* labfullstmt: LABEL labfullstmt */ -#line 337 "perly.y" +#line 338 "perly.y" { SV *label = cSVOPx_sv((ps[-1].val.opval)); (yyval.opval) = newSTATEOP(SvFLAGS(label) & SVf_UTF8, @@ -274,13 +274,13 @@ case 2: /* @1: %empty */ break; case 36: /* barestmt: PLUGSTMT */ -#line 347 "perly.y" +#line 348 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 37: /* barestmt: KW_FORMAT startformsub formname formblock */ -#line 349 "perly.y" +#line 350 "perly.y" { CV *fmtcv = PL_compcv; newFORM((ps[-2].val.ival), (ps[-1].val.opval), (ps[0].val.opval)); @@ -294,7 +294,7 @@ case 2: /* @1: %empty */ break; case 38: /* $@10: %empty */ -#line 361 "perly.y" +#line 362 "perly.y" { init_named_cv(PL_compcv, (ps[-1].val.opval)); parser->in_my = 0; @@ -304,7 +304,7 @@ case 2: /* @1: %empty */ break; case 39: /* barestmt: KW_SUB_named subname startsub $@10 proto subattrlist optsubbody */ -#line 367 "perly.y" +#line 368 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (ps[-5].val.opval)->op_type == OP_CONST @@ -319,7 +319,7 @@ case 2: /* @1: %empty */ break; case 40: /* $@11: %empty */ -#line 382 "perly.y" +#line 383 "perly.y" { init_named_cv(PL_compcv, (ps[-1].val.opval)); if((ps[-2].val.ival) == KW_METHOD_named) { @@ -333,7 +333,7 @@ case 2: /* @1: %empty */ break; case 41: /* barestmt: sigsub_or_method_named subname startsub $@11 subattrlist optsigsubbody */ -#line 392 "perly.y" +#line 393 "perly.y" { OP *body = (ps[0].val.opval); @@ -350,7 +350,7 @@ case 2: /* @1: %empty */ break; case 42: /* $@12: %empty */ -#line 405 "perly.y" +#line 406 "perly.y" { switch((ps[-1].val.ival)) { case KEY_ADJUST: @@ -365,7 +365,7 @@ case 2: /* @1: %empty */ break; case 43: /* barestmt: PHASER startsub $@12 optsubbody */ -#line 416 "perly.y" +#line 417 "perly.y" { OP *body = (ps[0].val.opval); SvREFCNT_inc_simple_void(PL_compcv); @@ -384,7 +384,7 @@ case 2: /* @1: %empty */ break; case 44: /* barestmt: KW_PACKAGE BAREWORD BAREWORD PERLY_SEMICOLON */ -#line 435 "perly.y" +#line 436 "perly.y" { package((ps[-1].val.opval)); if ((ps[-2].val.opval)) @@ -395,7 +395,7 @@ case 2: /* @1: %empty */ break; case 45: /* barestmt: KW_CLASS BAREWORD BAREWORD subattrlist PERLY_SEMICOLON */ -#line 442 "perly.y" +#line 443 "perly.y" { package((ps[-2].val.opval)); if ((ps[-3].val.opval)) @@ -410,13 +410,13 @@ case 2: /* @1: %empty */ break; case 46: /* $@13: %empty */ -#line 453 "perly.y" +#line 454 "perly.y" { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ } break; case 47: /* barestmt: KW_USE_or_NO startsub $@13 BAREWORD BAREWORD optlistexpr PERLY_SEMICOLON */ -#line 457 "perly.y" +#line 458 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); utilize((ps[-6].val.ival), (ps[-5].val.ival), (ps[-3].val.opval), (ps[-2].val.opval), (ps[-1].val.opval)); @@ -427,7 +427,7 @@ case 2: /* @1: %empty */ break; case 48: /* barestmt: KW_IF PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock else */ -#line 464 "perly.y" +#line 465 "perly.y" { (yyval.opval) = block_end((ps[-4].val.ival), newCONDOP(0, (ps[-3].val.opval), op_scope((ps[-1].val.opval)), (ps[0].val.opval))); @@ -437,7 +437,7 @@ case 2: /* @1: %empty */ break; case 49: /* barestmt: KW_UNLESS PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock else */ -#line 470 "perly.y" +#line 471 "perly.y" { (yyval.opval) = block_end((ps[-4].val.ival), newCONDOP(0, (ps[-3].val.opval), (ps[0].val.opval), op_scope((ps[-1].val.opval)))); @@ -446,8 +446,29 @@ case 2: /* @1: %empty */ break; - case 50: /* barestmt: KW_WHILE PERLY_PAREN_OPEN remember texpr PERLY_PAREN_CLOSE mintro mblock cont */ -#line 476 "perly.y" + case 50: /* barestmt: KW_GIVEN PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock */ +#line 477 "perly.y" + { + (yyval.opval) = block_end((ps[-3].val.ival), newGIVENOP((ps[-2].val.opval), op_scope((ps[0].val.opval)), 0)); + parser->copline = (line_t)(ps[-5].val.ival); + } + + break; + + case 51: /* barestmt: KW_WHEN PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock */ +#line 482 "perly.y" + { (yyval.opval) = block_end((ps[-3].val.ival), newWHENOP((ps[-2].val.opval), op_scope((ps[0].val.opval)))); } + + break; + + case 52: /* barestmt: KW_DEFAULT block */ +#line 484 "perly.y" + { (yyval.opval) = newWHENOP(0, op_scope((ps[0].val.opval))); } + + break; + + case 53: /* barestmt: KW_WHILE PERLY_PAREN_OPEN remember texpr PERLY_PAREN_CLOSE mintro mblock cont */ +#line 486 "perly.y" { (yyval.opval) = block_end((ps[-5].val.ival), newWHILEOP(0, 1, NULL, @@ -457,8 +478,8 @@ case 2: /* @1: %empty */ break; - case 51: /* barestmt: KW_UNTIL PERLY_PAREN_OPEN remember iexpr PERLY_PAREN_CLOSE mintro mblock cont */ -#line 483 "perly.y" + case 54: /* barestmt: KW_UNTIL PERLY_PAREN_OPEN remember iexpr PERLY_PAREN_CLOSE mintro mblock cont */ +#line 493 "perly.y" { (yyval.opval) = block_end((ps[-5].val.ival), newWHILEOP(0, 1, NULL, @@ -468,20 +489,20 @@ case 2: /* @1: %empty */ break; - case 52: /* $@14: %empty */ -#line 490 "perly.y" + case 55: /* $@14: %empty */ +#line 500 "perly.y" { parser->expect = XTERM; } break; - case 53: /* $@15: %empty */ -#line 492 "perly.y" + case 56: /* $@15: %empty */ +#line 502 "perly.y" { parser->expect = XTERM; } break; - case 54: /* barestmt: KW_FOR PERLY_PAREN_OPEN remember mnexpr PERLY_SEMICOLON $@14 texpr PERLY_SEMICOLON $@15 mintro mnexpr PERLY_PAREN_CLOSE mblock */ -#line 495 "perly.y" + case 57: /* barestmt: KW_FOR PERLY_PAREN_OPEN remember mnexpr PERLY_SEMICOLON $@14 texpr PERLY_SEMICOLON $@15 mintro mnexpr PERLY_PAREN_CLOSE mblock */ +#line 505 "perly.y" { OP *initop = (ps[-9].val.opval); OP *forop = newWHILEOP(0, 1, NULL, @@ -499,8 +520,8 @@ case 2: /* @1: %empty */ break; - case 55: /* barestmt: KW_FOR KW_MY remember my_scalar PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 510 "perly.y" + case 58: /* barestmt: KW_FOR KW_MY remember my_scalar PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 520 "perly.y" { (yyval.opval) = block_end((ps[-6].val.ival), newFOROP(0, (ps[-5].val.opval), (ps[-3].val.opval), (ps[-1].val.opval), (ps[0].val.opval))); parser->copline = (line_t)(ps[-8].val.ival); @@ -508,8 +529,8 @@ case 2: /* @1: %empty */ break; - case 56: /* barestmt: KW_FOR KW_MY remember PERLY_PAREN_OPEN my_list_of_scalars PERLY_PAREN_CLOSE PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 515 "perly.y" + case 59: /* barestmt: KW_FOR KW_MY remember PERLY_PAREN_OPEN my_list_of_scalars PERLY_PAREN_CLOSE PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 525 "perly.y" { if ((ps[-6].val.opval)->op_type == OP_PADSV) /* degenerate case of 1 var: for my ($x) .... @@ -521,8 +542,8 @@ case 2: /* @1: %empty */ break; - case 57: /* barestmt: KW_FOR scalar PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 524 "perly.y" + case 60: /* barestmt: KW_FOR scalar PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 534 "perly.y" { (yyval.opval) = block_end((ps[-4].val.ival), newFOROP(0, op_lvalue((ps[-6].val.opval), OP_ENTERLOOP), (ps[-3].val.opval), (ps[-1].val.opval), (ps[0].val.opval))); @@ -531,14 +552,14 @@ case 2: /* @1: %empty */ break; - case 58: /* @16: %empty */ -#line 530 "perly.y" + case 61: /* @16: %empty */ +#line 540 "perly.y" { parser->in_my = 0; (yyval.opval) = my((ps[0].val.opval)); } break; - case 59: /* barestmt: KW_FOR my_refgen remember my_var @16 PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 532 "perly.y" + case 62: /* barestmt: KW_FOR my_refgen remember my_var @16 PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 542 "perly.y" { (yyval.opval) = block_end( (ps[-7].val.ival), @@ -554,8 +575,8 @@ case 2: /* @1: %empty */ break; - case 60: /* barestmt: KW_FOR REFGEN refgen_topic PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 545 "perly.y" + case 63: /* barestmt: KW_FOR REFGEN refgen_topic PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 555 "perly.y" { (yyval.opval) = block_end((ps[-4].val.ival), newFOROP( 0, op_lvalue(newUNOP(OP_REFGEN, 0, @@ -566,8 +587,8 @@ case 2: /* @1: %empty */ break; - case 61: /* barestmt: KW_FOR PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ -#line 553 "perly.y" + case 64: /* barestmt: KW_FOR PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock cont */ +#line 563 "perly.y" { (yyval.opval) = block_end((ps[-4].val.ival), newFOROP(0, NULL, (ps[-3].val.opval), (ps[-1].val.opval), (ps[0].val.opval))); @@ -576,8 +597,8 @@ case 2: /* @1: %empty */ break; - case 62: /* $@17: %empty */ -#line 559 "perly.y" + case 65: /* $@17: %empty */ +#line 569 "perly.y" { if(!(ps[0].val.opval)) { yyerror("catch block requires a (VAR)"); @@ -587,8 +608,8 @@ case 2: /* @1: %empty */ break; - case 63: /* barestmt: KW_TRY mblock KW_CATCH remember catch_paren $@17 mblock finally */ -#line 566 "perly.y" + case 66: /* barestmt: KW_TRY mblock KW_CATCH remember catch_paren $@17 mblock finally */ +#line 576 "perly.y" { (yyval.opval) = newTRYCATCHOP(0, (ps[-6].val.opval), (ps[-3].val.opval), block_end((ps[-4].val.ival), op_scope((ps[-1].val.opval)))); @@ -599,8 +620,8 @@ case 2: /* @1: %empty */ break; - case 64: /* barestmt: block cont */ -#line 574 "perly.y" + case 67: /* barestmt: block cont */ +#line 584 "perly.y" { /* a block is a loop that happens once */ (yyval.opval) = newWHILEOP(0, 1, NULL, @@ -609,8 +630,8 @@ case 2: /* @1: %empty */ break; - case 65: /* $@18: %empty */ -#line 580 "perly.y" + case 68: /* $@18: %empty */ +#line 590 "perly.y" { package((ps[-2].val.opval)); if ((ps[-3].val.opval)) { @@ -620,8 +641,8 @@ case 2: /* @1: %empty */ break; - case 66: /* barestmt: KW_PACKAGE BAREWORD BAREWORD PERLY_BRACE_OPEN remember $@18 stmtseq PERLY_BRACE_CLOSE */ -#line 587 "perly.y" + case 69: /* barestmt: KW_PACKAGE BAREWORD BAREWORD PERLY_BRACE_OPEN remember $@18 stmtseq PERLY_BRACE_CLOSE */ +#line 597 "perly.y" { /* a block is a loop that happens once */ (yyval.opval) = newWHILEOP(0, 1, NULL, @@ -632,8 +653,8 @@ case 2: /* @1: %empty */ break; - case 67: /* $@19: %empty */ -#line 595 "perly.y" + case 70: /* $@19: %empty */ +#line 605 "perly.y" { package((ps[-3].val.opval)); @@ -648,8 +669,8 @@ case 2: /* @1: %empty */ break; - case 68: /* barestmt: KW_CLASS BAREWORD BAREWORD subattrlist PERLY_BRACE_OPEN remember $@19 stmtseq PERLY_BRACE_CLOSE */ -#line 607 "perly.y" + case 71: /* barestmt: KW_CLASS BAREWORD BAREWORD subattrlist PERLY_BRACE_OPEN remember $@19 stmtseq PERLY_BRACE_CLOSE */ +#line 617 "perly.y" { /* a block is a loop that happens once */ (yyval.opval) = newWHILEOP(0, 1, NULL, @@ -660,32 +681,32 @@ case 2: /* @1: %empty */ break; - case 69: /* barestmt: fielddecl PERLY_SEMICOLON */ -#line 615 "perly.y" + case 72: /* barestmt: fielddecl PERLY_SEMICOLON */ +#line 625 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 70: /* barestmt: sideff PERLY_SEMICOLON */ -#line 619 "perly.y" + case 73: /* barestmt: sideff PERLY_SEMICOLON */ +#line 629 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 71: /* barestmt: KW_DEFER mblock */ -#line 623 "perly.y" + case 74: /* barestmt: KW_DEFER mblock */ +#line 633 "perly.y" { (yyval.opval) = newDEFEROP(0, op_scope((ps[0].val.opval))); } break; - case 72: /* barestmt: YADAYADA PERLY_SEMICOLON */ -#line 627 "perly.y" + case 75: /* barestmt: YADAYADA PERLY_SEMICOLON */ +#line 637 "perly.y" { /* diag_listed_as: Unimplemented */ (yyval.opval) = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0), @@ -694,8 +715,8 @@ case 2: /* @1: %empty */ break; - case 73: /* barestmt: PERLY_SEMICOLON */ -#line 633 "perly.y" + case 76: /* barestmt: PERLY_SEMICOLON */ +#line 643 "perly.y" { (yyval.opval) = NULL; parser->copline = NOLINE; @@ -703,8 +724,8 @@ case 2: /* @1: %empty */ break; - case 74: /* formline: THING formarg */ -#line 641 "perly.y" + case 77: /* formline: THING formarg */ +#line 651 "perly.y" { OP *list; if ((ps[0].val.opval)) { OP *term = (ps[0].val.opval); @@ -722,57 +743,63 @@ case 2: /* @1: %empty */ break; - case 76: /* formarg: FORMLBRACK stmtseq FORMRBRACK */ -#line 660 "perly.y" + case 79: /* formarg: FORMLBRACK stmtseq FORMRBRACK */ +#line 670 "perly.y" { (yyval.opval) = op_unscope((ps[-1].val.opval)); } break; - case 78: /* sideff: error */ -#line 668 "perly.y" + case 81: /* sideff: error */ +#line 678 "perly.y" { (yyval.opval) = NULL; } break; - case 79: /* sideff: expr */ -#line 670 "perly.y" + case 82: /* sideff: expr */ +#line 680 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 80: /* sideff: expr KW_IF condition */ -#line 672 "perly.y" + case 83: /* sideff: expr KW_IF condition */ +#line 682 "perly.y" { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[0].val.opval), (ps[-2].val.opval)); } break; - case 81: /* sideff: expr KW_UNLESS condition */ -#line 674 "perly.y" + case 84: /* sideff: expr KW_UNLESS condition */ +#line 684 "perly.y" { (yyval.opval) = newLOGOP(OP_OR, 0, (ps[0].val.opval), (ps[-2].val.opval)); } break; - case 82: /* sideff: expr KW_WHILE condition */ -#line 676 "perly.y" + case 85: /* sideff: expr KW_WHILE condition */ +#line 686 "perly.y" { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, scalar((ps[0].val.opval)), (ps[-2].val.opval)); } break; - case 83: /* sideff: expr KW_UNTIL iexpr */ -#line 678 "perly.y" + case 86: /* sideff: expr KW_UNTIL iexpr */ +#line 688 "perly.y" { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, (ps[0].val.opval), (ps[-2].val.opval)); } break; - case 84: /* sideff: expr KW_FOR condition */ -#line 680 "perly.y" + case 87: /* sideff: expr KW_FOR condition */ +#line 690 "perly.y" { (yyval.opval) = newFOROP(0, NULL, (ps[0].val.opval), (ps[-2].val.opval), NULL); parser->copline = (line_t)(ps[-1].val.ival); } break; - case 86: /* else: KW_ELSE mblock */ -#line 688 "perly.y" + case 88: /* sideff: expr KW_WHEN condition */ +#line 693 "perly.y" + { (yyval.opval) = newWHENOP((ps[0].val.opval), op_scope((ps[-2].val.opval))); } + + break; + + case 90: /* else: KW_ELSE mblock */ +#line 700 "perly.y" { ((ps[0].val.opval))->op_flags |= OPf_PARENS; (yyval.opval) = op_scope((ps[0].val.opval)); @@ -780,8 +807,8 @@ case 2: /* @1: %empty */ break; - case 87: /* else: KW_ELSIF PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock else */ -#line 693 "perly.y" + case 91: /* else: KW_ELSIF PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock else */ +#line 705 "perly.y" { parser->copline = (line_t)(ps[-5].val.ival); (yyval.opval) = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,(ps[-3].val.opval)), @@ -791,94 +818,94 @@ case 2: /* @1: %empty */ break; - case 89: /* cont: KW_CONTINUE block */ -#line 705 "perly.y" + case 93: /* cont: KW_CONTINUE block */ +#line 717 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; - case 90: /* finally: %empty */ -#line 710 "perly.y" + case 94: /* finally: %empty */ +#line 722 "perly.y" { (yyval.opval) = NULL; } break; - case 91: /* finally: KW_FINALLY block */ -#line 712 "perly.y" + case 95: /* finally: KW_FINALLY block */ +#line 724 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; - case 92: /* mintro: %empty */ -#line 717 "perly.y" + case 96: /* mintro: %empty */ +#line 729 "perly.y" { (yyval.ival) = (PL_min_intro_pending && PL_max_intro_pending >= PL_min_intro_pending); intro_my(); } break; - case 95: /* texpr: %empty */ -#line 729 "perly.y" + case 99: /* texpr: %empty */ +#line 741 "perly.y" { YYSTYPE tmplval; (void)scan_num("1", &tmplval); (yyval.opval) = tmplval.opval; } break; - case 97: /* iexpr: expr */ -#line 737 "perly.y" + case 101: /* iexpr: expr */ +#line 749 "perly.y" { (yyval.opval) = invert(scalar((ps[0].val.opval))); } break; - case 98: /* mexpr: expr */ -#line 742 "perly.y" + case 102: /* mexpr: expr */ +#line 754 "perly.y" { (yyval.opval) = (ps[0].val.opval); intro_my(); } break; - case 99: /* mnexpr: nexpr */ -#line 746 "perly.y" + case 103: /* mnexpr: nexpr */ +#line 758 "perly.y" { (yyval.opval) = (ps[0].val.opval); intro_my(); } break; - case 100: /* formname: BAREWORD */ -#line 749 "perly.y" + case 104: /* formname: BAREWORD */ +#line 761 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 102: /* startsub: %empty */ -#line 754 "perly.y" + case 106: /* startsub: %empty */ +#line 766 "perly.y" { (yyval.ival) = start_subparse(FALSE, 0); SAVEFREESV(PL_compcv); } break; - case 103: /* startanonsub: %empty */ -#line 760 "perly.y" + case 107: /* startanonsub: %empty */ +#line 772 "perly.y" { (yyval.ival) = start_subparse(FALSE, CVf_ANON); SAVEFREESV(PL_compcv); } break; - case 104: /* startanonmethod: %empty */ -#line 765 "perly.y" + case 108: /* startanonmethod: %empty */ +#line 777 "perly.y" { (yyval.ival) = start_subparse(FALSE, CVf_ANON|CVf_IsMETHOD); SAVEFREESV(PL_compcv); } break; - case 105: /* startformsub: %empty */ -#line 770 "perly.y" + case 109: /* startformsub: %empty */ +#line 782 "perly.y" { (yyval.ival) = start_subparse(TRUE, 0); SAVEFREESV(PL_compcv); } break; - case 111: /* subattrlist: COLONATTR THING */ -#line 789 "perly.y" + case 115: /* subattrlist: COLONATTR THING */ +#line 801 "perly.y" { OP *attrlist = (ps[0].val.opval); if(attrlist && !PL_parser->sig_seen) @@ -888,50 +915,50 @@ case 2: /* @1: %empty */ break; - case 112: /* subattrlist: COLONATTR */ -#line 796 "perly.y" + case 116: /* subattrlist: COLONATTR */ +#line 808 "perly.y" { (yyval.opval) = NULL; } break; - case 113: /* myattrlist: COLONATTR THING */ -#line 801 "perly.y" + case 117: /* myattrlist: COLONATTR THING */ +#line 813 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 114: /* myattrlist: COLONATTR */ -#line 803 "perly.y" + case 118: /* myattrlist: COLONATTR */ +#line 815 "perly.y" { (yyval.opval) = NULL; } break; - case 115: /* sigvarname: %empty */ -#line 814 "perly.y" + case 119: /* sigvarname: %empty */ +#line 826 "perly.y" { parser->in_my = 0; (yyval.opval) = NULL; } break; - case 116: /* sigvarname: PRIVATEREF */ -#line 816 "perly.y" + case 120: /* sigvarname: PRIVATEREF */ +#line 828 "perly.y" { parser->in_my = 0; (yyval.opval) = (ps[0].val.opval); } break; - case 117: /* sigslurpsigil: PERLY_SNAIL */ -#line 821 "perly.y" + case 121: /* sigslurpsigil: PERLY_SNAIL */ +#line 833 "perly.y" { (yyval.ival) = '@'; } break; - case 118: /* sigslurpsigil: PERLY_PERCENT_SIGN */ -#line 823 "perly.y" + case 122: /* sigslurpsigil: PERLY_PERCENT_SIGN */ +#line 835 "perly.y" { (yyval.ival) = '%'; } break; - case 119: /* sigslurpelem: sigslurpsigil sigvarname sigdefault */ -#line 827 "perly.y" + case 123: /* sigslurpelem: sigslurpsigil sigvarname sigdefault */ +#line 839 "perly.y" { I32 sigil = (ps[-2].val.ival); OP *var = (ps[-1].val.opval); @@ -950,14 +977,14 @@ case 2: /* @1: %empty */ break; - case 121: /* sigdefault: ASSIGNOP */ -#line 848 "perly.y" + case 125: /* sigdefault: ASSIGNOP */ +#line 860 "perly.y" { (yyval.opval) = newARGDEFELEMOP(0, newOP(OP_NULL, 0), parser->sig_elems); } break; - case 122: /* sigdefault: ASSIGNOP term */ -#line 850 "perly.y" + case 126: /* sigdefault: ASSIGNOP term */ +#line 862 "perly.y" { I32 flags = 0; if ((ps[-1].val.ival) == OP_DORASSIGN) @@ -969,8 +996,8 @@ case 2: /* @1: %empty */ break; - case 123: /* sigscalarelem: PERLY_DOLLAR sigvarname sigdefault */ -#line 863 "perly.y" + case 127: /* sigscalarelem: PERLY_DOLLAR sigvarname sigdefault */ +#line 875 "perly.y" { OP *var = (ps[-1].val.opval); OP *defop = (ps[0].val.opval); @@ -1029,46 +1056,46 @@ case 2: /* @1: %empty */ break; - case 124: /* sigelem: sigscalarelem */ -#line 923 "perly.y" + case 128: /* sigelem: sigscalarelem */ +#line 935 "perly.y" { parser->in_my = KEY_sigvar; (yyval.opval) = (ps[0].val.opval); } break; - case 125: /* sigelem: sigslurpelem */ -#line 925 "perly.y" + case 129: /* sigelem: sigslurpelem */ +#line 937 "perly.y" { parser->in_my = KEY_sigvar; (yyval.opval) = (ps[0].val.opval); } break; - case 126: /* siglist: siglist PERLY_COMMA */ -#line 931 "perly.y" + case 130: /* siglist: siglist PERLY_COMMA */ +#line 943 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 127: /* siglist: siglist PERLY_COMMA sigelem */ -#line 933 "perly.y" + case 131: /* siglist: siglist PERLY_COMMA sigelem */ +#line 945 "perly.y" { (yyval.opval) = op_append_list(OP_LINESEQ, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 128: /* siglist: sigelem */ -#line 937 "perly.y" + case 132: /* siglist: sigelem */ +#line 949 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 133: /* subsignature: PERLY_PAREN_OPEN subsigguts PERLY_PAREN_CLOSE */ -#line 954 "perly.y" + case 137: /* subsignature: PERLY_PAREN_OPEN subsigguts PERLY_PAREN_CLOSE */ +#line 966 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 134: /* $@20: %empty */ -#line 957 "perly.y" + case 138: /* $@20: %empty */ +#line 969 "perly.y" { ENTER; SAVEIV(parser->sig_elems); @@ -1082,8 +1109,8 @@ case 2: /* @1: %empty */ break; - case 135: /* subsigguts: $@20 optsiglist */ -#line 968 "perly.y" + case 139: /* subsigguts: $@20 optsiglist */ +#line 980 "perly.y" { OP *sigops = (ps[0].val.opval); struct op_argcheck_aux *aux; @@ -1139,14 +1166,14 @@ case 2: /* @1: %empty */ break; - case 137: /* optsubbody: PERLY_SEMICOLON */ -#line 1025 "perly.y" + case 141: /* optsubbody: PERLY_SEMICOLON */ +#line 1037 "perly.y" { (yyval.opval) = NULL; } break; - case 138: /* subbody: remember PERLY_BRACE_OPEN stmtseq PERLY_BRACE_CLOSE */ -#line 1031 "perly.y" + case 142: /* subbody: remember PERLY_BRACE_OPEN stmtseq PERLY_BRACE_CLOSE */ +#line 1043 "perly.y" { if (parser->copline > (line_t)(ps[-2].val.ival)) parser->copline = (line_t)(ps[-2].val.ival); @@ -1155,20 +1182,20 @@ case 2: /* @1: %empty */ break; - case 140: /* optsigsubbody: PERLY_SEMICOLON */ -#line 1043 "perly.y" + case 144: /* optsigsubbody: PERLY_SEMICOLON */ +#line 1055 "perly.y" { (yyval.opval) = NULL; } break; - case 141: /* $@21: %empty */ -#line 1048 "perly.y" + case 145: /* $@21: %empty */ +#line 1060 "perly.y" { PL_parser->sig_seen = FALSE; } break; - case 142: /* sigsubbody: remember optsubsignature PERLY_BRACE_OPEN $@21 stmtseq PERLY_BRACE_CLOSE */ -#line 1050 "perly.y" + case 146: /* sigsubbody: remember optsubsignature PERLY_BRACE_OPEN $@21 stmtseq PERLY_BRACE_CLOSE */ +#line 1062 "perly.y" { if (parser->copline > (line_t)(ps[-3].val.ival)) parser->copline = (line_t)(ps[-3].val.ival); @@ -1178,38 +1205,38 @@ case 2: /* @1: %empty */ break; - case 143: /* expr: expr ANDOP expr */ -#line 1061 "perly.y" + case 147: /* expr: expr ANDOP expr */ +#line 1073 "perly.y" { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 144: /* expr: expr PLUGIN_LOGICAL_AND_LOW_OP expr */ -#line 1063 "perly.y" + case 148: /* expr: expr PLUGIN_LOGICAL_AND_LOW_OP expr */ +#line 1075 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 145: /* expr: expr OROP expr */ -#line 1065 "perly.y" + case 149: /* expr: expr OROP expr */ +#line 1077 "perly.y" { (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 146: /* expr: expr PLUGIN_LOGICAL_OR_LOW_OP expr */ -#line 1067 "perly.y" + case 150: /* expr: expr PLUGIN_LOGICAL_OR_LOW_OP expr */ +#line 1079 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 148: /* listexpr: listexpr PERLY_COMMA */ -#line 1073 "perly.y" + case 152: /* listexpr: listexpr PERLY_COMMA */ +#line 1085 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 149: /* listexpr: listexpr PERLY_COMMA term */ -#line 1075 "perly.y" + case 153: /* listexpr: listexpr PERLY_COMMA term */ +#line 1087 "perly.y" { OP* term = (ps[0].val.opval); (yyval.opval) = op_append_elem(OP_LIST, (ps[-2].val.opval), term); @@ -1217,24 +1244,24 @@ case 2: /* @1: %empty */ break; - case 151: /* listop: LSTOP indirob listexpr */ -#line 1084 "perly.y" + case 155: /* listop: LSTOP indirob listexpr */ +#line 1096 "perly.y" { (yyval.opval) = op_convert_list((ps[-2].val.ival), OPf_STACKED, op_prepend_elem(OP_LIST, newGVREF((ps[-2].val.ival),(ps[-1].val.opval)), (ps[0].val.opval)) ); } break; - case 152: /* listop: FUNC PERLY_PAREN_OPEN indirob expr PERLY_PAREN_CLOSE */ -#line 1088 "perly.y" + case 156: /* listop: FUNC PERLY_PAREN_OPEN indirob expr PERLY_PAREN_CLOSE */ +#line 1100 "perly.y" { (yyval.opval) = op_convert_list((ps[-4].val.ival), OPf_STACKED, op_prepend_elem(OP_LIST, newGVREF((ps[-4].val.ival),(ps[-2].val.opval)), (ps[-1].val.opval)) ); } break; - case 153: /* listop: term ARROW methodname PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1092 "perly.y" + case 157: /* listop: term ARROW methodname PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ +#line 1104 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, scalar((ps[-5].val.opval)), (ps[-1].val.opval)), @@ -1243,8 +1270,8 @@ case 2: /* @1: %empty */ break; - case 154: /* listop: term ARROW methodname */ -#line 1098 "perly.y" + case 158: /* listop: term ARROW methodname */ +#line 1110 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, scalar((ps[-2].val.opval)), newMETHOP(OP_METHOD, 0, (ps[0].val.opval)))); @@ -1252,8 +1279,8 @@ case 2: /* @1: %empty */ break; - case 155: /* listop: METHCALL0 indirob optlistexpr */ -#line 1103 "perly.y" + case 159: /* listop: METHCALL0 indirob optlistexpr */ +#line 1115 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)), @@ -1262,8 +1289,8 @@ case 2: /* @1: %empty */ break; - case 156: /* listop: METHCALL indirob PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1109 "perly.y" + case 160: /* listop: METHCALL indirob PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ +#line 1121 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-3].val.opval), (ps[-1].val.opval)), @@ -1272,26 +1299,26 @@ case 2: /* @1: %empty */ break; - case 157: /* listop: LSTOP optlistexpr */ -#line 1115 "perly.y" + case 161: /* listop: LSTOP optlistexpr */ +#line 1127 "perly.y" { (yyval.opval) = op_convert_list((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; - case 158: /* listop: FUNC PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1117 "perly.y" + case 162: /* listop: FUNC PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ +#line 1129 "perly.y" { (yyval.opval) = op_convert_list((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; - case 159: /* listop: FUNC SUBLEXSTART optexpr SUBLEXEND */ -#line 1119 "perly.y" + case 163: /* listop: FUNC SUBLEXSTART optexpr SUBLEXEND */ +#line 1131 "perly.y" { (yyval.opval) = op_convert_list((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; - case 160: /* @22: %empty */ -#line 1121 "perly.y" + case 164: /* @22: %empty */ +#line 1133 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-1].val.ival), 0, NULL, (ps[0].val.opval)); /* prevent double op_free() if the following fails to parse */ @@ -1300,8 +1327,8 @@ case 2: /* @1: %empty */ break; - case 161: /* listop: LSTOPSUB startanonsub block @22 optlistexpr */ -#line 1127 "perly.y" + case 165: /* listop: LSTOPSUB startanonsub block @22 optlistexpr */ +#line 1139 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)), (ps[-4].val.opval))); @@ -1309,21 +1336,21 @@ case 2: /* @1: %empty */ break; - case 164: /* subscripted: gelem PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1142 "perly.y" + case 168: /* subscripted: gelem PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1154 "perly.y" { (yyval.opval) = newBINOP(OP_GELEM, 0, (ps[-4].val.opval), scalar((ps[-2].val.opval))); } break; - case 165: /* subscripted: scalar PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1144 "perly.y" + case 169: /* subscripted: scalar PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1156 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, oopsAV((ps[-3].val.opval)), scalar((ps[-1].val.opval))); } break; - case 166: /* subscripted: term ARROW PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1147 "perly.y" + case 170: /* subscripted: term ARROW PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1159 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[-4].val.opval)),OP_RV2AV), scalar((ps[-1].val.opval))); @@ -1331,8 +1358,8 @@ case 2: /* @1: %empty */ break; - case 167: /* subscripted: subscripted PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1152 "perly.y" + case 171: /* subscripted: subscripted PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1164 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[-3].val.opval)),OP_RV2AV), scalar((ps[-1].val.opval))); @@ -1340,31 +1367,31 @@ case 2: /* @1: %empty */ break; - case 168: /* subscripted: scalar PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1157 "perly.y" + case 172: /* subscripted: scalar PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1169 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, oopsHV((ps[-4].val.opval)), jmaybe((ps[-2].val.opval))); } break; - case 169: /* subscripted: term ARROW PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1160 "perly.y" + case 173: /* subscripted: term ARROW PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1172 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[-5].val.opval)),OP_RV2HV), jmaybe((ps[-2].val.opval))); } break; - case 170: /* subscripted: subscripted PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1164 "perly.y" + case 174: /* subscripted: subscripted PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1176 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[-4].val.opval)),OP_RV2HV), jmaybe((ps[-2].val.opval))); } break; - case 171: /* subscripted: term ARROW PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1168 "perly.y" + case 175: /* subscripted: term ARROW PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1180 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, newCVREF(0, scalar((ps[-3].val.opval)))); if (parser->expect == XBLOCK) @@ -1373,8 +1400,8 @@ case 2: /* @1: %empty */ break; - case 172: /* subscripted: term ARROW PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1174 "perly.y" + case 176: /* subscripted: term ARROW PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1186 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), newCVREF(0, scalar((ps[-4].val.opval))))); @@ -1384,8 +1411,8 @@ case 2: /* @1: %empty */ break; - case 173: /* subscripted: subscripted PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1182 "perly.y" + case 177: /* subscripted: subscripted PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1194 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), newCVREF(0, scalar((ps[-3].val.opval))))); @@ -1395,8 +1422,8 @@ case 2: /* @1: %empty */ break; - case 174: /* subscripted: subscripted PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1189 "perly.y" + case 178: /* subscripted: subscripted PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1201 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, newCVREF(0, scalar((ps[-2].val.opval)))); if (parser->expect == XBLOCK) @@ -1405,56 +1432,56 @@ case 2: /* @1: %empty */ break; - case 175: /* subscripted: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1195 "perly.y" + case 179: /* subscripted: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1207 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-4].val.opval)); } break; - case 176: /* subscripted: QWLIST PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1197 "perly.y" + case 180: /* subscripted: QWLIST PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1209 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-3].val.opval)); } break; - case 177: /* subscripted: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1199 "perly.y" + case 181: /* subscripted: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1211 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), NULL); } break; - case 178: /* termbinop: term PLUGIN_HIGH_OP term */ -#line 1204 "perly.y" + case 182: /* termbinop: term PLUGIN_HIGH_OP term */ +#line 1216 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 179: /* termbinop: term ASSIGNOP term */ -#line 1206 "perly.y" + case 183: /* termbinop: term ASSIGNOP term */ +#line 1218 "perly.y" { (yyval.opval) = newASSIGNOP(OPf_STACKED, (ps[-2].val.opval), (ps[-1].val.ival), (ps[0].val.opval)); } break; - case 180: /* termbinop: term PLUGIN_ASSIGN_OP term */ -#line 1208 "perly.y" + case 184: /* termbinop: term PLUGIN_ASSIGN_OP term */ +#line 1220 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 181: /* termbinop: term POWOP term */ -#line 1210 "perly.y" + case 185: /* termbinop: term POWOP term */ +#line 1222 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 182: /* termbinop: term PLUGIN_POW_OP term */ -#line 1212 "perly.y" + case 186: /* termbinop: term PLUGIN_POW_OP term */ +#line 1224 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 183: /* termbinop: term MULOP term */ -#line 1214 "perly.y" + case 187: /* termbinop: term MULOP term */ +#line 1226 "perly.y" { if ((ps[-1].val.ival) != OP_REPEAT) scalar((ps[-2].val.opval)); (yyval.opval) = newBINOP((ps[-1].val.ival), 0, (ps[-2].val.opval), scalar((ps[0].val.opval))); @@ -1462,220 +1489,220 @@ case 2: /* @1: %empty */ break; - case 184: /* termbinop: term PLUGIN_MUL_OP term */ -#line 1219 "perly.y" + case 188: /* termbinop: term PLUGIN_MUL_OP term */ +#line 1231 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 185: /* termbinop: term ADDOP term */ -#line 1221 "perly.y" + case 189: /* termbinop: term ADDOP term */ +#line 1233 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 186: /* termbinop: term PLUGIN_ADD_OP term */ -#line 1223 "perly.y" + case 190: /* termbinop: term PLUGIN_ADD_OP term */ +#line 1235 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 187: /* termbinop: term SHIFTOP term */ -#line 1225 "perly.y" + case 191: /* termbinop: term SHIFTOP term */ +#line 1237 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 188: /* termbinop: termrelop */ -#line 1227 "perly.y" + case 192: /* termbinop: termrelop */ +#line 1239 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 189: /* termbinop: termeqop */ -#line 1229 "perly.y" + case 193: /* termbinop: termeqop */ +#line 1241 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 190: /* termbinop: term BITANDOP term */ -#line 1231 "perly.y" + case 194: /* termbinop: term BITANDOP term */ +#line 1243 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 191: /* termbinop: term BITOROP term */ -#line 1233 "perly.y" + case 195: /* termbinop: term BITOROP term */ +#line 1245 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 192: /* termbinop: term DOTDOT term */ -#line 1235 "perly.y" + case 196: /* termbinop: term DOTDOT term */ +#line 1247 "perly.y" { (yyval.opval) = newRANGE((ps[-1].val.ival), scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 193: /* termbinop: term ANDAND term */ -#line 1237 "perly.y" + case 197: /* termbinop: term ANDAND term */ +#line 1249 "perly.y" { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 194: /* termbinop: term PLUGIN_LOGICAL_AND_OP term */ -#line 1239 "perly.y" + case 198: /* termbinop: term PLUGIN_LOGICAL_AND_OP term */ +#line 1251 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 195: /* termbinop: term OROR term */ -#line 1241 "perly.y" + case 199: /* termbinop: term OROR term */ +#line 1253 "perly.y" { (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 196: /* termbinop: term PLUGIN_LOGICAL_OR_OP term */ -#line 1243 "perly.y" + case 200: /* termbinop: term PLUGIN_LOGICAL_OR_OP term */ +#line 1255 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 197: /* termbinop: term DORDOR term */ -#line 1245 "perly.y" + case 201: /* termbinop: term DORDOR term */ +#line 1257 "perly.y" { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 198: /* termbinop: term MATCHOP term */ -#line 1247 "perly.y" + case 202: /* termbinop: term MATCHOP term */ +#line 1259 "perly.y" { (yyval.opval) = bind_match((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 199: /* termbinop: term PLUGIN_LOW_OP term */ -#line 1249 "perly.y" + case 203: /* termbinop: term PLUGIN_LOW_OP term */ +#line 1261 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 200: /* termrelop: relopchain */ -#line 1253 "perly.y" + case 204: /* termrelop: relopchain */ +#line 1265 "perly.y" { (yyval.opval) = cmpchain_finish((ps[0].val.opval)); } break; - case 201: /* termrelop: term NCRELOP term */ -#line 1255 "perly.y" + case 205: /* termrelop: term NCRELOP term */ +#line 1267 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 202: /* termrelop: termrelop NCRELOP */ -#line 1257 "perly.y" + case 206: /* termrelop: termrelop NCRELOP */ +#line 1269 "perly.y" { yyerror("syntax error"); YYERROR; } break; - case 203: /* termrelop: termrelop CHRELOP */ -#line 1259 "perly.y" + case 207: /* termrelop: termrelop CHRELOP */ +#line 1271 "perly.y" { yyerror("syntax error"); YYERROR; } break; - case 204: /* termrelop: term PLUGIN_REL_OP term */ -#line 1261 "perly.y" + case 208: /* termrelop: term PLUGIN_REL_OP term */ +#line 1273 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; - case 205: /* relopchain: term CHRELOP term */ -#line 1265 "perly.y" + case 209: /* relopchain: term CHRELOP term */ +#line 1277 "perly.y" { (yyval.opval) = cmpchain_start((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 206: /* relopchain: relopchain CHRELOP term */ -#line 1267 "perly.y" + case 210: /* relopchain: relopchain CHRELOP term */ +#line 1279 "perly.y" { (yyval.opval) = cmpchain_extend((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 207: /* termeqop: eqopchain */ -#line 1271 "perly.y" + case 211: /* termeqop: eqopchain */ +#line 1283 "perly.y" { (yyval.opval) = cmpchain_finish((ps[0].val.opval)); } break; - case 208: /* termeqop: term NCEQOP term */ -#line 1273 "perly.y" + case 212: /* termeqop: term NCEQOP term */ +#line 1285 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; - case 209: /* termeqop: termeqop NCEQOP */ -#line 1275 "perly.y" + case 213: /* termeqop: termeqop NCEQOP */ +#line 1287 "perly.y" { yyerror("syntax error"); YYERROR; } break; - case 210: /* termeqop: termeqop CHEQOP */ -#line 1277 "perly.y" + case 214: /* termeqop: termeqop CHEQOP */ +#line 1289 "perly.y" { yyerror("syntax error"); YYERROR; } break; - case 211: /* eqopchain: term CHEQOP term */ -#line 1281 "perly.y" + case 215: /* eqopchain: term CHEQOP term */ +#line 1293 "perly.y" { (yyval.opval) = cmpchain_start((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 212: /* eqopchain: eqopchain CHEQOP term */ -#line 1283 "perly.y" + case 216: /* eqopchain: eqopchain CHEQOP term */ +#line 1295 "perly.y" { (yyval.opval) = cmpchain_extend((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 213: /* termunop: PERLY_MINUS term */ -#line 1288 "perly.y" + case 217: /* termunop: PERLY_MINUS term */ +#line 1300 "perly.y" { (yyval.opval) = newUNOP(OP_NEGATE, 0, scalar((ps[0].val.opval))); } break; - case 214: /* termunop: PERLY_PLUS term */ -#line 1290 "perly.y" + case 218: /* termunop: PERLY_PLUS term */ +#line 1302 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 215: /* termunop: PERLY_EXCLAMATION_MARK term */ -#line 1293 "perly.y" + case 219: /* termunop: PERLY_EXCLAMATION_MARK term */ +#line 1305 "perly.y" { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); } break; - case 216: /* termunop: PERLY_TILDE term */ -#line 1295 "perly.y" + case 220: /* termunop: PERLY_TILDE term */ +#line 1307 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, scalar((ps[0].val.opval))); } break; - case 217: /* termunop: term POSTINC */ -#line 1297 "perly.y" + case 221: /* termunop: term POSTINC */ +#line 1309 "perly.y" { (yyval.opval) = newUNOP(OP_POSTINC, 0, op_lvalue(scalar((ps[-1].val.opval)), OP_POSTINC)); } break; - case 218: /* termunop: term POSTDEC */ -#line 1300 "perly.y" + case 222: /* termunop: term POSTDEC */ +#line 1312 "perly.y" { (yyval.opval) = newUNOP(OP_POSTDEC, 0, op_lvalue(scalar((ps[-1].val.opval)), OP_POSTDEC));} break; - case 219: /* termunop: term POSTJOIN */ -#line 1303 "perly.y" + case 223: /* termunop: term POSTJOIN */ +#line 1315 "perly.y" { (yyval.opval) = op_convert_list(OP_JOIN, 0, op_append_elem( OP_LIST, @@ -1689,48 +1716,48 @@ case 2: /* @1: %empty */ break; - case 220: /* termunop: PREINC term */ -#line 1314 "perly.y" + case 224: /* termunop: PREINC term */ +#line 1326 "perly.y" { (yyval.opval) = newUNOP(OP_PREINC, 0, op_lvalue(scalar((ps[0].val.opval)), OP_PREINC)); } break; - case 221: /* termunop: PREDEC term */ -#line 1317 "perly.y" + case 225: /* termunop: PREDEC term */ +#line 1329 "perly.y" { (yyval.opval) = newUNOP(OP_PREDEC, 0, op_lvalue(scalar((ps[0].val.opval)), OP_PREDEC)); } break; - case 222: /* anonymous: PERLY_BRACKET_OPEN optexpr PERLY_BRACKET_CLOSE */ -#line 1325 "perly.y" + case 226: /* anonymous: PERLY_BRACKET_OPEN optexpr PERLY_BRACKET_CLOSE */ +#line 1337 "perly.y" { (yyval.opval) = newANONLIST((ps[-1].val.opval)); } break; - case 223: /* anonymous: HASHBRACK optexpr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1327 "perly.y" + case 227: /* anonymous: HASHBRACK optexpr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1339 "perly.y" { (yyval.opval) = newANONHASH((ps[-2].val.opval)); } break; - case 224: /* anonymous: KW_SUB_anon startanonsub proto subattrlist subbody */ -#line 1329 "perly.y" + case 228: /* anonymous: KW_SUB_anon startanonsub proto subattrlist subbody */ +#line 1341 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-3].val.ival), (ps[-2].val.opval), (ps[-1].val.opval), (ps[0].val.opval)); } break; - case 225: /* anonymous: KW_SUB_anon_sig startanonsub subattrlist sigsubbody */ -#line 1332 "perly.y" + case 229: /* anonymous: KW_SUB_anon_sig startanonsub subattrlist sigsubbody */ +#line 1344 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-2].val.ival), NULL, (ps[-1].val.opval), (ps[0].val.opval)); } break; - case 226: /* anonymous: KW_METHOD_anon startanonmethod subattrlist sigsubbody */ -#line 1335 "perly.y" + case 230: /* anonymous: KW_METHOD_anon startanonmethod subattrlist sigsubbody */ +#line 1347 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-2].val.ival), NULL, (ps[-1].val.opval), (ps[0].val.opval)); @@ -1738,98 +1765,98 @@ case 2: /* @1: %empty */ break; - case 227: /* termdo: KW_DO term */ -#line 1343 "perly.y" + case 231: /* termdo: KW_DO term */ +#line 1355 "perly.y" { (yyval.opval) = dofile((ps[0].val.opval), (ps[-1].val.ival));} break; - case 228: /* termdo: KW_DO block */ -#line 1345 "perly.y" + case 232: /* termdo: KW_DO block */ +#line 1357 "perly.y" { (yyval.opval) = newUNOP(OP_NULL, OPf_SPECIAL, op_scope((ps[0].val.opval)));} break; - case 233: /* term: term PERLY_QUESTION_MARK term PERLY_COLON term */ -#line 1353 "perly.y" + case 237: /* term: term PERLY_QUESTION_MARK term PERLY_COLON term */ +#line 1365 "perly.y" { (yyval.opval) = newCONDOP(0, (ps[-4].val.opval), (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 234: /* term: REFGEN term */ -#line 1355 "perly.y" + case 238: /* term: REFGEN term */ +#line 1367 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, (ps[0].val.opval)); } break; - case 235: /* term: myattrterm */ -#line 1357 "perly.y" + case 239: /* term: myattrterm */ +#line 1369 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 236: /* term: KW_LOCAL term */ -#line 1359 "perly.y" + case 240: /* term: KW_LOCAL term */ +#line 1371 "perly.y" { (yyval.opval) = localize((ps[0].val.opval),0); } break; - case 237: /* term: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1361 "perly.y" + case 241: /* term: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1373 "perly.y" { (yyval.opval) = sawparens((ps[-1].val.opval)); } break; - case 238: /* term: QWLIST */ -#line 1363 "perly.y" + case 242: /* term: QWLIST */ +#line 1375 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 239: /* term: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1365 "perly.y" + case 243: /* term: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1377 "perly.y" { (yyval.opval) = sawparens(newNULLLIST()); } break; - case 240: /* term: scalar */ -#line 1367 "perly.y" + case 244: /* term: scalar */ +#line 1379 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 241: /* term: star */ -#line 1369 "perly.y" + case 245: /* term: star */ +#line 1381 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 242: /* term: hsh */ -#line 1371 "perly.y" + case 246: /* term: hsh */ +#line 1383 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 243: /* term: ary */ -#line 1373 "perly.y" + case 247: /* term: ary */ +#line 1385 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 244: /* term: arylen */ -#line 1375 "perly.y" + case 248: /* term: arylen */ +#line 1387 "perly.y" { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((ps[0].val.opval), OP_AV2ARYLEN));} break; - case 245: /* term: subscripted */ -#line 1377 "perly.y" + case 249: /* term: subscripted */ +#line 1389 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 246: /* term: sliceme PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1379 "perly.y" + case 250: /* term: sliceme PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1391 "perly.y" { (yyval.opval) = op_prepend_elem(OP_ASLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_ASLICE, 0, @@ -1842,8 +1869,8 @@ case 2: /* @1: %empty */ break; - case 247: /* term: kvslice PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1389 "perly.y" + case 251: /* term: kvslice PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ +#line 1401 "perly.y" { (yyval.opval) = op_prepend_elem(OP_KVASLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_KVASLICE, 0, @@ -1856,8 +1883,8 @@ case 2: /* @1: %empty */ break; - case 248: /* term: sliceme PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1399 "perly.y" + case 252: /* term: sliceme PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1411 "perly.y" { (yyval.opval) = op_prepend_elem(OP_HSLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_HSLICE, 0, @@ -1870,8 +1897,8 @@ case 2: /* @1: %empty */ break; - case 249: /* term: kvslice PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1409 "perly.y" + case 253: /* term: kvslice PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ +#line 1421 "perly.y" { (yyval.opval) = op_prepend_elem(OP_KVHSLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_KVHSLICE, 0, @@ -1884,27 +1911,27 @@ case 2: /* @1: %empty */ break; - case 250: /* term: THING */ -#line 1419 "perly.y" + case 254: /* term: THING */ +#line 1431 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 251: /* term: amper */ -#line 1421 "perly.y" + case 255: /* term: amper */ +#line 1433 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((ps[0].val.opval))); } break; - case 252: /* term: amper PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1423 "perly.y" + case 256: /* term: amper PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1435 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[-2].val.opval))); } break; - case 253: /* term: amper PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1426 "perly.y" + case 257: /* term: amper PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1438 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), scalar((ps[-3].val.opval)))); @@ -1912,153 +1939,153 @@ case 2: /* @1: %empty */ break; - case 254: /* term: NOAMP subname optlistexpr */ -#line 1431 "perly.y" + case 258: /* term: NOAMP subname optlistexpr */ +#line 1443 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval)))); } break; - case 255: /* term: term ARROW PERLY_DOLLAR PERLY_STAR */ -#line 1435 "perly.y" + case 259: /* term: term ARROW PERLY_DOLLAR PERLY_STAR */ +#line 1447 "perly.y" { (yyval.opval) = newSVREF((ps[-3].val.opval)); } break; - case 256: /* term: term ARROW PERLY_SNAIL PERLY_STAR */ -#line 1437 "perly.y" + case 260: /* term: term ARROW PERLY_SNAIL PERLY_STAR */ +#line 1449 "perly.y" { (yyval.opval) = newAVREF((ps[-3].val.opval)); } break; - case 257: /* term: term ARROW PERLY_PERCENT_SIGN PERLY_STAR */ -#line 1439 "perly.y" + case 261: /* term: term ARROW PERLY_PERCENT_SIGN PERLY_STAR */ +#line 1451 "perly.y" { (yyval.opval) = newHVREF((ps[-3].val.opval)); } break; - case 258: /* term: term ARROW PERLY_AMPERSAND PERLY_STAR */ -#line 1441 "perly.y" + case 262: /* term: term ARROW PERLY_AMPERSAND PERLY_STAR */ +#line 1453 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar(newCVREF((ps[-1].val.ival),(ps[-3].val.opval)))); } break; - case 259: /* term: term ARROW PERLY_STAR PERLY_STAR */ -#line 1444 "perly.y" + case 263: /* term: term ARROW PERLY_STAR PERLY_STAR */ +#line 1456 "perly.y" { (yyval.opval) = newGVREF(0,(ps[-3].val.opval)); } break; - case 260: /* term: LOOPEX */ -#line 1446 "perly.y" + case 264: /* term: LOOPEX */ +#line 1458 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), OPf_SPECIAL); PL_hints |= HINT_BLOCK_SCOPE; } break; - case 261: /* term: LOOPEX term */ -#line 1449 "perly.y" + case 265: /* term: LOOPEX term */ +#line 1461 "perly.y" { (yyval.opval) = newLOOPEX((ps[-1].val.ival),(ps[0].val.opval)); } break; - case 262: /* term: NOTOP listexpr */ -#line 1451 "perly.y" + case 266: /* term: NOTOP listexpr */ +#line 1463 "perly.y" { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); } break; - case 263: /* term: UNIOP */ -#line 1453 "perly.y" + case 267: /* term: UNIOP */ +#line 1465 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), 0); } break; - case 264: /* term: UNIOP block */ -#line 1455 "perly.y" + case 268: /* term: UNIOP block */ +#line 1467 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; - case 265: /* term: UNIOP term */ -#line 1457 "perly.y" + case 269: /* term: UNIOP term */ +#line 1469 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; - case 266: /* term: KW_REQUIRE */ -#line 1459 "perly.y" + case 270: /* term: KW_REQUIRE */ +#line 1471 "perly.y" { (yyval.opval) = newOP(OP_REQUIRE, (ps[0].val.ival) ? OPf_SPECIAL : 0); } break; - case 267: /* term: KW_REQUIRE term */ -#line 1461 "perly.y" + case 271: /* term: KW_REQUIRE term */ +#line 1473 "perly.y" { (yyval.opval) = newUNOP(OP_REQUIRE, (ps[-1].val.ival) ? OPf_SPECIAL : 0, (ps[0].val.opval)); } break; - case 268: /* term: UNIOPSUB */ -#line 1463 "perly.y" + case 272: /* term: UNIOPSUB */ +#line 1475 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); } break; - case 269: /* term: UNIOPSUB term */ -#line 1465 "perly.y" + case 273: /* term: UNIOPSUB term */ +#line 1477 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval)))); } break; - case 270: /* term: FUNC0 */ -#line 1468 "perly.y" + case 274: /* term: FUNC0 */ +#line 1480 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), 0); } break; - case 271: /* term: FUNC0 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1470 "perly.y" + case 275: /* term: FUNC0 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1482 "perly.y" { (yyval.opval) = newOP((ps[-2].val.ival), 0);} break; - case 272: /* term: FUNC0OP */ -#line 1472 "perly.y" + case 276: /* term: FUNC0OP */ +#line 1484 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 273: /* term: FUNC0OP PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1474 "perly.y" + case 277: /* term: FUNC0OP PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1486 "perly.y" { (yyval.opval) = (ps[-2].val.opval); } break; - case 274: /* term: FUNC0SUB */ -#line 1476 "perly.y" + case 278: /* term: FUNC0SUB */ +#line 1488 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); } break; - case 275: /* term: FUNC1 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1478 "perly.y" + case 279: /* term: FUNC1 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1490 "perly.y" { (yyval.opval) = ((ps[-2].val.ival) == OP_NOT) ? newUNOP((ps[-2].val.ival), 0, newSVOP(OP_CONST, 0, newSViv(0))) : newOP((ps[-2].val.ival), OPf_SPECIAL); } break; - case 276: /* term: FUNC1 PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1482 "perly.y" + case 280: /* term: FUNC1 PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1494 "perly.y" { (yyval.opval) = newUNOP((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; - case 277: /* @23: %empty */ -#line 1484 "perly.y" + case 281: /* @23: %empty */ +#line 1496 "perly.y" { if ( (ps[0].val.opval)->op_type != OP_TRANS && (ps[0].val.opval)->op_type != OP_TRANSR @@ -2072,68 +2099,68 @@ case 2: /* @1: %empty */ break; - case 278: /* term: PMFUNC @23 SUBLEXSTART listexpr optrepl SUBLEXEND */ -#line 1495 "perly.y" + case 282: /* term: PMFUNC @23 SUBLEXSTART listexpr optrepl SUBLEXEND */ +#line 1507 "perly.y" { (yyval.opval) = pmruntime((ps[-5].val.opval), (ps[-2].val.opval), (ps[-1].val.opval), 1, (ps[-4].val.ival)); } break; - case 282: /* myattrterm: KW_MY myterm myattrlist */ -#line 1504 "perly.y" + case 286: /* myattrterm: KW_MY myterm myattrlist */ +#line 1516 "perly.y" { (yyval.opval) = my_attrs((ps[-1].val.opval),(ps[0].val.opval)); } break; - case 283: /* myattrterm: KW_MY myterm */ -#line 1506 "perly.y" + case 287: /* myattrterm: KW_MY myterm */ +#line 1518 "perly.y" { (yyval.opval) = localize((ps[0].val.opval),1); } break; - case 284: /* myattrterm: KW_MY REFGEN myterm myattrlist */ -#line 1508 "perly.y" + case 288: /* myattrterm: KW_MY REFGEN myterm myattrlist */ +#line 1520 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, my_attrs((ps[-1].val.opval),(ps[0].val.opval))); } break; - case 285: /* myattrterm: KW_MY REFGEN term */ -#line 1510 "perly.y" + case 289: /* myattrterm: KW_MY REFGEN term */ +#line 1522 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, localize((ps[0].val.opval),1)); } break; - case 286: /* myterm: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1515 "perly.y" + case 290: /* myterm: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ +#line 1527 "perly.y" { (yyval.opval) = sawparens((ps[-1].val.opval)); } break; - case 287: /* myterm: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1517 "perly.y" + case 291: /* myterm: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ +#line 1529 "perly.y" { (yyval.opval) = sawparens(newNULLLIST()); } break; - case 288: /* myterm: scalar */ -#line 1520 "perly.y" + case 292: /* myterm: scalar */ +#line 1532 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 289: /* myterm: hsh */ -#line 1522 "perly.y" + case 293: /* myterm: hsh */ +#line 1534 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 290: /* myterm: ary */ -#line 1524 "perly.y" + case 294: /* myterm: ary */ +#line 1536 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 291: /* fieldvar: scalar */ -#line 1529 "perly.y" + case 295: /* fieldvar: scalar */ +#line 1541 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2141,8 +2168,8 @@ case 2: /* @1: %empty */ break; - case 292: /* fieldvar: hsh */ -#line 1534 "perly.y" + case 296: /* fieldvar: hsh */ +#line 1546 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2150,8 +2177,8 @@ case 2: /* @1: %empty */ break; - case 293: /* fieldvar: ary */ -#line 1539 "perly.y" + case 297: /* fieldvar: ary */ +#line 1551 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2159,20 +2186,20 @@ case 2: /* @1: %empty */ break; - case 294: /* optfieldattrlist: COLONATTR THING */ -#line 1547 "perly.y" + case 298: /* optfieldattrlist: COLONATTR THING */ +#line 1559 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 295: /* optfieldattrlist: COLONATTR */ -#line 1549 "perly.y" + case 299: /* optfieldattrlist: COLONATTR */ +#line 1561 "perly.y" { (yyval.opval) = NULL; } break; - case 297: /* fielddecl: KW_FIELD fieldvar optfieldattrlist */ -#line 1555 "perly.y" + case 301: /* fielddecl: KW_FIELD fieldvar optfieldattrlist */ +#line 1567 "perly.y" { parser->in_my = 0; if((ps[0].val.opval)) @@ -2182,8 +2209,8 @@ case 2: /* @1: %empty */ break; - case 298: /* $@24: %empty */ -#line 1562 "perly.y" + case 302: /* $@24: %empty */ +#line 1574 "perly.y" { parser->in_my = 0; if((ps[-1].val.opval)) @@ -2194,8 +2221,8 @@ case 2: /* @1: %empty */ break; - case 299: /* fielddecl: KW_FIELD fieldvar optfieldattrlist ASSIGNOP $@24 term */ -#line 1570 "perly.y" + case 303: /* fielddecl: KW_FIELD fieldvar optfieldattrlist ASSIGNOP $@24 term */ +#line 1582 "perly.y" { class_set_field_defop((PADNAME *)(ps[-4].val.pval), (ps[-2].val.ival), (ps[0].val.opval)); LEAVE; @@ -2204,122 +2231,122 @@ case 2: /* @1: %empty */ break; - case 305: /* optrepl: PERLY_SLASH expr */ -#line 1590 "perly.y" + case 309: /* optrepl: PERLY_SLASH expr */ +#line 1602 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; - case 306: /* my_scalar: scalar */ -#line 1596 "perly.y" + case 310: /* my_scalar: scalar */ +#line 1608 "perly.y" { parser->in_my = 0; (yyval.opval) = my((ps[0].val.opval)); } break; - case 307: /* list_of_scalars: list_of_scalars PERLY_COMMA */ -#line 1601 "perly.y" + case 311: /* list_of_scalars: list_of_scalars PERLY_COMMA */ +#line 1613 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; - case 308: /* list_of_scalars: list_of_scalars PERLY_COMMA scalar */ -#line 1603 "perly.y" + case 312: /* list_of_scalars: list_of_scalars PERLY_COMMA scalar */ +#line 1615 "perly.y" { (yyval.opval) = op_append_elem(OP_LIST, (ps[-2].val.opval), (ps[0].val.opval)); } break; - case 310: /* my_list_of_scalars: list_of_scalars */ -#line 1610 "perly.y" + case 314: /* my_list_of_scalars: list_of_scalars */ +#line 1622 "perly.y" { parser->in_my = 0; (yyval.opval) = (ps[0].val.opval); } break; - case 318: /* amper: PERLY_AMPERSAND indirob */ -#line 1627 "perly.y" + case 322: /* amper: PERLY_AMPERSAND indirob */ +#line 1639 "perly.y" { (yyval.opval) = newCVREF((ps[-1].val.ival),(ps[0].val.opval)); } break; - case 319: /* scalar: PERLY_DOLLAR indirob */ -#line 1631 "perly.y" + case 323: /* scalar: PERLY_DOLLAR indirob */ +#line 1643 "perly.y" { (yyval.opval) = newSVREF((ps[0].val.opval)); } break; - case 320: /* ary: PERLY_SNAIL indirob */ -#line 1635 "perly.y" + case 324: /* ary: PERLY_SNAIL indirob */ +#line 1647 "perly.y" { (yyval.opval) = newAVREF((ps[0].val.opval)); if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival); } break; - case 321: /* hsh: PERLY_PERCENT_SIGN indirob */ -#line 1641 "perly.y" + case 325: /* hsh: PERLY_PERCENT_SIGN indirob */ +#line 1653 "perly.y" { (yyval.opval) = newHVREF((ps[0].val.opval)); if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival); } break; - case 322: /* arylen: DOLSHARP indirob */ -#line 1647 "perly.y" + case 326: /* arylen: DOLSHARP indirob */ +#line 1659 "perly.y" { (yyval.opval) = newAVREF((ps[0].val.opval)); } break; - case 323: /* arylen: term ARROW DOLSHARP PERLY_STAR */ -#line 1649 "perly.y" + case 327: /* arylen: term ARROW DOLSHARP PERLY_STAR */ +#line 1661 "perly.y" { (yyval.opval) = newAVREF((ps[-3].val.opval)); } break; - case 324: /* star: PERLY_STAR indirob */ -#line 1653 "perly.y" + case 328: /* star: PERLY_STAR indirob */ +#line 1665 "perly.y" { (yyval.opval) = newGVREF(0,(ps[0].val.opval)); } break; - case 326: /* sliceme: term ARROW PERLY_SNAIL */ -#line 1658 "perly.y" + case 330: /* sliceme: term ARROW PERLY_SNAIL */ +#line 1670 "perly.y" { (yyval.opval) = newAVREF((ps[-2].val.opval)); } break; - case 328: /* kvslice: term ARROW PERLY_PERCENT_SIGN */ -#line 1663 "perly.y" + case 332: /* kvslice: term ARROW PERLY_PERCENT_SIGN */ +#line 1675 "perly.y" { (yyval.opval) = newHVREF((ps[-2].val.opval)); } break; - case 330: /* gelem: term ARROW PERLY_STAR */ -#line 1668 "perly.y" + case 334: /* gelem: term ARROW PERLY_STAR */ +#line 1680 "perly.y" { (yyval.opval) = newGVREF(0,(ps[-2].val.opval)); } break; - case 331: /* indirob: BAREWORD */ -#line 1673 "perly.y" + case 335: /* indirob: BAREWORD */ +#line 1685 "perly.y" { (yyval.opval) = scalar((ps[0].val.opval)); } break; - case 332: /* indirob: scalar */ -#line 1675 "perly.y" + case 336: /* indirob: scalar */ +#line 1687 "perly.y" { (yyval.opval) = scalar((ps[0].val.opval)); } break; - case 333: /* indirob: block */ -#line 1677 "perly.y" + case 337: /* indirob: block */ +#line 1689 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; - case 334: /* indirob: PRIVATEREF */ -#line 1680 "perly.y" + case 338: /* indirob: PRIVATEREF */ +#line 1692 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; @@ -2331,6 +2358,6 @@ case 2: /* @1: %empty */ /* Generated from: - * 9fc11f4af92f701d8d7909a9cd9dc52e01098c42c2504fb84c15e1d1e72f4803 perly.y + * 823630846fc59cc2a19502726ec723b568eabded55fdc5e9722c600e1098779e perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.h b/perly.h index 49877e206ea2..27ab872b4e94 100644 --- a/perly.h +++ b/perly.h @@ -98,94 +98,97 @@ extern int yydebug; KW_UNTIL = 292, /* KW_UNTIL */ KW_WHILE = 293, /* KW_WHILE */ KW_CONTINUE = 294, /* KW_CONTINUE */ - KW_TRY = 295, /* KW_TRY */ - KW_CATCH = 296, /* KW_CATCH */ - KW_FINALLY = 297, /* KW_FINALLY */ - KW_DEFER = 298, /* KW_DEFER */ - KW_REQUIRE = 299, /* KW_REQUIRE */ - KW_DO = 300, /* KW_DO */ - KW_USE_or_NO = 301, /* KW_USE_or_NO */ - KW_SUB_named = 302, /* KW_SUB_named */ - KW_SUB_named_sig = 303, /* KW_SUB_named_sig */ - KW_SUB_anon = 304, /* KW_SUB_anon */ - KW_SUB_anon_sig = 305, /* KW_SUB_anon_sig */ - KW_METHOD_named = 306, /* KW_METHOD_named */ - KW_METHOD_anon = 307, /* KW_METHOD_anon */ - BAREWORD = 308, /* BAREWORD */ - METHCALL0 = 309, /* METHCALL0 */ - METHCALL = 310, /* METHCALL */ - THING = 311, /* THING */ - PMFUNC = 312, /* PMFUNC */ - PRIVATEREF = 313, /* PRIVATEREF */ - QWLIST = 314, /* QWLIST */ - FUNC0OP = 315, /* FUNC0OP */ - FUNC0SUB = 316, /* FUNC0SUB */ - UNIOPSUB = 317, /* UNIOPSUB */ - LSTOPSUB = 318, /* LSTOPSUB */ - PLUGEXPR = 319, /* PLUGEXPR */ - PLUGSTMT = 320, /* PLUGSTMT */ - LABEL = 321, /* LABEL */ - LOOPEX = 322, /* LOOPEX */ - DOTDOT = 323, /* DOTDOT */ - YADAYADA = 324, /* YADAYADA */ - FUNC0 = 325, /* FUNC0 */ - FUNC1 = 326, /* FUNC1 */ - FUNC = 327, /* FUNC */ - UNIOP = 328, /* UNIOP */ - LSTOP = 329, /* LSTOP */ - POWOP = 330, /* POWOP */ - MULOP = 331, /* MULOP */ - ADDOP = 332, /* ADDOP */ - DOLSHARP = 333, /* DOLSHARP */ - HASHBRACK = 334, /* HASHBRACK */ - NOAMP = 335, /* NOAMP */ - COLONATTR = 336, /* COLONATTR */ - FORMLBRACK = 337, /* FORMLBRACK */ - FORMRBRACK = 338, /* FORMRBRACK */ - SUBLEXSTART = 339, /* SUBLEXSTART */ - SUBLEXEND = 340, /* SUBLEXEND */ - PHASER = 341, /* PHASER */ - PREC_LOW = 342, /* PREC_LOW */ - PLUGIN_LOW_OP = 343, /* PLUGIN_LOW_OP */ - OROP = 344, /* OROP */ - PLUGIN_LOGICAL_OR_LOW_OP = 345, /* PLUGIN_LOGICAL_OR_LOW_OP */ - ANDOP = 346, /* ANDOP */ - PLUGIN_LOGICAL_AND_LOW_OP = 347, /* PLUGIN_LOGICAL_AND_LOW_OP */ - NOTOP = 348, /* NOTOP */ - ASSIGNOP = 349, /* ASSIGNOP */ - PLUGIN_ASSIGN_OP = 350, /* PLUGIN_ASSIGN_OP */ - PERLY_QUESTION_MARK = 351, /* PERLY_QUESTION_MARK */ - PERLY_COLON = 352, /* PERLY_COLON */ - OROR = 353, /* OROR */ - DORDOR = 354, /* DORDOR */ - PLUGIN_LOGICAL_OR_OP = 355, /* PLUGIN_LOGICAL_OR_OP */ - ANDAND = 356, /* ANDAND */ - PLUGIN_LOGICAL_AND_OP = 357, /* PLUGIN_LOGICAL_AND_OP */ - BITOROP = 358, /* BITOROP */ - BITANDOP = 359, /* BITANDOP */ - CHEQOP = 360, /* CHEQOP */ - NCEQOP = 361, /* NCEQOP */ - CHRELOP = 362, /* CHRELOP */ - NCRELOP = 363, /* NCRELOP */ - PLUGIN_REL_OP = 364, /* PLUGIN_REL_OP */ - SHIFTOP = 365, /* SHIFTOP */ - PLUGIN_ADD_OP = 366, /* PLUGIN_ADD_OP */ - PLUGIN_MUL_OP = 367, /* PLUGIN_MUL_OP */ - MATCHOP = 368, /* MATCHOP */ - PERLY_EXCLAMATION_MARK = 369, /* PERLY_EXCLAMATION_MARK */ - PERLY_TILDE = 370, /* PERLY_TILDE */ - UMINUS = 371, /* UMINUS */ - REFGEN = 372, /* REFGEN */ - PLUGIN_POW_OP = 373, /* PLUGIN_POW_OP */ - PREINC = 374, /* PREINC */ - PREDEC = 375, /* PREDEC */ - POSTINC = 376, /* POSTINC */ - POSTDEC = 377, /* POSTDEC */ - POSTJOIN = 378, /* POSTJOIN */ - PLUGIN_HIGH_OP = 379, /* PLUGIN_HIGH_OP */ - ARROW = 380, /* ARROW */ - PERLY_PAREN_CLOSE = 381, /* PERLY_PAREN_CLOSE */ - PERLY_PAREN_OPEN = 382 /* PERLY_PAREN_OPEN */ + KW_GIVEN = 295, /* KW_GIVEN */ + KW_WHEN = 296, /* KW_WHEN */ + KW_DEFAULT = 297, /* KW_DEFAULT */ + KW_TRY = 298, /* KW_TRY */ + KW_CATCH = 299, /* KW_CATCH */ + KW_FINALLY = 300, /* KW_FINALLY */ + KW_DEFER = 301, /* KW_DEFER */ + KW_REQUIRE = 302, /* KW_REQUIRE */ + KW_DO = 303, /* KW_DO */ + KW_USE_or_NO = 304, /* KW_USE_or_NO */ + KW_SUB_named = 305, /* KW_SUB_named */ + KW_SUB_named_sig = 306, /* KW_SUB_named_sig */ + KW_SUB_anon = 307, /* KW_SUB_anon */ + KW_SUB_anon_sig = 308, /* KW_SUB_anon_sig */ + KW_METHOD_named = 309, /* KW_METHOD_named */ + KW_METHOD_anon = 310, /* KW_METHOD_anon */ + BAREWORD = 311, /* BAREWORD */ + METHCALL0 = 312, /* METHCALL0 */ + METHCALL = 313, /* METHCALL */ + THING = 314, /* THING */ + PMFUNC = 315, /* PMFUNC */ + PRIVATEREF = 316, /* PRIVATEREF */ + QWLIST = 317, /* QWLIST */ + FUNC0OP = 318, /* FUNC0OP */ + FUNC0SUB = 319, /* FUNC0SUB */ + UNIOPSUB = 320, /* UNIOPSUB */ + LSTOPSUB = 321, /* LSTOPSUB */ + PLUGEXPR = 322, /* PLUGEXPR */ + PLUGSTMT = 323, /* PLUGSTMT */ + LABEL = 324, /* LABEL */ + LOOPEX = 325, /* LOOPEX */ + DOTDOT = 326, /* DOTDOT */ + YADAYADA = 327, /* YADAYADA */ + FUNC0 = 328, /* FUNC0 */ + FUNC1 = 329, /* FUNC1 */ + FUNC = 330, /* FUNC */ + UNIOP = 331, /* UNIOP */ + LSTOP = 332, /* LSTOP */ + POWOP = 333, /* POWOP */ + MULOP = 334, /* MULOP */ + ADDOP = 335, /* ADDOP */ + DOLSHARP = 336, /* DOLSHARP */ + HASHBRACK = 337, /* HASHBRACK */ + NOAMP = 338, /* NOAMP */ + COLONATTR = 339, /* COLONATTR */ + FORMLBRACK = 340, /* FORMLBRACK */ + FORMRBRACK = 341, /* FORMRBRACK */ + SUBLEXSTART = 342, /* SUBLEXSTART */ + SUBLEXEND = 343, /* SUBLEXEND */ + PHASER = 344, /* PHASER */ + PREC_LOW = 345, /* PREC_LOW */ + PLUGIN_LOW_OP = 346, /* PLUGIN_LOW_OP */ + OROP = 347, /* OROP */ + PLUGIN_LOGICAL_OR_LOW_OP = 348, /* PLUGIN_LOGICAL_OR_LOW_OP */ + ANDOP = 349, /* ANDOP */ + PLUGIN_LOGICAL_AND_LOW_OP = 350, /* PLUGIN_LOGICAL_AND_LOW_OP */ + NOTOP = 351, /* NOTOP */ + ASSIGNOP = 352, /* ASSIGNOP */ + PLUGIN_ASSIGN_OP = 353, /* PLUGIN_ASSIGN_OP */ + PERLY_QUESTION_MARK = 354, /* PERLY_QUESTION_MARK */ + PERLY_COLON = 355, /* PERLY_COLON */ + OROR = 356, /* OROR */ + DORDOR = 357, /* DORDOR */ + PLUGIN_LOGICAL_OR_OP = 358, /* PLUGIN_LOGICAL_OR_OP */ + ANDAND = 359, /* ANDAND */ + PLUGIN_LOGICAL_AND_OP = 360, /* PLUGIN_LOGICAL_AND_OP */ + BITOROP = 361, /* BITOROP */ + BITANDOP = 362, /* BITANDOP */ + CHEQOP = 363, /* CHEQOP */ + NCEQOP = 364, /* NCEQOP */ + CHRELOP = 365, /* CHRELOP */ + NCRELOP = 366, /* NCRELOP */ + PLUGIN_REL_OP = 367, /* PLUGIN_REL_OP */ + SHIFTOP = 368, /* SHIFTOP */ + PLUGIN_ADD_OP = 369, /* PLUGIN_ADD_OP */ + PLUGIN_MUL_OP = 370, /* PLUGIN_MUL_OP */ + MATCHOP = 371, /* MATCHOP */ + PERLY_EXCLAMATION_MARK = 372, /* PERLY_EXCLAMATION_MARK */ + PERLY_TILDE = 373, /* PERLY_TILDE */ + UMINUS = 374, /* UMINUS */ + REFGEN = 375, /* REFGEN */ + PLUGIN_POW_OP = 376, /* PLUGIN_POW_OP */ + PREINC = 377, /* PREINC */ + PREDEC = 378, /* PREDEC */ + POSTINC = 379, /* POSTINC */ + POSTDEC = 380, /* POSTDEC */ + POSTJOIN = 381, /* POSTJOIN */ + PLUGIN_HIGH_OP = 382, /* PLUGIN_HIGH_OP */ + ARROW = 383, /* ARROW */ + PERLY_PAREN_CLOSE = 384, /* PERLY_PAREN_CLOSE */ + PERLY_PAREN_OPEN = 385 /* PERLY_PAREN_OPEN */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -240,6 +243,6 @@ int yyparse (void); /* Generated from: - * 9fc11f4af92f701d8d7909a9cd9dc52e01098c42c2504fb84c15e1d1e72f4803 perly.y + * 823630846fc59cc2a19502726ec723b568eabded55fdc5e9722c600e1098779e perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.tab b/perly.tab index 42292d0eb14b..f6fbc9b79cf1 100644 --- a/perly.tab +++ b/perly.tab @@ -48,208 +48,211 @@ enum yysymbol_kind_t YYSYMBOL_KW_UNTIL = 37, /* KW_UNTIL */ YYSYMBOL_KW_WHILE = 38, /* KW_WHILE */ YYSYMBOL_KW_CONTINUE = 39, /* KW_CONTINUE */ - YYSYMBOL_KW_TRY = 40, /* KW_TRY */ - YYSYMBOL_KW_CATCH = 41, /* KW_CATCH */ - YYSYMBOL_KW_FINALLY = 42, /* KW_FINALLY */ - YYSYMBOL_KW_DEFER = 43, /* KW_DEFER */ - YYSYMBOL_KW_REQUIRE = 44, /* KW_REQUIRE */ - YYSYMBOL_KW_DO = 45, /* KW_DO */ - YYSYMBOL_KW_USE_or_NO = 46, /* KW_USE_or_NO */ - YYSYMBOL_KW_SUB_named = 47, /* KW_SUB_named */ - YYSYMBOL_KW_SUB_named_sig = 48, /* KW_SUB_named_sig */ - YYSYMBOL_KW_SUB_anon = 49, /* KW_SUB_anon */ - YYSYMBOL_KW_SUB_anon_sig = 50, /* KW_SUB_anon_sig */ - YYSYMBOL_KW_METHOD_named = 51, /* KW_METHOD_named */ - YYSYMBOL_KW_METHOD_anon = 52, /* KW_METHOD_anon */ - YYSYMBOL_BAREWORD = 53, /* BAREWORD */ - YYSYMBOL_METHCALL0 = 54, /* METHCALL0 */ - YYSYMBOL_METHCALL = 55, /* METHCALL */ - YYSYMBOL_THING = 56, /* THING */ - YYSYMBOL_PMFUNC = 57, /* PMFUNC */ - YYSYMBOL_PRIVATEREF = 58, /* PRIVATEREF */ - YYSYMBOL_QWLIST = 59, /* QWLIST */ - YYSYMBOL_FUNC0OP = 60, /* FUNC0OP */ - YYSYMBOL_FUNC0SUB = 61, /* FUNC0SUB */ - YYSYMBOL_UNIOPSUB = 62, /* UNIOPSUB */ - YYSYMBOL_LSTOPSUB = 63, /* LSTOPSUB */ - YYSYMBOL_PLUGEXPR = 64, /* PLUGEXPR */ - YYSYMBOL_PLUGSTMT = 65, /* PLUGSTMT */ - YYSYMBOL_LABEL = 66, /* LABEL */ - YYSYMBOL_LOOPEX = 67, /* LOOPEX */ - YYSYMBOL_DOTDOT = 68, /* DOTDOT */ - YYSYMBOL_YADAYADA = 69, /* YADAYADA */ - YYSYMBOL_FUNC0 = 70, /* FUNC0 */ - YYSYMBOL_FUNC1 = 71, /* FUNC1 */ - YYSYMBOL_FUNC = 72, /* FUNC */ - YYSYMBOL_UNIOP = 73, /* UNIOP */ - YYSYMBOL_LSTOP = 74, /* LSTOP */ - YYSYMBOL_POWOP = 75, /* POWOP */ - YYSYMBOL_MULOP = 76, /* MULOP */ - YYSYMBOL_ADDOP = 77, /* ADDOP */ - YYSYMBOL_DOLSHARP = 78, /* DOLSHARP */ - YYSYMBOL_HASHBRACK = 79, /* HASHBRACK */ - YYSYMBOL_NOAMP = 80, /* NOAMP */ - YYSYMBOL_COLONATTR = 81, /* COLONATTR */ - YYSYMBOL_FORMLBRACK = 82, /* FORMLBRACK */ - YYSYMBOL_FORMRBRACK = 83, /* FORMRBRACK */ - YYSYMBOL_SUBLEXSTART = 84, /* SUBLEXSTART */ - YYSYMBOL_SUBLEXEND = 85, /* SUBLEXEND */ - YYSYMBOL_PHASER = 86, /* PHASER */ - YYSYMBOL_PREC_LOW = 87, /* PREC_LOW */ - YYSYMBOL_PLUGIN_LOW_OP = 88, /* PLUGIN_LOW_OP */ - YYSYMBOL_OROP = 89, /* OROP */ - YYSYMBOL_PLUGIN_LOGICAL_OR_LOW_OP = 90, /* PLUGIN_LOGICAL_OR_LOW_OP */ - YYSYMBOL_ANDOP = 91, /* ANDOP */ - YYSYMBOL_PLUGIN_LOGICAL_AND_LOW_OP = 92, /* PLUGIN_LOGICAL_AND_LOW_OP */ - YYSYMBOL_NOTOP = 93, /* NOTOP */ - YYSYMBOL_ASSIGNOP = 94, /* ASSIGNOP */ - YYSYMBOL_PLUGIN_ASSIGN_OP = 95, /* PLUGIN_ASSIGN_OP */ - YYSYMBOL_PERLY_QUESTION_MARK = 96, /* PERLY_QUESTION_MARK */ - YYSYMBOL_PERLY_COLON = 97, /* PERLY_COLON */ - YYSYMBOL_OROR = 98, /* OROR */ - YYSYMBOL_DORDOR = 99, /* DORDOR */ - YYSYMBOL_PLUGIN_LOGICAL_OR_OP = 100, /* PLUGIN_LOGICAL_OR_OP */ - YYSYMBOL_ANDAND = 101, /* ANDAND */ - YYSYMBOL_PLUGIN_LOGICAL_AND_OP = 102, /* PLUGIN_LOGICAL_AND_OP */ - YYSYMBOL_BITOROP = 103, /* BITOROP */ - YYSYMBOL_BITANDOP = 104, /* BITANDOP */ - YYSYMBOL_CHEQOP = 105, /* CHEQOP */ - YYSYMBOL_NCEQOP = 106, /* NCEQOP */ - YYSYMBOL_CHRELOP = 107, /* CHRELOP */ - YYSYMBOL_NCRELOP = 108, /* NCRELOP */ - YYSYMBOL_PLUGIN_REL_OP = 109, /* PLUGIN_REL_OP */ - YYSYMBOL_SHIFTOP = 110, /* SHIFTOP */ - YYSYMBOL_PLUGIN_ADD_OP = 111, /* PLUGIN_ADD_OP */ - YYSYMBOL_PLUGIN_MUL_OP = 112, /* PLUGIN_MUL_OP */ - YYSYMBOL_MATCHOP = 113, /* MATCHOP */ - YYSYMBOL_PERLY_EXCLAMATION_MARK = 114, /* PERLY_EXCLAMATION_MARK */ - YYSYMBOL_PERLY_TILDE = 115, /* PERLY_TILDE */ - YYSYMBOL_UMINUS = 116, /* UMINUS */ - YYSYMBOL_REFGEN = 117, /* REFGEN */ - YYSYMBOL_PLUGIN_POW_OP = 118, /* PLUGIN_POW_OP */ - YYSYMBOL_PREINC = 119, /* PREINC */ - YYSYMBOL_PREDEC = 120, /* PREDEC */ - YYSYMBOL_POSTINC = 121, /* POSTINC */ - YYSYMBOL_POSTDEC = 122, /* POSTDEC */ - YYSYMBOL_POSTJOIN = 123, /* POSTJOIN */ - YYSYMBOL_PLUGIN_HIGH_OP = 124, /* PLUGIN_HIGH_OP */ - YYSYMBOL_ARROW = 125, /* ARROW */ - YYSYMBOL_PERLY_PAREN_CLOSE = 126, /* PERLY_PAREN_CLOSE */ - YYSYMBOL_PERLY_PAREN_OPEN = 127, /* PERLY_PAREN_OPEN */ - YYSYMBOL_YYACCEPT = 128, /* $accept */ - YYSYMBOL_grammar = 129, /* grammar */ - YYSYMBOL_130_1 = 130, /* @1 */ - YYSYMBOL_131_2 = 131, /* @2 */ - YYSYMBOL_132_3 = 132, /* @3 */ - YYSYMBOL_133_4 = 133, /* @4 */ - YYSYMBOL_134_5 = 134, /* @5 */ - YYSYMBOL_135_6 = 135, /* @6 */ - YYSYMBOL_136_7 = 136, /* @7 */ - YYSYMBOL_sigsub_or_method_named = 137, /* sigsub_or_method_named */ - YYSYMBOL_block = 138, /* block */ - YYSYMBOL_empty = 139, /* empty */ - YYSYMBOL_formblock = 140, /* formblock */ - YYSYMBOL_remember = 141, /* remember */ - YYSYMBOL_mblock = 142, /* mblock */ - YYSYMBOL_mremember = 143, /* mremember */ - YYSYMBOL_catch_paren = 144, /* catch_paren */ - YYSYMBOL_145_8 = 145, /* $@8 */ - YYSYMBOL_146_9 = 146, /* $@9 */ - YYSYMBOL_stmtseq = 147, /* stmtseq */ - YYSYMBOL_formstmtseq = 148, /* formstmtseq */ - YYSYMBOL_fullstmt = 149, /* fullstmt */ - YYSYMBOL_labfullstmt = 150, /* labfullstmt */ - YYSYMBOL_barestmt = 151, /* barestmt */ - YYSYMBOL_152_10 = 152, /* $@10 */ - YYSYMBOL_153_11 = 153, /* $@11 */ - YYSYMBOL_154_12 = 154, /* $@12 */ - YYSYMBOL_155_13 = 155, /* $@13 */ - YYSYMBOL_156_14 = 156, /* $@14 */ - YYSYMBOL_157_15 = 157, /* $@15 */ - YYSYMBOL_158_16 = 158, /* @16 */ - YYSYMBOL_159_17 = 159, /* $@17 */ - YYSYMBOL_160_18 = 160, /* $@18 */ - YYSYMBOL_161_19 = 161, /* $@19 */ - YYSYMBOL_formline = 162, /* formline */ - YYSYMBOL_formarg = 163, /* formarg */ - YYSYMBOL_condition = 164, /* condition */ - YYSYMBOL_sideff = 165, /* sideff */ - YYSYMBOL_else = 166, /* else */ - YYSYMBOL_cont = 167, /* cont */ - YYSYMBOL_finally = 168, /* finally */ - YYSYMBOL_mintro = 169, /* mintro */ - YYSYMBOL_nexpr = 170, /* nexpr */ - YYSYMBOL_texpr = 171, /* texpr */ - YYSYMBOL_iexpr = 172, /* iexpr */ - YYSYMBOL_mexpr = 173, /* mexpr */ - YYSYMBOL_mnexpr = 174, /* mnexpr */ - YYSYMBOL_formname = 175, /* formname */ - YYSYMBOL_startsub = 176, /* startsub */ - YYSYMBOL_startanonsub = 177, /* startanonsub */ - YYSYMBOL_startanonmethod = 178, /* startanonmethod */ - YYSYMBOL_startformsub = 179, /* startformsub */ - YYSYMBOL_subname = 180, /* subname */ - YYSYMBOL_proto = 181, /* proto */ - YYSYMBOL_subattrlist = 182, /* subattrlist */ - YYSYMBOL_myattrlist = 183, /* myattrlist */ - YYSYMBOL_sigvarname = 184, /* sigvarname */ - YYSYMBOL_sigslurpsigil = 185, /* sigslurpsigil */ - YYSYMBOL_sigslurpelem = 186, /* sigslurpelem */ - YYSYMBOL_sigdefault = 187, /* sigdefault */ - YYSYMBOL_sigscalarelem = 188, /* sigscalarelem */ - YYSYMBOL_sigelem = 189, /* sigelem */ - YYSYMBOL_siglist = 190, /* siglist */ - YYSYMBOL_optsiglist = 191, /* optsiglist */ - YYSYMBOL_optsubsignature = 192, /* optsubsignature */ - YYSYMBOL_subsignature = 193, /* subsignature */ - YYSYMBOL_subsigguts = 194, /* subsigguts */ - YYSYMBOL_195_20 = 195, /* $@20 */ - YYSYMBOL_optsubbody = 196, /* optsubbody */ - YYSYMBOL_subbody = 197, /* subbody */ - YYSYMBOL_optsigsubbody = 198, /* optsigsubbody */ - YYSYMBOL_sigsubbody = 199, /* sigsubbody */ - YYSYMBOL_200_21 = 200, /* $@21 */ - YYSYMBOL_expr = 201, /* expr */ - YYSYMBOL_listexpr = 202, /* listexpr */ - YYSYMBOL_listop = 203, /* listop */ - YYSYMBOL_204_22 = 204, /* @22 */ - YYSYMBOL_methodname = 205, /* methodname */ - YYSYMBOL_subscripted = 206, /* subscripted */ - YYSYMBOL_termbinop = 207, /* termbinop */ - YYSYMBOL_termrelop = 208, /* termrelop */ - YYSYMBOL_relopchain = 209, /* relopchain */ - YYSYMBOL_termeqop = 210, /* termeqop */ - YYSYMBOL_eqopchain = 211, /* eqopchain */ - YYSYMBOL_termunop = 212, /* termunop */ - YYSYMBOL_anonymous = 213, /* anonymous */ - YYSYMBOL_termdo = 214, /* termdo */ - YYSYMBOL_term = 215, /* term */ - YYSYMBOL_216_23 = 216, /* @23 */ - YYSYMBOL_myattrterm = 217, /* myattrterm */ - YYSYMBOL_myterm = 218, /* myterm */ - YYSYMBOL_fieldvar = 219, /* fieldvar */ - YYSYMBOL_optfieldattrlist = 220, /* optfieldattrlist */ - YYSYMBOL_fielddecl = 221, /* fielddecl */ - YYSYMBOL_222_24 = 222, /* $@24 */ - YYSYMBOL_optlistexpr = 223, /* optlistexpr */ - YYSYMBOL_optexpr = 224, /* optexpr */ - YYSYMBOL_optrepl = 225, /* optrepl */ - YYSYMBOL_my_scalar = 226, /* my_scalar */ - YYSYMBOL_list_of_scalars = 227, /* list_of_scalars */ - YYSYMBOL_my_list_of_scalars = 228, /* my_list_of_scalars */ - YYSYMBOL_my_var = 229, /* my_var */ - YYSYMBOL_refgen_topic = 230, /* refgen_topic */ - YYSYMBOL_my_refgen = 231, /* my_refgen */ - YYSYMBOL_amper = 232, /* amper */ - YYSYMBOL_scalar = 233, /* scalar */ - YYSYMBOL_ary = 234, /* ary */ - YYSYMBOL_hsh = 235, /* hsh */ - YYSYMBOL_arylen = 236, /* arylen */ - YYSYMBOL_star = 237, /* star */ - YYSYMBOL_sliceme = 238, /* sliceme */ - YYSYMBOL_kvslice = 239, /* kvslice */ - YYSYMBOL_gelem = 240, /* gelem */ - YYSYMBOL_indirob = 241 /* indirob */ + YYSYMBOL_KW_GIVEN = 40, /* KW_GIVEN */ + YYSYMBOL_KW_WHEN = 41, /* KW_WHEN */ + YYSYMBOL_KW_DEFAULT = 42, /* KW_DEFAULT */ + YYSYMBOL_KW_TRY = 43, /* KW_TRY */ + YYSYMBOL_KW_CATCH = 44, /* KW_CATCH */ + YYSYMBOL_KW_FINALLY = 45, /* KW_FINALLY */ + YYSYMBOL_KW_DEFER = 46, /* KW_DEFER */ + YYSYMBOL_KW_REQUIRE = 47, /* KW_REQUIRE */ + YYSYMBOL_KW_DO = 48, /* KW_DO */ + YYSYMBOL_KW_USE_or_NO = 49, /* KW_USE_or_NO */ + YYSYMBOL_KW_SUB_named = 50, /* KW_SUB_named */ + YYSYMBOL_KW_SUB_named_sig = 51, /* KW_SUB_named_sig */ + YYSYMBOL_KW_SUB_anon = 52, /* KW_SUB_anon */ + YYSYMBOL_KW_SUB_anon_sig = 53, /* KW_SUB_anon_sig */ + YYSYMBOL_KW_METHOD_named = 54, /* KW_METHOD_named */ + YYSYMBOL_KW_METHOD_anon = 55, /* KW_METHOD_anon */ + YYSYMBOL_BAREWORD = 56, /* BAREWORD */ + YYSYMBOL_METHCALL0 = 57, /* METHCALL0 */ + YYSYMBOL_METHCALL = 58, /* METHCALL */ + YYSYMBOL_THING = 59, /* THING */ + YYSYMBOL_PMFUNC = 60, /* PMFUNC */ + YYSYMBOL_PRIVATEREF = 61, /* PRIVATEREF */ + YYSYMBOL_QWLIST = 62, /* QWLIST */ + YYSYMBOL_FUNC0OP = 63, /* FUNC0OP */ + YYSYMBOL_FUNC0SUB = 64, /* FUNC0SUB */ + YYSYMBOL_UNIOPSUB = 65, /* UNIOPSUB */ + YYSYMBOL_LSTOPSUB = 66, /* LSTOPSUB */ + YYSYMBOL_PLUGEXPR = 67, /* PLUGEXPR */ + YYSYMBOL_PLUGSTMT = 68, /* PLUGSTMT */ + YYSYMBOL_LABEL = 69, /* LABEL */ + YYSYMBOL_LOOPEX = 70, /* LOOPEX */ + YYSYMBOL_DOTDOT = 71, /* DOTDOT */ + YYSYMBOL_YADAYADA = 72, /* YADAYADA */ + YYSYMBOL_FUNC0 = 73, /* FUNC0 */ + YYSYMBOL_FUNC1 = 74, /* FUNC1 */ + YYSYMBOL_FUNC = 75, /* FUNC */ + YYSYMBOL_UNIOP = 76, /* UNIOP */ + YYSYMBOL_LSTOP = 77, /* LSTOP */ + YYSYMBOL_POWOP = 78, /* POWOP */ + YYSYMBOL_MULOP = 79, /* MULOP */ + YYSYMBOL_ADDOP = 80, /* ADDOP */ + YYSYMBOL_DOLSHARP = 81, /* DOLSHARP */ + YYSYMBOL_HASHBRACK = 82, /* HASHBRACK */ + YYSYMBOL_NOAMP = 83, /* NOAMP */ + YYSYMBOL_COLONATTR = 84, /* COLONATTR */ + YYSYMBOL_FORMLBRACK = 85, /* FORMLBRACK */ + YYSYMBOL_FORMRBRACK = 86, /* FORMRBRACK */ + YYSYMBOL_SUBLEXSTART = 87, /* SUBLEXSTART */ + YYSYMBOL_SUBLEXEND = 88, /* SUBLEXEND */ + YYSYMBOL_PHASER = 89, /* PHASER */ + YYSYMBOL_PREC_LOW = 90, /* PREC_LOW */ + YYSYMBOL_PLUGIN_LOW_OP = 91, /* PLUGIN_LOW_OP */ + YYSYMBOL_OROP = 92, /* OROP */ + YYSYMBOL_PLUGIN_LOGICAL_OR_LOW_OP = 93, /* PLUGIN_LOGICAL_OR_LOW_OP */ + YYSYMBOL_ANDOP = 94, /* ANDOP */ + YYSYMBOL_PLUGIN_LOGICAL_AND_LOW_OP = 95, /* PLUGIN_LOGICAL_AND_LOW_OP */ + YYSYMBOL_NOTOP = 96, /* NOTOP */ + YYSYMBOL_ASSIGNOP = 97, /* ASSIGNOP */ + YYSYMBOL_PLUGIN_ASSIGN_OP = 98, /* PLUGIN_ASSIGN_OP */ + YYSYMBOL_PERLY_QUESTION_MARK = 99, /* PERLY_QUESTION_MARK */ + YYSYMBOL_PERLY_COLON = 100, /* PERLY_COLON */ + YYSYMBOL_OROR = 101, /* OROR */ + YYSYMBOL_DORDOR = 102, /* DORDOR */ + YYSYMBOL_PLUGIN_LOGICAL_OR_OP = 103, /* PLUGIN_LOGICAL_OR_OP */ + YYSYMBOL_ANDAND = 104, /* ANDAND */ + YYSYMBOL_PLUGIN_LOGICAL_AND_OP = 105, /* PLUGIN_LOGICAL_AND_OP */ + YYSYMBOL_BITOROP = 106, /* BITOROP */ + YYSYMBOL_BITANDOP = 107, /* BITANDOP */ + YYSYMBOL_CHEQOP = 108, /* CHEQOP */ + YYSYMBOL_NCEQOP = 109, /* NCEQOP */ + YYSYMBOL_CHRELOP = 110, /* CHRELOP */ + YYSYMBOL_NCRELOP = 111, /* NCRELOP */ + YYSYMBOL_PLUGIN_REL_OP = 112, /* PLUGIN_REL_OP */ + YYSYMBOL_SHIFTOP = 113, /* SHIFTOP */ + YYSYMBOL_PLUGIN_ADD_OP = 114, /* PLUGIN_ADD_OP */ + YYSYMBOL_PLUGIN_MUL_OP = 115, /* PLUGIN_MUL_OP */ + YYSYMBOL_MATCHOP = 116, /* MATCHOP */ + YYSYMBOL_PERLY_EXCLAMATION_MARK = 117, /* PERLY_EXCLAMATION_MARK */ + YYSYMBOL_PERLY_TILDE = 118, /* PERLY_TILDE */ + YYSYMBOL_UMINUS = 119, /* UMINUS */ + YYSYMBOL_REFGEN = 120, /* REFGEN */ + YYSYMBOL_PLUGIN_POW_OP = 121, /* PLUGIN_POW_OP */ + YYSYMBOL_PREINC = 122, /* PREINC */ + YYSYMBOL_PREDEC = 123, /* PREDEC */ + YYSYMBOL_POSTINC = 124, /* POSTINC */ + YYSYMBOL_POSTDEC = 125, /* POSTDEC */ + YYSYMBOL_POSTJOIN = 126, /* POSTJOIN */ + YYSYMBOL_PLUGIN_HIGH_OP = 127, /* PLUGIN_HIGH_OP */ + YYSYMBOL_ARROW = 128, /* ARROW */ + YYSYMBOL_PERLY_PAREN_CLOSE = 129, /* PERLY_PAREN_CLOSE */ + YYSYMBOL_PERLY_PAREN_OPEN = 130, /* PERLY_PAREN_OPEN */ + YYSYMBOL_YYACCEPT = 131, /* $accept */ + YYSYMBOL_grammar = 132, /* grammar */ + YYSYMBOL_133_1 = 133, /* @1 */ + YYSYMBOL_134_2 = 134, /* @2 */ + YYSYMBOL_135_3 = 135, /* @3 */ + YYSYMBOL_136_4 = 136, /* @4 */ + YYSYMBOL_137_5 = 137, /* @5 */ + YYSYMBOL_138_6 = 138, /* @6 */ + YYSYMBOL_139_7 = 139, /* @7 */ + YYSYMBOL_sigsub_or_method_named = 140, /* sigsub_or_method_named */ + YYSYMBOL_block = 141, /* block */ + YYSYMBOL_empty = 142, /* empty */ + YYSYMBOL_formblock = 143, /* formblock */ + YYSYMBOL_remember = 144, /* remember */ + YYSYMBOL_mblock = 145, /* mblock */ + YYSYMBOL_mremember = 146, /* mremember */ + YYSYMBOL_catch_paren = 147, /* catch_paren */ + YYSYMBOL_148_8 = 148, /* $@8 */ + YYSYMBOL_149_9 = 149, /* $@9 */ + YYSYMBOL_stmtseq = 150, /* stmtseq */ + YYSYMBOL_formstmtseq = 151, /* formstmtseq */ + YYSYMBOL_fullstmt = 152, /* fullstmt */ + YYSYMBOL_labfullstmt = 153, /* labfullstmt */ + YYSYMBOL_barestmt = 154, /* barestmt */ + YYSYMBOL_155_10 = 155, /* $@10 */ + YYSYMBOL_156_11 = 156, /* $@11 */ + YYSYMBOL_157_12 = 157, /* $@12 */ + YYSYMBOL_158_13 = 158, /* $@13 */ + YYSYMBOL_159_14 = 159, /* $@14 */ + YYSYMBOL_160_15 = 160, /* $@15 */ + YYSYMBOL_161_16 = 161, /* @16 */ + YYSYMBOL_162_17 = 162, /* $@17 */ + YYSYMBOL_163_18 = 163, /* $@18 */ + YYSYMBOL_164_19 = 164, /* $@19 */ + YYSYMBOL_formline = 165, /* formline */ + YYSYMBOL_formarg = 166, /* formarg */ + YYSYMBOL_condition = 167, /* condition */ + YYSYMBOL_sideff = 168, /* sideff */ + YYSYMBOL_else = 169, /* else */ + YYSYMBOL_cont = 170, /* cont */ + YYSYMBOL_finally = 171, /* finally */ + YYSYMBOL_mintro = 172, /* mintro */ + YYSYMBOL_nexpr = 173, /* nexpr */ + YYSYMBOL_texpr = 174, /* texpr */ + YYSYMBOL_iexpr = 175, /* iexpr */ + YYSYMBOL_mexpr = 176, /* mexpr */ + YYSYMBOL_mnexpr = 177, /* mnexpr */ + YYSYMBOL_formname = 178, /* formname */ + YYSYMBOL_startsub = 179, /* startsub */ + YYSYMBOL_startanonsub = 180, /* startanonsub */ + YYSYMBOL_startanonmethod = 181, /* startanonmethod */ + YYSYMBOL_startformsub = 182, /* startformsub */ + YYSYMBOL_subname = 183, /* subname */ + YYSYMBOL_proto = 184, /* proto */ + YYSYMBOL_subattrlist = 185, /* subattrlist */ + YYSYMBOL_myattrlist = 186, /* myattrlist */ + YYSYMBOL_sigvarname = 187, /* sigvarname */ + YYSYMBOL_sigslurpsigil = 188, /* sigslurpsigil */ + YYSYMBOL_sigslurpelem = 189, /* sigslurpelem */ + YYSYMBOL_sigdefault = 190, /* sigdefault */ + YYSYMBOL_sigscalarelem = 191, /* sigscalarelem */ + YYSYMBOL_sigelem = 192, /* sigelem */ + YYSYMBOL_siglist = 193, /* siglist */ + YYSYMBOL_optsiglist = 194, /* optsiglist */ + YYSYMBOL_optsubsignature = 195, /* optsubsignature */ + YYSYMBOL_subsignature = 196, /* subsignature */ + YYSYMBOL_subsigguts = 197, /* subsigguts */ + YYSYMBOL_198_20 = 198, /* $@20 */ + YYSYMBOL_optsubbody = 199, /* optsubbody */ + YYSYMBOL_subbody = 200, /* subbody */ + YYSYMBOL_optsigsubbody = 201, /* optsigsubbody */ + YYSYMBOL_sigsubbody = 202, /* sigsubbody */ + YYSYMBOL_203_21 = 203, /* $@21 */ + YYSYMBOL_expr = 204, /* expr */ + YYSYMBOL_listexpr = 205, /* listexpr */ + YYSYMBOL_listop = 206, /* listop */ + YYSYMBOL_207_22 = 207, /* @22 */ + YYSYMBOL_methodname = 208, /* methodname */ + YYSYMBOL_subscripted = 209, /* subscripted */ + YYSYMBOL_termbinop = 210, /* termbinop */ + YYSYMBOL_termrelop = 211, /* termrelop */ + YYSYMBOL_relopchain = 212, /* relopchain */ + YYSYMBOL_termeqop = 213, /* termeqop */ + YYSYMBOL_eqopchain = 214, /* eqopchain */ + YYSYMBOL_termunop = 215, /* termunop */ + YYSYMBOL_anonymous = 216, /* anonymous */ + YYSYMBOL_termdo = 217, /* termdo */ + YYSYMBOL_term = 218, /* term */ + YYSYMBOL_219_23 = 219, /* @23 */ + YYSYMBOL_myattrterm = 220, /* myattrterm */ + YYSYMBOL_myterm = 221, /* myterm */ + YYSYMBOL_fieldvar = 222, /* fieldvar */ + YYSYMBOL_optfieldattrlist = 223, /* optfieldattrlist */ + YYSYMBOL_fielddecl = 224, /* fielddecl */ + YYSYMBOL_225_24 = 225, /* $@24 */ + YYSYMBOL_optlistexpr = 226, /* optlistexpr */ + YYSYMBOL_optexpr = 227, /* optexpr */ + YYSYMBOL_optrepl = 228, /* optrepl */ + YYSYMBOL_my_scalar = 229, /* my_scalar */ + YYSYMBOL_list_of_scalars = 230, /* list_of_scalars */ + YYSYMBOL_my_list_of_scalars = 231, /* my_list_of_scalars */ + YYSYMBOL_my_var = 232, /* my_var */ + YYSYMBOL_refgen_topic = 233, /* refgen_topic */ + YYSYMBOL_my_refgen = 234, /* my_refgen */ + YYSYMBOL_amper = 235, /* amper */ + YYSYMBOL_scalar = 236, /* scalar */ + YYSYMBOL_ary = 237, /* ary */ + YYSYMBOL_hsh = 238, /* hsh */ + YYSYMBOL_arylen = 239, /* arylen */ + YYSYMBOL_star = 240, /* star */ + YYSYMBOL_sliceme = 241, /* sliceme */ + YYSYMBOL_kvslice = 242, /* kvslice */ + YYSYMBOL_gelem = 243, /* gelem */ + YYSYMBOL_indirob = 244 /* indirob */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -258,19 +261,19 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; #define YYFINAL 16 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 3652 +#define YYLAST 3705 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 128 +#define YYNTOKENS 131 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 114 /* YYNRULES -- Number of rules. */ -#define YYNRULES 334 +#define YYNRULES 338 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 654 +#define YYNSTATES 670 /* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 382 +#define YYMAXUTOK 385 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -282,7 +285,7 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex. */ -static const yytype_int8 yytranslate[] = +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -322,47 +325,47 @@ static const yytype_int8 yytranslate[] = 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127 + 125, 126, 127, 128, 129, 130 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 160, 160, 159, 171, 170, 181, 180, 194, 193, - 207, 206, 220, 219, 230, 229, 243, 245, 250, 258, - 262, 269, 274, 281, 287, 291, 293, 290, 300, 301, - 311, 312, 321, 325, 329, 336, 346, 348, 361, 358, - 382, 377, 405, 404, 430, 441, 453, 452, 463, 469, - 475, 482, 490, 492, 489, 509, 514, 523, 530, 529, - 544, 552, 559, 558, 573, 580, 579, 595, 594, 614, - 618, 622, 626, 632, 640, 658, 659, 663, 667, 669, - 671, 673, 675, 677, 679, 686, 687, 692, 703, 704, - 709, 711, 716, 723, 724, 728, 732, 736, 741, 745, - 749, 750, 753, 759, 764, 769, 775, 776, 781, 782, - 787, 788, 795, 800, 802, 813, 815, 820, 822, 826, - 846, 847, 849, 862, 922, 924, 930, 932, 936, 942, - 943, 948, 949, 953, 957, 957, 1024, 1025, 1030, 1042, - 1043, 1048, 1047, 1060, 1062, 1064, 1066, 1068, 1072, 1074, - 1079, 1083, 1087, 1091, 1097, 1102, 1108, 1114, 1116, 1118, - 1121, 1120, 1134, 1135, 1139, 1143, 1146, 1151, 1156, 1159, - 1163, 1167, 1173, 1181, 1188, 1194, 1196, 1198, 1203, 1205, - 1207, 1209, 1211, 1213, 1218, 1220, 1222, 1224, 1226, 1228, - 1230, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, - 1252, 1254, 1256, 1258, 1260, 1264, 1266, 1270, 1272, 1274, - 1276, 1280, 1282, 1287, 1289, 1292, 1294, 1296, 1299, 1302, - 1313, 1316, 1324, 1326, 1328, 1331, 1334, 1342, 1344, 1348, - 1349, 1350, 1351, 1352, 1354, 1356, 1358, 1360, 1362, 1364, - 1366, 1368, 1370, 1372, 1374, 1376, 1378, 1388, 1398, 1408, - 1418, 1420, 1422, 1425, 1430, 1434, 1436, 1438, 1440, 1443, - 1445, 1448, 1450, 1452, 1454, 1456, 1458, 1460, 1462, 1464, - 1467, 1469, 1471, 1473, 1475, 1477, 1481, 1484, 1483, 1496, - 1497, 1498, 1503, 1505, 1507, 1509, 1514, 1516, 1519, 1521, - 1523, 1528, 1533, 1538, 1546, 1548, 1550, 1554, 1562, 1561, - 1579, 1580, 1584, 1585, 1589, 1590, 1595, 1600, 1602, 1606, - 1609, 1613, 1614, 1615, 1618, 1619, 1622, 1623, 1626, 1630, - 1634, 1640, 1646, 1648, 1652, 1656, 1657, 1661, 1662, 1666, - 1667, 1672, 1674, 1676, 1679 + 0, 161, 161, 160, 172, 171, 182, 181, 195, 194, + 208, 207, 221, 220, 231, 230, 244, 246, 251, 259, + 263, 270, 275, 282, 288, 292, 294, 291, 301, 302, + 312, 313, 322, 326, 330, 337, 347, 349, 362, 359, + 383, 378, 406, 405, 431, 442, 454, 453, 464, 470, + 476, 481, 483, 485, 492, 500, 502, 499, 519, 524, + 533, 540, 539, 554, 562, 569, 568, 583, 590, 589, + 605, 604, 624, 628, 632, 636, 642, 650, 668, 669, + 673, 677, 679, 681, 683, 685, 687, 689, 692, 698, + 699, 704, 715, 716, 721, 723, 728, 735, 736, 740, + 744, 748, 753, 757, 761, 762, 765, 771, 776, 781, + 787, 788, 793, 794, 799, 800, 807, 812, 814, 825, + 827, 832, 834, 838, 858, 859, 861, 874, 934, 936, + 942, 944, 948, 954, 955, 960, 961, 965, 969, 969, + 1036, 1037, 1042, 1054, 1055, 1060, 1059, 1072, 1074, 1076, + 1078, 1080, 1084, 1086, 1091, 1095, 1099, 1103, 1109, 1114, + 1120, 1126, 1128, 1130, 1133, 1132, 1146, 1147, 1151, 1155, + 1158, 1163, 1168, 1171, 1175, 1179, 1185, 1193, 1200, 1206, + 1208, 1210, 1215, 1217, 1219, 1221, 1223, 1225, 1230, 1232, + 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, 1252, + 1254, 1256, 1258, 1260, 1264, 1266, 1268, 1270, 1272, 1276, + 1278, 1282, 1284, 1286, 1288, 1292, 1294, 1299, 1301, 1304, + 1306, 1308, 1311, 1314, 1325, 1328, 1336, 1338, 1340, 1343, + 1346, 1354, 1356, 1360, 1361, 1362, 1363, 1364, 1366, 1368, + 1370, 1372, 1374, 1376, 1378, 1380, 1382, 1384, 1386, 1388, + 1390, 1400, 1410, 1420, 1430, 1432, 1434, 1437, 1442, 1446, + 1448, 1450, 1452, 1455, 1457, 1460, 1462, 1464, 1466, 1468, + 1470, 1472, 1474, 1476, 1479, 1481, 1483, 1485, 1487, 1489, + 1493, 1496, 1495, 1508, 1509, 1510, 1515, 1517, 1519, 1521, + 1526, 1528, 1531, 1533, 1535, 1540, 1545, 1550, 1558, 1560, + 1562, 1566, 1574, 1573, 1591, 1592, 1596, 1597, 1601, 1602, + 1607, 1612, 1614, 1618, 1621, 1625, 1626, 1627, 1630, 1631, + 1634, 1635, 1638, 1642, 1646, 1652, 1658, 1660, 1664, 1668, + 1669, 1673, 1674, 1678, 1679, 1684, 1686, 1688, 1691 }; #endif @@ -387,16 +390,16 @@ static const char *const yytname[] = "PERLY_SLASH", "PERLY_SNAIL", "PERLY_STAR", "KW_FORMAT", "KW_PACKAGE", "KW_CLASS", "KW_LOCAL", "KW_MY", "KW_FIELD", "KW_IF", "KW_ELSE", "KW_ELSIF", "KW_UNLESS", "KW_FOR", "KW_UNTIL", "KW_WHILE", "KW_CONTINUE", - "KW_TRY", "KW_CATCH", "KW_FINALLY", "KW_DEFER", "KW_REQUIRE", "KW_DO", - "KW_USE_or_NO", "KW_SUB_named", "KW_SUB_named_sig", "KW_SUB_anon", - "KW_SUB_anon_sig", "KW_METHOD_named", "KW_METHOD_anon", "BAREWORD", - "METHCALL0", "METHCALL", "THING", "PMFUNC", "PRIVATEREF", "QWLIST", - "FUNC0OP", "FUNC0SUB", "UNIOPSUB", "LSTOPSUB", "PLUGEXPR", "PLUGSTMT", - "LABEL", "LOOPEX", "DOTDOT", "YADAYADA", "FUNC0", "FUNC1", "FUNC", - "UNIOP", "LSTOP", "POWOP", "MULOP", "ADDOP", "DOLSHARP", "HASHBRACK", - "NOAMP", "COLONATTR", "FORMLBRACK", "FORMRBRACK", "SUBLEXSTART", - "SUBLEXEND", "PHASER", "PREC_LOW", "PLUGIN_LOW_OP", "OROP", - "PLUGIN_LOGICAL_OR_LOW_OP", "ANDOP", "PLUGIN_LOGICAL_AND_LOW_OP", + "KW_GIVEN", "KW_WHEN", "KW_DEFAULT", "KW_TRY", "KW_CATCH", "KW_FINALLY", + "KW_DEFER", "KW_REQUIRE", "KW_DO", "KW_USE_or_NO", "KW_SUB_named", + "KW_SUB_named_sig", "KW_SUB_anon", "KW_SUB_anon_sig", "KW_METHOD_named", + "KW_METHOD_anon", "BAREWORD", "METHCALL0", "METHCALL", "THING", "PMFUNC", + "PRIVATEREF", "QWLIST", "FUNC0OP", "FUNC0SUB", "UNIOPSUB", "LSTOPSUB", + "PLUGEXPR", "PLUGSTMT", "LABEL", "LOOPEX", "DOTDOT", "YADAYADA", "FUNC0", + "FUNC1", "FUNC", "UNIOP", "LSTOP", "POWOP", "MULOP", "ADDOP", "DOLSHARP", + "HASHBRACK", "NOAMP", "COLONATTR", "FORMLBRACK", "FORMRBRACK", + "SUBLEXSTART", "SUBLEXEND", "PHASER", "PREC_LOW", "PLUGIN_LOW_OP", + "OROP", "PLUGIN_LOGICAL_OR_LOW_OP", "ANDOP", "PLUGIN_LOGICAL_AND_LOW_OP", "NOTOP", "ASSIGNOP", "PLUGIN_ASSIGN_OP", "PERLY_QUESTION_MARK", "PERLY_COLON", "OROR", "DORDOR", "PLUGIN_LOGICAL_OR_OP", "ANDAND", "PLUGIN_LOGICAL_AND_OP", "BITOROP", "BITANDOP", "CHEQOP", "NCEQOP", @@ -432,12 +435,12 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-540) +#define YYPACT_NINF (-544) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) -#define YYTABLE_NINF (-333) +#define YYTABLE_NINF (-337) #define yytable_value_is_error(Yyn) \ ((Yyn) == YYTABLE_NINF) @@ -446,72 +449,73 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int16 yypact[] = { - 693, -540, -540, -540, -540, -540, -540, -540, 40, -540, - 2935, 37, 1904, 1792, -540, -540, -540, -540, 354, 2935, - 354, 2935, 354, 2935, 354, 354, 2935, 3, 2935, 2224, - -540, -540, -540, -540, 354, 354, -540, -540, 60, -45, - -540, 2935, -540, -540, 2935, -41, -34, 0, 2224, 2145, - 354, 2935, 71, 2935, 2935, 2935, 2935, 2935, 2935, 2303, - -540, 217, 82, -540, 15, -540, -1, -8, 79, 13, - -540, -540, -540, 3123, -540, -540, 11, 152, 190, 235, - -540, 114, 244, 280, 134, -540, -540, -540, -540, -540, - 113, 116, 343, 23, 81, 26, 88, 91, 208, 208, - -540, 71, -540, -540, -540, 202, -540, 71, 189, -540, - 215, 391, 218, 1792, -540, -540, -540, -540, 774, -540, - 429, 886, -540, -540, -540, -540, -540, 233, -540, 315, - -540, 315, -540, -540, 3527, 3014, 2382, 173, -540, -540, - -540, 3527, -540, 3527, 204, 200, 200, 2935, 161, 177, - 2935, 166, 3527, 37, 3123, 174, 2461, 2935, 2145, -540, - 3527, 3093, -540, 82, -540, 2540, 2935, -540, 277, -540, - -540, 2935, 82, 315, 315, 315, 256, 256, 302, 295, - 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2619, -540, -540, - 2935, -540, -540, 2935, 2935, 2935, 2935, 2935, 2935, 2935, - 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2935, - 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2935, 2935, -540, - -540, -540, 2935, 41, 2698, 2935, 2935, 2935, 2935, 2935, - 2935, 2935, -540, 263, 286, 287, 260, -540, -540, -540, - -540, -540, 225, 511, -540, -540, 221, -540, -540, -540, - 308, -540, -540, -540, -540, -540, -540, 37, -540, -540, - -540, 2935, 2935, 2935, 2935, 2935, -540, -540, -540, -540, - 292, -540, -540, -540, 292, -540, -540, -540, 337, -540, - -540, 2777, 315, 173, 42, 51, 70, -540, 309, 297, - -540, -540, -540, 200, 304, -540, -540, -540, -540, 2935, - 2935, 66, -540, -540, -540, -540, 420, 279, 240, 2935, - 82, 350, -540, 2935, 356, 97, 97, -540, -540, 3225, - 195, 86, -540, 424, 3488, 3468, 3327, 315, 349, 375, - 3174, 3225, 3225, 570, 3366, 3366, 3366, 3389, 3389, 3428, - 3449, 3468, 3468, 3488, 3488, 3507, 3294, 375, 349, 315, - 315, 80, 363, 2935, 2935, 318, 369, 370, 372, -540, - 380, 2856, 248, -540, -540, 496, 222, 90, 236, 101, - 241, 108, 246, 1008, -540, -540, 390, 47, 200, 353, - -540, 316, 2935, 2935, -540, 19, -540, -540, 289, -540, - -540, -540, -540, 1985, 343, -540, 2935, 2935, -540, -540, - 365, -540, 398, -540, -540, -540, 217, -540, -540, -540, - 217, -540, -540, 331, 331, 429, 24, 503, -540, -540, - -540, -540, -540, 303, -540, -540, 305, 53, -540, 2935, - -540, -540, -540, 559, -540, 180, 2935, 430, -540, -540, - 2935, -540, 255, 206, -540, -540, -540, -540, -540, -540, - 563, 2935, -540, 431, -540, 432, -540, 436, -540, 444, - -540, -540, -540, -540, -540, 56, -540, -540, 306, 217, - 332, 447, 338, -540, -540, -540, -540, -540, 352, 442, - 175, -540, 2935, 359, 366, 217, 1120, 342, 438, 204, - -540, 483, -540, -540, 200, 2935, -540, -540, -540, -540, - 50, -540, -540, -540, 484, -540, -540, 2935, -540, 419, - -540, -540, -540, 213, -540, 3276, 494, -540, -540, 381, - -540, -540, -540, -540, 497, -540, -540, -540, 2935, 208, - 208, 507, 392, -540, 2935, 2935, 208, -540, 396, 400, - -540, -540, -540, -540, -540, -540, 2935, 200, -540, 506, - 3123, 404, -540, 217, -540, -540, -540, -540, 450, -540, - -540, 3123, 162, 162, 447, 407, 413, 414, 189, 2935, - 2935, 208, 208, 208, 447, 208, 520, 398, 1232, -540, - -540, -540, -540, -540, -540, 1344, -540, 208, 418, -540, - -540, -540, -540, 2935, 208, 208, -540, 525, 423, 189, - 189, 189, -540, 509, -540, -540, -540, 1456, -540, 16, - -540, 1568, -540, 2935, 428, 189, 189, -540, 208, -540, - -540, -540, 433, 37, -540, -540, 538, 474, -540, -540, - 434, 208, -540, -540, -540, 189, -540, -540, -540, -540, - -540, -540, 208, 189, 2066, -540, 1680, 162, -540, 437, - -540, -540, 208, -540 + 775, -544, -544, -544, -544, -544, -544, -544, 62, -544, + 2930, 58, 1898, 1783, -544, -544, -544, -544, 41, 2930, + 41, 2930, 41, 2930, 41, 41, 2930, 3, 2930, 2219, + -544, -544, -544, -544, 41, 41, -544, -544, 86, -12, + -544, 2930, -544, -544, 2930, 11, 38, -58, 2219, 2140, + 41, 2930, 105, 2930, 2930, 2930, 2930, 2930, 2930, 2298, + -544, 255, 157, -544, 4, -544, -45, 68, -17, 8, + -544, -544, -544, 3173, -544, -544, 51, 94, 183, 217, + -544, 173, 229, 244, 187, -544, -544, -544, -544, -544, + 162, 169, 147, 73, 103, 12, 111, 126, 138, 140, + 58, 260, 260, -544, 105, -544, -544, -544, 267, -544, + 105, 253, -544, 284, 432, 285, 1783, -544, -544, -544, + -544, 681, -544, 163, 853, -544, -544, -544, -544, -544, + 298, -544, 416, -544, 416, -544, -544, 3577, 3009, 2377, + 231, -544, -544, -544, 3577, -544, 3577, 261, 237, 237, + 2930, 193, 238, 2930, 195, 3577, 58, 3173, 204, 2456, + 2930, 2140, -544, 3577, 3088, -544, 157, -544, 2535, 2930, + -544, 312, -544, -544, 2930, 157, 416, 416, 416, 647, + 647, 322, 251, 2930, 2930, 2930, 2930, 2930, 2930, 2930, + 2614, -544, -544, 2930, -544, -544, 2930, 2930, 2930, 2930, + 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, + 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, + 2930, 2930, -544, -544, -544, 2930, 101, 2693, 2930, 2930, + 2930, 2930, 2930, 2930, 2930, -544, 281, 282, 299, 272, + -544, -544, -544, -544, -544, 239, 455, -544, -544, 227, + -544, -544, -544, -544, -544, -544, 318, -544, -544, -544, + -544, -544, -544, 58, -544, -544, -544, 2930, 2930, 2930, + 2930, 2930, 2930, -544, -544, -544, -544, 302, -544, -544, + -544, 302, -544, -544, -544, 358, -544, -544, 2772, 416, + 231, 63, 69, 76, -544, 355, 319, -544, -544, -544, + 237, 320, -544, -544, -544, -544, 2930, 2930, 96, -544, + -544, -544, -544, 409, 286, 252, 2930, 157, 373, -544, + 2930, 375, 54, 54, -544, -544, 3275, 122, 116, -544, + 466, 3538, 3518, 3377, 416, 315, 503, 3224, 3275, 3275, + 3122, 3416, 3416, 3416, 3439, 3439, 3478, 3499, 3518, 3518, + 3538, 3538, 3557, 3344, 503, 315, 416, 416, 65, 372, + 2930, 2930, 39, 374, 376, 378, -544, 379, 2851, 256, + -544, -544, 481, 185, 129, 236, 142, 259, 159, 277, + 968, -544, -544, 382, 27, 237, 348, -544, 311, 2930, + 2930, -544, 6, -544, -544, 287, -544, -544, -544, -544, + 1982, 147, -544, 2930, 2930, 2930, 2930, -544, -544, 356, + -544, 396, -544, -544, -544, 255, -544, -544, -544, 255, + -544, -544, -544, 327, 327, 163, 20, 569, -544, -544, + -544, -544, -544, 295, -544, -544, 297, 83, -544, 2930, + -544, -544, -544, 575, -544, 181, 2930, 420, -544, -544, + 2930, -544, 361, 224, -544, -544, -544, -544, -544, -544, + 673, 2930, -544, 421, -544, 423, -544, 433, -544, 445, + -544, -544, -544, -544, -544, 29, -544, -544, 330, 255, + 331, 428, 333, -544, -544, -544, -544, -544, 337, 450, + 273, -544, 2930, 345, 347, 255, 349, 351, 1093, 352, + 427, 261, -544, 477, -544, -544, 237, 2930, -544, -544, + -544, -544, 75, -544, -544, -544, 479, -544, -544, 2930, + -544, 404, -544, -544, -544, 247, -544, 3326, 483, -544, + -544, 368, -544, -544, -544, -544, 476, -544, -544, -544, + 2930, 260, 260, 490, 377, -544, 2930, 2930, 260, -544, + 380, 383, -544, -544, 260, 260, -544, -544, -544, -544, + 2930, 237, -544, 485, 3173, 385, -544, 255, -544, -544, + -544, -544, 425, -544, -544, 3173, 179, 179, 428, 386, + 389, 390, 253, 2930, 2930, 260, 260, 260, -544, -544, + 428, 260, 487, 396, 1208, -544, -544, -544, -544, -544, + -544, 1323, -544, 260, 392, -544, -544, -544, -544, 2930, + 260, 260, -544, 493, 391, 253, 253, 253, -544, 484, + -544, -544, -544, 1438, -544, 31, -544, 1553, -544, 2930, + 399, 253, 253, -544, 260, -544, -544, -544, 410, 58, + -544, -544, 516, 460, -544, -544, 418, 260, -544, -544, + -544, 253, -544, -544, -544, -544, -544, -544, 260, 253, + 2061, -544, 1668, 179, -544, 424, -544, -544, 260, -544 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -520,105 +524,106 @@ static const yytype_int16 yypact[] = static const yytype_int16 yydefact[] = { 0, 2, 4, 6, 8, 10, 12, 14, 0, 21, - 19, 0, 0, 0, 19, 134, 1, 19, 0, 19, - 0, 0, 0, 0, 0, 0, 0, 0, 266, 0, - 103, 103, 104, 279, 0, 0, 250, 277, 238, 272, - 274, 268, 103, 281, 260, 270, 0, 0, 263, 19, + 19, 0, 0, 0, 19, 138, 1, 19, 0, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 270, 0, + 107, 107, 108, 283, 0, 0, 254, 281, 242, 276, + 278, 272, 107, 285, 264, 274, 0, 0, 267, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, - 302, 303, 147, 280, 245, 229, 188, 200, 189, 207, - 230, 231, 232, 150, 235, 5, 251, 240, 243, 242, - 244, 241, 0, 0, 0, 21, 7, 78, 73, 105, + 306, 307, 151, 284, 249, 233, 192, 204, 193, 211, + 234, 235, 236, 154, 239, 5, 255, 244, 247, 246, + 248, 245, 0, 0, 0, 21, 7, 81, 76, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 102, 0, 16, 17, 36, 0, 102, 0, 19, 9, - 0, 79, 0, 0, 11, 33, 32, 28, 0, 15, - 19, 0, 331, 334, 333, 332, 318, 0, 319, 213, - 321, 214, 320, 324, 236, 0, 0, 283, 288, 290, - 289, 267, 228, 227, 19, 19, 19, 19, 0, 0, - 0, 0, 269, 0, 261, 0, 0, 19, 19, 264, - 265, 279, 300, 301, 157, 240, 0, 322, 0, 106, - 107, 19, 262, 215, 216, 234, 220, 221, 239, 0, - 0, 0, 0, 0, 148, 0, 0, 0, 203, 202, - 0, 210, 209, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 106, 0, 16, 17, 36, 0, 106, + 0, 19, 9, 0, 82, 0, 0, 11, 33, 32, + 28, 0, 15, 19, 0, 335, 338, 337, 336, 322, + 0, 323, 217, 325, 218, 324, 328, 240, 0, 0, + 287, 292, 294, 293, 271, 232, 231, 19, 19, 19, + 19, 0, 0, 0, 0, 273, 0, 265, 0, 0, + 19, 19, 268, 269, 283, 304, 305, 161, 244, 0, + 326, 0, 110, 111, 19, 266, 219, 220, 238, 224, + 225, 243, 0, 0, 0, 0, 0, 152, 0, 0, + 0, 207, 206, 0, 214, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, - 218, 219, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 19, 19, 0, 0, 19, 291, 293, 292, - 21, 21, 21, 0, 21, 21, 0, 21, 21, 23, - 0, 71, 46, 102, 72, 42, 102, 0, 88, 64, - 70, 0, 0, 0, 0, 0, 69, 35, 34, 29, - 115, 118, 117, 129, 115, 125, 124, 128, 130, 135, - 222, 0, 285, 0, 240, 243, 242, 287, 0, 114, - 282, 109, 108, 19, 112, 110, 21, 21, 155, 19, - 0, 0, 273, 160, 271, 275, 0, 0, 0, 0, - 151, 0, 254, 0, 237, 145, 146, 143, 144, 149, - 0, 0, 174, 0, 206, 212, 192, 181, 183, 185, - 199, 179, 180, 0, 195, 197, 196, 193, 194, 191, - 190, 211, 208, 205, 201, 204, 187, 186, 184, 198, - 182, 178, 0, 0, 0, 0, 328, 326, 330, 162, - 0, 0, 154, 163, 252, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 100, 101, 0, 0, 19, 295, - 296, 297, 0, 0, 316, 0, 317, 314, 0, 315, - 311, 312, 313, 0, 0, 21, 0, 95, 19, 21, - 0, 38, 21, 40, 89, 80, 77, 81, 84, 83, - 97, 82, 116, 19, 19, 126, 239, 0, 284, 286, - 113, 21, 111, 19, 225, 226, 0, 19, 176, 19, - 276, 159, 158, 0, 223, 0, 0, 0, 167, 173, - 0, 258, 0, 0, 255, 257, 256, 259, 323, 171, - 0, 19, 253, 0, 165, 0, 246, 0, 247, 0, - 18, 21, 37, 21, 44, 0, 294, 298, 0, 98, - 0, 0, 0, 306, 21, 93, 94, 99, 0, 0, - 79, 58, 0, 0, 0, 96, 0, 19, 0, 19, - 137, 0, 43, 136, 19, 121, 120, 123, 119, 127, - 237, 224, 134, 131, 0, 132, 156, 0, 304, 0, - 161, 152, 177, 0, 170, 233, 0, 166, 172, 0, - 168, 248, 249, 164, 0, 65, 21, 45, 0, 0, - 0, 310, 0, 309, 0, 0, 0, 52, 0, 0, - 92, 92, 22, 25, 24, 62, 19, 19, 19, 21, - 122, 0, 141, 305, 278, 175, 169, 153, 0, 19, - 67, 299, 19, 19, 307, 0, 0, 0, 19, 95, - 0, 0, 0, 0, 0, 0, 0, 21, 0, 140, - 41, 139, 133, 19, 19, 0, 19, 0, 0, 85, - 48, 49, 308, 0, 0, 0, 61, 0, 0, 19, - 19, 19, 26, 90, 47, 39, 138, 0, 30, 0, - 66, 0, 86, 0, 0, 19, 19, 53, 0, 57, - 51, 50, 0, 0, 63, 142, 0, 19, 31, 68, - 0, 0, 55, 60, 92, 19, 27, 91, 20, 19, - 75, 74, 0, 19, 0, 59, 0, 19, 56, 0, - 76, 87, 0, 54 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 221, 222, 223, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 19, 0, 0, 19, + 295, 297, 296, 21, 21, 21, 0, 21, 21, 0, + 21, 21, 21, 21, 52, 23, 0, 74, 46, 106, + 75, 42, 106, 0, 92, 67, 73, 0, 0, 0, + 0, 0, 0, 72, 35, 34, 29, 119, 122, 121, + 133, 119, 129, 128, 132, 134, 139, 226, 0, 289, + 0, 244, 247, 246, 291, 0, 118, 286, 113, 112, + 19, 116, 114, 21, 21, 159, 19, 0, 0, 277, + 164, 275, 279, 0, 0, 0, 0, 155, 0, 258, + 0, 241, 149, 150, 147, 148, 153, 0, 0, 178, + 0, 210, 216, 196, 185, 187, 189, 203, 183, 184, + 0, 199, 201, 200, 197, 198, 195, 194, 215, 212, + 209, 205, 208, 191, 190, 188, 202, 186, 182, 0, + 0, 0, 0, 332, 330, 334, 166, 0, 0, 158, + 167, 256, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 19, 299, 300, 301, 0, + 0, 320, 0, 321, 318, 0, 319, 315, 316, 317, + 0, 0, 21, 0, 99, 0, 0, 19, 21, 0, + 38, 21, 40, 93, 83, 80, 84, 87, 86, 101, + 85, 88, 120, 19, 19, 130, 243, 0, 288, 290, + 117, 21, 115, 19, 229, 230, 0, 19, 180, 19, + 280, 163, 162, 0, 227, 0, 0, 0, 171, 177, + 0, 262, 0, 0, 259, 261, 260, 263, 327, 175, + 0, 19, 257, 0, 169, 0, 250, 0, 251, 0, + 18, 21, 37, 21, 44, 0, 298, 302, 0, 102, + 0, 0, 0, 310, 21, 97, 98, 103, 0, 0, + 82, 61, 0, 0, 0, 100, 0, 0, 0, 19, + 0, 19, 141, 0, 43, 140, 19, 125, 124, 127, + 123, 131, 241, 228, 138, 135, 0, 136, 160, 0, + 308, 0, 165, 156, 181, 0, 174, 237, 0, 170, + 176, 0, 172, 252, 253, 168, 0, 68, 21, 45, + 0, 0, 0, 314, 0, 313, 0, 0, 0, 55, + 0, 0, 96, 96, 0, 0, 22, 25, 24, 65, + 19, 19, 19, 21, 126, 0, 145, 309, 282, 179, + 173, 157, 0, 19, 70, 303, 19, 19, 311, 0, + 0, 0, 19, 99, 0, 0, 0, 0, 50, 51, + 0, 0, 0, 21, 0, 144, 41, 143, 137, 19, + 19, 0, 19, 0, 0, 89, 48, 49, 312, 0, + 0, 0, 64, 0, 0, 19, 19, 19, 26, 94, + 47, 39, 142, 0, 30, 0, 69, 0, 90, 0, + 0, 19, 19, 56, 0, 60, 54, 53, 0, 0, + 66, 146, 0, 19, 31, 71, 0, 0, 58, 63, + 96, 19, 27, 95, 20, 19, 78, 77, 0, 19, + 0, 62, 0, 19, 59, 0, 79, 91, 0, 57 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -540, -540, -540, -540, -540, -540, -540, -540, -540, -540, - -4, -10, -540, -6, -70, -540, -540, -540, -540, -16, - -540, 544, 449, -2, -540, -540, -540, -540, -540, -540, - -540, -540, -540, -540, -540, -540, -32, -385, -539, -429, - -540, -508, -540, -5, 169, -361, -78, -540, -89, 46, - -540, -540, -11, 84, -133, 285, 323, -540, -540, 155, - -540, 164, -540, -540, -540, -540, 75, -540, 21, 159, - -540, -293, -540, 93, -38, -540, -540, -540, -540, -540, - -540, -540, -540, -540, -540, -540, -540, 555, -540, -540, - 466, -540, -540, -540, -540, -135, -17, -540, -540, -540, - -540, 210, -540, -540, 364, 67, -22, -21, -540, -540, - -540, -540, -540, 25 + -544, -544, -544, -544, -544, -544, -544, -544, -544, -544, + -4, -10, -544, 50, -55, -544, -544, -544, -544, -16, + -544, 536, 436, -1, -544, -544, -544, -544, -544, -544, + -544, -544, -544, -544, -544, -544, -5, -395, -543, -221, + -544, -521, -544, -29, 161, -220, -95, -544, -97, 37, + -544, -544, -67, 67, -146, 279, 289, -544, -544, 153, + -544, 146, -544, -544, -544, -544, 64, -544, -13, 154, + -544, -294, -544, 16, -47, -544, -544, -544, -544, -544, + -544, -544, -544, -544, -544, -544, -544, 631, -544, -544, + 446, -544, -544, -544, -544, -126, -15, -544, -544, -544, + -544, 186, -544, -544, 343, 36, -19, -14, -544, -544, + -544, -544, -544, 59 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - 0, 8, 9, 10, 11, 12, 13, 14, 15, 107, - 108, 117, 462, 423, 250, 398, 545, 574, 622, 118, - 609, 269, 115, 116, 489, 494, 402, 400, 569, 634, - 538, 575, 559, 586, 628, 641, 405, 110, 590, 259, - 624, 572, 477, 484, 409, 468, 479, 376, 252, 144, - 146, 233, 171, 293, 296, 290, 413, 274, 275, 497, - 276, 277, 278, 279, 504, 505, 119, 120, 492, 493, - 580, 424, 583, 111, 62, 63, 429, 362, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 149, 74, - 137, 236, 381, 112, 528, 164, 75, 509, 472, 531, - 532, 387, 388, 245, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 128 + 0, 8, 9, 10, 11, 12, 13, 14, 15, 110, + 111, 120, 472, 433, 256, 407, 559, 590, 638, 121, + 625, 276, 118, 119, 501, 506, 411, 409, 583, 650, + 550, 591, 573, 602, 644, 657, 414, 113, 606, 265, + 640, 586, 487, 494, 418, 478, 489, 383, 258, 147, + 149, 236, 174, 300, 303, 297, 423, 281, 282, 509, + 283, 284, 285, 286, 516, 517, 122, 123, 504, 505, + 596, 434, 599, 114, 62, 63, 439, 369, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 152, 74, + 140, 239, 388, 115, 540, 167, 75, 521, 482, 543, + 544, 394, 395, 248, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 131 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -626,853 +631,864 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 60, 121, 127, 17, 425, 139, 140, 86, 476, 60, - 109, 163, 298, 297, 124, 172, 124, 255, 124, 20, - 124, 124, 470, 22, 591, 142, 185, 24, 186, 251, - 124, 124, 478, 573, 168, 20, 312, 313, 626, 162, - 16, 60, 20, 126, 159, 124, 124, 130, 85, 132, - 133, 352, 353, 225, 354, 226, 242, 355, 463, 147, - 148, 356, -325, 436, -325, 357, 358, 526, 184, 464, - 238, 239, 627, 150, 166, 167, 507, 145, 527, 232, - 428, -327, 151, -327, 157, 125, 155, 125, 153, 125, - 253, 125, 125, 156, 138, 359, 256, 184, 258, 190, - 438, 125, 125, 61, 454, -287, 188, 189, 651, 163, - 273, 268, 61, 285, 286, 456, 165, 125, 193, 360, - 135, 539, 458, -288, 169, -329, 644, 158, 310, 170, - 136, -286, -290, 163, 292, 295, 295, 162, 224, 596, - 307, 308, 187, 243, 61, 231, 471, 60, 60, 303, - 240, -289, 179, 244, 124, 180, 181, 182, 183, 237, - 421, 162, 246, 225, 401, 226, 234, 403, 361, 235, - 619, 620, 621, 566, 567, 180, 181, 182, 183, 180, - 181, 182, 183, 309, 191, 192, 632, 633, 182, 183, - 180, 181, 182, 183, 512, 587, 588, 180, 181, 182, - 183, -325, 284, -325, -333, 223, 645, 261, 241, 598, - 262, 263, 264, 265, 648, 247, 373, 437, 248, 249, - 517, 391, 392, 375, 254, 165, 380, 555, 257, 288, - 407, 408, 614, 411, 382, 383, 385, 260, 393, 394, - 266, 396, 397, 301, 453, 465, -327, 280, -327, 306, - 61, 61, 630, 404, 289, 227, 581, 228, 455, 476, - 291, 300, 427, 457, 180, 181, 182, 183, 459, 180, - 181, 182, 183, 315, 316, 317, 318, 516, 320, 321, - 323, 294, 426, 295, 180, 181, 182, 183, 299, 60, - 363, 229, 302, 230, 510, 180, 181, 182, 183, 311, - 304, -98, 180, 181, 182, 183, 180, 181, 182, 183, - 390, 180, 181, 182, 183, 313, 374, 365, 366, 367, - 368, 369, 370, 371, 372, 180, 181, 182, 183, 85, - 180, 181, 182, 183, 20, 180, 181, 182, 183, 377, - 378, 379, 384, 444, 180, 181, 182, 183, 395, 399, - 412, 124, 415, 420, 406, 406, 406, 410, 406, 20, - 422, 549, 434, 22, 431, 85, 432, 24, 295, 436, - 20, 122, 391, 392, 417, 451, 123, -333, -333, -333, - 222, 223, 486, 475, 180, 181, 182, 183, 441, 482, - 195, 163, 61, 487, 445, 446, 491, 447, 180, 181, - 182, 183, 433, 496, 496, 448, 435, 122, 461, 466, - 467, 576, 123, 503, 577, 491, 474, 508, 488, 162, - 490, 314, 125, 261, 195, 495, 262, 263, 264, 265, - 502, 506, 529, 218, 519, 419, 219, 220, 221, 222, - 223, 60, 514, 520, 521, 270, 442, 443, 522, 271, - 195, 196, 473, 272, 450, 524, 523, 525, 530, 562, - 563, 390, 217, 20, 537, 534, 568, 218, 535, 543, - 219, 220, 221, 222, 223, 469, 469, 544, 536, 292, - 180, 181, 182, 183, 295, 540, 480, 216, 217, 410, - 485, 546, 541, 218, 548, 552, 219, 220, 221, 222, - 223, 599, 600, 601, 554, 603, 556, 557, 163, 180, - 181, 182, 183, 180, 181, 182, 183, 612, 565, 558, - 560, 18, 564, 570, 615, 616, 571, 20, 579, 513, - 582, 22, 578, 584, 593, 24, 162, 295, 533, 594, - 595, 386, 604, 585, 61, 613, 430, 617, 635, 618, - 439, 623, 589, 589, 631, 638, 639, 114, 258, 636, - 642, 643, 267, 652, 597, 483, 649, 607, 418, 498, - 611, 491, 647, 547, 608, 469, 129, 551, 131, 499, - 501, 134, 653, 141, 143, 180, 181, 182, 183, 258, - 258, 258, 180, 181, 182, 183, 152, 414, 605, 154, - 553, 283, 0, 160, 481, 258, 258, 389, 0, 173, - 174, 175, 176, 177, 0, 0, 0, 640, 0, 637, - 0, 0, 452, 646, 0, 258, 0, 469, 469, 500, - 0, 592, 0, 258, 475, 0, 0, 589, 194, 0, - 0, 602, 0, 0, 0, 195, 196, 197, 180, 181, - 182, 183, 180, 181, 182, 183, 0, 0, 198, 0, - 0, 0, 485, 469, 199, 200, 201, 440, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 0, 511, 469, 0, 218, 518, - 282, 219, 220, 221, 222, 223, 1, 2, 3, 4, - 5, 6, 7, 0, 0, 0, 469, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 319, - 0, 0, 0, 0, 0, 324, 0, 0, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 349, 350, -13, 87, 0, 351, 0, 0, - 0, 0, 0, 0, 18, 85, 0, 19, 0, 0, - 20, 0, 0, 21, 22, 23, 88, 0, 24, 25, - 89, 90, 91, 26, 27, 92, 93, 0, 0, 94, - 95, 96, 97, 0, 98, 0, 0, 99, 28, 29, - 100, 101, 102, 30, 31, 103, 32, 33, 34, 35, - 36, 37, 0, 38, 39, 40, 41, 42, 43, 104, - 113, 44, 0, 105, 45, 46, 47, 48, 49, 0, - 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, - 106, 0, 0, 0, 0, 0, 0, 53, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -3, 87, 54, 55, - 0, 56, 0, 57, 58, 0, 18, 85, 0, 19, - 0, 59, 20, 0, 0, 21, 22, 23, 88, 0, - 24, 25, 89, 90, 91, 26, 27, 92, 93, 0, - 0, 94, 95, 96, 97, 0, 98, 0, 0, 99, - 28, 29, 100, 101, 102, 30, 31, 103, 32, 33, + 60, 124, 166, 304, 130, 486, 175, 86, 142, 60, + 435, 112, 261, 143, 127, 188, 127, 189, 127, 20, + 127, 127, 20, 22, 305, 145, 61, 24, 20, 160, + 127, 127, 587, 320, 607, 61, 171, 259, 473, 165, + 538, 60, 245, 262, 162, 127, 127, 257, 319, 474, + 85, 539, 85, 642, 128, 20, 128, 20, 128, 17, + 128, 128, 16, 141, 454, 191, 192, 61, 148, 85, + 128, 128, 161, 241, 228, 182, 229, 129, 242, 156, + -329, 133, -329, 135, 136, 168, 128, -331, 446, -331, + 643, 194, 195, 150, 151, 125, 254, 125, 187, 153, + 126, 264, 126, 166, -291, 228, 519, 229, 169, 170, + 438, 359, 360, 280, 361, 275, 196, 362, 154, 292, + 667, 363, 317, 138, 293, 364, 365, 166, 240, 660, + 448, 249, 246, 139, 190, 235, 481, 299, 302, 302, + 165, 158, 247, 464, 447, 314, 315, -292, 185, 186, + 60, 60, 310, -294, 431, 295, 466, 127, 366, -290, + -293, 172, 410, 20, 165, 412, 173, 22, 159, 308, + 480, 24, 187, 468, 291, 313, 61, 61, 193, 277, + 488, 227, 367, 278, -333, 496, 497, 279, 183, 184, + 185, 186, -337, 226, -329, 524, -329, 168, 234, 322, + 323, 324, 325, 243, 327, 328, 330, 463, 183, 184, + 185, 186, 603, 604, 183, 184, 185, 186, 237, 380, + 316, 183, 184, 185, 186, 238, 382, 398, -331, 387, + -331, 368, 399, 244, 183, 184, 185, 186, 529, 475, + 230, 250, 231, 372, 373, 374, 375, 376, 377, 378, + 379, 183, 184, 185, 186, 232, 251, 233, 465, 413, + 437, 569, 370, 416, 417, 486, 420, 421, 252, 597, + 253, 255, 551, 183, 184, 185, 186, 183, 184, 185, + 186, 467, 397, 415, 415, 415, 419, 415, 415, 260, + 302, 436, 263, 389, 390, 392, 60, 400, 401, 469, + 403, 404, 405, 406, 427, 267, 266, 273, 268, 269, + 270, 271, 287, 522, 272, 296, 183, 184, 185, 186, + 298, 301, 61, 306, 309, 307, 580, 581, 183, 184, + 185, 186, 443, 311, 318, 320, 445, 381, 384, 183, + 184, 185, 186, 183, 184, 185, 186, 183, 184, 185, + 186, 183, 184, 185, 186, 385, 386, 402, 127, 391, + 563, 612, 408, 422, 614, 183, 184, 185, 186, 183, + 184, 185, 186, 425, 441, 302, 452, 453, 430, 432, + 321, 442, 398, 528, 460, 444, 461, 399, 446, 630, + 485, 498, 166, 198, 635, 636, 637, 451, 128, 455, + 471, 456, -102, 457, 458, 479, 479, 476, 477, 646, + 648, 649, 500, 508, 508, 593, 490, 484, 502, 419, + 495, 479, 479, 515, 507, 514, 518, 520, 483, 165, + 661, 220, 526, 532, 592, 533, 221, 397, 664, 222, + 223, 224, 225, 226, 20, 534, 531, 183, 184, 185, + 186, 60, 492, 183, 184, 185, 186, 535, 499, 541, + 542, 503, 525, 546, 267, 18, 548, 268, 269, 270, + 271, 20, 549, 272, 552, 22, 553, 61, 554, 24, + 555, 503, 557, 560, 429, 393, 576, 577, 562, 558, + 566, 299, 568, 582, 198, 570, 302, 571, 572, 588, + 589, 183, 184, 185, 186, 578, 579, 595, 479, 620, + 584, 600, 585, 166, 598, 633, 609, 545, 610, 611, + 634, 536, 629, 537, 183, 184, 185, 186, 647, 639, + 615, 616, 617, 654, 547, 567, 619, 221, 440, 652, + 222, 223, 224, 225, 226, 655, 594, 658, 628, 117, + 165, 302, 274, 668, 613, 631, 632, 601, 183, 184, + 185, 186, 479, 479, 493, 665, 605, 605, 561, 428, + 424, 511, 264, 183, 184, 185, 186, 510, 565, 651, + 621, 198, 199, 623, 290, 513, 627, 491, 574, 396, + 624, 0, 659, 0, 0, 449, 0, 0, 0, 495, + 479, 0, 0, 663, 0, 264, 264, 264, 0, 0, + 462, 0, 0, 669, 608, 0, 0, 0, 219, 220, + 0, 264, 264, 0, 221, 479, 618, 222, 223, 224, + 225, 226, 0, 656, 0, 653, 0, 0, 0, 662, + 0, 264, 0, 503, 0, 479, 0, 0, 0, 264, + 485, 0, 132, 605, 134, 0, 0, 137, 0, 144, + 146, 183, 184, 185, 186, 0, 0, 183, 184, 185, + 186, 0, 155, 0, 0, 157, 0, 0, 0, 163, + 0, -13, 87, 0, 0, 176, 177, 178, 179, 180, + 0, 18, 85, 0, 19, 0, 0, 20, 512, 0, + 21, 22, 23, 88, 523, 24, 25, 89, 90, 91, + 26, 27, 92, 93, 0, 0, 94, 95, 96, 97, + 0, 98, 99, 100, 101, 0, 0, 102, 28, 29, + 103, 104, 105, 30, 31, 106, 32, 33, 34, 35, + 36, 37, 0, 38, 39, 40, 41, 42, 43, 107, + 116, 44, 0, 108, 45, 46, 47, 48, 49, 0, + 0, 0, 50, 51, 52, 183, 184, 185, 186, 289, + 109, -337, -337, -337, 225, 226, 0, 53, 1, 2, + 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, + 0, 56, 530, 57, 58, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 0, 0, 0, 0, 326, 0, + 0, 0, 0, 0, 331, 0, 0, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, -3, 87, 0, 358, 0, 0, 0, + 0, 0, 0, 18, 85, 0, 19, 0, 0, 20, + 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, + 90, 91, 26, 27, 92, 93, 0, 0, 94, 95, + 96, 97, 0, 98, 99, 100, 101, 0, 0, 102, + 28, 29, 103, 104, 105, 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, - 43, 104, 113, 44, 0, 105, 45, 46, 47, 48, + 43, 107, 116, 44, 0, 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, - 0, 0, 106, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 515, 0, 0, 0, 0, - 54, 55, 0, 56, 0, 57, 58, 0, 0, 87, - 0, 0, 0, 59, 0, 0, 0, 0, 18, 85, - 460, 19, 0, 0, 20, 0, 0, 21, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 54, 55, 0, 56, 0, 57, 58, 0, 18, 85, + 470, 19, 0, 59, 20, 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, 90, 91, 26, 27, 92, - 93, 0, 0, 94, 95, 96, 97, 0, 98, 0, - 550, 99, 28, 29, 100, 101, 102, 30, 31, 103, - 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, - 41, 42, 43, 104, 113, 44, 0, 105, 45, 46, - 47, 48, 49, 561, 0, 0, 50, 51, 52, 0, - 0, 0, 0, 0, 106, 0, 0, 0, 0, 0, - 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 87, 54, 55, 0, 56, 0, 57, 58, 0, - 18, 85, 542, 19, 0, 59, 20, 0, 0, 21, - 22, 23, 88, 0, 24, 25, 89, 90, 91, 26, - 27, 92, 93, 0, 0, 94, 95, 96, 97, 0, - 98, 0, 0, 99, 28, 29, 100, 101, 102, 30, - 31, 103, 32, 33, 34, 35, 36, 37, 0, 38, - 39, 40, 41, 42, 43, 104, 113, 44, 0, 105, - 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, - 52, 0, 0, 0, 0, 0, 106, 0, 0, 0, - 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, + 93, 0, 0, 94, 95, 96, 97, 0, 98, 99, + 100, 101, 0, 0, 102, 28, 29, 103, 104, 105, + 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 107, 116, 44, 0, + 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, + 51, 52, 0, 0, 0, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 87, 54, 55, 0, 56, 0, 57, - 58, 0, 18, 85, 606, 19, 0, 59, 20, 0, - 0, 21, 22, 23, 88, 0, 24, 25, 89, 90, - 91, 26, 27, 92, 93, 0, 0, 94, 95, 96, - 97, 0, 98, 0, 0, 99, 28, 29, 100, 101, - 102, 30, 31, 103, 32, 33, 34, 35, 36, 37, - 0, 38, 39, 40, 41, 42, 43, 104, 113, 44, - 0, 105, 45, 46, 47, 48, 49, 0, 0, 0, - 50, 51, 52, 0, 0, 0, 0, 0, 106, 0, - 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, + 0, 527, 0, 0, 0, 54, 55, 0, 56, 0, + 57, 58, 0, 0, 87, 0, 0, 0, 59, 0, + 0, 0, 0, 18, 85, 556, 19, 0, 0, 20, + 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, + 90, 91, 26, 27, 92, 93, 0, 0, 94, 95, + 96, 97, 0, 98, 99, 100, 101, 0, 564, 102, + 28, 29, 103, 104, 105, 30, 31, 106, 32, 33, + 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, + 43, 107, 116, 44, 0, 108, 45, 46, 47, 48, + 49, 575, 0, 0, 50, 51, 52, 0, 0, 0, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 87, 54, 55, 0, 56, - 0, 57, 58, 0, 18, 85, 610, 19, 0, 59, - 20, 0, 0, 21, 22, 23, 88, 0, 24, 25, - 89, 90, 91, 26, 27, 92, 93, 0, 0, 94, - 95, 96, 97, 0, 98, 0, 0, 99, 28, 29, - 100, 101, 102, 30, 31, 103, 32, 33, 34, 35, - 36, 37, 0, 38, 39, 40, 41, 42, 43, 104, - 113, 44, 0, 105, 45, 46, 47, 48, 49, 0, - 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, - 106, 0, 0, 0, 0, 0, 0, 53, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 54, 55, 0, 56, 0, 57, 58, 0, 18, 85, + 622, 19, 0, 59, 20, 0, 0, 21, 22, 23, + 88, 0, 24, 25, 89, 90, 91, 26, 27, 92, + 93, 0, 0, 94, 95, 96, 97, 0, 98, 99, + 100, 101, 0, 0, 102, 28, 29, 103, 104, 105, + 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 107, 116, 44, 0, + 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, + 51, 52, 0, 0, 0, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 87, 54, 55, - 0, 56, 0, 57, 58, 0, 18, 85, 625, 19, - 0, 59, 20, 0, 0, 21, 22, 23, 88, 0, - 24, 25, 89, 90, 91, 26, 27, 92, 93, 0, - 0, 94, 95, 96, 97, 0, 98, 0, 0, 99, - 28, 29, 100, 101, 102, 30, 31, 103, 32, 33, + 0, 0, 0, 0, 87, 54, 55, 0, 56, 0, + 57, 58, 0, 18, 85, 626, 19, 0, 59, 20, + 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, + 90, 91, 26, 27, 92, 93, 0, 0, 94, 95, + 96, 97, 0, 98, 99, 100, 101, 0, 0, 102, + 28, 29, 103, 104, 105, 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, - 43, 104, 113, 44, 0, 105, 45, 46, 47, 48, + 43, 107, 116, 44, 0, 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, - 0, 0, 106, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 54, 55, 0, 56, 0, 57, 58, 0, 18, 85, - 629, 19, 0, 59, 20, 0, 0, 21, 22, 23, + 641, 19, 0, 59, 20, 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, 90, 91, 26, 27, 92, - 93, 0, 0, 94, 95, 96, 97, 0, 98, 0, - 0, 99, 28, 29, 100, 101, 102, 30, 31, 103, - 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, - 41, 42, 43, 104, 113, 44, 0, 105, 45, 46, - 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, - 0, 0, 0, 0, 106, 0, 0, 0, 0, 0, - 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 0, 0, 94, 95, 96, 97, 0, 98, 99, + 100, 101, 0, 0, 102, 28, 29, 103, 104, 105, + 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 107, 116, 44, 0, + 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, + 51, 52, 0, 0, 0, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 87, 54, 55, 0, 56, 0, 57, 58, 0, - 18, 85, 0, 19, 0, 59, 20, 0, 0, 21, - 22, 23, 88, 0, 24, 25, 89, 90, 91, 26, - 27, 92, 93, 0, 0, 94, 95, 96, 97, 0, - 98, 0, 0, 99, 28, 29, 100, 101, 102, 30, - 31, 103, 32, 33, 34, 35, 36, 37, 0, 38, - 39, 40, 41, 42, 43, 104, 113, 44, 0, 105, - 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, - 52, 0, 0, 650, 0, 0, 106, 0, 0, 0, - 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 87, 54, 55, 0, 56, 0, + 57, 58, 0, 18, 85, 645, 19, 0, 59, 20, + 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, + 90, 91, 26, 27, 92, 93, 0, 0, 94, 95, + 96, 97, 0, 98, 99, 100, 101, 0, 0, 102, + 28, 29, 103, 104, 105, 30, 31, 106, 32, 33, + 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, + 43, 107, 116, 44, 0, 108, 45, 46, 47, 48, + 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 87, 54, 55, 0, 56, 0, 57, - 58, 0, 18, 85, 0, 19, 0, 59, 20, 0, - 0, 21, 22, 23, 88, 0, 24, 25, 89, 90, - 91, 26, 27, 92, 93, 0, 0, 94, 95, 96, - 97, 0, 98, 0, 0, 99, 28, 29, 100, 101, - 102, 30, 31, 103, 32, 33, 34, 35, 36, 37, - 0, 38, 39, 40, 41, 42, 43, 104, 113, 44, - 0, 105, 45, 46, 47, 48, 49, 0, 0, 0, - 50, 51, 52, 0, 0, 0, 0, 0, 106, 0, - 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 54, 55, 0, 56, 0, 57, 58, 0, 18, 85, + 0, 19, 0, 59, 20, 0, 0, 21, 22, 23, + 88, 0, 24, 25, 89, 90, 91, 26, 27, 92, + 93, 0, 0, 94, 95, 96, 97, 0, 98, 99, + 100, 101, 0, 0, 102, 28, 29, 103, 104, 105, + 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 107, 116, 44, 0, + 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, + 51, 52, 0, 0, 666, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 87, 54, 55, 0, 56, - 0, 57, 58, 0, 18, 85, 0, 19, 0, 59, - 20, 0, 0, 21, 22, 23, 88, 0, 24, 25, - 89, 90, 91, 26, 27, 92, 93, 0, 0, 94, - 95, 96, 97, 0, 98, 0, 0, 99, 28, 29, - 100, 101, 102, 30, 31, 103, 32, 33, 34, 35, - 36, 37, 0, 38, 39, 40, 41, 42, 43, 104, - 0, 44, 0, 105, 45, 46, 47, 48, 49, 0, - 0, 0, 50, 51, 52, 0, 87, 0, 0, 0, - 106, 0, 0, 0, 0, 18, 0, 53, 19, 0, - 0, 20, 0, 0, 21, 22, 23, -19, 0, 24, - 25, 0, 0, 0, 26, 27, 0, 0, 54, 55, - 0, 56, 0, 57, 58, 0, 0, 0, 0, 28, - 29, 59, 0, 0, 30, 31, 0, 32, 33, 34, - 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, - 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, - 0, 0, 0, 50, 51, 52, 0, 87, 0, 0, - 0, 0, 0, 0, 0, 0, 18, 0, 53, 19, - 0, 0, 20, 0, 0, 21, 22, 23, 0, 0, - 24, 25, 0, 0, 0, 26, 27, 0, 0, 54, - 55, 0, 56, 0, 57, 58, 0, 0, 0, 0, - 28, 29, 59, 0, 0, 30, 31, 0, 32, 33, + 0, 0, 0, 0, 87, 54, 55, 0, 56, 0, + 57, 58, 0, 18, 85, 0, 19, 0, 59, 20, + 0, 0, 21, 22, 23, 88, 0, 24, 25, 89, + 90, 91, 26, 27, 92, 93, 0, 0, 94, 95, + 96, 97, 0, 98, 99, 100, 101, 0, 0, 102, + 28, 29, 103, 104, 105, 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, - 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, + 43, 107, 116, 44, 0, 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, - 0, 0, 0, 0, 0, 18, 85, 0, 19, 53, - 0, 20, 0, 0, 21, 22, 23, 0, 0, 24, - 25, 0, 0, 0, 26, 27, 0, 0, 0, 0, - 54, 55, 0, 56, 0, 57, 58, 0, 0, 28, - 29, 0, -19, 59, 30, 31, 0, 32, 161, 34, - 35, 36, 37, 123, 38, 39, 40, 41, 42, 43, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 54, 55, 0, 56, 0, 57, 58, 0, 18, 85, + 0, 19, 0, 59, 20, 0, 0, 21, 22, 23, + 88, 0, 24, 25, 89, 90, 91, 26, 27, 92, + 93, 0, 0, 94, 95, 96, 97, 0, 98, 99, + 100, 101, 0, 0, 102, 28, 29, 103, 104, 105, + 30, 31, 106, 32, 33, 34, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 107, 0, 44, 0, + 108, 45, 46, 47, 48, 49, 0, 0, 0, 50, + 51, 52, 0, 87, 0, 0, 0, 109, 0, 0, + 0, 0, 18, 0, 53, 19, 0, 0, 20, 0, + 0, 21, 22, 23, -19, 0, 24, 25, 0, 0, + 0, 26, 27, 0, 0, 54, 55, 0, 56, 0, + 57, 58, 0, 0, 0, 0, 0, 0, 59, 28, + 29, 0, 0, 0, 30, 31, 0, 32, 33, 34, + 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, - 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, - 0, 0, 0, 0, 18, 85, 0, 19, 53, 0, - 20, 0, 0, 21, 22, 23, 0, 0, 24, 25, - 0, 0, 0, 26, 27, 0, 0, 0, 0, 54, + 0, 0, 87, 50, 51, 52, 0, 0, 0, 0, + 0, 18, 0, 0, 19, 0, 0, 20, 53, 0, + 21, 22, 23, 0, 0, 24, 25, 0, 0, 0, + 26, 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, 0, 28, 29, 0, 0, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, - 0, 0, 0, 18, 0, 0, 19, 53, 0, 20, - 0, 0, 21, 22, 23, 0, 0, 24, 25, 0, - 0, 0, 26, 27, 0, 0, 0, 0, 54, 55, + 18, 85, 0, 19, 0, 0, 20, 53, 0, 21, + 22, 23, 0, 0, 24, 25, 0, 0, 0, 26, + 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, 0, 28, 29, 0, - 0, 59, 30, 31, 0, 32, 33, 34, 35, 36, - 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, + -19, 59, 30, 31, 0, 32, 164, 34, 35, 36, + 37, 126, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, - 0, 50, 51, 52, 0, 0, 0, 0, 0, 0, - 0, 0, 18, 0, 0, 19, 53, 0, 20, 0, - 0, 21, 22, 23, 0, 0, 24, 25, 0, 0, - 0, 26, 27, 0, 0, 0, 0, 54, 55, 0, - 56, 0, 57, 58, 0, 0, 28, 29, 0, 178, + 0, 50, 51, 52, 0, 0, 0, 0, 0, 18, + 85, 0, 19, 0, 0, 20, 53, 0, 21, 22, + 23, 0, 0, 24, 25, 0, 0, 0, 26, 27, + 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, + 56, 0, 57, 58, 0, 0, 28, 29, 0, 0, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, - 50, 51, 52, 0, 0, 0, 0, 0, 0, 0, - 0, 18, 0, 0, 19, 53, 0, 20, 0, 0, - 21, 22, 23, 0, 0, 24, 25, 0, 0, 0, - 26, 27, 0, 0, 0, 0, 54, 55, 0, 56, - 0, 57, 58, 0, 0, 28, 29, 0, 287, 59, + 50, 51, 52, 0, 0, 0, 0, 0, 18, 0, + 0, 19, 0, 0, 20, 53, 0, 21, 22, 23, + 0, 0, 24, 25, 0, 0, 0, 26, 27, 0, + 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, + 0, 57, 58, 0, 0, 28, 29, 0, 0, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, - 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, - -332, 225, 0, 226, 53, 0, -332, 0, 0, -332, - -332, -332, 0, 0, -332, -332, 0, 0, 0, -332, - -332, 0, 0, 0, 0, 54, 55, 0, 56, 0, - 57, 58, 0, 0, -332, -332, 0, 305, 59, -332, - -332, 0, -332, -332, -332, -332, -332, -332, 0, -332, - -332, -332, -332, -332, -332, 0, 0, -332, 0, 0, - -332, -332, -332, -332, -332, 0, 0, 0, -332, -332, - -332, 0, 0, 0, 0, 0, 0, 0, 0, 18, - 0, 0, 19, -332, 0, 20, 0, 0, 21, 22, - 23, 0, 0, 24, 25, 0, 0, 0, 26, 27, - 0, 0, 0, 0, -332, -332, 0, -332, 0, -332, - -332, 0, 0, 28, 29, 0, 0, -332, 30, 31, + 51, 52, 0, 0, 0, 0, 0, 18, 0, 0, + 19, 0, 0, 20, 53, 0, 21, 22, 23, 0, + 0, 24, 25, 0, 0, 0, 26, 27, 0, 0, + 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, + 57, 58, 0, 0, 28, 29, 0, 181, 59, 30, + 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, + 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, + 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, + 52, 0, 0, 0, 0, 0, 18, 0, 0, 19, + 0, 0, 20, 53, 0, 21, 22, 23, 0, 0, + 24, 25, 0, 0, 0, 26, 27, 0, 0, 0, + 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, + 58, 0, 0, 28, 29, 0, 294, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, - 0, 19, 53, 0, 20, 0, 0, 21, 22, 23, - 0, 0, 24, 25, 0, 0, 0, 26, 27, 0, + 0, 0, 0, 0, 0, -336, 228, 0, 229, 0, + 0, -336, 53, 0, -336, -336, -336, 0, 0, -336, + -336, 0, 0, 0, -336, -336, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, - 0, 0, 28, 29, 0, 322, 59, 30, 31, 0, - 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, - 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, - 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, - 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, - 19, 53, 0, 20, 0, 0, 21, 22, 23, 0, - 0, 24, 25, 0, 0, 0, 26, 27, 0, 0, - 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, - 0, 28, 29, 0, 364, 59, 30, 31, 0, 32, + 0, 0, -336, -336, 0, 312, 59, -336, -336, 0, + -336, -336, -336, -336, -336, -336, 0, -336, -336, -336, + -336, -336, -336, 0, 0, -336, 0, 0, -336, -336, + -336, -336, -336, 0, 0, 0, -336, -336, -336, 0, + 0, 0, 0, 0, 18, 0, 0, 19, 0, 0, + 20, -336, 0, 21, 22, 23, 0, 0, 24, 25, + 0, 0, 0, 26, 27, 0, 0, 0, 0, 0, + 0, 0, -336, -336, 0, -336, 0, -336, -336, 0, + 0, 28, 29, 0, 0, -336, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, - 0, 0, 0, 0, 0, 0, 18, 0, 0, 19, - 53, 0, 20, 0, 0, 21, 22, 23, 0, 0, - 24, 25, 0, 0, 0, 26, 27, 0, 0, 0, + 0, 0, 0, 18, 0, 0, 19, 0, 0, 20, + 53, 0, 21, 22, 23, 0, 0, 24, 25, 0, + 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, 0, - 28, 29, 0, 416, 59, 30, 31, 0, 32, 33, + 28, 29, 0, 329, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, - 0, 0, 0, 0, 0, 18, 0, 0, 19, 53, - 0, 20, 0, 0, 21, 22, 23, 0, 0, 24, - 25, 0, 0, 0, 26, 27, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 19, 0, 0, 20, 53, + 0, 21, 22, 23, 0, 0, 24, 25, 0, 0, + 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, 0, 28, - 29, 0, 449, 59, 30, 31, 0, 32, 33, 34, + 29, 0, 371, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, - 0, 0, 0, 0, 18, 0, 0, 19, 53, 0, - 20, 0, 0, 21, 22, 23, 0, 0, 24, 25, - 0, 0, 0, 26, 27, 0, 0, 0, 0, 54, + 0, 18, 0, 0, 19, 0, 0, 20, 53, 0, + 21, 22, 23, 0, 0, 24, 25, 0, 0, 0, + 26, 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 0, 57, 58, 0, 0, 28, 29, - 0, 0, 59, 30, 31, 0, 32, 33, 34, 35, + 0, 426, 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, - 0, 0, 0, -331, 0, 0, -331, 53, 0, -331, - 0, 0, -331, -331, -331, 0, 0, -331, -331, 0, - 0, 0, -331, -331, 0, 0, 0, 0, 54, 55, - 0, 56, 0, 57, 58, 0, 0, -331, -331, 0, - 0, 281, -331, -331, 0, -331, -331, -331, -331, -331, - -331, 0, -331, -331, -331, -331, -331, -331, 0, 0, - -331, 0, 0, -331, -331, -331, -331, -331, 0, 0, - 0, -331, -331, -331, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -331, 0, 0, 0, - 0, 194, 0, 0, 0, 0, 0, 0, 195, 196, - 197, 0, 0, 0, 0, 0, 0, -331, -331, 0, - -331, 198, -331, -331, 0, 0, 0, 199, 200, 201, - -331, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 0, 0, 0, - 0, 218, 194, 0, 219, 220, 221, 222, 223, 195, - 196, 197, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -333, 0, 0, 0, 0, 0, 199, 200, - 201, 0, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 0, 0, - 0, 0, 218, 194, 0, 219, 220, 221, 222, 223, - 195, 196, 197, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, - 200, 201, 0, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 0, - 0, 0, 0, 218, 194, 0, 219, 220, 221, 222, - 223, 195, 196, 197, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, - 196, 197, 201, 0, 202, 203, 204, 205, 206, 207, + 18, 0, 0, 19, 0, 0, 20, 53, 0, 21, + 22, 23, 0, 0, 24, 25, 0, 0, 0, 26, + 27, 0, 0, 0, 0, 0, 0, 0, 54, 55, + 0, 56, 0, 57, 58, 0, 0, 28, 29, 0, + 459, 59, 30, 31, 0, 32, 33, 34, 35, 36, + 37, 0, 38, 39, 40, 41, 42, 43, 0, 0, + 44, 0, 0, 45, 46, 47, 48, 49, 0, 0, + 0, 50, 51, 52, 0, 0, 0, 0, 0, 18, + 0, 0, 19, 0, 0, 20, 53, 0, 21, 22, + 23, 0, 0, 24, 25, 0, 0, 0, 26, 27, + 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, + 56, 0, 57, 58, 0, 0, 28, 29, 0, 0, + 59, 30, 31, 0, 32, 33, 34, 35, 36, 37, + 0, 38, 39, 40, 41, 42, 43, 0, 0, 44, + 0, 0, 45, 46, 47, 48, 49, 0, 0, 0, + 50, 51, 52, 0, 0, 0, 0, 0, -335, 0, + 0, -335, 0, 0, -335, 53, 0, -335, -335, -335, + 0, 0, -335, -335, 0, 0, 0, -335, -335, 0, + 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, + 0, 57, 58, 0, 0, -335, -335, 0, 0, 288, + -335, -335, 0, -335, -335, -335, -335, -335, -335, 0, + -335, -335, -335, -335, -335, -335, 0, 0, -335, 0, + 0, -335, -335, -335, -335, -335, 0, 0, 0, -335, + -335, -335, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -335, 0, 0, 0, 0, 0, + 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, + 198, 199, 200, 0, 0, -335, -335, 0, -335, 0, + -335, -335, 0, 201, 0, 0, 0, 0, -335, 202, + 203, 204, 450, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 0, + 0, 0, 0, 221, 197, 0, 222, 223, 224, 225, + 226, 198, 199, 200, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 0, 0, 0, 0, 0, + 202, 203, 204, 0, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 0, 0, 0, 0, 221, 197, 0, 222, 223, 224, + 225, 226, 198, 199, 200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -337, 0, 0, 0, 0, + 0, 202, 203, 204, 0, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 0, 0, 0, 0, 221, 197, 0, 222, 223, + 224, 225, 226, 198, 199, 200, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 202, 203, 204, 0, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 0, 0, 0, 0, 221, 197, 0, 222, + 223, 224, 225, 226, 198, 199, 200, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 198, 199, 200, 204, 0, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 0, 0, 0, 0, 218, -333, 0, 219, 220, 221, - 222, 223, 195, 196, 197, 215, 216, 217, 0, 0, - 0, 0, 218, 0, 0, 219, 220, 221, 222, 223, - 0, 0, 0, 0, 0, 202, 203, 204, 205, 206, + 218, 219, 220, 0, 0, 0, 0, 221, -337, 0, + 222, 223, 224, 225, 226, 198, 199, 200, 218, 219, + 220, 0, 0, 0, 0, 221, 0, 0, 222, 223, + 224, 225, 226, 0, 0, 0, 0, 0, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 195, 196, 197, 0, 218, 0, 0, 219, 220, - 221, 222, 223, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 196, 197, 205, 206, 207, + 217, 218, 219, 220, 198, 199, 200, 0, 221, 0, + 0, 222, 223, 224, 225, 226, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 199, 200, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 0, 0, 0, 0, 218, 0, 0, 219, 220, 221, - 222, 223, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 195, 196, 197, 0, 218, 0, 0, - 219, 220, 221, 222, 223, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 196, 197, 0, 0, 0, - 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 0, 195, 196, 197, 218, 0, 0, 219, - 220, 221, 222, 223, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 195, 196, 197, 0, 218, 0, 0, - 219, 220, 221, 222, 223, 211, 212, 213, 214, 215, - 216, 217, 195, 196, 197, 0, 218, 0, 0, 219, - 220, 221, 222, 223, 0, 0, 0, 213, 214, 215, - 216, 217, 195, 196, 197, 0, 218, 0, 0, 219, - 220, 221, 222, 223, 0, 0, -333, 214, 215, 216, - 217, 0, 0, 0, 0, 218, 0, 0, 219, 220, - 221, 222, 223, 0, 0, 0, 0, 214, 215, 216, - 217, 0, 0, 0, 0, 218, 0, 0, 219, 220, - 221, 222, 223 + 218, 219, 220, 0, 0, 0, 0, 221, 0, 0, + 222, 223, 224, 225, 226, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 198, 199, 200, 0, + 221, 0, 0, 222, 223, 224, 225, 226, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 199, 200, + 0, 0, 0, 0, 0, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 0, 198, 199, 200, 221, + 0, 0, 222, 223, 224, 225, 226, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 198, 199, 200, 0, + 221, 0, 0, 222, 223, 224, 225, 226, 214, 215, + 216, 217, 218, 219, 220, 198, 199, 200, 0, 221, + 0, 0, 222, 223, 224, 225, 226, 0, 0, 0, + 216, 217, 218, 219, 220, 198, 199, 200, 0, 221, + 0, 0, 222, 223, 224, 225, 226, 0, 0, -337, + 217, 218, 219, 220, 0, 0, 0, 0, 221, 0, + 0, 222, 223, 224, 225, 226, 0, 0, 0, 0, + 217, 218, 219, 220, 0, 0, 0, 0, 221, 0, + 0, 222, 223, 224, 225, 226 }; static const yytype_int16 yycheck[] = { - 10, 17, 19, 9, 297, 27, 27, 11, 393, 19, - 12, 49, 147, 146, 18, 53, 20, 106, 22, 16, - 24, 25, 383, 20, 563, 29, 11, 24, 13, 99, - 34, 35, 393, 541, 51, 16, 171, 13, 22, 49, - 0, 51, 16, 18, 48, 49, 50, 22, 11, 24, - 25, 10, 11, 11, 13, 13, 30, 16, 11, 34, - 35, 20, 11, 13, 13, 24, 25, 11, 15, 22, - 92, 92, 56, 13, 49, 50, 23, 31, 22, 85, - 14, 11, 127, 13, 84, 18, 127, 20, 42, 22, - 101, 24, 25, 127, 27, 54, 107, 15, 108, 107, - 14, 34, 35, 10, 14, 81, 107, 108, 647, 147, - 120, 113, 19, 135, 135, 14, 49, 50, 105, 78, - 117, 482, 14, 81, 53, 11, 634, 127, 166, 58, - 127, 81, 81, 171, 144, 145, 146, 147, 127, 568, - 157, 158, 127, 117, 51, 11, 127, 157, 158, 153, - 127, 81, 59, 127, 158, 89, 90, 91, 92, 92, - 293, 171, 95, 11, 253, 13, 53, 256, 127, 53, - 599, 600, 601, 534, 535, 89, 90, 91, 92, 89, - 90, 91, 92, 158, 105, 106, 615, 616, 91, 92, - 89, 90, 91, 92, 14, 33, 34, 89, 90, 91, - 92, 11, 135, 13, 124, 125, 635, 32, 127, 570, - 35, 36, 37, 38, 643, 127, 232, 22, 127, 11, - 14, 243, 243, 233, 22, 158, 236, 14, 39, 136, - 262, 263, 593, 265, 240, 241, 242, 22, 244, 245, - 22, 247, 248, 150, 22, 378, 11, 14, 13, 156, - 157, 158, 613, 257, 81, 11, 549, 13, 22, 644, - 56, 84, 300, 22, 89, 90, 91, 92, 22, 89, - 90, 91, 92, 180, 181, 182, 183, 22, 185, 186, - 187, 81, 299, 293, 89, 90, 91, 92, 127, 299, - 223, 11, 126, 13, 429, 89, 90, 91, 92, 22, - 126, 126, 89, 90, 91, 92, 89, 90, 91, 92, - 243, 89, 90, 91, 92, 13, 53, 224, 225, 226, - 227, 228, 229, 230, 231, 89, 90, 91, 92, 11, - 89, 90, 91, 92, 16, 89, 90, 91, 92, 53, - 53, 81, 117, 25, 89, 90, 91, 92, 127, 41, - 58, 355, 15, 56, 261, 262, 263, 264, 265, 16, - 56, 494, 12, 20, 85, 11, 126, 24, 378, 13, - 16, 53, 394, 394, 281, 127, 58, 121, 122, 123, - 124, 125, 398, 393, 89, 90, 91, 92, 25, 395, - 75, 429, 299, 399, 25, 25, 402, 25, 89, 90, - 91, 92, 309, 413, 414, 25, 313, 53, 18, 56, - 94, 546, 58, 423, 547, 421, 127, 427, 53, 429, - 22, 126, 355, 32, 75, 94, 35, 36, 37, 38, - 127, 126, 126, 118, 451, 126, 121, 122, 123, 124, - 125, 451, 12, 12, 12, 16, 353, 354, 12, 20, - 75, 76, 385, 24, 361, 461, 12, 463, 126, 529, - 530, 394, 113, 16, 22, 127, 536, 118, 474, 127, - 121, 122, 123, 124, 125, 382, 383, 487, 126, 489, - 89, 90, 91, 92, 494, 126, 393, 112, 113, 396, - 397, 53, 126, 118, 11, 11, 121, 122, 123, 124, - 125, 571, 572, 573, 85, 575, 12, 126, 546, 89, - 90, 91, 92, 89, 90, 91, 92, 587, 126, 22, - 526, 10, 15, 127, 594, 595, 126, 16, 22, 436, - 126, 20, 548, 83, 127, 24, 546, 547, 471, 126, - 126, 30, 22, 559, 451, 127, 126, 22, 618, 126, - 126, 42, 562, 563, 126, 17, 82, 13, 568, 126, - 126, 631, 113, 126, 569, 396, 644, 583, 283, 414, - 586, 577, 642, 489, 584, 482, 21, 502, 23, 415, - 421, 26, 652, 28, 29, 89, 90, 91, 92, 599, - 600, 601, 89, 90, 91, 92, 41, 274, 577, 44, - 507, 135, -1, 48, 394, 615, 616, 243, -1, 54, - 55, 56, 57, 58, -1, -1, -1, 627, -1, 623, - -1, -1, 126, 639, -1, 635, -1, 534, 535, 126, - -1, 564, -1, 643, 644, -1, -1, 647, 68, -1, - -1, 574, -1, -1, -1, 75, 76, 77, 89, 90, - 91, 92, 89, 90, 91, 92, -1, -1, 88, -1, - -1, -1, 569, 570, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, -1, 126, 593, -1, 118, 126, - 135, 121, 122, 123, 124, 125, 3, 4, 5, 6, - 7, 8, 9, -1, -1, -1, 613, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, 17, 49, 149, 19, 400, 53, 11, 27, 19, + 304, 12, 109, 27, 18, 11, 20, 13, 22, 16, + 24, 25, 16, 20, 150, 29, 10, 24, 16, 87, + 34, 35, 553, 13, 577, 19, 51, 104, 11, 49, + 11, 51, 30, 110, 48, 49, 50, 102, 174, 22, + 11, 22, 11, 22, 18, 16, 20, 16, 22, 9, + 24, 25, 0, 27, 25, 110, 111, 51, 31, 11, + 34, 35, 130, 92, 11, 59, 13, 18, 92, 42, + 11, 22, 13, 24, 25, 49, 50, 11, 13, 13, + 59, 108, 109, 34, 35, 56, 100, 56, 15, 13, + 61, 111, 61, 150, 84, 11, 23, 13, 49, 50, + 14, 10, 11, 123, 13, 116, 108, 16, 130, 138, + 663, 20, 169, 120, 138, 24, 25, 174, 92, 650, + 14, 95, 120, 130, 130, 85, 130, 147, 148, 149, + 150, 130, 130, 14, 22, 160, 161, 84, 94, 95, + 160, 161, 156, 84, 300, 139, 14, 161, 57, 84, + 84, 56, 259, 16, 174, 262, 61, 20, 130, 153, + 390, 24, 15, 14, 138, 159, 160, 161, 110, 16, + 400, 130, 81, 20, 11, 405, 406, 24, 92, 93, + 94, 95, 127, 128, 11, 14, 13, 161, 11, 183, + 184, 185, 186, 130, 188, 189, 190, 22, 92, 93, + 94, 95, 33, 34, 92, 93, 94, 95, 56, 235, + 161, 92, 93, 94, 95, 56, 236, 246, 11, 239, + 13, 130, 246, 130, 92, 93, 94, 95, 14, 385, + 11, 130, 13, 227, 228, 229, 230, 231, 232, 233, + 234, 92, 93, 94, 95, 11, 130, 13, 22, 263, + 307, 14, 226, 268, 269, 660, 271, 272, 130, 563, + 130, 11, 492, 92, 93, 94, 95, 92, 93, 94, + 95, 22, 246, 267, 268, 269, 270, 271, 272, 22, + 300, 306, 39, 243, 244, 245, 306, 247, 248, 22, + 250, 251, 252, 253, 288, 32, 22, 22, 35, 36, + 37, 38, 14, 439, 41, 84, 92, 93, 94, 95, + 59, 84, 306, 130, 129, 87, 546, 547, 92, 93, + 94, 95, 316, 129, 22, 13, 320, 56, 56, 92, + 93, 94, 95, 92, 93, 94, 95, 92, 93, 94, + 95, 92, 93, 94, 95, 56, 84, 130, 362, 120, + 506, 582, 44, 61, 584, 92, 93, 94, 95, 92, + 93, 94, 95, 15, 88, 385, 360, 361, 59, 59, + 129, 129, 401, 22, 368, 12, 130, 401, 13, 609, + 400, 407, 439, 78, 615, 616, 617, 25, 362, 25, + 18, 25, 129, 25, 25, 389, 390, 59, 97, 629, + 631, 632, 56, 423, 424, 561, 400, 130, 22, 403, + 404, 405, 406, 433, 97, 130, 129, 437, 392, 439, + 651, 116, 12, 12, 560, 12, 121, 401, 659, 124, + 125, 126, 127, 128, 16, 12, 461, 92, 93, 94, + 95, 461, 402, 92, 93, 94, 95, 12, 408, 129, + 129, 411, 446, 130, 32, 10, 129, 35, 36, 37, + 38, 16, 22, 41, 129, 20, 129, 461, 129, 24, + 129, 431, 130, 56, 129, 30, 541, 542, 11, 499, + 11, 501, 88, 548, 78, 12, 506, 129, 22, 554, + 555, 92, 93, 94, 95, 15, 129, 22, 492, 22, + 130, 86, 129, 560, 129, 22, 130, 481, 129, 129, + 129, 471, 130, 473, 92, 93, 94, 95, 129, 45, + 585, 586, 587, 17, 484, 519, 591, 121, 129, 129, + 124, 125, 126, 127, 128, 85, 562, 129, 603, 13, + 560, 561, 116, 129, 583, 610, 611, 573, 92, 93, + 94, 95, 546, 547, 403, 660, 576, 577, 501, 290, + 281, 425, 582, 92, 93, 94, 95, 424, 514, 634, + 593, 78, 79, 599, 138, 431, 602, 401, 538, 246, + 600, -1, 647, -1, -1, 129, -1, -1, -1, 583, + 584, -1, -1, 658, -1, 615, 616, 617, -1, -1, + 129, -1, -1, 668, 578, -1, -1, -1, 115, 116, + -1, 631, 632, -1, 121, 609, 590, 124, 125, 126, + 127, 128, -1, 643, -1, 639, -1, -1, -1, 655, + -1, 651, -1, 593, -1, 629, -1, -1, -1, 659, + 660, -1, 21, 663, 23, -1, -1, 26, -1, 28, + 29, 92, 93, 94, 95, -1, -1, 92, 93, 94, + 95, -1, 41, -1, -1, 44, -1, -1, -1, 48, + -1, 0, 1, -1, -1, 54, 55, 56, 57, 58, + -1, 10, 11, -1, 13, -1, -1, 16, 129, -1, + 19, 20, 21, 22, 129, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, 35, 36, 37, 38, + -1, 40, 41, 42, 43, -1, -1, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, -1, 62, 63, 64, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, 75, 76, 77, -1, + -1, -1, 81, 82, 83, 92, 93, 94, 95, 138, + 89, 124, 125, 126, 127, 128, -1, 96, 3, 4, + 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, 120, 129, 122, 123, -1, -1, -1, -1, -1, + -1, 130, -1, -1, -1, -1, -1, -1, 187, -1, + -1, -1, -1, -1, 193, -1, -1, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 221, 0, 1, -1, 225, -1, -1, -1, + -1, -1, -1, 10, 11, -1, 13, -1, -1, 16, + -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, 35, 36, + 37, 38, -1, 40, 41, 42, 43, -1, -1, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, -1, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 89, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 184, - -1, -1, -1, -1, -1, 190, -1, -1, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 0, 1, -1, 222, -1, -1, - -1, -1, -1, -1, 10, 11, -1, 13, -1, -1, - 16, -1, -1, 19, 20, 21, 22, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, 35, - 36, 37, 38, -1, 40, -1, -1, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, 74, -1, - -1, -1, 78, 79, 80, -1, -1, -1, -1, -1, - 86, -1, -1, -1, -1, -1, -1, 93, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, + 117, 118, -1, 120, -1, 122, 123, -1, 10, 11, + 12, 13, -1, 130, 16, -1, -1, 19, 20, 21, + 22, -1, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, 35, 36, 37, 38, -1, 40, 41, + 42, 43, -1, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, -1, -1, -1, 89, -1, -1, + -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, 114, 115, - -1, 117, -1, 119, 120, -1, 10, 11, -1, 13, - -1, 127, 16, -1, -1, 19, 20, 21, 22, -1, - 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, - -1, 35, 36, 37, 38, -1, 40, -1, -1, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - 74, -1, -1, -1, 78, 79, 80, -1, -1, -1, - -1, -1, 86, -1, -1, -1, -1, -1, -1, 93, + -1, 450, -1, -1, -1, 117, 118, -1, 120, -1, + 122, 123, -1, -1, 1, -1, -1, -1, 130, -1, + -1, -1, -1, 10, 11, 12, 13, -1, -1, 16, + -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, 35, 36, + 37, 38, -1, 40, 41, 42, 43, -1, 507, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, 540, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 89, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 440, -1, -1, -1, -1, - 114, 115, -1, 117, -1, 119, 120, -1, -1, 1, - -1, -1, -1, 127, -1, -1, -1, -1, 10, 11, - 12, 13, -1, -1, 16, -1, -1, 19, 20, 21, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, + 117, 118, -1, 120, -1, 122, 123, -1, 10, 11, + 12, 13, -1, 130, 16, -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, 29, 30, 31, - 32, -1, -1, 35, 36, 37, 38, -1, 40, -1, - 495, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, 74, 528, -1, -1, 78, 79, 80, -1, - -1, -1, -1, -1, 86, -1, -1, -1, -1, -1, - -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, + 32, -1, -1, 35, 36, 37, 38, -1, 40, 41, + 42, 43, -1, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, -1, -1, -1, 89, -1, -1, + -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1, 114, 115, -1, 117, -1, 119, 120, -1, - 10, 11, 12, 13, -1, 127, 16, -1, -1, 19, - 20, 21, 22, -1, 24, 25, 26, 27, 28, 29, - 30, 31, 32, -1, -1, 35, 36, 37, 38, -1, - 40, -1, -1, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, 74, -1, -1, -1, 78, 79, - 80, -1, -1, -1, -1, -1, 86, -1, -1, -1, - -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, 117, 118, -1, 120, -1, + 122, 123, -1, 10, 11, 12, 13, -1, 130, 16, + -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, 35, 36, + 37, 38, -1, 40, 41, 42, 43, -1, -1, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, -1, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 89, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1, 114, 115, -1, 117, -1, 119, - 120, -1, 10, 11, 12, 13, -1, 127, 16, -1, - -1, 19, 20, 21, 22, -1, 24, 25, 26, 27, - 28, 29, 30, 31, 32, -1, -1, 35, 36, 37, - 38, -1, 40, -1, -1, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, 74, -1, -1, -1, - 78, 79, 80, -1, -1, -1, -1, -1, 86, -1, - -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1, 114, 115, -1, 117, - -1, 119, 120, -1, 10, 11, 12, 13, -1, 127, - 16, -1, -1, 19, 20, 21, 22, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, 35, - 36, 37, 38, -1, 40, -1, -1, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, 74, -1, - -1, -1, 78, 79, 80, -1, -1, -1, -1, -1, - 86, -1, -1, -1, -1, -1, -1, 93, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, + 117, 118, -1, 120, -1, 122, 123, -1, 10, 11, + 12, 13, -1, 130, 16, -1, -1, 19, 20, 21, + 22, -1, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, 35, 36, 37, 38, -1, 40, 41, + 42, 43, -1, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, -1, -1, -1, 89, -1, -1, + -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1, 114, 115, - -1, 117, -1, 119, 120, -1, 10, 11, 12, 13, - -1, 127, 16, -1, -1, 19, 20, 21, 22, -1, - 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, - -1, 35, 36, 37, 38, -1, 40, -1, -1, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - 74, -1, -1, -1, 78, 79, 80, -1, -1, -1, - -1, -1, 86, -1, -1, -1, -1, -1, -1, 93, + -1, -1, -1, -1, 1, 117, 118, -1, 120, -1, + 122, 123, -1, 10, 11, 12, 13, -1, 130, 16, + -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, 35, 36, + 37, 38, -1, 40, 41, 42, 43, -1, -1, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, -1, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 89, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, - 114, 115, -1, 117, -1, 119, 120, -1, 10, 11, - 12, 13, -1, 127, 16, -1, -1, 19, 20, 21, + 117, 118, -1, 120, -1, 122, 123, -1, 10, 11, + -1, 13, -1, 130, 16, -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, 27, 28, 29, 30, 31, - 32, -1, -1, 35, 36, 37, 38, -1, 40, -1, - -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, 74, -1, -1, -1, 78, 79, 80, -1, - -1, -1, -1, -1, 86, -1, -1, -1, -1, -1, - -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1, 114, 115, -1, 117, -1, 119, 120, -1, - 10, 11, -1, 13, -1, 127, 16, -1, -1, 19, - 20, 21, 22, -1, 24, 25, 26, 27, 28, 29, - 30, 31, 32, -1, -1, 35, 36, 37, 38, -1, - 40, -1, -1, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, 74, -1, -1, -1, 78, 79, - 80, -1, -1, 83, -1, -1, 86, -1, -1, -1, - -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, + 32, -1, -1, 35, 36, 37, 38, -1, 40, 41, + 42, 43, -1, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, 86, -1, -1, 89, -1, -1, + -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1, 114, 115, -1, 117, -1, 119, - 120, -1, 10, 11, -1, 13, -1, 127, 16, -1, - -1, 19, 20, 21, 22, -1, 24, 25, 26, 27, - 28, 29, 30, 31, 32, -1, -1, 35, 36, 37, - 38, -1, 40, -1, -1, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, 74, -1, -1, -1, - 78, 79, 80, -1, -1, -1, -1, -1, 86, -1, - -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, + -1, -1, -1, -1, 1, 117, 118, -1, 120, -1, + 122, 123, -1, 10, 11, -1, 13, -1, 130, 16, + -1, -1, 19, 20, 21, 22, -1, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, 35, 36, + 37, 38, -1, 40, 41, 42, 43, -1, -1, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, -1, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 89, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1, 114, 115, -1, 117, - -1, 119, 120, -1, 10, 11, -1, 13, -1, 127, - 16, -1, -1, 19, 20, 21, 22, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, 35, - 36, 37, 38, -1, 40, -1, -1, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - -1, 67, -1, 69, 70, 71, 72, 73, 74, -1, - -1, -1, 78, 79, 80, -1, 1, -1, -1, -1, - 86, -1, -1, -1, -1, 10, -1, 93, 13, -1, - -1, 16, -1, -1, 19, 20, 21, 22, -1, 24, - 25, -1, -1, -1, 29, 30, -1, -1, 114, 115, - -1, 117, -1, 119, 120, -1, -1, -1, -1, 44, - 45, 127, -1, -1, 49, 50, -1, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - -1, -1, 67, -1, -1, 70, 71, 72, 73, 74, - -1, -1, -1, 78, 79, 80, -1, 1, -1, -1, - -1, -1, -1, -1, -1, -1, 10, -1, 93, 13, - -1, -1, 16, -1, -1, 19, 20, 21, -1, -1, - 24, 25, -1, -1, -1, 29, 30, -1, -1, 114, - 115, -1, 117, -1, 119, 120, -1, -1, -1, -1, - 44, 45, 127, -1, -1, 49, 50, -1, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, -1, -1, 70, 71, 72, 73, - 74, -1, -1, -1, 78, 79, 80, -1, -1, -1, - -1, -1, -1, -1, -1, 10, 11, -1, 13, 93, - -1, 16, -1, -1, 19, 20, 21, -1, -1, 24, - 25, -1, -1, -1, 29, 30, -1, -1, -1, -1, - 114, 115, -1, 117, -1, 119, 120, -1, -1, 44, - 45, -1, 126, 127, 49, 50, -1, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - -1, -1, 67, -1, -1, 70, 71, 72, 73, 74, - -1, -1, -1, 78, 79, 80, -1, -1, -1, -1, - -1, -1, -1, -1, 10, 11, -1, 13, 93, -1, - 16, -1, -1, 19, 20, 21, -1, -1, 24, 25, - -1, -1, -1, 29, 30, -1, -1, -1, -1, 114, - 115, -1, 117, -1, 119, 120, -1, -1, 44, 45, - -1, -1, 127, 49, 50, -1, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, - -1, 67, -1, -1, 70, 71, 72, 73, 74, -1, - -1, -1, 78, 79, 80, -1, -1, -1, -1, -1, - -1, -1, -1, 10, -1, -1, 13, 93, -1, 16, - -1, -1, 19, 20, 21, -1, -1, 24, 25, -1, - -1, -1, 29, 30, -1, -1, -1, -1, 114, 115, - -1, 117, -1, 119, 120, -1, -1, 44, 45, -1, - -1, 127, 49, 50, -1, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, - 67, -1, -1, 70, 71, 72, 73, 74, -1, -1, - -1, 78, 79, 80, -1, -1, -1, -1, -1, -1, - -1, -1, 10, -1, -1, 13, 93, -1, 16, -1, - -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, - -1, 29, 30, -1, -1, -1, -1, 114, 115, -1, - 117, -1, 119, 120, -1, -1, 44, 45, -1, 126, - 127, 49, 50, -1, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, - -1, -1, 70, 71, 72, 73, 74, -1, -1, -1, - 78, 79, 80, -1, -1, -1, -1, -1, -1, -1, - -1, 10, -1, -1, 13, 93, -1, 16, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, + 117, 118, -1, 120, -1, 122, 123, -1, 10, 11, + -1, 13, -1, 130, 16, -1, -1, 19, 20, 21, + 22, -1, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, 35, 36, 37, 38, -1, 40, 41, + 42, 43, -1, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, 68, -1, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, 1, -1, -1, -1, 89, -1, -1, + -1, -1, 10, -1, 96, 13, -1, -1, 16, -1, + -1, 19, 20, 21, 22, -1, 24, 25, -1, -1, + -1, 29, 30, -1, -1, 117, 118, -1, 120, -1, + 122, 123, -1, -1, -1, -1, -1, -1, 130, 47, + 48, -1, -1, -1, 52, 53, -1, 55, 56, 57, + 58, 59, 60, -1, 62, 63, 64, 65, 66, 67, + -1, -1, 70, -1, -1, 73, 74, 75, 76, 77, + -1, -1, 1, 81, 82, 83, -1, -1, -1, -1, + -1, 10, -1, -1, 13, -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, - 29, 30, -1, -1, -1, -1, 114, 115, -1, 117, - -1, 119, 120, -1, -1, 44, 45, -1, 126, 127, - 49, 50, -1, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, -1, - -1, 70, 71, 72, 73, 74, -1, -1, -1, 78, - 79, 80, -1, -1, -1, -1, -1, -1, -1, -1, - 10, 11, -1, 13, 93, -1, 16, -1, -1, 19, + 29, 30, -1, -1, -1, -1, -1, -1, -1, 117, + 118, -1, 120, -1, 122, 123, -1, -1, 47, 48, + -1, -1, 130, 52, 53, -1, 55, 56, 57, 58, + 59, 60, -1, 62, 63, 64, 65, 66, 67, -1, + -1, 70, -1, -1, 73, 74, 75, 76, 77, -1, + -1, -1, 81, 82, 83, -1, -1, -1, -1, -1, + 10, 11, -1, 13, -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, - 30, -1, -1, -1, -1, 114, 115, -1, 117, -1, - 119, 120, -1, -1, 44, 45, -1, 126, 127, 49, - 50, -1, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, -1, -1, 67, -1, -1, - 70, 71, 72, 73, 74, -1, -1, -1, 78, 79, - 80, -1, -1, -1, -1, -1, -1, -1, -1, 10, - -1, -1, 13, 93, -1, 16, -1, -1, 19, 20, + 30, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, 120, -1, 122, 123, -1, -1, 47, 48, -1, + 129, 130, 52, 53, -1, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, -1, -1, + 70, -1, -1, 73, 74, 75, 76, 77, -1, -1, + -1, 81, 82, 83, -1, -1, -1, -1, -1, 10, + 11, -1, 13, -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, - -1, -1, -1, -1, 114, 115, -1, 117, -1, 119, - 120, -1, -1, 44, 45, -1, -1, 127, 49, 50, - -1, 52, 53, 54, 55, 56, 57, -1, 59, 60, - 61, 62, 63, 64, -1, -1, 67, -1, -1, 70, - 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, - -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, - -1, 13, 93, -1, 16, -1, -1, 19, 20, 21, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, + 120, -1, 122, 123, -1, -1, 47, 48, -1, -1, + 130, 52, 53, -1, 55, 56, 57, 58, 59, 60, + -1, 62, 63, 64, 65, 66, 67, -1, -1, 70, + -1, -1, 73, 74, 75, 76, 77, -1, -1, -1, + 81, 82, 83, -1, -1, -1, -1, -1, 10, -1, + -1, 13, -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, -1, - -1, -1, -1, 114, 115, -1, 117, -1, 119, 120, - -1, -1, 44, 45, -1, 126, 127, 49, 50, -1, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, -1, -1, 67, -1, -1, 70, 71, - 72, 73, 74, -1, -1, -1, 78, 79, 80, -1, - -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, - 13, 93, -1, 16, -1, -1, 19, 20, 21, -1, + -1, -1, -1, -1, -1, -1, 117, 118, -1, 120, + -1, 122, 123, -1, -1, 47, 48, -1, -1, 130, + 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, -1, -1, 70, -1, + -1, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, -1, -1, -1, 10, -1, -1, + 13, -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, -1, -1, - -1, -1, 114, 115, -1, 117, -1, 119, 120, -1, - -1, 44, 45, -1, 126, 127, 49, 50, -1, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, -1, -1, 67, -1, -1, 70, 71, 72, - 73, 74, -1, -1, -1, 78, 79, 80, -1, -1, - -1, -1, -1, -1, -1, -1, 10, -1, -1, 13, - 93, -1, 16, -1, -1, 19, 20, 21, -1, -1, + -1, -1, -1, -1, -1, 117, 118, -1, 120, -1, + 122, 123, -1, -1, 47, 48, -1, 129, 130, 52, + 53, -1, 55, 56, 57, 58, 59, 60, -1, 62, + 63, 64, 65, 66, 67, -1, -1, 70, -1, -1, + 73, 74, 75, 76, 77, -1, -1, -1, 81, 82, + 83, -1, -1, -1, -1, -1, 10, -1, -1, 13, + -1, -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, -1, -1, -1, - -1, 114, 115, -1, 117, -1, 119, 120, -1, -1, - 44, 45, -1, 126, 127, 49, 50, -1, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, -1, -1, 70, 71, 72, 73, - 74, -1, -1, -1, 78, 79, 80, -1, -1, -1, - -1, -1, -1, -1, -1, 10, -1, -1, 13, 93, - -1, 16, -1, -1, 19, 20, 21, -1, -1, 24, + -1, -1, -1, -1, 117, 118, -1, 120, -1, 122, + 123, -1, -1, 47, 48, -1, 129, 130, 52, 53, + -1, 55, 56, 57, 58, 59, 60, -1, 62, 63, + 64, 65, 66, 67, -1, -1, 70, -1, -1, 73, + 74, 75, 76, 77, -1, -1, -1, 81, 82, 83, + -1, -1, -1, -1, -1, 10, 11, -1, 13, -1, + -1, 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, -1, -1, -1, -1, - 114, 115, -1, 117, -1, 119, 120, -1, -1, 44, - 45, -1, 126, 127, 49, 50, -1, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - -1, -1, 67, -1, -1, 70, 71, 72, 73, 74, - -1, -1, -1, 78, 79, 80, -1, -1, -1, -1, - -1, -1, -1, -1, 10, -1, -1, 13, 93, -1, - 16, -1, -1, 19, 20, 21, -1, -1, 24, 25, - -1, -1, -1, 29, 30, -1, -1, -1, -1, 114, - 115, -1, 117, -1, 119, 120, -1, -1, 44, 45, - -1, -1, 127, 49, 50, -1, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, - -1, 67, -1, -1, 70, 71, 72, 73, 74, -1, - -1, -1, 78, 79, 80, -1, -1, -1, -1, -1, - -1, -1, -1, 10, -1, -1, 13, 93, -1, 16, - -1, -1, 19, 20, 21, -1, -1, 24, 25, -1, - -1, -1, 29, 30, -1, -1, -1, -1, 114, 115, - -1, 117, -1, 119, 120, -1, -1, 44, 45, -1, - -1, 127, 49, 50, -1, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, - 67, -1, -1, 70, 71, 72, 73, 74, -1, -1, - -1, 78, 79, 80, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, - -1, 68, -1, -1, -1, -1, -1, -1, 75, 76, - 77, -1, -1, -1, -1, -1, -1, 114, 115, -1, - 117, 88, 119, 120, -1, -1, -1, 94, 95, 96, - 127, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, -1, -1, -1, - -1, 118, 68, -1, 121, 122, 123, 124, 125, 75, - 76, 77, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 88, -1, -1, -1, -1, -1, 94, 95, - 96, -1, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, -1, -1, - -1, -1, 118, 68, -1, 121, 122, 123, 124, 125, - 75, 76, 77, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, - 95, 96, -1, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, -1, - -1, -1, -1, 118, 68, -1, 121, 122, 123, 124, - 125, 75, 76, 77, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, - 76, 77, 96, -1, 98, 99, 100, 101, 102, 103, + -1, -1, -1, 117, 118, -1, 120, -1, 122, 123, + -1, -1, 47, 48, -1, 129, 130, 52, 53, -1, + 55, 56, 57, 58, 59, 60, -1, 62, 63, 64, + 65, 66, 67, -1, -1, 70, -1, -1, 73, 74, + 75, 76, 77, -1, -1, -1, 81, 82, 83, -1, + -1, -1, -1, -1, 10, -1, -1, 13, -1, -1, + 16, 96, -1, 19, 20, 21, -1, -1, 24, 25, + -1, -1, -1, 29, 30, -1, -1, -1, -1, -1, + -1, -1, 117, 118, -1, 120, -1, 122, 123, -1, + -1, 47, 48, -1, -1, 130, 52, 53, -1, 55, + 56, 57, 58, 59, 60, -1, 62, 63, 64, 65, + 66, 67, -1, -1, 70, -1, -1, 73, 74, 75, + 76, 77, -1, -1, -1, 81, 82, 83, -1, -1, + -1, -1, -1, 10, -1, -1, 13, -1, -1, 16, + 96, -1, 19, 20, 21, -1, -1, 24, 25, -1, + -1, -1, 29, 30, -1, -1, -1, -1, -1, -1, + -1, 117, 118, -1, 120, -1, 122, 123, -1, -1, + 47, 48, -1, 129, 130, 52, 53, -1, 55, 56, + 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, + 67, -1, -1, 70, -1, -1, 73, 74, 75, 76, + 77, -1, -1, -1, 81, 82, 83, -1, -1, -1, + -1, -1, 10, -1, -1, 13, -1, -1, 16, 96, + -1, 19, 20, 21, -1, -1, 24, 25, -1, -1, + -1, 29, 30, -1, -1, -1, -1, -1, -1, -1, + 117, 118, -1, 120, -1, 122, 123, -1, -1, 47, + 48, -1, 129, 130, 52, 53, -1, 55, 56, 57, + 58, 59, 60, -1, 62, 63, 64, 65, 66, 67, + -1, -1, 70, -1, -1, 73, 74, 75, 76, 77, + -1, -1, -1, 81, 82, 83, -1, -1, -1, -1, + -1, 10, -1, -1, 13, -1, -1, 16, 96, -1, + 19, 20, 21, -1, -1, 24, 25, -1, -1, -1, + 29, 30, -1, -1, -1, -1, -1, -1, -1, 117, + 118, -1, 120, -1, 122, 123, -1, -1, 47, 48, + -1, 129, 130, 52, 53, -1, 55, 56, 57, 58, + 59, 60, -1, 62, 63, 64, 65, 66, 67, -1, + -1, 70, -1, -1, 73, 74, 75, 76, 77, -1, + -1, -1, 81, 82, 83, -1, -1, -1, -1, -1, + 10, -1, -1, 13, -1, -1, 16, 96, -1, 19, + 20, 21, -1, -1, 24, 25, -1, -1, -1, 29, + 30, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, 120, -1, 122, 123, -1, -1, 47, 48, -1, + 129, 130, 52, 53, -1, 55, 56, 57, 58, 59, + 60, -1, 62, 63, 64, 65, 66, 67, -1, -1, + 70, -1, -1, 73, 74, 75, 76, 77, -1, -1, + -1, 81, 82, 83, -1, -1, -1, -1, -1, 10, + -1, -1, 13, -1, -1, 16, 96, -1, 19, 20, + 21, -1, -1, 24, 25, -1, -1, -1, 29, 30, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, + 120, -1, 122, 123, -1, -1, 47, 48, -1, -1, + 130, 52, 53, -1, 55, 56, 57, 58, 59, 60, + -1, 62, 63, 64, 65, 66, 67, -1, -1, 70, + -1, -1, 73, 74, 75, 76, 77, -1, -1, -1, + 81, 82, 83, -1, -1, -1, -1, -1, 10, -1, + -1, 13, -1, -1, 16, 96, -1, 19, 20, 21, + -1, -1, 24, 25, -1, -1, -1, 29, 30, -1, + -1, -1, -1, -1, -1, -1, 117, 118, -1, 120, + -1, 122, 123, -1, -1, 47, 48, -1, -1, 130, + 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, + 62, 63, 64, 65, 66, 67, -1, -1, 70, -1, + -1, 73, 74, 75, 76, 77, -1, -1, -1, 81, + 82, 83, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, + -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, + 78, 79, 80, -1, -1, 117, 118, -1, 120, -1, + 122, 123, -1, 91, -1, -1, -1, -1, 130, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + -1, -1, -1, 121, 71, -1, 124, 125, 126, 127, + 128, 78, 79, 80, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 91, -1, -1, -1, -1, -1, + 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, -1, -1, -1, 121, 71, -1, 124, 125, 126, + 127, 128, 78, 79, 80, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 91, -1, -1, -1, -1, + -1, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, -1, -1, -1, 121, 71, -1, 124, 125, + 126, 127, 128, 78, 79, 80, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 97, 98, 99, -1, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, -1, -1, -1, 121, 71, -1, 124, + 125, 126, 127, 128, 78, 79, 80, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 78, 79, 80, 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - -1, -1, -1, -1, 118, 68, -1, 121, 122, 123, - 124, 125, 75, 76, 77, 111, 112, 113, -1, -1, - -1, -1, 118, -1, -1, 121, 122, 123, 124, 125, - -1, -1, -1, -1, -1, 98, 99, 100, 101, 102, + 114, 115, 116, -1, -1, -1, -1, 121, 71, -1, + 124, 125, 126, 127, 128, 78, 79, 80, 114, 115, + 116, -1, -1, -1, -1, 121, -1, -1, 124, 125, + 126, 127, 128, -1, -1, -1, -1, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 75, 76, 77, -1, 118, -1, -1, 121, 122, - 123, 124, 125, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 101, 102, 103, + 113, 114, 115, 116, 78, 79, 80, -1, 121, -1, + -1, 124, 125, 126, 127, 128, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 78, 79, 80, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - -1, -1, -1, -1, 118, -1, -1, 121, 122, 123, - 124, 125, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 75, 76, 77, -1, 118, -1, -1, - 121, 122, 123, 124, 125, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, -1, -1, -1, - -1, -1, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, -1, 75, 76, 77, 118, -1, -1, 121, - 122, 123, 124, 125, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 75, 76, 77, -1, 118, -1, -1, - 121, 122, 123, 124, 125, 107, 108, 109, 110, 111, - 112, 113, 75, 76, 77, -1, 118, -1, -1, 121, - 122, 123, 124, 125, -1, -1, -1, 109, 110, 111, - 112, 113, 75, 76, 77, -1, 118, -1, -1, 121, - 122, 123, 124, 125, -1, -1, 109, 110, 111, 112, - 113, -1, -1, -1, -1, 118, -1, -1, 121, 122, - 123, 124, 125, -1, -1, -1, -1, 110, 111, 112, - 113, -1, -1, -1, -1, 118, -1, -1, 121, 122, - 123, 124, 125 + 114, 115, 116, -1, -1, -1, -1, 121, -1, -1, + 124, 125, 126, 127, 128, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 78, 79, 80, -1, + 121, -1, -1, 124, 125, 126, 127, 128, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 78, 79, 80, + -1, -1, -1, -1, -1, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 78, 79, 80, 121, + -1, -1, 124, 125, 126, 127, 128, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 78, 79, 80, -1, + 121, -1, -1, 124, 125, 126, 127, 128, 110, 111, + 112, 113, 114, 115, 116, 78, 79, 80, -1, 121, + -1, -1, 124, 125, 126, 127, 128, -1, -1, -1, + 112, 113, 114, 115, 116, 78, 79, 80, -1, 121, + -1, -1, 124, 125, 126, 127, 128, -1, -1, 112, + 113, 114, 115, 116, -1, -1, -1, -1, 121, -1, + -1, 124, 125, 126, 127, 128, -1, -1, -1, -1, + 113, 114, 115, 116, -1, -1, -1, -1, 121, -1, + -1, 124, 125, 126, 127, 128 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 5, 6, 7, 8, 9, 129, 130, - 131, 132, 133, 134, 135, 136, 0, 141, 10, 13, - 16, 19, 20, 21, 24, 25, 29, 30, 44, 45, - 49, 50, 52, 53, 54, 55, 56, 57, 59, 60, - 61, 62, 63, 64, 67, 70, 71, 72, 73, 74, - 78, 79, 80, 93, 114, 115, 117, 119, 120, 127, - 139, 201, 202, 203, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 217, 224, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 11, 138, 1, 22, 26, - 27, 28, 31, 32, 35, 36, 37, 38, 40, 43, - 46, 47, 48, 51, 65, 69, 86, 137, 138, 151, - 165, 201, 221, 66, 149, 150, 151, 139, 147, 194, - 195, 147, 53, 58, 138, 233, 241, 224, 241, 215, - 241, 215, 241, 241, 215, 117, 127, 218, 233, 234, - 235, 215, 138, 215, 177, 177, 178, 241, 241, 216, - 13, 127, 215, 177, 215, 127, 127, 84, 127, 138, - 215, 53, 139, 202, 223, 233, 241, 241, 224, 53, - 58, 180, 202, 215, 215, 215, 215, 215, 126, 201, - 89, 90, 91, 92, 15, 11, 13, 127, 107, 108, - 107, 105, 106, 105, 68, 75, 76, 77, 88, 94, - 95, 96, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 118, 121, - 122, 123, 124, 125, 127, 11, 13, 11, 13, 11, - 13, 11, 141, 179, 53, 53, 219, 233, 234, 235, - 127, 127, 30, 117, 127, 231, 233, 127, 127, 11, - 142, 142, 176, 180, 22, 176, 180, 39, 139, 167, - 22, 32, 35, 36, 37, 38, 22, 150, 151, 149, - 16, 20, 24, 139, 185, 186, 188, 189, 190, 191, - 14, 127, 215, 218, 233, 234, 235, 126, 201, 81, - 183, 56, 139, 181, 81, 139, 182, 182, 223, 127, - 84, 201, 126, 138, 126, 126, 201, 224, 224, 241, - 202, 22, 223, 13, 126, 201, 201, 201, 201, 215, - 201, 201, 126, 201, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 10, 11, 13, 16, 20, 24, 25, 54, - 78, 127, 205, 233, 126, 201, 201, 201, 201, 201, - 201, 201, 201, 147, 53, 139, 175, 53, 53, 81, - 139, 220, 141, 141, 117, 141, 30, 229, 230, 232, - 233, 234, 235, 141, 141, 127, 141, 141, 143, 41, - 155, 176, 154, 176, 138, 164, 201, 164, 164, 172, - 201, 164, 58, 184, 184, 15, 126, 201, 183, 126, - 56, 182, 56, 141, 199, 199, 224, 202, 14, 204, - 126, 85, 126, 201, 12, 201, 13, 22, 14, 126, - 97, 25, 201, 201, 25, 25, 25, 25, 25, 126, - 201, 127, 126, 22, 14, 22, 14, 22, 14, 22, - 12, 18, 140, 11, 22, 182, 56, 94, 173, 201, - 173, 127, 226, 233, 127, 139, 165, 170, 173, 174, - 201, 229, 141, 172, 171, 201, 147, 141, 53, 152, - 22, 141, 196, 197, 153, 94, 139, 187, 187, 189, - 126, 197, 127, 139, 192, 193, 126, 23, 139, 225, - 223, 126, 14, 201, 12, 215, 22, 14, 126, 224, - 12, 12, 12, 12, 141, 141, 11, 22, 222, 126, - 126, 227, 228, 233, 127, 141, 126, 22, 158, 173, - 126, 126, 12, 127, 139, 144, 53, 181, 11, 182, - 215, 194, 11, 201, 85, 14, 12, 126, 22, 160, - 141, 215, 142, 142, 15, 126, 173, 173, 142, 156, - 127, 126, 169, 169, 145, 159, 223, 182, 147, 22, - 198, 199, 126, 200, 83, 147, 161, 33, 34, 139, - 166, 166, 233, 127, 126, 126, 167, 171, 173, 142, - 142, 142, 233, 142, 22, 196, 12, 147, 139, 148, - 12, 147, 142, 127, 173, 142, 142, 22, 126, 167, - 167, 167, 146, 42, 168, 12, 22, 56, 162, 12, - 173, 126, 167, 167, 157, 142, 126, 138, 17, 82, - 139, 163, 126, 142, 169, 167, 147, 142, 167, 174, - 83, 166, 126, 142 + 0, 3, 4, 5, 6, 7, 8, 9, 132, 133, + 134, 135, 136, 137, 138, 139, 0, 144, 10, 13, + 16, 19, 20, 21, 24, 25, 29, 30, 47, 48, + 52, 53, 55, 56, 57, 58, 59, 60, 62, 63, + 64, 65, 66, 67, 70, 73, 74, 75, 76, 77, + 81, 82, 83, 96, 117, 118, 120, 122, 123, 130, + 142, 204, 205, 206, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 220, 227, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 11, 141, 1, 22, 26, + 27, 28, 31, 32, 35, 36, 37, 38, 40, 41, + 42, 43, 46, 49, 50, 51, 54, 68, 72, 89, + 140, 141, 154, 168, 204, 224, 69, 152, 153, 154, + 142, 150, 197, 198, 150, 56, 61, 141, 236, 244, + 227, 244, 218, 244, 218, 244, 244, 218, 120, 130, + 221, 236, 237, 238, 218, 141, 218, 180, 180, 181, + 244, 244, 219, 13, 130, 218, 180, 218, 130, 130, + 87, 130, 141, 218, 56, 142, 205, 226, 236, 244, + 244, 227, 56, 61, 183, 205, 218, 218, 218, 218, + 218, 129, 204, 92, 93, 94, 95, 15, 11, 13, + 130, 110, 111, 110, 108, 109, 108, 71, 78, 79, + 80, 91, 97, 98, 99, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 121, 124, 125, 126, 127, 128, 130, 11, 13, + 11, 13, 11, 13, 11, 144, 182, 56, 56, 222, + 236, 237, 238, 130, 130, 30, 120, 130, 234, 236, + 130, 130, 130, 130, 141, 11, 145, 145, 179, 183, + 22, 179, 183, 39, 142, 170, 22, 32, 35, 36, + 37, 38, 41, 22, 153, 154, 152, 16, 20, 24, + 142, 188, 189, 191, 192, 193, 194, 14, 130, 218, + 221, 236, 237, 238, 129, 204, 84, 186, 59, 142, + 184, 84, 142, 185, 185, 226, 130, 87, 204, 129, + 141, 129, 129, 204, 227, 227, 244, 205, 22, 226, + 13, 129, 204, 204, 204, 204, 218, 204, 204, 129, + 204, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 10, + 11, 13, 16, 20, 24, 25, 57, 81, 130, 208, + 236, 129, 204, 204, 204, 204, 204, 204, 204, 204, + 150, 56, 142, 178, 56, 56, 84, 142, 223, 144, + 144, 120, 144, 30, 232, 233, 235, 236, 237, 238, + 144, 144, 130, 144, 144, 144, 144, 146, 44, 158, + 179, 157, 179, 141, 167, 204, 167, 167, 175, 204, + 167, 167, 61, 187, 187, 15, 129, 204, 186, 129, + 59, 185, 59, 144, 202, 202, 227, 205, 14, 207, + 129, 88, 129, 204, 12, 204, 13, 22, 14, 129, + 100, 25, 204, 204, 25, 25, 25, 25, 25, 129, + 204, 130, 129, 22, 14, 22, 14, 22, 14, 22, + 12, 18, 143, 11, 22, 185, 59, 97, 176, 204, + 176, 130, 229, 236, 130, 142, 168, 173, 176, 177, + 204, 232, 144, 175, 174, 204, 176, 176, 150, 144, + 56, 155, 22, 144, 199, 200, 156, 97, 142, 190, + 190, 192, 129, 200, 130, 142, 195, 196, 129, 23, + 142, 228, 226, 129, 14, 204, 12, 218, 22, 14, + 129, 227, 12, 12, 12, 12, 144, 144, 11, 22, + 225, 129, 129, 230, 231, 236, 130, 144, 129, 22, + 161, 176, 129, 129, 129, 129, 12, 130, 142, 147, + 56, 184, 11, 185, 218, 197, 11, 204, 88, 14, + 12, 129, 22, 163, 144, 218, 145, 145, 15, 129, + 176, 176, 145, 159, 130, 129, 172, 172, 145, 145, + 148, 162, 226, 185, 150, 22, 201, 202, 129, 203, + 86, 150, 164, 33, 34, 142, 169, 169, 236, 130, + 129, 129, 170, 174, 176, 145, 145, 145, 236, 145, + 22, 199, 12, 150, 142, 151, 12, 150, 145, 130, + 176, 145, 145, 22, 129, 170, 170, 170, 149, 45, + 171, 12, 22, 59, 165, 12, 176, 129, 170, 170, + 160, 145, 129, 141, 17, 85, 142, 166, 129, 145, + 172, 170, 150, 145, 170, 177, 86, 169, 129, 145 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_uint8 yyr1[] = { - 0, 128, 130, 129, 131, 129, 132, 129, 133, 129, - 134, 129, 135, 129, 136, 129, 137, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 144, 147, 147, - 148, 148, 149, 149, 150, 150, 151, 151, 152, 151, - 153, 151, 154, 151, 151, 151, 155, 151, 151, 151, - 151, 151, 156, 157, 151, 151, 151, 151, 158, 151, - 151, 151, 159, 151, 151, 160, 151, 161, 151, 151, - 151, 151, 151, 151, 162, 163, 163, 164, 165, 165, - 165, 165, 165, 165, 165, 166, 166, 166, 167, 167, - 168, 168, 169, 170, 170, 171, 171, 172, 173, 174, - 175, 175, 176, 177, 178, 179, 180, 180, 181, 181, - 182, 182, 182, 183, 183, 184, 184, 185, 185, 186, - 187, 187, 187, 188, 189, 189, 190, 190, 190, 191, - 191, 192, 192, 193, 195, 194, 196, 196, 197, 198, - 198, 200, 199, 201, 201, 201, 201, 201, 202, 202, - 202, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 204, 203, 205, 205, 206, 206, 206, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, 207, 207, - 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, - 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, - 208, 208, 208, 208, 208, 209, 209, 210, 210, 210, - 210, 211, 211, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 213, 213, 213, 213, 213, 214, 214, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 216, 215, 215, - 215, 215, 217, 217, 217, 217, 218, 218, 218, 218, - 218, 219, 219, 219, 220, 220, 220, 221, 222, 221, - 223, 223, 224, 224, 225, 225, 226, 227, 227, 227, - 228, 229, 229, 229, 230, 230, 231, 231, 232, 233, - 234, 235, 236, 236, 237, 238, 238, 239, 239, 240, - 240, 241, 241, 241, 241 + 0, 131, 133, 132, 134, 132, 135, 132, 136, 132, + 137, 132, 138, 132, 139, 132, 140, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 147, 150, 150, + 151, 151, 152, 152, 153, 153, 154, 154, 155, 154, + 156, 154, 157, 154, 154, 154, 158, 154, 154, 154, + 154, 154, 154, 154, 154, 159, 160, 154, 154, 154, + 154, 161, 154, 154, 154, 162, 154, 154, 163, 154, + 164, 154, 154, 154, 154, 154, 154, 165, 166, 166, + 167, 168, 168, 168, 168, 168, 168, 168, 168, 169, + 169, 169, 170, 170, 171, 171, 172, 173, 173, 174, + 174, 175, 176, 177, 178, 178, 179, 180, 181, 182, + 183, 183, 184, 184, 185, 185, 185, 186, 186, 187, + 187, 188, 188, 189, 190, 190, 190, 191, 192, 192, + 193, 193, 193, 194, 194, 195, 195, 196, 198, 197, + 199, 199, 200, 201, 201, 203, 202, 204, 204, 204, + 204, 204, 205, 205, 205, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 207, 206, 208, 208, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 211, 211, 211, 211, 211, 212, + 212, 213, 213, 213, 213, 214, 214, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 216, 216, 216, 216, + 216, 217, 217, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 219, 218, 218, 218, 218, 220, 220, 220, 220, + 221, 221, 221, 221, 221, 222, 222, 222, 223, 223, + 223, 224, 225, 224, 226, 226, 227, 227, 228, 228, + 229, 230, 230, 230, 231, 232, 232, 232, 233, 233, + 234, 234, 235, 236, 237, 238, 239, 239, 240, 241, + 241, 242, 242, 243, 243, 244, 244, 244, 244 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ @@ -1483,35 +1499,35 @@ static const yytype_int8 yyr2[] = 7, 0, 4, 0, 1, 0, 0, 5, 1, 2, 1, 2, 1, 1, 2, 2, 1, 4, 0, 7, 0, 6, 0, 4, 4, 5, 0, 7, 7, 7, - 8, 8, 0, 0, 13, 9, 11, 8, 0, 10, - 9, 7, 0, 8, 2, 0, 8, 0, 9, 2, - 2, 2, 2, 1, 2, 1, 3, 1, 1, 1, - 3, 3, 3, 3, 3, 1, 2, 6, 1, 2, - 0, 2, 0, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, - 1, 2, 1, 2, 1, 0, 1, 1, 1, 3, - 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, - 1, 1, 1, 3, 0, 2, 1, 1, 4, 1, - 1, 0, 6, 3, 3, 3, 3, 1, 2, 3, - 1, 3, 5, 6, 3, 3, 5, 2, 4, 4, - 0, 5, 1, 1, 5, 4, 5, 4, 5, 6, - 5, 4, 5, 4, 3, 6, 4, 5, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 1, 3, 2, 2, 3, 3, 3, 1, 3, 2, - 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 4, 5, 4, 4, 2, 2, 1, - 1, 1, 1, 5, 2, 1, 2, 3, 1, 2, - 1, 1, 1, 1, 1, 1, 4, 4, 5, 5, - 1, 1, 3, 4, 3, 4, 4, 4, 4, 4, - 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, - 1, 3, 1, 3, 1, 3, 4, 0, 6, 1, - 1, 1, 3, 2, 4, 3, 3, 2, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 3, 0, 6, - 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, - 2, 2, 2, 4, 2, 1, 3, 1, 3, 1, - 3, 1, 1, 1, 1 + 6, 6, 2, 8, 8, 0, 0, 13, 9, 11, + 8, 0, 10, 9, 7, 0, 8, 2, 0, 8, + 0, 9, 2, 2, 2, 2, 1, 2, 1, 3, + 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, + 2, 6, 1, 2, 0, 2, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 2, 1, 2, 1, 0, + 1, 1, 1, 3, 1, 1, 2, 3, 1, 1, + 2, 3, 1, 1, 1, 1, 1, 3, 0, 2, + 1, 1, 4, 1, 1, 0, 6, 3, 3, 3, + 3, 1, 2, 3, 1, 3, 5, 6, 3, 3, + 5, 2, 4, 4, 0, 5, 1, 1, 5, 4, + 5, 4, 5, 6, 5, 4, 5, 4, 3, 6, + 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 1, 3, 2, 2, 3, 3, + 3, 1, 3, 2, 2, 3, 3, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 4, 5, 4, + 4, 2, 2, 1, 1, 1, 1, 5, 2, 1, + 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, + 4, 4, 5, 5, 1, 1, 3, 4, 3, 4, + 4, 4, 4, 4, 1, 2, 2, 1, 2, 2, + 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, + 4, 0, 6, 1, 1, 1, 3, 2, 4, 3, + 3, 2, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 3, 0, 6, 1, 1, 1, 1, 1, 2, + 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 4, 2, 1, + 3, 1, 3, 1, 3, 1, 1, 1, 1 }; typedef enum { @@ -1531,15 +1547,15 @@ static const toketypes yy_type_tab[] = toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, + toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, - toketype_ival, toketype_ival, toketype_ival, toketype_opval, - toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, + toketype_ival, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, - toketype_opval, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, - toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, + toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_ival, toketype_ival, toketype_ival, + toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, - toketype_ival, toketype_ival, toketype_ival, + toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_ival, @@ -1569,6 +1585,6 @@ static const toketypes yy_type_tab[] = }; /* Generated from: - * 9fc11f4af92f701d8d7909a9cd9dc52e01098c42c2504fb84c15e1d1e72f4803 perly.y + * 823630846fc59cc2a19502726ec723b568eabded55fdc5e9722c600e1098779e perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.y b/perly.y index 6a6510823f0a..3f524bfabc66 100644 --- a/perly.y +++ b/perly.y @@ -68,6 +68,7 @@ %token KW_LOCAL KW_MY KW_FIELD %token KW_IF KW_ELSE KW_ELSIF KW_UNLESS %token KW_FOR KW_UNTIL KW_WHILE KW_CONTINUE +%token KW_GIVEN KW_WHEN KW_DEFAULT %token KW_TRY KW_CATCH KW_FINALLY KW_DEFER %token KW_REQUIRE KW_DO @@ -472,6 +473,15 @@ barestmt: PLUGSTMT newCONDOP(0, $mexpr, $else, op_scope($mblock))); parser->copline = (line_t)$KW_UNLESS; } + | KW_GIVEN PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock + { + $$ = block_end($remember, newGIVENOP($mexpr, op_scope($mblock), 0)); + parser->copline = (line_t)$KW_GIVEN; + } + | KW_WHEN PERLY_PAREN_OPEN remember mexpr PERLY_PAREN_CLOSE mblock + { $$ = block_end($remember, newWHENOP($mexpr, op_scope($mblock))); } + | KW_DEFAULT block + { $$ = newWHENOP(0, op_scope($block)); } | KW_WHILE PERLY_PAREN_OPEN remember texpr PERLY_PAREN_CLOSE mintro mblock cont { $$ = block_end($remember, @@ -679,6 +689,8 @@ sideff : error | expr[body] KW_FOR condition { $$ = newFOROP(0, NULL, $condition, $body, NULL); parser->copline = (line_t)$KW_FOR; } + | expr[body] KW_WHEN condition + { $$ = newWHENOP($condition, op_scope($body)); } ; /* else and elsif blocks */ diff --git a/pod/perldiag.pod b/pod/perldiag.pod index a48ddff5931b..f19bab3feb39 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -868,6 +868,15 @@ object instance. (F) Only hard references may be blessed. This is how Perl "enforces" encapsulation of objects. See L. +=item Can't "break" in a loop topicalizer + +(F) You called C, but you're in a C block rather than +a C block. You probably meant to use C or C. + +=item Can't "break" outside a given block + +(F) You called C, but you're not inside a C block. + =item Can't call destructor for 0x%p in global destruction (S) This should not happen. Internals code has set up a destructor @@ -934,6 +943,11 @@ You CAN say but then $foo no longer contains a glob. +=item Can't "continue" outside a when block + +(F) You called C, but you're not inside a C +or C block. + =item can't convert empty path (F) On Cygwin, you called a path conversion function with an empty path. @@ -949,6 +963,13 @@ quotas or other plumbing problems. (F) Only scalar, array, and hash variables may be declared as "my", "our" or "state" variables. They must have ordinary identifiers as names. +=item Can't "default" outside a topicalizer + +(F) You have used a C block that is neither inside a +C loop nor a C block. (Note that this error is +issued on exit from the C block, so you won't get the +error if you use an explicit C.) + =item Can't determine class of operator %s, assuming BASEOP (S) This warning indicates something wrong in the internals of perl. @@ -1147,6 +1168,11 @@ error occurs in cases such as these: (F) A C statement was executed to jump into the scope of a C block. This is not permitted. +=item Can't "goto" into a "given" block + +(F) A "goto" statement was executed to jump into the middle of a C +block. You can't get there from here. See L. + =item Can't "goto" into the middle of a foreach loop (F) A "goto" statement was executed to jump into the middle of a foreach @@ -1675,6 +1701,13 @@ instead. (F) You attempted to weaken something that was not a reference. Only references can be weakened. +=item Can't "when" outside a topicalizer + +(F) You have used a when() block that is neither inside a C +loop nor a C block. (Note that this error is issued on exit +from the C block, so you won't get the error if the match fails, +or if you use an explicit C.) + =item Can't x= to read-only value (F) You tried to repeat a constant value (often the undefined value) @@ -2723,6 +2756,12 @@ L. arguments are provided in key/value pairs, with the keys being one of C, C or C, followed by a boolean. +=item given is deprecated + +(D deprecated::smartmatch) C depends on smartmatch, which is +deprecated. It will be removed in Perl 5.42. See the explanation under +L. + =item Global symbol "%s" requires explicit package name (did you forget to declare "my %s"?) @@ -8170,6 +8209,14 @@ but in actual fact, you got So put in parentheses to say what you really mean. +=item when is deprecated + +(D deprecated::smartmatch) C depends on smartmatch, which is +deprecated. Additionally, it has several special cases that may +not be immediately obvious, and it will be removed in Perl 5.42. +See the explanation +under L. + =item Wide character in %s (S utf8) Perl met a wide character (ordinal >255) when it wasn't diff --git a/pod/perlguts.pod b/pod/perlguts.pod index df6404c36874..4a7fbaf487d9 100644 --- a/pod/perlguts.pod +++ b/pod/perlguts.pod @@ -4195,6 +4195,7 @@ valid. =for apidoc Cmnh||CXt_BLOCK =for apidoc_item ||CXt_EVAL =for apidoc_item ||CXt_FORMAT +=for apidoc_item ||CXt_GIVEN =for apidoc_item ||CXt_LOOP_ARY =for apidoc_item ||CXt_LOOP_LAZYIV =for apidoc_item ||CXt_LOOP_LAZYSV @@ -4203,6 +4204,7 @@ valid. =for apidoc_item ||CXt_NULL =for apidoc_item ||CXt_SUB =for apidoc_item ||CXt_SUBST +=for apidoc_item ||CXt_WHEN The main division in the context struct is between a substitution scope (C) and block scopes, which are everything else. The former is diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index b5ad0cda01f6..323a70b4b78e 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -216,9 +216,22 @@ it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons. X +The C modifier is an experimental feature that first appeared in Perl +5.14. To use it, you should include a C declaration. +(Technically, it requires only the C feature, but that aspect of it +was not available before 5.14.) Operative only from within a C +loop or a C block, it executes the statement only if the smartmatch +C<< $_ ~~ I >> is true. If the statement executes, it is followed by +a C from inside a C and C from inside a C. + +Under the current implementation, the C loop can be +anywhere within the C modifier's dynamic scope, but must be +within the C block's lexical scope. This restriction may +be relaxed in a future release. See L below. + =head2 Compound Statements X X X X X -X<{> X<}> X X X X X X X +X<{> X<}> X X X X X X X X In Perl, a sequence of statements that defines a scope is called a block. Sometimes a block is delimited by the file containing it (in the case @@ -248,6 +261,8 @@ The following compound statements may be used to control flow: unless (EXPR) BLOCK elsif (EXPR) BLOCK ... unless (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK + given (EXPR) BLOCK + LABEL while (EXPR) BLOCK LABEL while (EXPR) BLOCK continue BLOCK @@ -280,6 +295,9 @@ If enabled by the C feature, the following may also be used try BLOCK catch (VAR) BLOCK try BLOCK catch (VAR) BLOCK finally BLOCK +The experimental C statement is I; see +L below for how to do so, and the attendant caveats. + Unlike in C and Pascal, in Perl these are all defined in terms of BLOCKs, not statements. This means that the curly brackets are I--no dangling statements allowed. If you want to write conditionals without @@ -754,8 +772,9 @@ and a switch: $nothing = 1; } -Such constructs are quite frequently used, both because -Perl has no official C statement. +Such constructs are quite frequently used, both because older versions of +Perl had no official C statement, and also because the new version +described immediately below remains experimental and can sometimes be confusing. =head2 defer blocks X @@ -840,10 +859,93 @@ C. =head2 Switch Statements -Switch statements were removed in Perl 5.42. - X X X X X +Starting from Perl 5.10.1 (well, 5.10.0, but it didn't work +right), you can say + + use feature "switch"; + +to enable an experimental switch feature. This is loosely based on an +old version of a Raku proposal, but it no longer resembles the Raku +construct. You also get the switch feature whenever you declare that your +code prefers to run under a version of Perl between 5.10 and 5.34. For +example: + + use v5.14; + +Under the "switch" feature, Perl gains the experimental keywords +C, C, C, C, and C. +Starting from Perl 5.16, one can prefix the switch +keywords with C to access the feature without a C +statement. The keywords C and +C are analogous to C and +C in other languages -- though C is not -- so the code +in the previous section could be rewritten as + + use v5.10.1; + for ($var) { + when (/^abc/) { $abc = 1 } + when (/^def/) { $def = 1 } + when (/^xyz/) { $xyz = 1 } + default { $nothing = 1 } + } + +The C is the non-experimental way to set a topicalizer. +If you wish to use the highly experimental C, that could be +written like this: + + use v5.10.1; + given ($var) { + when (/^abc/) { $abc = 1 } + when (/^def/) { $def = 1 } + when (/^xyz/) { $xyz = 1 } + default { $nothing = 1 } + } + +As of 5.14, that can also be written this way: + + use v5.14; + for ($var) { + $abc = 1 when /^abc/; + $def = 1 when /^def/; + $xyz = 1 when /^xyz/; + default { $nothing = 1 } + } + +Or if you don't care to play it safe, like this: + + use v5.14; + given ($var) { + $abc = 1 when /^abc/; + $def = 1 when /^def/; + $xyz = 1 when /^xyz/; + default { $nothing = 1 } + } + +The arguments to C and C are in scalar context, +and C assigns the C<$_> variable its topic value. + +Exactly what the I argument to C does is hard to describe +precisely, but in general, it tries to guess what you want done. Sometimes +it is interpreted as C<< $_ ~~ I >>, and sometimes it is not. It +also behaves differently when lexically enclosed by a C block than +it does when dynamically enclosed by a C loop. The rules are far +too difficult to understand to be described here. See L later on. + +Due to an unfortunate bug in how C was implemented between Perl 5.10 +and 5.16, under those implementations the version of C<$_> governed by +C is merely a lexically scoped copy of the original, not a +dynamically scoped alias to the original, as it would be if it were a +C or under both the original and the current Raku language +specification. This bug was fixed in Perl 5.18 (and lexicalized C<$_> itself +was removed in Perl 5.24). + +If your code still needs to run on older versions, +stick to C for your topicalizer and +you will be less unhappy. + =head2 Goto X @@ -1053,4 +1155,336 @@ shell: __END__ foo at goop line 345. +=head2 Experimental Details on given and when + +As previously mentioned, the "switch" feature is considered highly +experimental (it is also scheduled to be removed in perl 5.42.0); +it is subject to change with little notice. In particular, +C has tricky behaviours that are expected to change to become less +tricky in the future. Do not rely upon its current (mis)implementation. +Before Perl 5.18, C also had tricky behaviours that you should still +beware of if your code must run on older versions of Perl. + +Here is a longer example of C: + + use feature ":5.10"; + given ($foo) { + when (undef) { + say '$foo is undefined'; + } + when ("foo") { + say '$foo is the string "foo"'; + } + when ([1,3,5,7,9]) { + say '$foo is an odd digit'; + continue; # Fall through + } + when ($_ < 100) { + say '$foo is numerically less than 100'; + } + when (\&complicated_check) { + say 'a complicated check for $foo is true'; + } + default { + die q(I don't know what to do with $foo); + } + } + +Before Perl 5.18, C assigned the value of I to +merely a lexically scoped I> (!) of C<$_>, not a dynamically +scoped alias the way C does. That made it similar to + + do { my $_ = EXPR; ... } + +except that the block was automatically broken out of by a successful +C or an explicit C. Because it was only a copy, and because +it was only lexically scoped, not dynamically scoped, you could not do the +things with it that you are used to in a C loop. In particular, +it did not work for arbitrary function calls if those functions might try +to access $_. Best stick to C for that. + +Most of the power comes from the implicit smartmatching that can +sometimes apply. Most of the time, C is treated as an +implicit smartmatch of C<$_>, that is, C<$_ ~~ EXPR>. (See +L for more information on smartmatching.) +But when I is one of the 10 exceptional cases (or things like them) +listed below, it is used directly as a boolean. + +=over 4 + +=item Z<>1. + +A user-defined subroutine call or a method invocation. + +=item Z<>2. + +A regular expression match in the form of C, C<$foo =~ /REGEX/>, +or C<$foo =~ EXPR>. Also, a negated regular expression match in +the form C, C<$foo !~ /REGEX/>, or C<$foo !~ EXPR>. + +=item Z<>3. + +A smart match that uses an explicit C<~~> operator, such as C. + +B You will often have to use C<$c ~~ $_> because the default case +uses C<$_ ~~ $c> , which is frequently the opposite of what you want. + +=item Z<>4. + +A boolean comparison operator such as C<$_ E 10> or C<$x eq "abc">. The +relational operators that this applies to are the six numeric comparisons +(C<< < >>, C<< > >>, C<< <= >>, C<< >= >>, C<< == >>, and C<< != >>), and +the six string comparisons (C, C, C, C, C, and C). + +=item Z<>5. + +At least the three builtin functions C, C, and +C. We might someday add more of these later if we think of them. + +=item Z<>6. + +A negated expression, whether C or C, or a logical +exclusive-or, C<(EXPR1) xor (EXPR2)>. The bitwise versions (C<~> and C<^>) +are not included. + +=item Z<>7. + +A filetest operator, with exactly 4 exceptions: C<-s>, C<-M>, C<-A>, and +C<-C>, as these return numerical values, not boolean ones. The C<-z> +filetest operator is not included in the exception list. + +=item Z<>8. + +The C<..> and C<...> flip-flop operators. Note that the C<...> flip-flop +operator is completely different from the C<...> elliptical statement +just described. + +=back + +In those 8 cases above, the value of EXPR is used directly as a boolean, so +no smartmatching is done. You may think of C as a smartsmartmatch. + +Furthermore, Perl inspects the operands of logical operators to +decide whether to use smartmatching for each one by applying the +above test to the operands: + +=over 4 + +=item Z<>9. + +If EXPR is C or C, the test is applied +I to both EXPR1 and EXPR2. +Only if I operands also pass the +test, I, will the expression be treated as boolean. Otherwise, +smartmatching is used. + +=item Z<>10. + +If EXPR is C, C, or C, the +test is applied I to EXPR1 only (which might itself be a +higher-precedence AND operator, for example, and thus subject to the +previous rule), not to EXPR2. If EXPR1 is to use smartmatching, then EXPR2 +also does so, no matter what EXPR2 contains. But if EXPR2 does not get to +use smartmatching, then the second argument will not be either. This is +quite different from the C<&&> case just described, so be careful. + +=back + +These rules are complicated, but the goal is for them to do what you want +(even if you don't quite understand why they are doing it). For example: + + when (/^\d+$/ && $_ < 75) { ... } + +will be treated as a boolean match because the rules say both +a regex match and an explicit test on C<$_> will be treated +as boolean. + +Also: + + when ([qw(foo bar)] && /baz/) { ... } + +will use smartmatching because only I of the operands is a boolean: +the other uses smartmatching, and that wins. + +Further: + + when ([qw(foo bar)] || /^baz/) { ... } + +will use smart matching (only the first operand is considered), whereas + + when (/^baz/ || [qw(foo bar)]) { ... } + +will test only the regex, which causes both operands to be +treated as boolean. Watch out for this one, then, because an +arrayref is always a true value, which makes it effectively +redundant. Not a good idea. + +Tautologous boolean operators are still going to be optimized +away. Don't be tempted to write + + when ("foo" or "bar") { ... } + +This will optimize down to C<"foo">, so C<"bar"> will never be considered (even +though the rules say to use a smartmatch +on C<"foo">). For an alternation like +this, an array ref will work, because this will instigate smartmatching: + + when ([qw(foo bar)] { ... } + +This is somewhat equivalent to the C-style switch statement's fallthrough +functionality (not to be confused with I fallthrough +functionality--see below), wherein the same block is used for several +C statements. + +Another useful shortcut is that, if you use a literal array or hash as the +argument to C, it is turned into a reference. So C is +the same as C, for example. + +C behaves exactly like C, which is +to say that it always matches. + +=head3 Breaking out + +You can use the C keyword to break out of the enclosing +C block. Every C block is implicitly ended with +a C. + +=head3 Fall-through + +You can use the C keyword to fall through from one +case to the next immediate C or C: + + given($foo) { + when (/x/) { say '$foo contains an x'; continue } + when (/y/) { say '$foo contains a y' } + default { say '$foo does not contain a y' } + } + +=head3 Return value + +When a C statement is also a valid expression (for example, +when it's the last statement of a block), it evaluates to: + +=over 4 + +=item * + +An empty list as soon as an explicit C is encountered. + +=item * + +The value of the last evaluated expression of the successful +C/C clause, if there happens to be one. + +=item * + +The value of the last evaluated expression of the C block if no +condition is true. + +=back + +In both last cases, the last expression is evaluated in the context that +was applied to the C block. + +Note that, unlike C and C, failed C statements always +evaluate to an empty list. + + my $price = do { + given ($item) { + when (["pear", "apple"]) { 1 } + break when "vote"; # My vote cannot be bought + 1e10 when /Mona Lisa/; + "unknown"; + } + }; + +Currently, C blocks can't always +be used as proper expressions. This +may be addressed in a future version of Perl. + +=head3 Switching in a loop + +Instead of using C, you can use a C loop. +For example, here's one way to count how many times a particular +string occurs in an array: + + use v5.10.1; + my $count = 0; + for (@array) { + when ("foo") { ++$count } + } + print "\@array contains $count copies of 'foo'\n"; + +Or in a more recent version: + + use v5.14; + my $count = 0; + for (@array) { + ++$count when "foo"; + } + print "\@array contains $count copies of 'foo'\n"; + +At the end of all C blocks, there is an implicit C. +You can override that with an explicit C if you're +interested in only the first match alone. + +This doesn't work if you explicitly specify a loop variable, as +in C. You have to use the default variable C<$_>. + +=head3 Differences from Raku + +The Perl 5 smartmatch and C/C constructs are not compatible +with their Raku analogues. The most visible difference and least +important difference is that, in Perl 5, parentheses are required around +the argument to C and C (except when this last one is used +as a statement modifier). Parentheses in Raku are always optional in a +control construct such as C, C, or C; they can't be +made optional in Perl 5 without a great deal of potential confusion, +because Perl 5 would parse the expression + + given $foo { + ... + } + +as though the argument to C were an element of the hash +C<%foo>, interpreting the braces as hash-element syntax. + +However, there are many, many other differences. For example, +this works in Perl 5: + + use v5.12; + my @primary = ("red", "blue", "green"); + + if (@primary ~~ "red") { + say "primary smartmatches red"; + } + + if ("red" ~~ @primary) { + say "red smartmatches primary"; + } + + say "that's all, folks!"; + +But it doesn't work at all in Raku. Instead, you should +use the (parallelizable) C operator: + + if any(@primary) eq "red" { + say "primary smartmatches red"; + } + + if "red" eq any(@primary) { + say "red smartmatches primary"; + } + +The table of smartmatches in L is not +identical to that proposed by the Raku specification, mainly due to +differences between Raku's and Perl 5's data models, but also because +the Raku spec has changed since Perl 5 rushed into early adoption. + +In Raku, C will always do an implicit smartmatch with its +argument, while in Perl 5 it is convenient (albeit potentially confusing) to +suppress this implicit smartmatch in various rather loosely-defined +situations, as roughly outlined above. (The difference is largely because +Perl 5 does not have, even internally, a boolean type.) + =cut diff --git a/pp_ctl.c b/pp_ctl.c index acc56cf6eb38..79518211461b 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1480,12 +1480,14 @@ PP_wrapped(pp_flop, (GIMME_V == G_LIST) ? 2 : 1, 0) static const char * const context_name[] = { "pseudo-block", + NULL, /* CXt_WHEN never actually needs "block" */ NULL, /* CXt_BLOCK never actually needs "block" */ - NULL, /* CXt_LOOP_ARY never actually needs "loop" */ - NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */ + NULL, /* CXt_GIVEN never actually needs "block" */ + NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */ NULL, /* CXt_LOOP_LAZYIV never actually needs "loop" */ + NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */ NULL, /* CXt_LOOP_LIST never actually needs "loop" */ - NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */ + NULL, /* CXt_LOOP_ARY never actually needs "loop" */ "subroutine", "format", "eval", @@ -1704,6 +1706,53 @@ S_dopoptoloop(pTHX_ I32 startingblock) return i; } +/* find the next GIVEN or FOR (with implicit $_) loop context block */ + +STATIC I32 +S_dopoptogivenfor(pTHX_ I32 startingblock) +{ + I32 i; + for (i = startingblock; i >= 0; i--) { + const PERL_CONTEXT *cx = &cxstack[i]; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_GIVEN: + DEBUG_l( Perl_deb(aTHX_ "(dopoptogivenfor(): found given at cx=%ld)\n", (long)i)); + return i; + case CXt_LOOP_PLAIN: + assert(!(cx->cx_type & CXp_FOR_DEF)); + break; + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_LIST: + case CXt_LOOP_ARY: + if (cx->cx_type & CXp_FOR_DEF) { + DEBUG_l( Perl_deb(aTHX_ "(dopoptogivenfor(): found foreach at cx=%ld)\n", (long)i)); + return i; + } + } + } + return i; +} + +STATIC I32 +S_dopoptowhen(pTHX_ I32 startingblock) +{ + I32 i; + for (i = startingblock; i >= 0; i--) { + const PERL_CONTEXT *cx = &cxstack[i]; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_WHEN: + DEBUG_l( Perl_deb(aTHX_ "(dopoptowhen(): found when at cx=%ld)\n", (long)i)); + return i; + } + } + return i; +} + /* dounwind(): pop all contexts above (but not including) cxix. * Note that it clears the savestack frame associated with each popped * context entry, but doesn't free any temps. @@ -1748,6 +1797,12 @@ Perl_dounwind(pTHX_ I32 cxix) case CXt_LOOP_ARY: cx_poploop(cx); break; + case CXt_WHEN: + cx_popwhen(cx); + break; + case CXt_GIVEN: + cx_popgiven(cx); + break; case CXt_BLOCK: case CXt_NULL: case CXt_DEFER: @@ -3005,7 +3060,8 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac o->op_type == OP_SCOPE || o->op_type == OP_LEAVELOOP || o->op_type == OP_LEAVESUB || - o->op_type == OP_LEAVETRY) + o->op_type == OP_LEAVETRY || + o->op_type == OP_LEAVEGIVEN) { *ops++ = cUNOPo->op_first; } @@ -3097,6 +3153,9 @@ S_check_op_type(pTHX_ OP * const o) if (o->op_type == OP_ENTERITER) Perl_croak(aTHX_ "Can't \"goto\" into the middle of a foreach loop"); + if (o->op_type == OP_ENTERGIVEN) + Perl_croak(aTHX_ + "Can't \"goto\" into a \"given\" block"); } /* also used for: pp_dump() */ @@ -3437,6 +3496,8 @@ PP(pp_goto) case CXt_LOOP_LAZYSV: case CXt_LOOP_LIST: case CXt_LOOP_ARY: + case CXt_GIVEN: + case CXt_WHEN: gotoprobe = OpSIBLING(cx->blk_oldcop); break; case CXt_SUBST: @@ -5645,6 +5706,46 @@ PP(pp_leavetry) return retop; } +PP(pp_entergiven) +{ + PERL_CONTEXT *cx; + const U8 gimme = GIMME_V; + SV *origsv = DEFSV; + + assert(!PL_op->op_targ); /* used to be set for lexical $_ */ + GvSV(PL_defgv) = rpp_pop_1_norc(); + + cx = cx_pushblock(CXt_GIVEN, gimme, PL_stack_sp, PL_savestack_ix); + cx_pushgiven(cx, origsv); + + return NORMAL; +} + +PP(pp_leavegiven) +{ + PERL_CONTEXT *cx; + U8 gimme; + SV **oldsp; + PERL_UNUSED_CONTEXT; + + cx = CX_CUR(); + assert(CxTYPE(cx) == CXt_GIVEN); + oldsp = PL_stack_base + cx->blk_oldsp; + gimme = cx->blk_gimme; + + if (gimme == G_VOID) + rpp_popfree_to_NN(oldsp); + else + leave_adjust_stacks(oldsp, oldsp, gimme, 1); + + CX_LEAVE_SCOPE(cx); + cx_popgiven(cx); + cx_popblock(cx); + CX_POP(cx); + + return NORMAL; +} + /* Helper routines used by pp_smartmatch */ STATIC PMOP * S_make_matcher(pTHX_ REGEXP *re) @@ -6159,6 +6260,124 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) } +PP(pp_enterwhen) +{ + PERL_CONTEXT *cx; + const U8 gimme = GIMME_V; + + /* This is essentially an optimization: if the match + fails, we don't want to push a context and then + pop it again right away, so we skip straight + to the op that follows the leavewhen. + */ + if (!(PL_op->op_flags & OPf_SPECIAL)) { /* SPECIAL implies no condition */ + bool tr = SvTRUEx(*PL_stack_sp); + rpp_popfree_1_NN(); + if (!tr) { + if (gimme == G_SCALAR) + rpp_push_IMM(&PL_sv_undef); + return cLOGOP->op_other->op_next; + } + } + + cx = cx_pushblock(CXt_WHEN, gimme, PL_stack_sp, PL_savestack_ix); + cx_pushwhen(cx); + + return NORMAL; +} + +PP(pp_leavewhen) +{ + I32 cxix; + PERL_CONTEXT *cx; + U8 gimme; + SV **oldsp; + + cx = CX_CUR(); + assert(CxTYPE(cx) == CXt_WHEN); + gimme = cx->blk_gimme; + + cxix = dopoptogivenfor(cxstack_ix); + if (cxix < 0) + /* diag_listed_as: Can't "when" outside a topicalizer */ + DIE(aTHX_ "Can't \"%s\" outside a topicalizer", + PL_op->op_flags & OPf_SPECIAL ? "default" : "when"); + + oldsp = PL_stack_base + cx->blk_oldsp; + if (gimme == G_VOID) + rpp_popfree_to_NN(oldsp); + else + leave_adjust_stacks(oldsp, oldsp, gimme, 1); + + /* pop the WHEN, BLOCK and anything else before the GIVEN/FOR */ + assert(cxix < cxstack_ix); + dounwind(cxix); + + cx = &cxstack[cxix]; + + if (CxFOREACH(cx)) { + /* emulate pp_next. Note that any stack(s) cleanup will be + * done by the pp_unstack which op_nextop should point to */ + cx = CX_CUR(); + cx_topblock(cx); + PL_curcop = cx->blk_oldcop; + return cx->blk_loop.my_op->op_nextop; + } + else { + PERL_ASYNC_CHECK(); + assert(cx->blk_givwhen.leave_op->op_type == OP_LEAVEGIVEN); + return cx->blk_givwhen.leave_op; + } +} + +PP(pp_continue) +{ + I32 cxix; + PERL_CONTEXT *cx; + OP *nextop; + + cxix = dopoptowhen(cxstack_ix); + if (cxix < 0) + DIE(aTHX_ "Can't \"continue\" outside a when block"); + + if (cxix < cxstack_ix) + dounwind(cxix); + + cx = CX_CUR(); + assert(CxTYPE(cx) == CXt_WHEN); + rpp_popfree_to_NN(PL_stack_base + cx->blk_oldsp); + CX_LEAVE_SCOPE(cx); + cx_popwhen(cx); + cx_popblock(cx); + nextop = cx->blk_givwhen.leave_op->op_next; + CX_POP(cx); + + return nextop; +} + +PP(pp_break) +{ + I32 cxix; + PERL_CONTEXT *cx; + + cxix = dopoptogivenfor(cxstack_ix); + if (cxix < 0) + DIE(aTHX_ "Can't \"break\" outside a given block"); + + cx = &cxstack[cxix]; + if (CxFOREACH(cx)) + DIE(aTHX_ "Can't \"break\" in a loop topicalizer"); + + if (cxix < cxstack_ix) + dounwind(cxix); + + /* Restore the sp at the time we entered the given block */ + cx = CX_CUR(); + rpp_popfree_to_NN(PL_stack_base + cx->blk_oldsp); + + return cx->blk_givwhen.leave_op; +} + static void _invoke_defer_block(pTHX_ U8 type, void *_arg) { diff --git a/pp_proto.h b/pp_proto.h index 1b9544163e99..cbb598db6e71 100644 --- a/pp_proto.h +++ b/pp_proto.h @@ -34,6 +34,7 @@ PERL_CALLCONV PP(pp_bit_and) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_bit_or) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_bless) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_blessed) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_break) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_caller) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_catch) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_ceil) __attribute__visibility__("hidden"); @@ -52,6 +53,7 @@ PERL_CALLCONV PP(pp_complement) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_concat) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_cond_expr) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_const) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_continue) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_coreargs) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_crypt) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_dbmopen) __attribute__visibility__("hidden"); @@ -65,11 +67,13 @@ PERL_CALLCONV PP(pp_ehostent) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_emptyavhv) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_enter) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_entereval) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_entergiven) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_enteriter) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_enterloop) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_entersub) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_entertry) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_entertrycatch) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_enterwhen) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_enterwrite) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_eof) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_eq) __attribute__visibility__("hidden"); @@ -147,11 +151,13 @@ PERL_CALLCONV PP(pp_lc) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_le) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leave) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leaveeval) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_leavegiven) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leaveloop) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leavesub) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leavesublv) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leavetry) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leavetrycatch) __attribute__visibility__("hidden"); +PERL_CALLCONV PP(pp_leavewhen) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_leavewrite) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_left_shift) __attribute__visibility__("hidden"); PERL_CALLCONV PP(pp_length) __attribute__visibility__("hidden"); diff --git a/proto.h b/proto.h index ddac2c71f5fd..4cb5441cbe5a 100644 --- a/proto.h +++ b/proto.h @@ -2869,6 +2869,12 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont) #define PERL_ARGS_ASSERT_NEWFOROP \ assert(expr) +PERL_CALLCONV OP * +Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off) + __attribute__warn_unused_result__; +#define PERL_ARGS_ASSERT_NEWGIVENOP \ + assert(cond); assert(block) + PERL_CALLCONV GP * Perl_newGP(pTHX_ GV * const gv); #define PERL_ARGS_ASSERT_NEWGP \ @@ -3166,6 +3172,12 @@ Perl_newUNOP_AUX(pTHX_ I32 type, I32 flags, OP *first, UNOP_AUX_item *aux) __attribute__warn_unused_result__; #define PERL_ARGS_ASSERT_NEWUNOP_AUX +PERL_CALLCONV OP * +Perl_newWHENOP(pTHX_ OP *cond, OP *block) + __attribute__warn_unused_result__; +#define PERL_ARGS_ASSERT_NEWWHENOP \ + assert(block) + PERL_CALLCONV OP * Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, OP *expr, OP *block, OP *cont, I32 has_my) __attribute__warn_unused_result__; @@ -7320,6 +7332,11 @@ STATIC OP * S_listkids(pTHX_ OP *o); # define PERL_ARGS_ASSERT_LISTKIDS +STATIC bool +S_looks_like_bool(pTHX_ const OP *o); +# define PERL_ARGS_ASSERT_LOOKS_LIKE_BOOL \ + assert(o) + STATIC OP * S_modkids(pTHX_ OP *o, I32 type); # define PERL_ARGS_ASSERT_MODKIDS @@ -7334,6 +7351,11 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp); # define PERL_ARGS_ASSERT_MY_KID \ assert(imopsp) +STATIC OP * +S_newGIVWHENOP(pTHX_ OP *cond, OP *block, I32 enter_opcode, I32 leave_opcode, PADOFFSET entertarg); +# define PERL_ARGS_ASSERT_NEWGIVWHENOP \ + assert(block) + STATIC OP * S_new_logop(pTHX_ I32 type, I32 flags, OP **firstp, OP **otherp) __attribute__warn_unused_result__; @@ -7717,6 +7739,11 @@ S_dopoptoeval(pTHX_ I32 startingblock) __attribute__warn_unused_result__; # define PERL_ARGS_ASSERT_DOPOPTOEVAL +STATIC I32 +S_dopoptogivenfor(pTHX_ I32 startingblock) + __attribute__warn_unused_result__; +# define PERL_ARGS_ASSERT_DOPOPTOGIVENFOR + STATIC I32 S_dopoptolabel(pTHX_ const char *label, STRLEN len, U32 flags) __attribute__warn_unused_result__; @@ -7734,6 +7761,11 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) # define PERL_ARGS_ASSERT_DOPOPTOSUB_AT \ assert(cxstk) +STATIC I32 +S_dopoptowhen(pTHX_ I32 startingblock) + __attribute__warn_unused_result__; +# define PERL_ARGS_ASSERT_DOPOPTOWHEN + STATIC PMOP * S_make_matcher(pTHX_ REGEXP *re) __attribute__warn_unused_result__; @@ -10057,6 +10089,11 @@ Perl_cx_popformat(pTHX_ PERL_CONTEXT *cx); # define PERL_ARGS_ASSERT_CX_POPFORMAT \ assert(cx) +PERL_STATIC_INLINE void +Perl_cx_popgiven(pTHX_ PERL_CONTEXT *cx); +# define PERL_ARGS_ASSERT_CX_POPGIVEN \ + assert(cx) + PERL_STATIC_INLINE void Perl_cx_poploop(pTHX_ PERL_CONTEXT *cx); # define PERL_ARGS_ASSERT_CX_POPLOOP \ @@ -10077,6 +10114,11 @@ Perl_cx_popsub_common(pTHX_ PERL_CONTEXT *cx); # define PERL_ARGS_ASSERT_CX_POPSUB_COMMON \ assert(cx) +PERL_STATIC_INLINE void +Perl_cx_popwhen(pTHX_ PERL_CONTEXT *cx); +# define PERL_ARGS_ASSERT_CX_POPWHEN \ + assert(cx) + PERL_STATIC_INLINE PERL_CONTEXT * Perl_cx_pushblock(pTHX_ U8 type, U8 gimme, SV **sp, I32 saveix); # define PERL_ARGS_ASSERT_CX_PUSHBLOCK \ @@ -10093,6 +10135,11 @@ Perl_cx_pushformat(pTHX_ PERL_CONTEXT *cx, CV *cv, OP *retop, GV *gv); assert(cx); assert(cv); \ assert(SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM) +PERL_STATIC_INLINE void +Perl_cx_pushgiven(pTHX_ PERL_CONTEXT *cx, SV *orig_defsv); +# define PERL_ARGS_ASSERT_CX_PUSHGIVEN \ + assert(cx) + PERL_STATIC_INLINE void Perl_cx_pushloop_for(pTHX_ PERL_CONTEXT *cx, void *itervarp, SV *itersave); # define PERL_ARGS_ASSERT_CX_PUSHLOOP_FOR \ @@ -10114,6 +10161,11 @@ Perl_cx_pushtry(pTHX_ PERL_CONTEXT *cx, OP *retop); # define PERL_ARGS_ASSERT_CX_PUSHTRY \ assert(cx) +PERL_STATIC_INLINE void +Perl_cx_pushwhen(pTHX_ PERL_CONTEXT *cx); +# define PERL_ARGS_ASSERT_CX_PUSHWHEN \ + assert(cx) + PERL_STATIC_INLINE void Perl_cx_topblock(pTHX_ PERL_CONTEXT *cx); # define PERL_ARGS_ASSERT_CX_TOPBLOCK \ diff --git a/regen/keywords.pl b/regen/keywords.pl index a48eb6517472..4854fda3778e 100755 --- a/regen/keywords.pl +++ b/regen/keywords.pl @@ -38,7 +38,11 @@ my %feature_kw = ( state => 'state', say => 'say', + given => 'switch', + when => 'switch', + default => 'switch', # continue is already a keyword + break => 'switch', evalbytes => 'evalbytes', __SUB__ => '__SUB__', fc => 'fc', @@ -137,6 +141,7 @@ END -bind -binmode -bless +-break -caller +catch -chdir @@ -156,6 +161,7 @@ END -crypt -dbmclose -dbmopen ++default +defer +defined +delete @@ -217,6 +223,7 @@ END -getservent -getsockname -getsockopt ++given +glob -gmtime +goto @@ -369,6 +376,7 @@ END -waitpid -wantarray -warn ++when +while -write -x diff --git a/regen/opcodes b/regen/opcodes index 1757742fba89..714db81f548d 100644 --- a/regen/opcodes +++ b/regen/opcodes @@ -329,6 +329,13 @@ method_super super with known name ck_null d. method_redir redirect method with known name ck_null d. method_redir_super redirect super method with known name ck_null d. +entergiven given() ck_null d| +leavegiven leave given block ck_null 1 +enterwhen when() ck_null d| +leavewhen leave when block ck_null 1 +break break ck_null 0 +continue continue ck_null 0 + # I/O. open open ck_open ismt@ F S? L diff --git a/sv.c b/sv.c index 0cfea4571a5e..ebc1bf5a2dfd 100644 --- a/sv.c +++ b/sv.c @@ -15174,8 +15174,13 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param) ncx->blk_format.dfoutgv = gv_dup_inc(ncx->blk_format.dfoutgv, param); break; + case CXt_GIVEN: + ncx->blk_givwhen.defsv_save = + sv_dup_inc(ncx->blk_givwhen.defsv_save, param); + break; case CXt_BLOCK: case CXt_NULL: + case CXt_WHEN: case CXt_DEFER: break; } diff --git a/t/lib/croak/pp_ctl b/t/lib/croak/pp_ctl index 266cb90e3cca..179c8d7aea89 100644 --- a/t/lib/croak/pp_ctl +++ b/t/lib/croak/pp_ctl @@ -11,13 +11,13 @@ no warnings 'deprecated'; goto f; CORE::given(1){f:} EXPECT -CORE::given is not a keyword at - line 3. +Can't "goto" into a "given" block at - line 3. ######## # NAME goto from given topic expression no warnings 'deprecated'; CORE::given(goto f){f:} EXPECT -CORE::given is not a keyword at - line 2. +Can't "goto" into a "given" block at - line 2. ######## # NAME goto into expression no warnings 'deprecated'; @@ -39,17 +39,16 @@ EXPECT Can't find label foo at - line 3. ######## # NAME when outside given -use 5.01; +use 5.01; no warnings 'deprecated'; when(undef){} EXPECT -syntax error at - line 2, near "){" -Execution of - aborted due to compilation errors. +Can't "when" outside a topicalizer at - line 2. ######## # NAME default outside given use 5.01; default{} EXPECT -Can't call method "default" without a package or object reference at - line 2. +Can't "default" outside a topicalizer at - line 2. ######## # NAME croak with read only $@ eval '"a" =~ /${*@=\_})/'; diff --git a/t/lib/feature/switch b/t/lib/feature/switch new file mode 100644 index 000000000000..4d379ea21322 --- /dev/null +++ b/t/lib/feature/switch @@ -0,0 +1,142 @@ +Check the lexical scoping of the switch keywords. +(The actual behaviour is tested in t/op/switch.t) + +__END__ +# No switch; given should be a bareword. +use warnings; no warnings 'deprecated'; +print STDOUT given; +EXPECT +Unquoted string "given" may clash with future reserved word at - line 3. +given +######## +# No switch; when should be a bareword. +use warnings; no warnings 'deprecated'; +print STDOUT when; +EXPECT +Unquoted string "when" may clash with future reserved word at - line 3. +when +######## +# No switch; default should be a bareword. +use warnings; no warnings 'deprecated'; +print STDOUT default; +EXPECT +Unquoted string "default" may clash with future reserved word at - line 3. +default +######## +# No switch; break should be a bareword. +use warnings; no warnings 'deprecated'; +print STDOUT break; +EXPECT +Unquoted string "break" may clash with future reserved word at - line 3. +break +######## +# No switch; but continue is still a keyword +print STDOUT continue; +EXPECT +Can't "continue" outside a when block at - line 2. +######## +# Use switch; so given is a keyword +use feature 'switch'; no warnings 'deprecated'; +given("okay\n") { print } +EXPECT +okay +######## +# Use switch; so when is a keyword +use feature 'switch'; no warnings 'deprecated'; +given(1) { when(1) { print "okay" } } +EXPECT +okay +######## +# Use switch; so default is a keyword +use feature 'switch'; no warnings 'deprecated'; +given(1) { default { print "okay" } } +EXPECT +okay +######## +# Use switch; so break is a keyword +use feature 'switch'; +break; +EXPECT +Can't "break" outside a given block at - line 3. +######## +# switch out of scope; given should be a bareword. +use warnings; no warnings 'deprecated'; +{ use feature 'switch'; + given (1) {print "Okay here\n";} +} +print STDOUT given; +EXPECT +Unquoted string "given" may clash with future reserved word at - line 6. +Okay here +given +######## +# switch out of scope; when should be a bareword. +use warnings; no warnings 'deprecated'; +{ use feature 'switch'; + given (1) { when(1) {print "Okay here\n";} } +} +print STDOUT when; +EXPECT +Unquoted string "when" may clash with future reserved word at - line 6. +Okay here +when +######## +# switch out of scope; default should be a bareword. +use warnings; no warnings 'deprecated'; +{ use feature 'switch'; + given (1) { default {print "Okay here\n";} } +} +print STDOUT default; +EXPECT +Unquoted string "default" may clash with future reserved word at - line 6. +Okay here +default +######## +# switch out of scope; break should be a bareword. +use warnings; no warnings 'deprecated'; +{ use feature 'switch'; + given (1) { break } +} +print STDOUT break; +EXPECT +Unquoted string "break" may clash with future reserved word at - line 6. +break +######## +# C should work +use warnings; no warnings 'deprecated'; +use feature 'switch'; +given (1) { when(1) {print "Okay here\n";} } +no feature 'switch'; +print STDOUT when; +EXPECT +Unquoted string "when" may clash with future reserved word at - line 6. +Okay here +when +######## +# C should work too +use warnings; no warnings 'deprecated'; +use feature 'switch'; +given (1) { when(1) {print "Okay here\n";} } +no feature; +print STDOUT when; +EXPECT +Unquoted string "when" may clash with future reserved word at - line 6. +Okay here +when +######## +# Without the feature, no 'Unambiguous use of' warning: +use warnings; no warnings 'deprecated'; +@break = ($break = "break"); +print ${break}, ${break[0]}; +EXPECT +breakbreak +######## +# With the feature, we get an 'Unambiguous use of' warning: +use warnings; no warnings 'deprecated'; +use feature 'switch'; +@break = ($break = "break"); +print ${break}, ${break[0]}; +EXPECT +Ambiguous use of ${break} resolved to $break at - line 5. +Ambiguous use of ${break[...]} resolved to $break[...] at - line 5. +breakbreak diff --git a/t/op/coreamp.t b/t/op/coreamp.t index 18e6475e999b..71649790a33c 100644 --- a/t/op/coreamp.t +++ b/t/op/coreamp.t @@ -370,6 +370,20 @@ like join(" ", &CORE::bless([],'parcel')), qr/^parcel=ARRAY(?!.* )/, "&bless in list context"; like &mybless([]), qr/^main=ARRAY/, '&bless with one arg'; +test_proto 'break'; +{ + $tests ++; + my $tmp; + no warnings 'deprecated'; + CORE::given(1) { + CORE::when(1) { + &mybreak; + $tmp = 'bad'; + } + } + is $tmp, undef, '&break'; +} + test_proto 'caller'; $tests += 4; sub caller_test { @@ -476,6 +490,16 @@ SKIP: lis [&myconnect('foo','bar')], [undef], '&connect in list context'; } +test_proto 'continue'; +$tests ++; +no warnings 'deprecated'; +CORE::given(1) { + CORE::when(1) { + &mycontinue(); + } + pass "&continue"; +} + test_proto 'cos'; test_proto 'crypt'; @@ -1166,8 +1190,7 @@ like $@, qr'^Undefined format "STDOUT" called', my %nottest_words = map { $_ => 1 } qw( ADJUST AUTOLOAD BEGIN CHECK CORE DESTROY END INIT UNITCHECK __DATA__ __END__ - and catch class cmp continue default defer do dump else elsif eq eval - field finally + and catch class cmp default defer do dump else elsif eq eval field finally for foreach format ge given goto grep gt if isa last le local lt m map method my ne next no or our package print printf q qq qr qw qx redo require return s say sort state sub tr try unless until use when while x xor y diff --git a/t/op/coresubs.t b/t/op/coresubs.t index 7be4b00fcaff..f7f97376b1eb 100644 --- a/t/op/coresubs.t +++ b/t/op/coresubs.t @@ -18,11 +18,11 @@ use B; my %unsupported = map +($_=>1), qw ( __DATA__ __END__ ADJUST AUTOLOAD BEGIN UNITCHECK CORE DESTROY END INIT CHECK - and catch class cmp continue defer do dump else elsif eq eval field - finally for foreach format ge goto grep gt if isa last le local + and catch class cmp default defer do dump else elsif eq eval field + finally for foreach format ge given goto grep gt if isa last le local lt m map method my ne next no or our package print printf q qq qr qw qx redo require return s say sort state sub tr try unless until use - while x xor y + when while x xor y ); my %args_for = ( dbmopen => '%1,$2,$3', diff --git a/t/op/cproto.t b/t/op/cproto.t index bf0d823d65c3..fec9fe6ba939 100644 --- a/t/op/cproto.t +++ b/t/op/cproto.t @@ -7,7 +7,7 @@ BEGIN { set_up_inc('../lib'); } -plan tests => 249; +plan tests => 254; while () { chomp; @@ -51,6 +51,7 @@ atan2 ($$) bind (*$) binmode (*;$) bless ($;$) +break () caller (;$) chdir (;$) chmod (@) @@ -63,10 +64,12 @@ close (;*) closedir (*) cmp undef connect (*$) +continue () cos (_) crypt ($$) dbmclose (\%) dbmopen (\%$$) +default undef defined undef delete undef die (@) @@ -125,6 +128,7 @@ getservbyport ($$) getservent () getsockname (*) getsockopt (*$$) +given undef glob (_;) gmtime (;$) goto undef @@ -274,6 +278,7 @@ wait () waitpid ($$) wantarray () warn (@) +when undef while undef write (;*) x undef diff --git a/t/op/state.t b/t/op/state.t index b5ebbb046271..f309b4ec3fca 100644 --- a/t/op/state.t +++ b/t/op/state.t @@ -9,7 +9,7 @@ BEGIN { use strict; -plan tests => 162; +plan tests => 166; # Before loading feature.pm, test it with CORE:: ok eval 'CORE::state $x = 1;', 'CORE::state outside of feature.pm scope'; @@ -341,6 +341,18 @@ foreach my $x (0 .. 4) { } +# +# Use with given. +# +my @spam = qw [spam ham bacon beans]; +foreach my $spam (@spam) { + no warnings 'deprecated'; + given (state $spam = $spam) { + when ($spam [0]) {ok 1, "given"} + default {ok 0, "given"} + } +} + # # Redefine. # diff --git a/t/op/switch.t b/t/op/switch.t new file mode 100644 index 000000000000..e1c079956f0d --- /dev/null +++ b/t/op/switch.t @@ -0,0 +1,1384 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + require './test.pl'; + set_up_inc('../lib'); +} + +use strict; +use warnings; +no warnings 'deprecated'; + +plan tests => 197; + +# The behaviour of the feature pragma should be tested by lib/feature.t +# using the tests in t/lib/feature/*. This file tests the behaviour of +# the switch ops themselves. + + +# Before loading feature, test the switch ops with CORE:: +CORE::given(3) { + CORE::when(3) { pass "CORE::given and CORE::when"; continue } + CORE::default { pass "continue (without feature) and CORE::default" } +} + + +use feature 'switch'; + +eval { continue }; +like($@, qr/^Can't "continue" outside/, "continue outside"); + +eval { break }; +like($@, qr/^Can't "break" outside/, "break outside"); + +# Scoping rules + +{ + my $x = "foo"; + given(my $x = "bar") { + is($x, "bar", "given scope starts"); + } + is($x, "foo", "given scope ends"); +} + +sub be_true {1} + +given(my $x = "foo") { + when(be_true(my $x = "bar")) { + is($x, "bar", "given scope starts"); + } + is($x, "foo", "given scope ends"); +} + +$_ = "outside"; +given("inside") { check_outside1() } +sub check_outside1 { is($_, "inside", "\$_ is not lexically scoped") } + +# Basic string/numeric comparisons and control flow + +{ + my $ok; + given(3) { + when(2) { $ok = 'two'; } + when(3) { $ok = 'three'; } + when(4) { $ok = 'four'; } + default { $ok = 'd'; } + } + is($ok, 'three', "numeric comparison"); +} + +{ + my $ok; + use integer; + given(3.14159265) { + when(2) { $ok = 'two'; } + when(3) { $ok = 'three'; } + when(4) { $ok = 'four'; } + default { $ok = 'd'; } + } + is($ok, 'three', "integer comparison"); +} + +{ + my ($ok1, $ok2); + given(3) { + when(3.1) { $ok1 = 'n'; } + when(3.0) { $ok1 = 'y'; continue } + when("3.0") { $ok2 = 'y'; } + default { $ok2 = 'n'; } + } + is($ok1, 'y', "more numeric (pt. 1)"); + is($ok2, 'y', "more numeric (pt. 2)"); +} + +{ + my $ok; + given("c") { + when("b") { $ok = 'B'; } + when("c") { $ok = 'C'; } + when("d") { $ok = 'D'; } + default { $ok = 'def'; } + } + is($ok, 'C', "string comparison"); +} + +{ + my $ok; + given("c") { + when("b") { $ok = 'B'; } + when("c") { $ok = 'C'; continue } + when("c") { $ok = 'CC'; } + default { $ok = 'D'; } + } + is($ok, 'CC', "simple continue"); +} + +# Definedness +{ + my $ok = 1; + given (0) { when(undef) {$ok = 0} } + is($ok, 1, "Given(0) when(undef)"); +} +{ + my $undef; + my $ok = 1; + given (0) { when($undef) {$ok = 0} } + is($ok, 1, 'Given(0) when($undef)'); +} +{ + my $undef; + my $ok = 0; + given (0) { when($undef++) {$ok = 1} } + is($ok, 1, "Given(0) when($undef++)"); +} +{ + no warnings "uninitialized"; + my $ok = 1; + given (undef) { when(0) {$ok = 0} } + is($ok, 1, "Given(undef) when(0)"); +} +{ + no warnings "uninitialized"; + my $undef; + my $ok = 1; + given ($undef) { when(0) {$ok = 0} } + is($ok, 1, 'Given($undef) when(0)'); +} +######## +{ + my $ok = 1; + given ("") { when(undef) {$ok = 0} } + is($ok, 1, 'Given("") when(undef)'); +} +{ + my $undef; + my $ok = 1; + given ("") { when($undef) {$ok = 0} } + is($ok, 1, 'Given("") when($undef)'); +} +{ + no warnings "uninitialized"; + my $ok = 1; + given (undef) { when("") {$ok = 0} } + is($ok, 1, 'Given(undef) when("")'); +} +{ + no warnings "uninitialized"; + my $undef; + my $ok = 1; + given ($undef) { when("") {$ok = 0} } + is($ok, 1, 'Given($undef) when("")'); +} +######## +{ + my $ok = 0; + given (undef) { when(undef) {$ok = 1} } + is($ok, 1, "Given(undef) when(undef)"); +} +{ + my $undef; + my $ok = 0; + given (undef) { when($undef) {$ok = 1} } + is($ok, 1, 'Given(undef) when($undef)'); +} +{ + my $undef; + my $ok = 0; + given ($undef) { when(undef) {$ok = 1} } + is($ok, 1, 'Given($undef) when(undef)'); +} +{ + my $undef; + my $ok = 0; + given ($undef) { when($undef) {$ok = 1} } + is($ok, 1, 'Given($undef) when($undef)'); +} + + +# Regular expressions +{ + my ($ok1, $ok2); + given("Hello, world!") { + when(/lo/) + { $ok1 = 'y'; continue} + when(/no/) + { $ok1 = 'n'; continue} + when(/^(Hello,|Goodbye cruel) world[!.?]/) + { $ok2 = 'Y'; continue} + when(/^(Hello cruel|Goodbye,) world[!.?]/) + { $ok2 = 'n'; continue} + } + is($ok1, 'y', "regex 1"); + is($ok2, 'Y', "regex 2"); +} + +# Comparisons +{ + my $test = "explicit numeric comparison (<)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ < 10) { $ok = "ten" } + when ($_ < 20) { $ok = "twenty" } + when ($_ < 30) { $ok = "thirty" } + when ($_ < 40) { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + +{ + use integer; + my $test = "explicit numeric comparison (integer <)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ < 10) { $ok = "ten" } + when ($_ < 20) { $ok = "twenty" } + when ($_ < 30) { $ok = "thirty" } + when ($_ < 40) { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + +{ + my $test = "explicit numeric comparison (<=)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ <= 10) { $ok = "ten" } + when ($_ <= 20) { $ok = "twenty" } + when ($_ <= 30) { $ok = "thirty" } + when ($_ <= 40) { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + +{ + use integer; + my $test = "explicit numeric comparison (integer <=)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ <= 10) { $ok = "ten" } + when ($_ <= 20) { $ok = "twenty" } + when ($_ <= 30) { $ok = "thirty" } + when ($_ <= 40) { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + + +{ + my $test = "explicit numeric comparison (>)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ > 40) { $ok = "forty" } + when ($_ > 30) { $ok = "thirty" } + when ($_ > 20) { $ok = "twenty" } + when ($_ > 10) { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + +{ + my $test = "explicit numeric comparison (>=)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ >= 40) { $ok = "forty" } + when ($_ >= 30) { $ok = "thirty" } + when ($_ >= 20) { $ok = "twenty" } + when ($_ >= 10) { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + +{ + use integer; + my $test = "explicit numeric comparison (integer >)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ > 40) { $ok = "forty" } + when ($_ > 30) { $ok = "thirty" } + when ($_ > 20) { $ok = "twenty" } + when ($_ > 10) { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + +{ + use integer; + my $test = "explicit numeric comparison (integer >=)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ >= 40) { $ok = "forty" } + when ($_ >= 30) { $ok = "thirty" } + when ($_ >= 20) { $ok = "twenty" } + when ($_ >= 10) { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + + +{ + my $test = "explicit string comparison (lt)"; + my $twenty_five = "25"; + my $ok; + given($twenty_five) { + when ($_ lt "10") { $ok = "ten" } + when ($_ lt "20") { $ok = "twenty" } + when ($_ lt "30") { $ok = "thirty" } + when ($_ lt "40") { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + +{ + my $test = "explicit string comparison (le)"; + my $twenty_five = "25"; + my $ok; + given($twenty_five) { + when ($_ le "10") { $ok = "ten" } + when ($_ le "20") { $ok = "twenty" } + when ($_ le "30") { $ok = "thirty" } + when ($_ le "40") { $ok = "forty" } + default { $ok = "default" } + } + is($ok, "thirty", $test); +} + +{ + my $test = "explicit string comparison (gt)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ ge "40") { $ok = "forty" } + when ($_ ge "30") { $ok = "thirty" } + when ($_ ge "20") { $ok = "twenty" } + when ($_ ge "10") { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + +{ + my $test = "explicit string comparison (ge)"; + my $twenty_five = 25; + my $ok; + given($twenty_five) { + when ($_ ge "40") { $ok = "forty" } + when ($_ ge "30") { $ok = "thirty" } + when ($_ ge "20") { $ok = "twenty" } + when ($_ ge "10") { $ok = "ten" } + default { $ok = "default" } + } + is($ok, "twenty", $test); +} + +# Optimized-away comparisons +{ + my $ok; + given(23) { + when (2 + 2 == 4) { $ok = 'y'; continue } + when (2 + 2 == 5) { $ok = 'n' } + } + is($ok, 'y', "Optimized-away comparison"); +} + +{ + my $ok; + given(23) { + when (scalar 24) { $ok = 'n'; continue } + default { $ok = 'y' } + } + is($ok,'y','scalar()'); +} + +# File tests +# (How to be both thorough and portable? Pinch a few ideas +# from t/op/filetest.t. We err on the side of portability for +# the time being.) + +{ + my ($ok_d, $ok_f, $ok_r); + given("op") { + when(-d) {$ok_d = 1; continue} + when(!-f) {$ok_f = 1; continue} + when(-r) {$ok_r = 1; continue} + } + ok($ok_d, "Filetest -d"); + ok($ok_f, "Filetest -f"); + ok($ok_r, "Filetest -r"); +} + +# Sub and method calls +sub notfoo {"bar"} +{ + my $ok = 0; + given("foo") { + when(notfoo()) {$ok = 1} + } + ok($ok, "Sub call acts as boolean") +} + +{ + my $ok = 0; + given("foo") { + when(main->notfoo()) {$ok = 1} + } + ok($ok, "Class-method call acts as boolean") +} + +{ + my $ok = 0; + my $obj = bless []; + given("foo") { + when($obj->notfoo()) {$ok = 1} + } + ok($ok, "Object-method call acts as boolean") +} + +# Other things that should not be smart matched +{ + my $ok = 0; + given(12) { + when( /(\d+)/ and ( 1 <= $1 and $1 <= 12 ) ) { + $ok = 1; + } + } + ok($ok, "bool not smartmatches"); +} + +{ + my $ok = 0; + given(0) { + when(eof(DATA)) { + $ok = 1; + } + } + ok($ok, "eof() not smartmatched"); +} + +{ + my $ok = 0; + my %foo = ("bar", 0); + given(0) { + when(exists $foo{bar}) { + $ok = 1; + } + } + ok($ok, "exists() not smartmatched"); +} + +{ + my $ok = 0; + given(0) { + when(defined $ok) { + $ok = 1; + } + } + ok($ok, "defined() not smartmatched"); +} + +{ + my $ok = 1; + given("foo") { + when((1 == 1) && "bar") { + $ok = 0; + } + when((1 == 1) && $_ eq "foo") { + $ok = 2; + } + } + is($ok, 2, "((1 == 1) && \"bar\") not smartmatched"); +} + +{ + my $n = 0; + for my $l (qw(a b c d)) { + given ($l) { + when ($_ eq "b" .. $_ eq "c") { $n = 1 } + default { $n = 0 } + } + ok(($n xor $l =~ /[ad]/), 'when(E1..E2) evaluates in boolean context'); + } +} + +{ + my $n = 0; + for my $l (qw(a b c d)) { + given ($l) { + when ($_ eq "b" ... $_ eq "c") { $n = 1 } + default { $n = 0 } + } + ok(($n xor $l =~ /[ad]/), 'when(E1...E2) evaluates in boolean context'); + } +} + +{ + my $ok = 0; + given("foo") { + when((1 == $ok) || "foo") { + $ok = 1; + } + } + ok($ok, '((1 == $ok) || "foo") smartmatched'); +} + +{ + my $ok = 0; + given("foo") { + when((1 == $ok || undef) // "foo") { + $ok = 1; + } + } + ok($ok, '((1 == $ok || undef) // "foo") smartmatched'); +} + +# Make sure we aren't invoking the get-magic more than once + +{ # A helper class to count the number of accesses. + package FetchCounter; + sub TIESCALAR { + my ($class) = @_; + bless {value => undef, count => 0}, $class; + } + sub STORE { + my ($self, $val) = @_; + $self->{count} = 0; + $self->{value} = $val; + } + sub FETCH { + my ($self) = @_; + # Avoid pre/post increment here + $self->{count} = 1 + $self->{count}; + $self->{value}; + } + sub count { + my ($self) = @_; + $self->{count}; + } +} + +my $f = tie my $v, "FetchCounter"; + +{ my $test_name = "Multiple FETCHes in given, due to aliasing"; + my $ok; + given($v = 23) { + when(undef) {} + when(sub{0}->()) {} + when(21) {} + when("22") {} + when(23) {$ok = 1} + when(/24/) {$ok = 0} + } + is($ok, 1, "precheck: $test_name"); + is($f->count(), 4, $test_name); +} + +{ my $test_name = "Only one FETCH (numeric when)"; + my $ok; + $v = 23; + is($f->count(), 0, "Sanity check: $test_name"); + given(23) { + when(undef) {} + when(sub{0}->()) {} + when(21) {} + when("22") {} + when($v) {$ok = 1} + when(/24/) {$ok = 0} + } + is($ok, 1, "precheck: $test_name"); + is($f->count(), 1, $test_name); +} + +{ my $test_name = "Only one FETCH (string when)"; + my $ok; + $v = "23"; + is($f->count(), 0, "Sanity check: $test_name"); + given("23") { + when(undef) {} + when(sub{0}->()) {} + when("21") {} + when("22") {} + when($v) {$ok = 1} + when(/24/) {$ok = 0} + } + is($ok, 1, "precheck: $test_name"); + is($f->count(), 1, $test_name); +} + +{ my $test_name = "Only one FETCH (undef)"; + my $ok; + $v = undef; + is($f->count(), 0, "Sanity check: $test_name"); + no warnings "uninitialized"; + given(my $undef) { + when(sub{0}->()) {} + when("21") {} + when("22") {} + when($v) {$ok = 1} + when(undef) {$ok = 0} + } + is($ok, 1, "precheck: $test_name"); + is($f->count(), 1, $test_name); +} + +# Loop topicalizer +{ + my $first = 1; + for (1, "two") { + when ("two") { + is($first, 0, "Loop: second"); + eval {break}; + like($@, qr/^Can't "break" in a loop topicalizer/, + q{Can't "break" in a loop topicalizer}); + } + when (1) { + is($first, 1, "Loop: first"); + $first = 0; + # Implicit break is okay + } + } +} + +{ + my $first = 1; + for $_ (1, "two") { + when ("two") { + is($first, 0, "Explicit \$_: second"); + eval {break}; + like($@, qr/^Can't "break" in a loop topicalizer/, + q{Can't "break" in a loop topicalizer}); + } + when (1) { + is($first, 1, "Explicit \$_: first"); + $first = 0; + # Implicit break is okay + } + } +} + + +# Code references +{ + my $called_foo = 0; + sub foo {$called_foo = 1; "@_" eq "foo"} + my $called_bar = 0; + sub bar {$called_bar = 1; "@_" eq "bar"} + my ($matched_foo, $matched_bar) = (0, 0); + given("foo") { + when(\&bar) {$matched_bar = 1} + when(\&foo) {$matched_foo = 1} + } + is($called_foo, 1, "foo() was called"); + is($called_bar, 1, "bar() was called"); + is($matched_bar, 0, "bar didn't match"); + is($matched_foo, 1, "foo did match"); +} + +sub contains_x { + my $x = shift; + return ($x =~ /x/); +} +{ + my ($ok1, $ok2) = (0,0); + given("foxy!") { + when(contains_x($_)) + { $ok1 = 1; continue } + when(\&contains_x) + { $ok2 = 1; continue } + } + is($ok1, 1, "Calling sub directly (true)"); + is($ok2, 1, "Calling sub indirectly (true)"); + + given("foggy") { + when(contains_x($_)) + { $ok1 = 2; continue } + when(\&contains_x) + { $ok2 = 2; continue } + } + is($ok1, 1, "Calling sub directly (false)"); + is($ok2, 1, "Calling sub indirectly (false)"); +} + +{ + # Test overloading + { package OverloadTest; + + use overload '""' => sub{"string value of obj"}; + use overload 'eq' => sub{"$_[0]" eq "$_[1]"}; + + use overload "~~" => sub { + my ($self, $other, $reversed) = @_; + if ($reversed) { + $self->{left} = $other; + $self->{right} = $self; + $self->{reversed} = 1; + } else { + $self->{left} = $self; + $self->{right} = $other; + $self->{reversed} = 0; + } + $self->{called} = 1; + return $self->{retval}; + }; + + sub new { + my ($pkg, $retval) = @_; + bless { + called => 0, + retval => $retval, + }, $pkg; + } + } + + { + my $test = "Overloaded obj in given (true)"; + my $obj = OverloadTest->new(1); + my $matched; + given($obj) { + when ("other arg") {$matched = 1} + default {$matched = 0} + } + + is($obj->{called}, 1, "$test: called"); + ok($matched, "$test: matched"); + } + + { + my $test = "Overloaded obj in given (false)"; + my $obj = OverloadTest->new(0); + my $matched; + given($obj) { + when ("other arg") {$matched = 1} + } + + is($obj->{called}, 1, "$test: called"); + ok(!$matched, "$test: not matched"); + } + + { + my $test = "Overloaded obj in when (true)"; + my $obj = OverloadTest->new(1); + my $matched; + given("topic") { + when ($obj) {$matched = 1} + default {$matched = 0} + } + + is($obj->{called}, 1, "$test: called"); + ok($matched, "$test: matched"); + is($obj->{left}, "topic", "$test: left"); + is($obj->{right}, "string value of obj", "$test: right"); + ok($obj->{reversed}, "$test: reversed"); + } + + { + my $test = "Overloaded obj in when (false)"; + my $obj = OverloadTest->new(0); + my $matched; + given("topic") { + when ($obj) {$matched = 1} + default {$matched = 0} + } + + is($obj->{called}, 1, "$test: called"); + ok(!$matched, "$test: not matched"); + is($obj->{left}, "topic", "$test: left"); + is($obj->{right}, "string value of obj", "$test: right"); + ok($obj->{reversed}, "$test: reversed"); + } +} + +# Postfix when +{ + my $ok; + given (undef) { + $ok = 1 when undef; + } + is($ok, 1, "postfix undef"); +} +{ + my $ok; + given (2) { + $ok += 1 when 7; + $ok += 2 when 9.1685; + $ok += 4 when $_ > 4; + $ok += 8 when $_ < 2.5; + } + is($ok, 8, "postfix numeric"); +} +{ + my $ok; + given ("apple") { + $ok = 1, continue when $_ eq "apple"; + $ok += 2; + $ok = 0 when "banana"; + } + is($ok, 3, "postfix string"); +} +{ + my $ok; + given ("pear") { + do { $ok = 1; continue } when /pea/; + $ok += 2; + $ok = 0 when /pie/; + default { $ok += 4 } + $ok = 0; + } + is($ok, 7, "postfix regex"); +} +# be_true is defined at the beginning of the file +{ + my $x = "what"; + given(my $x = "foo") { + do { + is($x, "foo", "scope inside ... when my \$x = ..."); + continue; + } when be_true(my $x = "bar"); + is($x, "bar", "scope after ... when my \$x = ..."); + } +} +{ + my $x = 0; + given(my $x = 1) { + my $x = 2, continue when be_true(); + is($x, undef, "scope after my \$x = ... when ..."); + } +} + +# Tests for last and next in when clauses +my $letter; + +$letter = ''; +for ("a".."e") { + given ($_) { + $letter = $_; + when ("b") { last } + } + $letter = "z"; +} +is($letter, "b", "last in when"); + +$letter = ''; +LETTER1: for ("a".."e") { + given ($_) { + $letter = $_; + when ("b") { last LETTER1 } + } + $letter = "z"; +} +is($letter, "b", "last LABEL in when"); + +$letter = ''; +for ("a".."e") { + given ($_) { + when (/b|d/) { next } + $letter .= $_; + } + $letter .= ','; +} +is($letter, "a,c,e,", "next in when"); + +$letter = ''; +LETTER2: for ("a".."e") { + given ($_) { + when (/b|d/) { next LETTER2 } + $letter .= $_; + } + $letter .= ','; +} +is($letter, "a,c,e,", "next LABEL in when"); + +# Test goto with given/when +{ + my $flag = 0; + goto GIVEN1; + $flag = 1; + GIVEN1: given ($flag) { + when (0) { break; } + $flag = 2; + } + is($flag, 0, "goto GIVEN1"); +} +{ + my $flag = 0; + given ($flag) { + when (0) { $flag = 1; } + goto GIVEN2; + $flag = 2; + } +GIVEN2: + is($flag, 1, "goto inside given"); +} +{ + my $flag = 0; + given ($flag) { + when (0) { $flag = 1; goto GIVEN3; $flag = 2; } + $flag = 3; + } +GIVEN3: + is($flag, 1, "goto inside given and when"); +} +{ + my $flag = 0; + for ($flag) { + when (0) { $flag = 1; goto GIVEN4; $flag = 2; } + $flag = 3; + } +GIVEN4: + is($flag, 1, "goto inside for and when"); +} +{ + my $flag = 0; +GIVEN5: + given ($flag) { + when (0) { $flag = 1; goto GIVEN5; $flag = 2; } + when (1) { break; } + $flag = 3; + } + is($flag, 1, "goto inside given and when to the given stmt"); +} + +# test with unreified @_ in smart match [perl #71078] +sub unreified_check { ok([@_] ~~ \@_) } # should always match +unreified_check(1,2,"lala"); +unreified_check(1,2,undef); +unreified_check(undef); +unreified_check(undef,""); + +# Test do { given } as a rvalue + +{ + # Simple scalar + my $lexical = 5; + my @things = (11 .. 26); # 16 elements + my @exp = (5, 16, 9); + no warnings 'void'; + for (0, 1, 2) { + my $scalar = do { given ($_) { + when (0) { $lexical } + when (2) { 'void'; 8, 9 } + @things; + } }; + is($scalar, shift(@exp), "rvalue given - simple scalar [$_]"); + } +} +{ + # Postfix scalar + my $lexical = 5; + my @exp = (5, 7, 9); + for (0, 1, 2) { + no warnings 'void'; + my $scalar = do { given ($_) { + $lexical when 0; + 8, 9 when 2; + 6, 7; + } }; + is($scalar, shift(@exp), "rvalue given - postfix scalar [$_]"); + } +} +{ + # Default scalar + my @exp = (5, 9, 9); + for (0, 1, 2) { + my $scalar = do { given ($_) { + no warnings 'void'; + when (0) { 5 } + default { 8, 9 } + 6, 7; + } }; + is($scalar, shift(@exp), "rvalue given - default scalar [$_]"); + } +} +{ + # Simple list + my @things = (11 .. 13); + my @exp = ('3 4 5', '11 12 13', '8 9'); + for (0, 1, 2) { + my @list = do { given ($_) { + when (0) { 3 .. 5 } + when (2) { my $fake = 'void'; 8, 9 } + @things; + } }; + is("@list", shift(@exp), "rvalue given - simple list [$_]"); + } +} +{ + # Postfix list + my @things = (12); + my @exp = ('3 4 5', '6 7', '12'); + for (0, 1, 2) { + my @list = do { given ($_) { + 3 .. 5 when 0; + @things when 2; + 6, 7; + } }; + is("@list", shift(@exp), "rvalue given - postfix list [$_]"); + } +} +{ + # Default list + my @things = (11 .. 20); # 10 elements + my @exp = ('m o o', '8 10', '8 10'); + for (0, 1, 2) { + my @list = do { given ($_) { + when (0) { "moo" =~ /(.)/g } + default { 8, scalar(@things) } + 6, 7; + } }; + is("@list", shift(@exp), "rvalue given - default list [$_]"); + } +} +{ + # Switch control + my @exp = ('6 7', '', '6 7'); + for (0, 1, 2, 3) { + my @list = do { given ($_) { + continue when $_ <= 1; + break when 1; + next when 2; + 6, 7; + } }; + is("@list", shift(@exp), "rvalue given - default list [$_]"); + } +} +{ + # Context propagation + my $smart_hash = sub { + do { given ($_[0]) { + 'undef' when undef; + when ([ 1 .. 3 ]) { 1 .. 3 } + when (4) { my $fake; do { 4, 5 } } + } }; + }; + + my $scalar; + + $scalar = $smart_hash->(); + is($scalar, 'undef', "rvalue given - scalar context propagation [undef]"); + + $scalar = $smart_hash->(4); + is($scalar, 5, "rvalue given - scalar context propagation [4]"); + + $scalar = $smart_hash->(999); + is($scalar, undef, "rvalue given - scalar context propagation [999]"); + + my @list; + + @list = $smart_hash->(); + is("@list", 'undef', "rvalue given - list context propagation [undef]"); + + @list = $smart_hash->(2); + is("@list", '1 2 3', "rvalue given - list context propagation [2]"); + + @list = $smart_hash->(4); + is("@list", '4 5', "rvalue given - list context propagation [4]"); + + @list = $smart_hash->(999); + is("@list", '', "rvalue given - list context propagation [999]"); +} +{ + # Array slices + my @list = 10 .. 15; + my @in_list; + my @in_slice; + for (5, 10, 15) { + given ($_) { + when (@list) { + push @in_list, $_; + continue; + } + when (@list[0..2]) { + push @in_slice, $_; + } + } + } + is("@in_list", "10 15", "when(array)"); + is("@in_slice", "10", "when(array slice)"); +} +{ + # Hash slices + my %list = map { $_ => $_ } "a" .. "f"; + my @in_list; + my @in_slice; + for ("a", "e", "i") { + given ($_) { + when (%list) { + push @in_list, $_; + continue; + } + when (@list{"a".."c"}) { + push @in_slice, $_; + } + } + } + is("@in_list", "a e", "when(hash)"); + is("@in_slice", "a", "when(hash slice)"); +} + +{ # RT#84526 - Handle magical TARG + my $x = my $y = "aaa"; + for ($x, $y) { + given ($_) { + is(pos, undef, "handle magical TARG"); + pos = 1; + } + } +} + +# Test that returned values are correctly propagated through several context +# levels (see RT #93548). +{ + my $tester = sub { + my $id = shift; + + package fmurrr; + + our ($when_loc, $given_loc, $ext_loc); + + my $ext_lex = 7; + our $ext_glob = 8; + local $ext_loc = 9; + + given ($id) { + my $given_lex = 4; + our $given_glob = 5; + local $given_loc = 6; + + when (0) { 0 } + + when (1) { my $when_lex = 1 } + when (2) { our $when_glob = 2 } + when (3) { local $when_loc = 3 } + + when (4) { $given_lex } + when (5) { $given_glob } + when (6) { $given_loc } + + when (7) { $ext_lex } + when (8) { $ext_glob } + when (9) { $ext_loc } + + 'fallback'; + } + }; + + my @descriptions = qw< + constant + + when-lexical + when-global + when-local + + given-lexical + given-global + given-local + + extern-lexical + extern-global + extern-local + >; + + for my $id (0 .. 9) { + my $desc = $descriptions[$id]; + + my $res = $tester->($id); + is $res, $id, "plain call - $desc"; + + $res = do { + my $id_plus_1 = $id + 1; + given ($id_plus_1) { + do { + when (/\d/) { + --$id_plus_1; + continue; + 456; + } + }; + default { + $tester->($id_plus_1); + } + 'XXX'; + } + }; + is $res, $id, "across continue and default - $desc"; + } +} + +# Check that values returned from given/when are destroyed at the right time. +{ + { + package Fmurrr; + + sub new { + bless { + flag => \($_[1]), + id => $_[2], + }, $_[0] + } + + sub DESTROY { + ${$_[0]->{flag}}++; + } + } + + my @descriptions = qw< + when + break + continue + default + >; + + for my $id (0 .. 3) { + my $desc = $descriptions[$id]; + + my $destroyed = 0; + my $res_id; + + { + my $res = do { + given ($id) { + my $x; + when (0) { Fmurrr->new($destroyed, 0) } + when (1) { my $y = Fmurrr->new($destroyed, 1); break } + when (2) { $x = Fmurrr->new($destroyed, 2); continue } + when (2) { $x } + default { Fmurrr->new($destroyed, 3) } + } + }; + $res_id = $res->{id}; + } + $res_id = $id if $id == 1; # break doesn't return anything + + is $res_id, $id, "given/when returns the right object - $desc"; + is $destroyed, 1, "given/when does not leak - $desc"; + }; +} + +# break() must reset the stack +{ + my @res = (1, do { + given ("x") { + 2, 3, do { + when (/[a-z]/) { + 4, 5, 6, break + } + } + } + }); + is "@res", "1", "break resets the stack"; +} + +# RT #94682: +# must ensure $_ is initialised and cleared at start/end of given block + +{ + package RT94682; + + my $d = 0; + sub DESTROY { $d++ }; + + sub f2 { + local $_ = 5; + given(bless [7]) { + ::is($_->[0], 7, "is [7]"); + } + ::is($_, 5, "is 5"); + ::is($d, 1, "DESTROY called once"); + } + f2(); +} + +# check that 'when' handles all 'for' loop types + +{ + my $i; + + $i = 0; + for (1..3) { + when (1) {$i += 1 } + when (2) {$i += 10 } + when (3) {$i += 100 } + default { $i += 1000 } + } + is($i, 111, "when in for 1..3"); + + $i = 0; + for ('a'..'c') { + when ('a') {$i += 1 } + when ('b') {$i += 10 } + when ('c') {$i += 100 } + default { $i += 1000 } + } + is($i, 111, "when in for a..c"); + + $i = 0; + for (1,2,3) { + when (1) {$i += 1 } + when (2) {$i += 10 } + when (3) {$i += 100 } + default { $i += 1000 } + } + is($i, 111, "when in for 1,2,3"); + + $i = 0; + my @a = (1,2,3); + for (@a) { + when (1) {$i += 1 } + when (2) {$i += 10 } + when (3) {$i += 100 } + default { $i += 1000 } + } + is($i, 111, 'when in for @a'); +} + +given("xyz") { + no warnings "void"; + my @a = (qw(a b c), do { when(/abc/) { qw(x y) } }, qw(d e f)); + is join(",", map { $_ // "u" } @a), "a,b,c,d,e,f", + "list value of false when"; + @a = (qw(a b c), scalar do { when(/abc/) { qw(x y) } }, qw(d e f)); + is join(",", map { $_ // "u" } @a), "a,b,c,u,d,e,f", + "scalar value of false when"; +} + +# RT #133368 +# index() and rindex() comparisons such as '> -1' are optimised away. Make +# sure that they're still treated as a direct boolean expression rather +# than when(X) being implicitly converted to when($_ ~~ X) + +{ + my $s = "abc"; + my $ok = 0; + given("xyz") { + when (index($s, 'a') > -1) { $ok = 1; } + } + ok($ok, "RT #133368 index"); + + $ok = 0; + given("xyz") { + when (rindex($s, 'a') > -1) { $ok = 1; } + } + ok($ok, "RT #133368 rindex"); +} + + +# Okay, that'll do for now. The intricacies of the smartmatch +# semantics are tested in t/op/smartmatch.t. Taintedness of +# returned values is checked in t/op/taint.t. +__END__ diff --git a/t/op/taint.t b/t/op/taint.t index a884a3e47721..daeb164efafe 100644 --- a/t/op/taint.t +++ b/t/op/taint.t @@ -25,7 +25,7 @@ if ($NoTaintSupport) { exit 0; } -plan tests => 1059; +plan tests => 1065; $| = 1; @@ -2440,6 +2440,32 @@ EOF is_tainted $dest, "ucfirst(tainted) taints its return value"; } +{ + # Taintedness of values returned from given() + use feature 'switch'; + no warnings 'experimental::smartmatch'; + + my @descriptions = ('when', 'given end', 'default'); + + for (qw) { + my $letter = "$_$TAINT"; + + my $desc = "tainted value returned from " . shift(@descriptions); + + my $res = do { + no warnings 'deprecated'; + given ($_) { + when ('x') { $letter } + when ('y') { goto leavegiven } + default { $letter } + leavegiven: $letter + } + }; + is $res, $letter, "$desc is correct"; + is_tainted $res, "$desc stays tainted"; + } +} + # tainted constants and index() # RT 64804; http://bugs.debian.org/291450 diff --git a/toke.c b/toke.c index a6c8b2603f07..6eaa9bdcac95 100644 --- a/toke.c +++ b/toke.c @@ -445,10 +445,12 @@ static struct debug_tokens { DEBUG_TOKEN (IVAL, KW_CATCH), DEBUG_TOKEN (IVAL, KW_CLASS), DEBUG_TOKEN (IVAL, KW_CONTINUE), + DEBUG_TOKEN (IVAL, KW_DEFAULT), DEBUG_TOKEN (IVAL, KW_DO), DEBUG_TOKEN (IVAL, KW_ELSE), DEBUG_TOKEN (IVAL, KW_ELSIF), DEBUG_TOKEN (IVAL, KW_FIELD), + DEBUG_TOKEN (IVAL, KW_GIVEN), DEBUG_TOKEN (IVAL, KW_FOR), DEBUG_TOKEN (IVAL, KW_FORMAT), DEBUG_TOKEN (IVAL, KW_IF), @@ -466,6 +468,7 @@ static struct debug_tokens { DEBUG_TOKEN (IVAL, KW_USE_or_NO), DEBUG_TOKEN (IVAL, KW_UNLESS), DEBUG_TOKEN (IVAL, KW_UNTIL), + DEBUG_TOKEN (IVAL, KW_WHEN), DEBUG_TOKEN (IVAL, KW_WHILE), DEBUG_TOKEN (OPVAL, LABEL), DEBUG_TOKEN (OPNUM, LOOPEX), @@ -8024,6 +8027,9 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_bless: LOP(OP_BLESS,XTERM); + case KEY_break: + FUN0(OP_BREAK); + case KEY_catch: PREBLOCK(KW_CATCH); @@ -8041,7 +8047,16 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct TOKEN(KW_CLASS); case KEY_continue: - PREBLOCK(KW_CONTINUE); + /* We have to disambiguate the two senses of + "continue". If the next token is a '{' then + treat it as the start of a continue block; + otherwise treat it as a control operator. + */ + s = skipspace(s); + if (*s == '{') + PREBLOCK(KW_CONTINUE); + else + FUN0(OP_CONTINUE); case KEY_chdir: /* may use HOME */ @@ -8084,6 +8099,9 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_chroot: UNI(OP_CHROOT); + case KEY_default: + PREBLOCK(KW_DEFAULT); + case KEY_defer: Perl_ck_warner_d(aTHX_ packWARN(WARN_EXPERIMENTAL__DEFER), "defer is experimental"); @@ -8317,6 +8335,12 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_getlogin: FUN0(OP_GETLOGIN); + case KEY_given: + pl_yylval.ival = CopLINE(PL_curcop); + Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED__SMARTMATCH), + "given is deprecated"); + OPERATOR(KW_GIVEN); + case KEY_glob: LOP( orig_keyword==KEY_glob ? -OP_GLOB : OP_GLOB, XTERM ); @@ -8820,6 +8844,15 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_vec: LOP(OP_VEC,XTERM); + case KEY_when: + if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_NONEXPR) + return REPORT(0); + pl_yylval.ival = CopLINE(PL_curcop); + Perl_ck_warner_d(aTHX_ + packWARN(WARN_DEPRECATED__SMARTMATCH), + "when is deprecated"); + OPERATOR(KW_WHEN); + case KEY_while: if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_NONEXPR) return REPORT(0); From 44d4f8c270617659ff6248fe698d6af267d0e52a Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Tue, 19 Nov 2024 14:21:16 +1100 Subject: [PATCH 09/12] add the smartmatch feature --- feature.h | 29 ++++++++++++--- lib/feature.pm | 91 ++++++++++++++++++++++++++++------------------- regen/feature.pl | 25 +++++++++++-- t/lib/feature/api | 8 ++--- 4 files changed, 105 insertions(+), 48 deletions(-) diff --git a/feature.h b/feature.h index 19702d06a28e..290830e4e761 100644 --- a/feature.h +++ b/feature.h @@ -30,11 +30,12 @@ #define FEATURE_REFALIASING_BIT 0x8000 #define FEATURE_SAY_BIT 0x10000 #define FEATURE_SIGNATURES_BIT 0x20000 -#define FEATURE_STATE_BIT 0x40000 -#define FEATURE_SWITCH_BIT 0x80000 -#define FEATURE_TRY_BIT 0x100000 -#define FEATURE_UNIEVAL_BIT 0x200000 -#define FEATURE_UNICODE_BIT 0x400000 +#define FEATURE_SMARTMATCH_BIT 0x40000 +#define FEATURE_STATE_BIT 0x80000 +#define FEATURE_SWITCH_BIT 0x100000 +#define FEATURE_TRY_BIT 0x200000 +#define FEATURE_UNIEVAL_BIT 0x400000 +#define FEATURE_UNICODE_BIT 0x800000 #define FEATURE_BUNDLE_DEFAULT 0 #define FEATURE_BUNDLE_510 1 @@ -156,6 +157,13 @@ FEATURE_IS_ENABLED_MASK(FEATURE_SIGNATURES_BIT)) \ ) +#define FEATURE_SMARTMATCH_IS_ENABLED \ + ( \ + CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_539 \ + || (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \ + FEATURE_IS_ENABLED_MASK(FEATURE_SMARTMATCH_BIT)) \ + ) + #define FEATURE___SUB___IS_ENABLED \ ( \ (CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_515 && \ @@ -425,6 +433,11 @@ S_magic_sethint_feature(pTHX_ SV *keysv, const char *keypv, STRLEN keylen, mask = FEATURE_SIGNATURES_BIT; break; } + else if (keylen == sizeof("feature_smartmatch")-1 + && memcmp(subf+1, "martmatch", keylen - sizeof("feature_")) == 0) { + mask = FEATURE_SMARTMATCH_BIT; + break; + } else if (keylen == sizeof("feature_state")-1 && memcmp(subf+1, "tate", keylen - sizeof("feature_")) == 0) { mask = FEATURE_STATE_BIT; @@ -588,6 +601,12 @@ PL_feature_bits[] = { STRLENs("feature_signatures"), FEATURE_SIGNATURES_BIT }, + { + /* feature smartmatch */ + "feature_smartmatch", + STRLENs("feature_smartmatch"), + FEATURE_SMARTMATCH_BIT + }, { /* feature state */ "feature_state", diff --git a/lib/feature.pm b/lib/feature.pm index fa9ed5ed2b2f..8750ebfa2f78 100644 --- a/lib/feature.pm +++ b/lib/feature.pm @@ -19,6 +19,7 @@ our %feature = ( indirect => 'feature_indirect', evalbytes => 'feature_evalbytes', signatures => 'feature_signatures', + smartmatch => 'feature_smartmatch', current_sub => 'feature___SUB__', module_true => 'feature_module_true', refaliasing => 'feature_refaliasing', @@ -33,17 +34,17 @@ our %feature = ( ); our %feature_bundle = ( - "5.10" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch)], - "5.11" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch unicode_strings)], - "5.15" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say state switch unicode_eval unicode_strings)], - "5.23" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)], - "5.27" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)], - "5.35" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc isa postderef_qq say signatures state unicode_eval unicode_strings)], - "5.37" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state unicode_eval unicode_strings)], - "5.39" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state try unicode_eval unicode_strings)], + "5.10" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say smartmatch state switch)], + "5.11" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional say smartmatch state switch unicode_strings)], + "5.15" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional say smartmatch state switch unicode_eval unicode_strings)], + "5.23" => [qw(apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say smartmatch state switch unicode_eval unicode_strings)], + "5.27" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say smartmatch state switch unicode_eval unicode_strings)], + "5.35" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc isa postderef_qq say signatures smartmatch state unicode_eval unicode_strings)], + "5.37" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures smartmatch state unicode_eval unicode_strings)], + "5.39" => [qw(apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures smartmatch state try unicode_eval unicode_strings)], "5.41" => [qw(bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures state try unicode_eval unicode_strings)], - "all" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise class current_sub declared_refs defer evalbytes extra_paired_delimiters fc indirect isa module_true multidimensional postderef_qq refaliasing say signatures state switch try unicode_eval unicode_strings)], - "default" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional)], + "all" => [qw(apostrophe_as_package_separator bareword_filehandles bitwise class current_sub declared_refs defer evalbytes extra_paired_delimiters fc indirect isa module_true multidimensional postderef_qq refaliasing say signatures smartmatch state switch try unicode_eval unicode_strings)], + "default" => [qw(apostrophe_as_package_separator bareword_filehandles indirect multidimensional smartmatch)], ); $feature_bundle{"5.12"} = $feature_bundle{"5.11"}; @@ -174,6 +175,23 @@ See L for details. This feature is available starting with Perl 5.10. +=head2 The 'smartmatch' feature + +C tells the compiler to enable the +smartmatch operator C<~~>. It is enabled by default, but can be +turned off to disallow the C<~~> operator. + +This feature is disabled by default in the 5.42 feature bundle +onwards: + + $x ~~ $y; # fine + use v5.42; + $x ~~ $y; # error + +This has no effect on the implicit smartmatches done by C. + +See L for details. + =head2 The 'switch' feature B: This feature is still experimental and the implementation may @@ -544,92 +562,93 @@ The following feature bundles are available: --------- ----------------- :default indirect multidimensional bareword_filehandles - apostrophe_as_package_separator + apostrophe_as_package_separator smartmatch :5.10 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state switch + multidimensional say smartmatch state switch :5.12 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state switch + multidimensional say smartmatch state switch unicode_strings :5.14 apostrophe_as_package_separator bareword_filehandles indirect - multidimensional say state switch + multidimensional say smartmatch state switch unicode_strings :5.16 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes - fc indirect multidimensional say state - switch unicode_eval unicode_strings + fc indirect multidimensional say smartmatch + state switch unicode_eval unicode_strings :5.18 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes - fc indirect multidimensional say state - switch unicode_eval unicode_strings + fc indirect multidimensional say smartmatch + state switch unicode_eval unicode_strings :5.20 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes - fc indirect multidimensional say state - switch unicode_eval unicode_strings + fc indirect multidimensional say smartmatch + state switch unicode_eval unicode_strings :5.22 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes - fc indirect multidimensional say state - switch unicode_eval unicode_strings + fc indirect multidimensional say smartmatch + state switch unicode_eval unicode_strings :5.24 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq - say state switch unicode_eval + say smartmatch state switch unicode_eval unicode_strings :5.26 apostrophe_as_package_separator bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq - say state switch unicode_eval + say smartmatch state switch unicode_eval unicode_strings :5.28 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state switch unicode_eval - unicode_strings + postderef_qq say smartmatch state switch + unicode_eval unicode_strings :5.30 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state switch unicode_eval - unicode_strings + postderef_qq say smartmatch state switch + unicode_eval unicode_strings :5.32 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state switch unicode_eval - unicode_strings + postderef_qq say smartmatch state switch + unicode_eval unicode_strings :5.34 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional - postderef_qq say state switch unicode_eval - unicode_strings + postderef_qq say smartmatch state switch + unicode_eval unicode_strings :5.36 apostrophe_as_package_separator bareword_filehandles bitwise current_sub evalbytes fc isa postderef_qq say signatures - state unicode_eval unicode_strings + smartmatch state unicode_eval + unicode_strings :5.38 apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true - postderef_qq say signatures state + postderef_qq say signatures smartmatch state unicode_eval unicode_strings :5.40 apostrophe_as_package_separator bitwise current_sub evalbytes fc isa module_true - postderef_qq say signatures state try - unicode_eval unicode_strings + postderef_qq say signatures smartmatch state + try unicode_eval unicode_strings :5.42 bitwise current_sub evalbytes fc isa module_true postderef_qq say signatures diff --git a/regen/feature.pl b/regen/feature.pl index 0528f0109aba..c0104352609e 100755 --- a/regen/feature.pl +++ b/regen/feature.pl @@ -47,6 +47,7 @@ BEGIN module_true => 'module_true', class => 'class', apostrophe_as_package_separator => 'apos_as_name_sep', + smartmatch => 'smartmatch', ); # NOTE: If a feature is ever enabled in a non-contiguous range of Perl @@ -56,7 +57,7 @@ BEGIN # 5.odd implies the next 5.even, but an explicit 5.even can override it. # features bundles -use constant V5_9_5 => sort qw{say state switch indirect multidimensional bareword_filehandles apostrophe_as_package_separator}; +use constant V5_9_5 => sort qw{say state switch indirect multidimensional bareword_filehandles apostrophe_as_package_separator smartmatch}; use constant V5_11 => sort ( +V5_9_5, qw{unicode_strings} ); use constant V5_15 => sort ( +V5_11, qw{unicode_eval evalbytes current_sub fc} ); use constant V5_23 => sort ( +V5_15, qw{postderef_qq} ); @@ -70,7 +71,8 @@ BEGIN use constant V5_39 => sort ( +V5_37, qw{try} ); use constant V5_41 => sort - grep {; $_ ne 'apostrophe_as_package_separator' } + grep {; $_ ne 'apostrophe_as_package_separator' + && $_ ne 'smartmatch' } ( +V5_39 ); # @@ -79,7 +81,7 @@ BEGIN my %feature_bundle = ( all => [ sort keys %feature ], default => [ qw{indirect multidimensional bareword_filehandles - apostrophe_as_package_separator} ], + apostrophe_as_package_separator smartmatch} ], # using 5.9.5 features bundle "5.9.5" => [ +V5_9_5 ], "5.10" => [ +V5_9_5 ], @@ -638,6 +640,23 @@ =head2 The 'state' feature This feature is available starting with Perl 5.10. +=head2 The 'smartmatch' feature + +C tells the compiler to enable the +smartmatch operator C<~~>. It is enabled by default, but can be +turned off to disallow the C<~~> operator. + +This feature is disabled by default in the 5.42 feature bundle +onwards: + + $x ~~ $y; # fine + use v5.42; + $x ~~ $y; # error + +This has no effect on the implicit smartmatches done by C. + +See L for details. + =head2 The 'switch' feature B: This feature is still experimental and the implementation may diff --git a/t/lib/feature/api b/t/lib/feature/api index 1b67edd1cb9d..621c21bafe4b 100644 --- a/t/lib/feature/api +++ b/t/lib/feature/api @@ -17,10 +17,10 @@ BEGIN { print "bundle: ", feature::feature_bundle(0) // "undef", "\n"; } EXPECT -default: apostrophe_as_package_separator bareword_filehandles indirect multidimensional +default: apostrophe_as_package_separator bareword_filehandles indirect multidimensional smartmatch unicode_strings is not enabled bundle: default -5.12: apostrophe_as_package_separator bareword_filehandles indirect multidimensional say state switch unicode_strings +5.12: apostrophe_as_package_separator bareword_filehandles indirect multidimensional say smartmatch state switch unicode_strings unicode_strings is enabled bundle: 5.11 ######## @@ -40,9 +40,9 @@ BEGIN { print "bundle: ", feature::feature_bundle(0) // "undef", "\n"; } EXPECT -no feature indirect: apostrophe_as_package_separator bareword_filehandles multidimensional +no feature indirect: apostrophe_as_package_separator bareword_filehandles multidimensional smartmatch indirect is not enabled bundle: undef -added unicode_strings: apostrophe_as_package_separator bareword_filehandles multidimensional unicode_strings +added unicode_strings: apostrophe_as_package_separator bareword_filehandles multidimensional smartmatch unicode_strings unicode_strings is enabled bundle: undef From cc8f844d4ff31ecf965f732cbcb3d01f65d1b8d8 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Wed, 20 Nov 2024 09:19:27 +1100 Subject: [PATCH 10/12] implement the smartmatch feature and test it interestingly the TOKEN(0) line here isn't exercised by the test suite, I haven't tracked down what it would take to exercise it. The deprecation messages will be removed in an upcoming commit --- MANIFEST | 1 + t/lib/feature/smartmatch | 49 ++++++++++++++++++++++++++++++++++++++++ toke.c | 3 ++- 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 t/lib/feature/smartmatch diff --git a/MANIFEST b/MANIFEST index 68d330820920..c3ca5d9dcd9c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -6118,6 +6118,7 @@ t/lib/feature/multidimensional Tests for enabling/disabling $foo{$x, $y} => $fo t/lib/feature/nonesuch Tests for enabling/disabling nonexistent feature t/lib/feature/removed Tests for enabling/disabling removed feature t/lib/feature/say Tests for enabling/disabling say feature +t/lib/feature/smartmatch Tests for enabling/disabling smartmatch feature t/lib/feature/switch Tests for enabling/disabling switch feature t/lib/h2ph.h Test header file for h2ph t/lib/h2ph.pht Generated output from h2ph.h by h2ph, for comparison diff --git a/t/lib/feature/smartmatch b/t/lib/feature/smartmatch new file mode 100644 index 000000000000..213fa4e4ab89 --- /dev/null +++ b/t/lib/feature/smartmatch @@ -0,0 +1,49 @@ +Test no feature smartmatch + +__END__ +# NAME default +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +Smartmatch is deprecated at - line 2. +######## +# NAME explicit disable +no feature "smartmatch"; +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +OPTION fatal +syntax error at - line 3, near ""b" ~" +Execution of - aborted due to compilation errors. +######## +# NAME explicit enable +use feature "smartmatch"; +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +Smartmatch is deprecated at - line 3. +######## +# NAME explicit disable then enable +no feature "smartmatch"; +use feature "smartmatch"; +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +Smartmatch is deprecated at - line 4. +######## +# NAME implicit disable +use v5.41; +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +OPTION fatal +syntax error at - line 3, near ""b" ~" +Execution of - aborted due to compilation errors. +######## +# NAME implicit disable then enable +use v5.41; +use feature "smartmatch"; +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +Smartmatch is deprecated at - line 4. diff --git a/toke.c b/toke.c index 6eaa9bdcac95..535800309190 100644 --- a/toke.c +++ b/toke.c @@ -6816,7 +6816,8 @@ static int yyl_tilde(pTHX_ char *s) { bool bof; - if (s[1] == '~' && (PL_expect == XOPERATOR || PL_expect == XTERMORDORDOR)) { + if (FEATURE_SMARTMATCH_IS_ENABLED && + s[1] == '~' && (PL_expect == XOPERATOR || PL_expect == XTERMORDORDOR)) { if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE) TOKEN(0); s += 2; From 0851d96e73cb76d5c2eccaab984741bcb79c9806 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Wed, 20 Nov 2024 11:09:12 +1100 Subject: [PATCH 11/12] undeprecate switch and smartmatch The deprecation warnings don't appear to have had any tests. --- lib/warnings.pm | 28 +++++++++++----------------- pod/perldeprecation.pod | 9 --------- pod/perldiag.pod | 22 ---------------------- regen/warnings.pl | 2 +- t/lib/feature/smartmatch | 4 ---- t/op/smartmatch.t | 1 - t/op/switch.t | 1 - toke.c | 8 -------- warnings.h | 9 ++------- 9 files changed, 14 insertions(+), 70 deletions(-) diff --git a/lib/warnings.pm b/lib/warnings.pm index 7edc55640b51..4088ad164c85 100644 --- a/lib/warnings.pm +++ b/lib/warnings.pm @@ -124,14 +124,11 @@ our %Offsets = ( # Warnings Categories added in Perl 5.037 'experimental::class' => 150, - # Warnings Categories added in Perl 5.03701 - 'deprecated::smartmatch' => 152, - # Warnings Categories added in Perl 5.039002 - 'deprecated::missing_import_called_with_args'=> 154, + 'deprecated::missing_import_called_with_args'=> 152, # Warnings Categories added in Perl 5.039008 - 'deprecated::subsequent_use_version'=> 156, + 'deprecated::subsequent_use_version'=> 154, ); our %Bits = ( @@ -141,13 +138,12 @@ our %Bits = ( 'closed' => "\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6] 'closure' => "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [1] 'debugging' => "\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [22] - 'deprecated' => "\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x10\x00\x00\x14\x15", # [2,48,49,62,73,74,76..78] + 'deprecated' => "\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x10\x00\x00\x14\x05", # [2,48,49,62,73,74,76,77] 'deprecated::delimiter_will_be_paired'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00", # [74] 'deprecated::dot_in_inc' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00", # [62] 'deprecated::goto_construct' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00", # [48] - 'deprecated::missing_import_called_with_args'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", # [77] - 'deprecated::smartmatch' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [76] - 'deprecated::subsequent_use_version'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", # [78] + 'deprecated::missing_import_called_with_args'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [76] + 'deprecated::subsequent_use_version'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", # [77] 'deprecated::unicode_property_name' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00", # [49] 'deprecated::version_downgrade' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00", # [73] 'digit' => "\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31] @@ -223,13 +219,12 @@ our %DeadBits = ( 'closed' => "\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6] 'closure' => "\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [1] 'debugging' => "\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [22] - 'deprecated' => "\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x20\x00\x00\x28\x2a", # [2,48,49,62,73,74,76..78] + 'deprecated' => "\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x20\x00\x00\x28\x0a", # [2,48,49,62,73,74,76,77] 'deprecated::delimiter_will_be_paired'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00", # [74] 'deprecated::dot_in_inc' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00", # [62] 'deprecated::goto_construct' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00", # [48] - 'deprecated::missing_import_called_with_args'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08", # [77] - 'deprecated::smartmatch' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [76] - 'deprecated::subsequent_use_version'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20", # [78] + 'deprecated::missing_import_called_with_args'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [76] + 'deprecated::subsequent_use_version'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08", # [77] 'deprecated::unicode_property_name' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00", # [49] 'deprecated::version_downgrade' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00", # [73] 'digit' => "\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31] @@ -299,6 +294,7 @@ our %DeadBits = ( ); our %NoOp = ( + 'deprecated::smartmatch' => 1, 'experimental::alpha_assertions' => 1, 'experimental::bitwise' => 1, 'experimental::const_attr' => 1, @@ -313,8 +309,8 @@ our %NoOp = ( # These are used by various things, including our own tests our $NONE = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x05\x00\x15\x14\x55\x55\x54\x15"; # [2,4,22,23,25,48,49,56..58,61,62,64..71,73..78] -our $LAST_BIT = 158 ; +our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x05\x00\x15\x14\x55\x55\x54\x05"; # [2,4,22,23,25,48,49,56..58,61,62,64..71,73..77] +our $LAST_BIT = 156 ; our $BYTES = 20 ; sub Croaker @@ -925,8 +921,6 @@ The current hierarchy is: | | | +- deprecated::missing_import_called_with_args | | - | +- deprecated::smartmatch - | | | +- deprecated::subsequent_use_version | | | +- deprecated::unicode_property_name diff --git a/pod/perldeprecation.pod b/pod/perldeprecation.pod index 207f4974e234..345d2c31bc0c 100644 --- a/pod/perldeprecation.pod +++ b/pod/perldeprecation.pod @@ -71,15 +71,6 @@ Category: "deprecated::subsequent_use_version" =head2 Perl 5.42 -=head3 Smartmatch - -Smartmatch is now seen as a failed experiment and was marked as deprecated -in Perl 5.37.10. This includes the C and C keywords, as well -as the smartmatch operator C<~~>. The feature will be removed entirely in the -Perl 5.42.0 production release. - -Category: "deprecated::smartmatch" - =head3 Goto Block Construct C will produce a deprecated warning when jumping into the body diff --git a/pod/perldiag.pod b/pod/perldiag.pod index f19bab3feb39..f6c9fd8aad06 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -2756,12 +2756,6 @@ L. arguments are provided in key/value pairs, with the keys being one of C, C or C, followed by a boolean. -=item given is deprecated - -(D deprecated::smartmatch) C depends on smartmatch, which is -deprecated. It will be removed in Perl 5.42. See the explanation under -L. - =item Global symbol "%s" requires explicit package name (did you forget to declare "my %s"?) @@ -6201,14 +6195,6 @@ so there can't be any left to fill later parameters. overload it: Perl refuses to use the object's underlying structure for the smart match. -=item Smartmatch is deprecated - -(D deprecated::smartmatch) This warning is emitted if you -use the smartmatch (C<~~>) operator. This is a deprecated -feature. Particularly, its behavior is noticed for being -unnecessarily complex and unintuitive, and it will be removed -in Perl 5.42. - =item Sorry, hash keys must be smaller than 2**31 bytes (F) You tried to create a hash containing a very large key, where "very @@ -8209,14 +8195,6 @@ but in actual fact, you got So put in parentheses to say what you really mean. -=item when is deprecated - -(D deprecated::smartmatch) C depends on smartmatch, which is -deprecated. Additionally, it has several special cases that may -not be immediately obvious, and it will be removed in Perl 5.42. -See the explanation -under L. - =item Wide character in %s (S utf8) Perl met a wide character (ordinal >255) when it wasn't diff --git a/regen/warnings.pl b/regen/warnings.pl index b39c4ad177c0..6e1eba91055c 100644 --- a/regen/warnings.pl +++ b/regen/warnings.pl @@ -80,7 +80,6 @@ BEGIN 'deprecated::dot_in_inc' => [ 5.025011, DEFAULT_ON], 'deprecated::version_downgrade' => [ 5.035009, DEFAULT_ON], 'deprecated::delimiter_will_be_paired' => [ 5.035010, DEFAULT_ON], - 'deprecated::smartmatch' => [ 5.037010, DEFAULT_ON], 'deprecated::missing_import_called_with_args' => [ 5.039002, DEFAULT_ON], 'deprecated::subsequent_use_version' => [ 5.039008, DEFAULT_ON], @@ -184,6 +183,7 @@ BEGIN # the experiments were successful (or abandonned), # so no warning bit is needed anymore my %NO_BIT_FOR = map { ( uc $_ => 1, $_ => 1 ) } qw( + deprecated::smartmatch experimental::lexical_subs experimental::postderef experimental::signatures diff --git a/t/lib/feature/smartmatch b/t/lib/feature/smartmatch index 213fa4e4ab89..e598a1f1b0cc 100644 --- a/t/lib/feature/smartmatch +++ b/t/lib/feature/smartmatch @@ -5,7 +5,6 @@ __END__ my @x = qw(a b c); my $y = "b" ~~ @x; EXPECT -Smartmatch is deprecated at - line 2. ######## # NAME explicit disable no feature "smartmatch"; @@ -21,7 +20,6 @@ use feature "smartmatch"; my @x = qw(a b c); my $y = "b" ~~ @x; EXPECT -Smartmatch is deprecated at - line 3. ######## # NAME explicit disable then enable no feature "smartmatch"; @@ -29,7 +27,6 @@ use feature "smartmatch"; my @x = qw(a b c); my $y = "b" ~~ @x; EXPECT -Smartmatch is deprecated at - line 4. ######## # NAME implicit disable use v5.41; @@ -46,4 +43,3 @@ use feature "smartmatch"; my @x = qw(a b c); my $y = "b" ~~ @x; EXPECT -Smartmatch is deprecated at - line 4. diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t index ca85d15785c2..e236c8fad60b 100644 --- a/t/op/smartmatch.t +++ b/t/op/smartmatch.t @@ -8,7 +8,6 @@ BEGIN { use strict; use warnings; no warnings 'uninitialized'; -no warnings 'deprecated'; # smartmatch is deprecated and will be removed in 5.042 ++$|; diff --git a/t/op/switch.t b/t/op/switch.t index e1c079956f0d..0cc03d6e8594 100644 --- a/t/op/switch.t +++ b/t/op/switch.t @@ -8,7 +8,6 @@ BEGIN { use strict; use warnings; -no warnings 'deprecated'; plan tests => 197; diff --git a/toke.c b/toke.c index 535800309190..9e0a243cf448 100644 --- a/toke.c +++ b/toke.c @@ -6821,9 +6821,6 @@ yyl_tilde(pTHX_ char *s) if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE) TOKEN(0); s += 2; - Perl_ck_warner_d(aTHX_ - packWARN(WARN_DEPRECATED__SMARTMATCH), - "Smartmatch is deprecated"); NCEop(OP_SMARTMATCH); } s++; @@ -8338,8 +8335,6 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_given: pl_yylval.ival = CopLINE(PL_curcop); - Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED__SMARTMATCH), - "given is deprecated"); OPERATOR(KW_GIVEN); case KEY_glob: @@ -8849,9 +8844,6 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_NONEXPR) return REPORT(0); pl_yylval.ival = CopLINE(PL_curcop); - Perl_ck_warner_d(aTHX_ - packWARN(WARN_DEPRECATED__SMARTMATCH), - "when is deprecated"); OPERATOR(KW_WHEN); case KEY_while: diff --git a/warnings.h b/warnings.h index e4897b655beb..3146a7da641a 100644 --- a/warnings.h +++ b/warnings.h @@ -150,17 +150,13 @@ #define WARN_EXPERIMENTAL__CLASS 75 -/* Warnings Categories added in Perl 5.03701 */ - -#define WARN_DEPRECATED__SMARTMATCH 76 - /* Warnings Categories added in Perl 5.039002 */ -#define WARN_DEPRECATED__MISSING_IMPORT_CALLED_WITH_ARGS 77 +#define WARN_DEPRECATED__MISSING_IMPORT_CALLED_WITH_ARGS 76 /* Warnings Categories added in Perl 5.039008 */ -#define WARN_DEPRECATED__SUBSEQUENT_USE_VERSION 78 +#define WARN_DEPRECATED__SUBSEQUENT_USE_VERSION 77 #define WARNsize 20 #define WARN_ALLstring "\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125" #define WARN_NONEstring "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" @@ -351,7 +347,6 @@ category parameters passed. =for apidoc Amnh||WARN_DEPRECATED__VERSION_DOWNGRADE =for apidoc Amnh||WARN_DEPRECATED__DELIMITER_WILL_BE_PAIRED =for apidoc Amnh||WARN_EXPERIMENTAL__CLASS -=for apidoc Amnh||WARN_DEPRECATED__SMARTMATCH =for apidoc Amnh||WARN_DEPRECATED__MISSING_IMPORT_CALLED_WITH_ARGS =for apidoc Amnh||WARN_DEPRECATED__SUBSEQUENT_USE_VERSION From 929b77f599a63865237a97033892a3814a0d6afa Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Wed, 20 Nov 2024 11:21:05 +1100 Subject: [PATCH 12/12] test that the switch and smartmatch features are independent --- t/lib/feature/smartmatch | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/t/lib/feature/smartmatch b/t/lib/feature/smartmatch index e598a1f1b0cc..a7b30215446d 100644 --- a/t/lib/feature/smartmatch +++ b/t/lib/feature/smartmatch @@ -43,3 +43,54 @@ use feature "smartmatch"; my @x = qw(a b c); my $y = "b" ~~ @x; EXPECT +######## +# NAME smartmatch and switch features independent +no feature "switch"; +use feature "smartmatch"; +BEGIN { + print STDERR "switch ", + feature::feature_enabled("switch") ? "is" : "is not", + " enabled\n"; + print STDERR "smartmatch ", + feature::feature_enabled("smartmatch") ? "is" : "is not", + " enabled\n"; +} +my @x = qw(a b c); +my $y = "b" ~~ @x; +given ($y) { + when (1) { + print "fail!"; + } +} +EXPECT +OPTION fatal +switch is not enabled +smartmatch is enabled +syntax error at - line 13, near ") {" +Execution of - aborted due to compilation errors. +######## +# NAME smartmatch and switch features independent +use feature "switch"; +no feature "smartmatch"; +BEGIN { + print STDERR "switch ", + feature::feature_enabled("switch") ? "is" : "is not", + " enabled\n"; + print STDERR "smartmatch ", + feature::feature_enabled("smartmatch") ? "is" : "is not", + " enabled\n"; +} +my $z; +given ($z) { + when (1) { + print "fail!"; + } +} +my @x = qw(a b c); +my $y = "b" ~~ @x; +EXPECT +OPTION fatal +switch is enabled +smartmatch is not enabled +syntax error at - line 18, near ""b" ~" +Execution of - aborted due to compilation errors.