latest switch/say/~~
Robin Houston [Sat, 17 Dec 2005 20:44:31 +0000 (20:44 +0000)]
Message-Id: <20051217204431.GB28940@rpc142.cs.man.ac.uk>

p4raw-id: //depot/perl@26400

45 files changed:
MANIFEST
cop.h
embed.fnc
embed.h
ext/B/B/Deparse.pm
ext/B/t/concise-xs.t
ext/B/t/f_map.t
ext/B/t/optree_samples.t
ext/IO/lib/IO/Handle.pm
ext/Opcode/Opcode.pm
global.sym
keywords.h
keywords.pl
lib/feature.pm [new file with mode: 0644]
lib/feature.t [new file with mode: 0644]
lib/overload.pm
lib/warnings.t
op.c
op.h
opcode.h
opcode.pl
opnames.h
perl.h
perl_keyword.pl
perly.act
perly.h
perly.tab
perly.y
pod/perldiag.pod
pod/perlfunc.pod
pod/perlop.pod
pod/perlsyn.pod
pp.sym
pp_ctl.c
pp_proto.h
proto.h
t/io/say.t [new file with mode: 0644]
t/lib/feature/nonesuch [new file with mode: 0644]
t/lib/feature/say [new file with mode: 0644]
t/lib/feature/smartmatch [new file with mode: 0644]
t/lib/feature/switch [new file with mode: 0644]
t/op/cproto.t
t/op/smartmatch.t [new file with mode: 0644]
t/op/switch.t [new file with mode: 0644]
toke.c

index 8c53662..7260b76 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1540,6 +1540,8 @@ lib/ExtUtils/xsubpp               External subroutine preprocessor
 lib/fastcwd.pl                 a faster but more dangerous getcwd
 lib/Fatal.pm                   Make errors in functions/builtins fatal
 lib/Fatal.t                    See if Fatal works
+lib/feature.pm                 Pragma to enable new syntax
+lib/feature.t                  See if features work
 lib/fields.pm                  Set up object field names for pseudo-hash-using classes
 lib/File/Basename.pm           Emulate the basename program
 lib/File/Basename.t            See if File::Basename works
@@ -2937,12 +2939,14 @@ t/io/open.t                     See if open works
 t/io/pipe.t                    See if secure pipes work
 t/io/print.t                   See if print commands work
 t/io/read.t                    See if read works
+t/io/say.t                     See if say works
 t/io/tell.t                    See if file seeking works
 t/io/through.t                 See if pipe passes data intact
 t/io/utf8.t                    See if file seeking works
 t/japh/abigail.t               Obscure tests
 t/lib/1_compile.t              See if the various libraries and extensions compile
 t/lib/commonsense.t            See if configuration meets basic needs
+t/lib/common.pl                        Helper for lib/{warnings,feature}.t
 t/lib/compmod.pl               Helper for 1_compile.t
 t/lib/contains_pod.xr          Pod-Parser test file
 t/lib/cygwin.t                 Builtin cygwin function tests
@@ -2965,6 +2969,10 @@ t/lib/dprof/test7_v              Perl code profiler tests
 t/lib/dprof/test8_t            Perl code profiler tests
 t/lib/dprof/test8_v            Perl code profiler tests
 t/lib/dprof/V.pm               Perl code profiler tests
+t/lib/feature/nonesuch         Tests for enabling/disabling nonexistent 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/Filter/Simple/ExportTest.pm      Helper file for Filter::Simple tests
 t/lib/Filter/Simple/FilterOnlyTest.pm  Helper file for Filter::Simple tests
 t/lib/Filter/Simple/FilterTest.pm      Helper file for Filter::Simple tests
@@ -3183,6 +3191,7 @@ t/op/re_tests                     Regular expressions for regexp.t
 t/op/reverse.t                 See if reverse operator works
 t/op/runlevel.t                        See if die() works from perl_call_*()
 t/op/sleep.t                   See if sleep 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
@@ -3199,6 +3208,7 @@ t/op/substr.t                     See if substr works
 t/op/subst.t                   See if substitution works
 t/op/subst_wamp.t              See if substitution works with $& present
 t/op/sub.t                     See if subroutines work
+t/op/switch.t                  See if switches (given/when) work
 t/op/sysio.t                   See if sysread and syswrite work
 t/op/taint.t                   See if tainting works
 t/op/threads.t                 Misc. tests for perl features with threads
diff --git a/cop.h b/cop.h
index eccb795..2444a75 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -419,6 +419,16 @@ struct block_loop {
        if (cx->blk_loop.iterary && cx->blk_loop.iterary != PL_curstack)\
            SvREFCNT_dec(cx->blk_loop.iterary);
 
+/* given/when context */
+struct block_givwhen {
+       OP *leave_op;
+};
+
+#define PUSHGIVEN(cx)                                                  \
+       cx->blk_givwhen.leave_op = cLOGOP->op_other;
+
+#define PUSHWHEN PUSHGIVEN
+
 /* context common to subroutines, evals and loops */
 struct block {
     I32                blku_oldsp;     /* stack pointer to copy stuff down to */
@@ -432,6 +442,7 @@ struct block {
        struct block_sub        blku_sub;
        struct block_eval       blku_eval;
        struct block_loop       blku_loop;
+       struct block_givwhen    blku_givwhen;
     } blk_u;
 };
 #define blk_oldsp      cx_u.cx_blk.blku_oldsp
@@ -443,6 +454,7 @@ struct block {
 #define blk_sub                cx_u.cx_blk.blk_u.blku_sub
 #define blk_eval       cx_u.cx_blk.blk_u.blku_eval
 #define blk_loop       cx_u.cx_blk.blk_u.blku_loop
+#define blk_givwhen    cx_u.cx_blk.blk_u.blku_givwhen
 
 /* Enter a block. */
 #define PUSHBLOCK(cx,t,sp) CXINC, cx = &cxstack[cxstack_ix],           \
@@ -545,6 +557,8 @@ struct context {
 #define CXt_SUBST      4
 #define CXt_BLOCK      5
 #define CXt_FORMAT     6
+#define CXt_GIVEN      7
+#define CXt_WHEN       8
 
 /* private flags for CXt_SUB and CXt_NULL */
 #define CXp_MULTICALL  0x00000400      /* part of a multicall (so don't
@@ -554,8 +568,10 @@ struct context {
 #define CXp_REAL       0x00000100      /* truly eval'', not a lookalike */
 #define CXp_TRYBLOCK   0x00000200      /* eval{}, not eval'' or similar */
 
-#ifdef USE_ITHREADS
 /* private flags for CXt_LOOP */
+#define CXp_FOREACH    0x00000200      /* a foreach loop */
+#define CXp_FOR_DEF    0x00000400      /* foreach using $_ */
+#ifdef USE_ITHREADS
 #  define CXp_PADVAR   0x00000100      /* itervar lives on pad, iterdata
                                           has pad offset; if not set,
                                           iterdata holds GV* */
@@ -570,6 +586,10 @@ struct context {
                         == (CXt_EVAL|CXp_REAL))
 #define CxTRYBLOCK(c)  (((c)->cx_type & (CXt_EVAL|CXp_TRYBLOCK))       \
                         == (CXt_EVAL|CXp_TRYBLOCK))
+#define CxFOREACH(c)   (((c)->cx_type & (CXt_LOOP|CXp_FOREACH))        \
+                         == (CXt_LOOP|CXp_FOREACH))
+#define CxFOREACHDEF(c)        (((c)->cx_type & (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))\
+                        == (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))
 
 #define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc()))
 
index 958672d..eb19e98 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -509,6 +509,7 @@ Apd |CV*    |newCONSTSUB    |NULLOK HV* stash|NULLOK const char* name|NULLOK SV* sv
 Ap     |void   |newFORM        |I32 floor|NULLOK OP* o|NULLOK OP* block
 Apa    |OP*    |newFOROP       |I32 flags|NULLOK char* label|line_t forline \
                                |NULLOK OP* sv|NN OP* expr|NULLOK OP* block|NULLOK OP* cont
+Apa    |OP*    |newGIVENOP     |NN OP* cond|NN OP* block|PADOFFSET defsv_off
 Apa    |OP*    |newLOGOP       |I32 optype|I32 flags|NN OP* left|NN OP* right
 Apa    |OP*    |newLOOPEX      |I32 type|NN OP* label
 Apa    |OP*    |newLOOPOP      |I32 flags|I32 debuggable|NULLOK OP* expr|NULLOK OP* block
@@ -552,6 +553,7 @@ Apa |SV*    |vnewSVpvf      |NN const char* pat|NULLOK va_list* args
 Apda   |SV*    |newSVrv        |NN SV* rv|NULLOK const char* classname
 Apda   |SV*    |newSVsv        |NULLOK SV* old
 Apa    |OP*    |newUNOP        |I32 type|I32 flags|NULLOK OP* first
+Apa    |OP*    |newWHENOP      |NULLOK OP* cond|NN OP* block
 Apa    |OP*    |newWHILEOP     |I32 flags|I32 debuggable|NULLOK LOOP* loop \
                                |I32 whileline|NULLOK OP* expr|NULLOK OP* block|NULLOK OP* cont \
                                |I32 has_my
@@ -1084,6 +1086,7 @@ pR        |OP*    |ck_return      |NN OP *o
 pR     |OP*    |ck_rfun        |NN OP *o
 pR     |OP*    |ck_rvconst     |NN OP *o
 pR     |OP*    |ck_sassign     |NN OP *o
+pR     |OP*    |ck_say         |NN OP *o
 pR     |OP*    |ck_select      |NN OP *o
 pR     |OP*    |ck_shift       |NN OP *o
 pR     |OP*    |ck_sort        |NN OP *o
@@ -1113,6 +1116,11 @@ s        |void   |no_bareword_allowed|NN const OP *o
 sR     |OP*    |no_fh_allowed|NN OP *o
 sR     |OP*    |too_few_arguments|NN OP *o|NN const char* name
 sR     |OP*    |too_many_arguments|NN OP *o|NN const char* name
+s      |bool   |looks_like_bool|NN OP* o
+s      |OP*    |newGIVWHENOP   |NULLOK OP* cond|NN OP *block \
+                               |I32 enter_opcode|I32 leave_opcode \
+                               |PADOFFSET entertarg
+s      |OP*    |ref_array_or_hash|NULLOK OP* cond
 #endif
 #if defined(PL_OP_SLAB_ALLOC)
 Apa    |void*  |Slab_Alloc     |int m|size_t sz
@@ -1172,16 +1180,22 @@ sR      |OP*    |dofindlabel    |NN OP *o|NN const char *label|NN OP **opstack|NN OP **opli
 sR     |OP*    |doparseform    |NN SV *sv
 snR    |bool   |num_overflow   |NV value|I32 fldsize|I32 frcsize
 sR     |I32    |dopoptoeval    |I32 startingblock
+sR     |I32    |dopoptogiven   |I32 startingblock
 sR     |I32    |dopoptolabel   |NN const char *label
 sR     |I32    |dopoptoloop    |I32 startingblock
 sR     |I32    |dopoptosub     |I32 startingblock
 sR     |I32    |dopoptosub_at  |NN const PERL_CONTEXT* cxstk|I32 startingblock
+sR     |I32    |dopoptowhen    |I32 startingblock
 s      |void   |save_lines     |NULLOK AV *array|NN SV *sv
 sR     |OP*    |doeval         |int gimme|NULLOK OP** startop|NULLOK CV* outside|U32 seq
 sR     |PerlIO *|check_type_and_open|NN const char *name|NN const char *mode
 sR     |PerlIO *|doopen_pm     |NN const char *name|NN const char *mode
 sR     |bool   |path_is_absolute|NN const char *name
 sR     |I32    |run_user_filter|int idx|NN SV *buf_sv|int maxlen
+sR     |PMOP*  |make_matcher   |NN regexp* re
+sR     |bool   |matcher_matches_sv|NN PMOP* matcher|NN SV* sv
+s      |void   |destroy_matcher|NN PMOP* matcher
+s      |OP*    |do_smartmatch  |NULLOK HV* seen_this|NULLOK HV* seen_other
 #endif
 
 #if defined(PERL_IN_PP_HOT_C) || defined(PERL_DECL_PROT)
@@ -1338,6 +1352,7 @@ s |char*  |scan_word      |NN char *s|NN char *dest|STRLEN destlen \
 sR     |char*  |skipspace      |NN char *s
 sR     |char*  |swallow_bom    |NN U8 *s
 s      |void   |checkcomma     |NN char *s|NN const char *name|NN const char *what
+s      |bool   |feature_is_enabled|NN char* name|STRLEN namelen
 s      |void   |force_ident    |NN const char *s|int kind
 s      |void   |incline        |NN char *s
 s      |int    |intuit_method  |NN char *s|NULLOK GV *gv
diff --git a/embed.h b/embed.h
index 5b1916a..9788e82 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define newCONSTSUB            Perl_newCONSTSUB
 #define newFORM                        Perl_newFORM
 #define newFOROP               Perl_newFOROP
+#define newGIVENOP             Perl_newGIVENOP
 #define newLOGOP               Perl_newLOGOP
 #define newLOOPEX              Perl_newLOOPEX
 #define newLOOPOP              Perl_newLOOPOP
 #define newSVrv                        Perl_newSVrv
 #define newSVsv                        Perl_newSVsv
 #define newUNOP                        Perl_newUNOP
+#define newWHENOP              Perl_newWHENOP
 #define newWHILEOP             Perl_newWHILEOP
 #define new_stackinfo          Perl_new_stackinfo
 #define scan_vstring           Perl_scan_vstring
 #define ck_rfun                        Perl_ck_rfun
 #define ck_rvconst             Perl_ck_rvconst
 #define ck_sassign             Perl_ck_sassign
+#define ck_say                 Perl_ck_say
 #define ck_select              Perl_ck_select
 #define ck_shift               Perl_ck_shift
 #define ck_sort                        Perl_ck_sort
 #define no_fh_allowed          S_no_fh_allowed
 #define too_few_arguments      S_too_few_arguments
 #define too_many_arguments     S_too_many_arguments
+#define looks_like_bool                S_looks_like_bool
+#define newGIVWHENOP           S_newGIVWHENOP
+#define ref_array_or_hash      S_ref_array_or_hash
 #endif
 #endif
 #if defined(PL_OP_SLAB_ALLOC)
 #define doparseform            S_doparseform
 #define num_overflow           S_num_overflow
 #define dopoptoeval            S_dopoptoeval
+#define dopoptogiven           S_dopoptogiven
 #define dopoptolabel           S_dopoptolabel
 #define dopoptoloop            S_dopoptoloop
 #define dopoptosub             S_dopoptosub
 #define dopoptosub_at          S_dopoptosub_at
+#define dopoptowhen            S_dopoptowhen
 #define save_lines             S_save_lines
 #define doeval                 S_doeval
 #define check_type_and_open    S_check_type_and_open
 #define doopen_pm              S_doopen_pm
 #define path_is_absolute       S_path_is_absolute
 #define run_user_filter                S_run_user_filter
+#define make_matcher           S_make_matcher
+#define matcher_matches_sv     S_matcher_matches_sv
+#define destroy_matcher                S_destroy_matcher
+#define do_smartmatch          S_do_smartmatch
 #endif
 #endif
 #if defined(PERL_IN_PP_HOT_C) || defined(PERL_DECL_PROT)
 #define skipspace              S_skipspace
 #define swallow_bom            S_swallow_bom
 #define checkcomma             S_checkcomma
+#define feature_is_enabled     S_feature_is_enabled
 #define force_ident            S_force_ident
 #define incline                        S_incline
 #define intuit_method          S_intuit_method
 #define ck_rfun                        Perl_ck_rfun
 #define ck_rvconst             Perl_ck_rvconst
 #define ck_sassign             Perl_ck_sassign
+#define ck_say                 Perl_ck_say
 #define ck_select              Perl_ck_select
 #define ck_shift               Perl_ck_shift
+#define ck_smartmatch          Perl_ck_smartmatch
 #define ck_sort                        Perl_ck_sort
 #define ck_spair               Perl_ck_spair
 #define ck_split               Perl_ck_split
 #define pp_bit_or              Perl_pp_bit_or
 #define pp_bit_xor             Perl_pp_bit_xor
 #define pp_bless               Perl_pp_bless
+#define pp_break               Perl_pp_break
 #define pp_caller              Perl_pp_caller
 #define pp_chdir               Perl_pp_chdir
 #define pp_chmod               Perl_pp_chmod
 #define pp_cond_expr           Perl_pp_cond_expr
 #define pp_connect             Perl_pp_connect
 #define pp_const               Perl_pp_const
+#define pp_continue            Perl_pp_continue
 #define pp_cos                 Perl_pp_cos
 #define pp_crypt               Perl_pp_crypt
 #define pp_dbmclose            Perl_pp_dbmclose
 #define pp_enetent             Perl_pp_enetent
 #define pp_enter               Perl_pp_enter
 #define pp_entereval           Perl_pp_entereval
+#define pp_entergiven          Perl_pp_entergiven
 #define pp_enteriter           Perl_pp_enteriter
 #define pp_enterloop           Perl_pp_enterloop
 #define pp_entersub            Perl_pp_entersub
 #define pp_entertry            Perl_pp_entertry
+#define pp_enterwhen           Perl_pp_enterwhen
 #define pp_enterwrite          Perl_pp_enterwrite
 #define pp_eof                 Perl_pp_eof
 #define pp_eprotoent           Perl_pp_eprotoent
 #define pp_le                  Perl_pp_le
 #define pp_leave               Perl_pp_leave
 #define pp_leaveeval           Perl_pp_leaveeval
+#define pp_leavegiven          Perl_pp_leavegiven
 #define pp_leaveloop           Perl_pp_leaveloop
 #define pp_leavesub            Perl_pp_leavesub
 #define pp_leavesublv          Perl_pp_leavesublv
 #define pp_leavetry            Perl_pp_leavetry
+#define pp_leavewhen           Perl_pp_leavewhen
 #define pp_leavewrite          Perl_pp_leavewrite
 #define pp_left_shift          Perl_pp_left_shift
 #define pp_length              Perl_pp_length
 #define pp_rv2hv               Perl_pp_rv2hv
 #define pp_rv2sv               Perl_pp_rv2sv
 #define pp_sassign             Perl_pp_sassign
+#define pp_say                 Perl_pp_say
 #define pp_scalar              Perl_pp_scalar
 #define pp_schomp              Perl_pp_schomp
 #define pp_schop               Perl_pp_schop
 #define pp_sle                 Perl_pp_sle
 #define pp_sleep               Perl_pp_sleep
 #define pp_slt                 Perl_pp_slt
+#define pp_smartmatch          Perl_pp_smartmatch
 #define pp_sne                 Perl_pp_sne
 #define pp_snetent             Perl_pp_snetent
 #define pp_socket              Perl_pp_socket
 #define newCONSTSUB(a,b,c)     Perl_newCONSTSUB(aTHX_ a,b,c)
 #define newFORM(a,b,c)         Perl_newFORM(aTHX_ a,b,c)
 #define newFOROP(a,b,c,d,e,f,g)        Perl_newFOROP(aTHX_ a,b,c,d,e,f,g)
+#define newGIVENOP(a,b,c)      Perl_newGIVENOP(aTHX_ a,b,c)
 #define newLOGOP(a,b,c,d)      Perl_newLOGOP(aTHX_ a,b,c,d)
 #define newLOOPEX(a,b)         Perl_newLOOPEX(aTHX_ a,b)
 #define newLOOPOP(a,b,c,d)     Perl_newLOOPOP(aTHX_ a,b,c,d)
 #define newSVrv(a,b)           Perl_newSVrv(aTHX_ a,b)
 #define newSVsv(a)             Perl_newSVsv(aTHX_ a)
 #define newUNOP(a,b,c)         Perl_newUNOP(aTHX_ a,b,c)
+#define newWHENOP(a,b)         Perl_newWHENOP(aTHX_ a,b)
 #define newWHILEOP(a,b,c,d,e,f,g,h)    Perl_newWHILEOP(aTHX_ a,b,c,d,e,f,g,h)
 #define new_stackinfo(a,b)     Perl_new_stackinfo(aTHX_ a,b)
 #define scan_vstring(a,b)      Perl_scan_vstring(aTHX_ a,b)
 #define ck_rfun(a)             Perl_ck_rfun(aTHX_ a)
 #define ck_rvconst(a)          Perl_ck_rvconst(aTHX_ a)
 #define ck_sassign(a)          Perl_ck_sassign(aTHX_ a)
+#define ck_say(a)              Perl_ck_say(aTHX_ a)
 #define ck_select(a)           Perl_ck_select(aTHX_ a)
 #define ck_shift(a)            Perl_ck_shift(aTHX_ a)
 #define ck_sort(a)             Perl_ck_sort(aTHX_ a)
 #define no_fh_allowed(a)       S_no_fh_allowed(aTHX_ a)
 #define too_few_arguments(a,b) S_too_few_arguments(aTHX_ a,b)
 #define too_many_arguments(a,b)        S_too_many_arguments(aTHX_ a,b)
+#define looks_like_bool(a)     S_looks_like_bool(aTHX_ a)
+#define newGIVWHENOP(a,b,c,d,e)        S_newGIVWHENOP(aTHX_ a,b,c,d,e)
+#define ref_array_or_hash(a)   S_ref_array_or_hash(aTHX_ a)
 #endif
 #endif
 #if defined(PL_OP_SLAB_ALLOC)
 #define doparseform(a)         S_doparseform(aTHX_ a)
 #define num_overflow           S_num_overflow
 #define dopoptoeval(a)         S_dopoptoeval(aTHX_ a)
+#define dopoptogiven(a)                S_dopoptogiven(aTHX_ a)
 #define dopoptolabel(a)                S_dopoptolabel(aTHX_ a)
 #define dopoptoloop(a)         S_dopoptoloop(aTHX_ a)
 #define dopoptosub(a)          S_dopoptosub(aTHX_ a)
 #define dopoptosub_at(a,b)     S_dopoptosub_at(aTHX_ a,b)
+#define dopoptowhen(a)         S_dopoptowhen(aTHX_ a)
 #define save_lines(a,b)                S_save_lines(aTHX_ a,b)
 #define doeval(a,b,c,d)                S_doeval(aTHX_ a,b,c,d)
 #define check_type_and_open(a,b)       S_check_type_and_open(aTHX_ a,b)
 #define doopen_pm(a,b)         S_doopen_pm(aTHX_ a,b)
 #define path_is_absolute(a)    S_path_is_absolute(aTHX_ a)
 #define run_user_filter(a,b,c) S_run_user_filter(aTHX_ a,b,c)
+#define make_matcher(a)                S_make_matcher(aTHX_ a)
+#define matcher_matches_sv(a,b)        S_matcher_matches_sv(aTHX_ a,b)
+#define destroy_matcher(a)     S_destroy_matcher(aTHX_ a)
+#define do_smartmatch(a,b)     S_do_smartmatch(aTHX_ a,b)
 #endif
 #endif
 #if defined(PERL_IN_PP_HOT_C) || defined(PERL_DECL_PROT)
 #define skipspace(a)           S_skipspace(aTHX_ a)
 #define swallow_bom(a)         S_swallow_bom(aTHX_ a)
 #define checkcomma(a,b,c)      S_checkcomma(aTHX_ a,b,c)
+#define feature_is_enabled(a,b)        S_feature_is_enabled(aTHX_ a,b)
 #define force_ident(a,b)       S_force_ident(aTHX_ a,b)
 #define incline(a)             S_incline(aTHX_ a)
 #define intuit_method(a,b)     S_intuit_method(aTHX_ a,b)
 #define ck_rfun(a)             Perl_ck_rfun(aTHX_ a)
 #define ck_rvconst(a)          Perl_ck_rvconst(aTHX_ a)
 #define ck_sassign(a)          Perl_ck_sassign(aTHX_ a)
+#define ck_say(a)              Perl_ck_say(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)
 #define pp_bit_or()            Perl_pp_bit_or(aTHX)
 #define pp_bit_xor()           Perl_pp_bit_xor(aTHX)
 #define pp_bless()             Perl_pp_bless(aTHX)
+#define pp_break()             Perl_pp_break(aTHX)
 #define pp_caller()            Perl_pp_caller(aTHX)
 #define pp_chdir()             Perl_pp_chdir(aTHX)
 #define pp_chmod()             Perl_pp_chmod(aTHX)
 #define pp_cond_expr()         Perl_pp_cond_expr(aTHX)
 #define pp_connect()           Perl_pp_connect(aTHX)
 #define pp_const()             Perl_pp_const(aTHX)
+#define pp_continue()          Perl_pp_continue(aTHX)
 #define pp_cos()               Perl_pp_cos(aTHX)
 #define pp_crypt()             Perl_pp_crypt(aTHX)
 #define pp_dbmclose()          Perl_pp_dbmclose(aTHX)
 #define pp_enetent()           Perl_pp_enetent(aTHX)
 #define pp_enter()             Perl_pp_enter(aTHX)
 #define pp_entereval()         Perl_pp_entereval(aTHX)
+#define pp_entergiven()                Perl_pp_entergiven(aTHX)
 #define pp_enteriter()         Perl_pp_enteriter(aTHX)
 #define pp_enterloop()         Perl_pp_enterloop(aTHX)
 #define pp_entersub()          Perl_pp_entersub(aTHX)
 #define pp_entertry()          Perl_pp_entertry(aTHX)
+#define pp_enterwhen()         Perl_pp_enterwhen(aTHX)
 #define pp_enterwrite()                Perl_pp_enterwrite(aTHX)
 #define pp_eof()               Perl_pp_eof(aTHX)
 #define pp_eprotoent()         Perl_pp_eprotoent(aTHX)
 #define pp_le()                        Perl_pp_le(aTHX)
 #define pp_leave()             Perl_pp_leave(aTHX)
 #define pp_leaveeval()         Perl_pp_leaveeval(aTHX)
+#define pp_leavegiven()                Perl_pp_leavegiven(aTHX)
 #define pp_leaveloop()         Perl_pp_leaveloop(aTHX)
 #define pp_leavesub()          Perl_pp_leavesub(aTHX)
 #define pp_leavesublv()                Perl_pp_leavesublv(aTHX)
 #define pp_leavetry()          Perl_pp_leavetry(aTHX)
+#define pp_leavewhen()         Perl_pp_leavewhen(aTHX)
 #define pp_leavewrite()                Perl_pp_leavewrite(aTHX)
 #define pp_left_shift()                Perl_pp_left_shift(aTHX)
 #define pp_length()            Perl_pp_length(aTHX)
 #define pp_rv2hv()             Perl_pp_rv2hv(aTHX)
 #define pp_rv2sv()             Perl_pp_rv2sv(aTHX)
 #define pp_sassign()           Perl_pp_sassign(aTHX)
+#define pp_say()               Perl_pp_say(aTHX)
 #define pp_scalar()            Perl_pp_scalar(aTHX)
 #define pp_schomp()            Perl_pp_schomp(aTHX)
 #define pp_schop()             Perl_pp_schop(aTHX)
 #define pp_sle()               Perl_pp_sle(aTHX)
 #define pp_sleep()             Perl_pp_sleep(aTHX)
 #define pp_slt()               Perl_pp_slt(aTHX)
+#define pp_smartmatch()                Perl_pp_smartmatch(aTHX)
 #define pp_sne()               Perl_pp_sne(aTHX)
 #define pp_snetent()           Perl_pp_snetent(aTHX)
 #define pp_socket()            Perl_pp_socket(aTHX)
index 218ab9c..958b137 100644 (file)
@@ -19,7 +19,7 @@ use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
          CVf_METHOD CVf_LOCKED CVf_LVALUE CVf_ASSERTION
         PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE PMf_SKIPWHITE
         PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED);
-$VERSION = 0.72;
+$VERSION = 0.73;
 use strict;
 use vars qw/$AUTOLOAD/;
 use warnings ();
@@ -116,6 +116,11 @@ use warnings ();
 # - option to use Data::Dumper for constants
 # - more bug fixes
 # - discovered lots more bugs not yet fixed
+#
+# ...
+#
+# Changes between 0.72 and 0.73
+# - support new switch constructs
 
 # Todo:
 #  (See also BUGS section at the end of this file)
@@ -1632,6 +1637,38 @@ sub pp_ggrgid { unop(@_, "getgrgid") }
 
 sub pp_lock { unop(@_, "lock") }
 
+sub pp_continue { unop(@_, "continue"); }
+sub pp_break {
+    my ($self, $op) = @_;
+    return "" if $op->flags & OPf_SPECIAL;
+    unop(@_, "break");
+}
+
+sub givwhen {
+    my $self = shift;
+    my($op, $cx, $givwhen) = @_;
+
+    my $enterop = $op->first;
+    my ($head, $block);
+    if ($enterop->flags & OPf_SPECIAL) {
+       $head = "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(@_, "given"); }
+sub pp_leavewhen  { givwhen(@_, "when"); }
+
 sub pp_exists {
     my $self = shift;
     my($op, $cx) = @_;
@@ -2008,6 +2045,16 @@ sub pp_scmp { binop(@_, "cmp", 14) }
 sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }
 sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN | LIST_CONTEXT) }
 
+sub pp_smartmatch {
+    my ($self, $op, $cx) = @_;
+    if ($op->flags & OPf_SPECIAL) {
+       return $self->deparse($op->first, $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.
index acce386..fe45773 100644 (file)
@@ -94,6 +94,7 @@ use Getopt::Std;
 use Carp;
 use Test::More tests => ( 1 * !!$Config::Config{useithreads}
                          + 3 * ($] > 5.009)
+                         + 12 * ($] >= 5.009003)
                          + 777 );
 
 require_ok("B::Concise");
index 25bed73..8e614a6 100644 (file)
@@ -176,7 +176,7 @@ checkOptree(note   => q{},
 # c  <1> rv2av[t6] sKRM/1
 # d  <#> gv[*_] s
 # e  <1> rv2gv sKRM/1
-# f  <{> enteriter(next->q last->t redo->g) lKS
+# f  <{> enteriter(next->q last->t redo->g) lKS/8
 # r  <0> iter s
 # s  <|> and(other->g) K/1
 # g      <;> nextstate(main 475 (eval 10):1) v
@@ -209,7 +209,7 @@ EOT_EOT
 # c  <1> rv2av[t3] sKRM/1
 # d  <$> gv(*_) s
 # e  <1> rv2gv sKRM/1
-# f  <{> enteriter(next->q last->t redo->g) lKS
+# f  <{> enteriter(next->q last->t redo->g) lKS/8
 # r  <0> iter s
 # s  <|> and(other->g) K/1
 # g      <;> nextstate(main 559 (eval 15):1) v
index 4f0d782..c7a8152 100644 (file)
@@ -259,7 +259,7 @@ checkOptree ( name  => '-exec sub { foreach (1..10) {print "foo $_"} }',
 # 3  <$> const[IV 1] s
 # 4  <$> const[IV 10] s
 # 5  <#> gv[*_] s
-# 6  <{> enteriter(next->d last->g redo->7) lKS
+# 6  <{> enteriter(next->d last->g redo->7) lKS/8
 # e  <0> iter s
 # f  <|> and(other->7) K/1
 # 7      <;> nextstate(main 442 optree.t:158) v
@@ -278,7 +278,7 @@ EOT_EOT
 # 3  <$> const(IV 1) s
 # 4  <$> const(IV 10) s
 # 5  <$> gv(*_) s
-# 6  <{> enteriter(next->d last->g redo->7) lKS
+# 6  <{> enteriter(next->d last->g redo->7) lKS/8
 # e  <0> iter s
 # f  <|> and(other->7) K/1
 # 7      <;> nextstate(main 443 optree_samples.t:182) v
@@ -302,7 +302,7 @@ checkOptree ( name  => '-basic sub { print "foo $_" foreach (1..10) }',
 # 1        <;> nextstate(main 445 optree.t:167) v ->2
 # 2        <;> nextstate(main 445 optree.t:167) v ->3
 # g        <2> leaveloop K/2 ->h
-# 7           <{> enteriter(next->d last->g redo->8) lKS ->e
+# 7           <{> enteriter(next->d last->g redo->8) lKS/8 ->e
 # -              <0> ex-pushmark s ->3
 # -              <1> ex-list lK ->6
 # 3                 <0> pushmark s ->4
@@ -328,7 +328,7 @@ EOT_EOT
 # 1        <;> nextstate(main 446 optree_samples.t:192) v ->2
 # 2        <;> nextstate(main 446 optree_samples.t:192) v ->3
 # g        <2> leaveloop K/2 ->h
-# 7           <{> enteriter(next->d last->g redo->8) lKS ->e
+# 7           <{> enteriter(next->d last->g redo->8) lKS/8 ->e
 # -              <0> ex-pushmark s ->3
 # -              <1> ex-list lK ->6
 # 3                 <0> pushmark s ->4
@@ -360,7 +360,7 @@ checkOptree ( name  => '-exec -e foreach (1..10) {print qq{foo $_}}',
 # 4  <$> const[IV 1] s
 # 5  <$> const[IV 10] s
 # 6  <#> gv[*_] s
-# 7  <{> enteriter(next->e last->h redo->8) lKS
+# 7  <{> enteriter(next->e last->h redo->8) lKS/8
 # f  <0> iter s
 # g  <|> and(other->8) vK/1
 # 8      <;> nextstate(main 1 -e:1) v
@@ -380,7 +380,7 @@ EOT_EOT
 # 4  <$> const(IV 1) s
 # 5  <$> const(IV 10) s
 # 6  <$> gv(*_) s
-# 7  <{> enteriter(next->e last->h redo->8) lKS
+# 7  <{> enteriter(next->e last->h redo->8) lKS/8
 # f  <0> iter s
 # g  <|> and(other->8) vK/1
 # 8      <;> nextstate(main 1 -e:1) v
@@ -405,7 +405,7 @@ checkOptree ( name  => '-exec sub { print "foo $_" foreach (1..10) }',
 # 4  <$> const[IV 1] s
 # 5  <$> const[IV 10] s
 # 6  <#> gv[*_] s
-# 7  <{> enteriter(next->d last->g redo->8) lKS
+# 7  <{> enteriter(next->d last->g redo->8) lKS/8
 # e  <0> iter s
 # f  <|> and(other->8) K/1
 # 8      <0> pushmark s
@@ -424,7 +424,7 @@ EOT_EOT
 # 4  <$> const(IV 1) s
 # 5  <$> const(IV 10) s
 # 6  <$> gv(*_) s
-# 7  <{> enteriter(next->d last->g redo->8) lKS
+# 7  <{> enteriter(next->d last->g redo->8) lKS/8
 # e  <0> iter s
 # f  <|> and(other->8) K/1
 # 8      <0> pushmark s
@@ -549,7 +549,7 @@ checkOptree ( name  => '%h=(); for $_(@a){$h{getkey($_)} = $_}',
 # a  <1> rv2av[t6] sKRM/1
 # b  <#> gv[*_] s
 # c  <1> rv2gv sKRM/1
-# d  <{> enteriter(next->o last->r redo->e) lKS
+# d  <{> enteriter(next->o last->r redo->e) lKS/8
 # p  <0> iter s
 # q  <|> and(other->e) K/1
 # e      <;> nextstate(main 505 (eval 24):1) v
@@ -579,7 +579,7 @@ EOT_EOT
 # a  <1> rv2av[t3] sKRM/1
 # b  <$> gv(*_) s
 # c  <1> rv2gv sKRM/1
-# d  <{> enteriter(next->o last->r redo->e) lKS
+# d  <{> enteriter(next->o last->r redo->e) lKS/8
 # p  <0> iter s
 # q  <|> and(other->e) K/1
 # e      <;> nextstate(main 505 (eval 24):1) v
index 329d26a..551988b 100644 (file)
@@ -69,6 +69,7 @@ corresponding built-in functions:
     $io->read ( BUF, LEN, [OFFSET] )
     $io->print ( ARGS )
     $io->printf ( FMT, [ARGS] )
+    $io->say ( ARGS )
     $io->stat
     $io->sysread ( BUF, LEN, [OFFSET] )
     $io->syswrite ( BUF, [LEN, [OFFSET]] )
@@ -264,7 +265,7 @@ use IO ();  # Load the XS module
 require Exporter;
 @ISA = qw(Exporter);
 
-$VERSION = "1.25";
+$VERSION = "1.26";
 $VERSION = eval $VERSION;
 
 @EXPORT_OK = qw(
@@ -284,6 +285,7 @@ $VERSION = eval $VERSION;
 
     print
     printf
+    say
     getline
     getlines
 
@@ -407,6 +409,13 @@ sub printf {
     printf $this @_;
 }
 
+sub say {
+    @_ or croak 'usage: $io->say(ARGS)';
+    my $this = shift;
+    use feature 'say';
+    say $this @_;
+}
+
 sub getline {
     @_ == 1 or croak 'usage: $io->getline()';
     my $this = shift;
index 9394734..9a1c92b 100644 (file)
@@ -382,7 +382,7 @@ account the magical open of ARGV.
 
     formline enterwrite leavewrite
 
-    print sysread syswrite send recv
+    print say sysread syswrite send recv
 
     eof tell seek sysseek
 
@@ -416,6 +416,11 @@ These are a hotchpotch of opcodes still waiting to be considered
 
     entertry leavetry -- can be used to 'hide' fatal errors
 
+    entergiven leavegiven
+    enterwhen leavewhen
+    break continue
+    smartmatch
+
     custom -- where should this go
 
 =item :base_math
index 1d86272..eb73405 100644 (file)
@@ -282,6 +282,7 @@ Perl_newCONDOP
 Perl_newCONSTSUB
 Perl_newFORM
 Perl_newFOROP
+Perl_newGIVENOP
 Perl_newLOGOP
 Perl_newLOOPEX
 Perl_newLOOPOP
@@ -325,6 +326,7 @@ Perl_vnewSVpvf
 Perl_newSVrv
 Perl_newSVsv
 Perl_newUNOP
+Perl_newWHENOP
 Perl_newWHILEOP
 Perl_new_stackinfo
 Perl_scan_vstring
index 3af51b8..c4834ac 100644 (file)
 #define KEY_bind               18
 #define KEY_binmode            19
 #define KEY_bless              20
-#define KEY_caller             21
-#define KEY_chdir              22
-#define KEY_chmod              23
-#define KEY_chomp              24
-#define KEY_chop               25
-#define KEY_chown              26
-#define KEY_chr                        27
-#define KEY_chroot             28
-#define KEY_close              29
-#define KEY_closedir           30
-#define KEY_cmp                        31
-#define KEY_connect            32
-#define KEY_continue           33
-#define KEY_cos                        34
-#define KEY_crypt              35
-#define KEY_dbmclose           36
-#define KEY_dbmopen            37
-#define KEY_defined            38
-#define KEY_delete             39
-#define KEY_die                        40
-#define KEY_do                 41
-#define KEY_dump               42
-#define KEY_each               43
-#define KEY_else               44
-#define KEY_elsif              45
-#define KEY_endgrent           46
-#define KEY_endhostent         47
-#define KEY_endnetent          48
-#define KEY_endprotoent                49
-#define KEY_endpwent           50
-#define KEY_endservent         51
-#define KEY_eof                        52
-#define KEY_eq                 53
-#define KEY_err                        54
-#define KEY_eval               55
-#define KEY_exec               56
-#define KEY_exists             57
-#define KEY_exit               58
-#define KEY_exp                        59
-#define KEY_fcntl              60
-#define KEY_fileno             61
-#define KEY_flock              62
-#define KEY_for                        63
-#define KEY_foreach            64
-#define KEY_fork               65
-#define KEY_format             66
-#define KEY_formline           67
-#define KEY_ge                 68
-#define KEY_getc               69
-#define KEY_getgrent           70
-#define KEY_getgrgid           71
-#define KEY_getgrnam           72
-#define KEY_gethostbyaddr      73
-#define KEY_gethostbyname      74
-#define KEY_gethostent         75
-#define KEY_getlogin           76
-#define KEY_getnetbyaddr       77
-#define KEY_getnetbyname       78
-#define KEY_getnetent          79
-#define KEY_getpeername                80
-#define KEY_getpgrp            81
-#define KEY_getppid            82
-#define KEY_getpriority                83
-#define KEY_getprotobyname     84
-#define KEY_getprotobynumber   85
-#define KEY_getprotoent                86
-#define KEY_getpwent           87
-#define KEY_getpwnam           88
-#define KEY_getpwuid           89
-#define KEY_getservbyname      90
-#define KEY_getservbyport      91
-#define KEY_getservent         92
-#define KEY_getsockname                93
-#define KEY_getsockopt         94
-#define KEY_glob               95
-#define KEY_gmtime             96
-#define KEY_goto               97
-#define KEY_grep               98
-#define KEY_gt                 99
-#define KEY_hex                        100
-#define KEY_if                 101
-#define KEY_index              102
-#define KEY_int                        103
-#define KEY_ioctl              104
-#define KEY_join               105
-#define KEY_keys               106
-#define KEY_kill               107
-#define KEY_last               108
-#define KEY_lc                 109
-#define KEY_lcfirst            110
-#define KEY_le                 111
-#define KEY_length             112
-#define KEY_link               113
-#define KEY_listen             114
-#define KEY_local              115
-#define KEY_localtime          116
-#define KEY_lock               117
-#define KEY_log                        118
-#define KEY_lstat              119
-#define KEY_lt                 120
-#define KEY_m                  121
-#define KEY_map                        122
-#define KEY_mkdir              123
-#define KEY_msgctl             124
-#define KEY_msgget             125
-#define KEY_msgrcv             126
-#define KEY_msgsnd             127
-#define KEY_my                 128
-#define KEY_ne                 129
-#define KEY_next               130
-#define KEY_no                 131
-#define KEY_not                        132
-#define KEY_oct                        133
-#define KEY_open               134
-#define KEY_opendir            135
-#define KEY_or                 136
-#define KEY_ord                        137
-#define KEY_our                        138
-#define KEY_pack               139
-#define KEY_package            140
-#define KEY_pipe               141
-#define KEY_pop                        142
-#define KEY_pos                        143
-#define KEY_print              144
-#define KEY_printf             145
-#define KEY_prototype          146
-#define KEY_push               147
-#define KEY_q                  148
-#define KEY_qq                 149
-#define KEY_qr                 150
-#define KEY_quotemeta          151
-#define KEY_qw                 152
-#define KEY_qx                 153
-#define KEY_rand               154
-#define KEY_read               155
-#define KEY_readdir            156
-#define KEY_readline           157
-#define KEY_readlink           158
-#define KEY_readpipe           159
-#define KEY_recv               160
-#define KEY_redo               161
-#define KEY_ref                        162
-#define KEY_rename             163
-#define KEY_require            164
-#define KEY_reset              165
-#define KEY_return             166
-#define KEY_reverse            167
-#define KEY_rewinddir          168
-#define KEY_rindex             169
-#define KEY_rmdir              170
-#define KEY_s                  171
-#define KEY_scalar             172
-#define KEY_seek               173
-#define KEY_seekdir            174
-#define KEY_select             175
-#define KEY_semctl             176
-#define KEY_semget             177
-#define KEY_semop              178
-#define KEY_send               179
-#define KEY_setgrent           180
-#define KEY_sethostent         181
-#define KEY_setnetent          182
-#define KEY_setpgrp            183
-#define KEY_setpriority                184
-#define KEY_setprotoent                185
-#define KEY_setpwent           186
-#define KEY_setservent         187
-#define KEY_setsockopt         188
-#define KEY_shift              189
-#define KEY_shmctl             190
-#define KEY_shmget             191
-#define KEY_shmread            192
-#define KEY_shmwrite           193
-#define KEY_shutdown           194
-#define KEY_sin                        195
-#define KEY_sleep              196
-#define KEY_socket             197
-#define KEY_socketpair         198
-#define KEY_sort               199
-#define KEY_splice             200
-#define KEY_split              201
-#define KEY_sprintf            202
-#define KEY_sqrt               203
-#define KEY_srand              204
-#define KEY_stat               205
-#define KEY_study              206
-#define KEY_sub                        207
-#define KEY_substr             208
-#define KEY_symlink            209
-#define KEY_syscall            210
-#define KEY_sysopen            211
-#define KEY_sysread            212
-#define KEY_sysseek            213
-#define KEY_system             214
-#define KEY_syswrite           215
-#define KEY_tell               216
-#define KEY_telldir            217
-#define KEY_tie                        218
-#define KEY_tied               219
-#define KEY_time               220
-#define KEY_times              221
-#define KEY_tr                 222
-#define KEY_truncate           223
-#define KEY_uc                 224
-#define KEY_ucfirst            225
-#define KEY_umask              226
-#define KEY_undef              227
-#define KEY_unless             228
-#define KEY_unlink             229
-#define KEY_unpack             230
-#define KEY_unshift            231
-#define KEY_untie              232
-#define KEY_until              233
-#define KEY_use                        234
-#define KEY_utime              235
-#define KEY_values             236
-#define KEY_vec                        237
-#define KEY_wait               238
-#define KEY_waitpid            239
-#define KEY_wantarray          240
-#define KEY_warn               241
-#define KEY_while              242
-#define KEY_write              243
-#define KEY_x                  244
-#define KEY_xor                        245
-#define KEY_y                  246
+#define KEY_break              21
+#define KEY_caller             22
+#define KEY_chdir              23
+#define KEY_chmod              24
+#define KEY_chomp              25
+#define KEY_chop               26
+#define KEY_chown              27
+#define KEY_chr                        28
+#define KEY_chroot             29
+#define KEY_close              30
+#define KEY_closedir           31
+#define KEY_cmp                        32
+#define KEY_connect            33
+#define KEY_continue           34
+#define KEY_cos                        35
+#define KEY_crypt              36
+#define KEY_dbmclose           37
+#define KEY_dbmopen            38
+#define KEY_default            39
+#define KEY_defined            40
+#define KEY_delete             41
+#define KEY_die                        42
+#define KEY_do                 43
+#define KEY_dump               44
+#define KEY_each               45
+#define KEY_else               46
+#define KEY_elsif              47
+#define KEY_endgrent           48
+#define KEY_endhostent         49
+#define KEY_endnetent          50
+#define KEY_endprotoent                51
+#define KEY_endpwent           52
+#define KEY_endservent         53
+#define KEY_eof                        54
+#define KEY_eq                 55
+#define KEY_err                        56
+#define KEY_eval               57
+#define KEY_exec               58
+#define KEY_exists             59
+#define KEY_exit               60
+#define KEY_exp                        61
+#define KEY_fcntl              62
+#define KEY_fileno             63
+#define KEY_flock              64
+#define KEY_for                        65
+#define KEY_foreach            66
+#define KEY_fork               67
+#define KEY_format             68
+#define KEY_formline           69
+#define KEY_ge                 70
+#define KEY_getc               71
+#define KEY_getgrent           72
+#define KEY_getgrgid           73
+#define KEY_getgrnam           74
+#define KEY_gethostbyaddr      75
+#define KEY_gethostbyname      76
+#define KEY_gethostent         77
+#define KEY_getlogin           78
+#define KEY_getnetbyaddr       79
+#define KEY_getnetbyname       80
+#define KEY_getnetent          81
+#define KEY_getpeername                82
+#define KEY_getpgrp            83
+#define KEY_getppid            84
+#define KEY_getpriority                85
+#define KEY_getprotobyname     86
+#define KEY_getprotobynumber   87
+#define KEY_getprotoent                88
+#define KEY_getpwent           89
+#define KEY_getpwnam           90
+#define KEY_getpwuid           91
+#define KEY_getservbyname      92
+#define KEY_getservbyport      93
+#define KEY_getservent         94
+#define KEY_getsockname                95
+#define KEY_getsockopt         96
+#define KEY_given              97
+#define KEY_glob               98
+#define KEY_gmtime             99
+#define KEY_goto               100
+#define KEY_grep               101
+#define KEY_gt                 102
+#define KEY_hex                        103
+#define KEY_if                 104
+#define KEY_index              105
+#define KEY_int                        106
+#define KEY_ioctl              107
+#define KEY_join               108
+#define KEY_keys               109
+#define KEY_kill               110
+#define KEY_last               111
+#define KEY_lc                 112
+#define KEY_lcfirst            113
+#define KEY_le                 114
+#define KEY_length             115
+#define KEY_link               116
+#define KEY_listen             117
+#define KEY_local              118
+#define KEY_localtime          119
+#define KEY_lock               120
+#define KEY_log                        121
+#define KEY_lstat              122
+#define KEY_lt                 123
+#define KEY_m                  124
+#define KEY_map                        125
+#define KEY_mkdir              126
+#define KEY_msgctl             127
+#define KEY_msgget             128
+#define KEY_msgrcv             129
+#define KEY_msgsnd             130
+#define KEY_my                 131
+#define KEY_ne                 132
+#define KEY_next               133
+#define KEY_no                 134
+#define KEY_not                        135
+#define KEY_oct                        136
+#define KEY_open               137
+#define KEY_opendir            138
+#define KEY_or                 139
+#define KEY_ord                        140
+#define KEY_our                        141
+#define KEY_pack               142
+#define KEY_package            143
+#define KEY_pipe               144
+#define KEY_pop                        145
+#define KEY_pos                        146
+#define KEY_print              147
+#define KEY_printf             148
+#define KEY_prototype          149
+#define KEY_push               150
+#define KEY_q                  151
+#define KEY_qq                 152
+#define KEY_qr                 153
+#define KEY_quotemeta          154
+#define KEY_qw                 155
+#define KEY_qx                 156
+#define KEY_rand               157
+#define KEY_read               158
+#define KEY_readdir            159
+#define KEY_readline           160
+#define KEY_readlink           161
+#define KEY_readpipe           162
+#define KEY_recv               163
+#define KEY_redo               164
+#define KEY_ref                        165
+#define KEY_rename             166
+#define KEY_require            167
+#define KEY_reset              168
+#define KEY_return             169
+#define KEY_reverse            170
+#define KEY_rewinddir          171
+#define KEY_rindex             172
+#define KEY_rmdir              173
+#define KEY_s                  174
+#define KEY_say                        175
+#define KEY_scalar             176
+#define KEY_seek               177
+#define KEY_seekdir            178
+#define KEY_select             179
+#define KEY_semctl             180
+#define KEY_semget             181
+#define KEY_semop              182
+#define KEY_send               183
+#define KEY_setgrent           184
+#define KEY_sethostent         185
+#define KEY_setnetent          186
+#define KEY_setpgrp            187
+#define KEY_setpriority                188
+#define KEY_setprotoent                189
+#define KEY_setpwent           190
+#define KEY_setservent         191
+#define KEY_setsockopt         192
+#define KEY_shift              193
+#define KEY_shmctl             194
+#define KEY_shmget             195
+#define KEY_shmread            196
+#define KEY_shmwrite           197
+#define KEY_shutdown           198
+#define KEY_sin                        199
+#define KEY_sleep              200
+#define KEY_socket             201
+#define KEY_socketpair         202
+#define KEY_sort               203
+#define KEY_splice             204
+#define KEY_split              205
+#define KEY_sprintf            206
+#define KEY_sqrt               207
+#define KEY_srand              208
+#define KEY_stat               209
+#define KEY_study              210
+#define KEY_sub                        211
+#define KEY_substr             212
+#define KEY_symlink            213
+#define KEY_syscall            214
+#define KEY_sysopen            215
+#define KEY_sysread            216
+#define KEY_sysseek            217
+#define KEY_system             218
+#define KEY_syswrite           219
+#define KEY_tell               220
+#define KEY_telldir            221
+#define KEY_tie                        222
+#define KEY_tied               223
+#define KEY_time               224
+#define KEY_times              225
+#define KEY_tr                 226
+#define KEY_truncate           227
+#define KEY_uc                 228
+#define KEY_ucfirst            229
+#define KEY_umask              230
+#define KEY_undef              231
+#define KEY_unless             232
+#define KEY_unlink             233
+#define KEY_unpack             234
+#define KEY_unshift            235
+#define KEY_untie              236
+#define KEY_until              237
+#define KEY_use                        238
+#define KEY_utime              239
+#define KEY_values             240
+#define KEY_vec                        241
+#define KEY_wait               242
+#define KEY_waitpid            243
+#define KEY_wantarray          244
+#define KEY_warn               245
+#define KEY_when               246
+#define KEY_while              247
+#define KEY_write              248
+#define KEY_x                  249
+#define KEY_xor                        250
+#define KEY_y                  251
 
 /* ex: set ro: */
index fe745d4..2f3a95a 100755 (executable)
@@ -68,6 +68,7 @@ atan2
 bind
 binmode
 bless
+break
 caller
 chdir
 chmod
@@ -85,6 +86,7 @@ cos
 crypt
 dbmclose
 dbmopen
+default
 defined
 delete
 die
@@ -142,6 +144,7 @@ getservbyport
 getservent
 getsockname
 getsockopt
+given
 glob
 gmtime
 goto
@@ -219,6 +222,7 @@ rewinddir
 rindex
 rmdir
 s
+say
 scalar
 seek
 seekdir
@@ -289,6 +293,7 @@ wait
 waitpid
 wantarray
 warn
+when
 while
 write
 x
diff --git a/lib/feature.pm b/lib/feature.pm
new file mode 100644 (file)
index 0000000..e0981d0
--- /dev/null
@@ -0,0 +1,116 @@
+package feature;
+
+our $VERSION = '1.00';
+$feature::hint_bits = 0x04020000; # HINT_LOCALIZE_HH | HINT_HH_FOR_EVAL
+
+# (feature name) => (internal name, used in %^H)
+my %feature = (
+    switch => 'switch',
+    "~~"   => "~~",
+    say    => "say",
+);
+
+
+# Here are some notes that probably shouldn't be in the public
+# documentation, but which it's useful to have somewhere.
+#
+# One side-effect of the change is that C<prototype("CORE::continue")>
+# no longer throws the error C<Can't find an opnumber for "continue">.
+# One of the tests in t/op/cproto.t had to be changed to accommodate
+# this, but it really shouldn't affect real-world code.
+#
+# TODO:
+# - sort out the smartmatch semantics
+# - think about versioned features (use switch => 2)
+#
+# -- Robin 2005-12
+
+=head1 NAME
+
+feature - Perl pragma to enable new syntactic features
+
+=head1 SYNOPSIS
+
+    use feature 'switch';
+    given ($foo) {
+       when (1)          { print "\$foo == 1\n" }
+       when ([2,3])      { print "\$foo == 2 || \$foo == 3\n" }
+       when (/^a[bc]d$/) { print "\$foo eq 'abd' || \$foo eq 'acd'\n" }
+       when ($_ > 100)   { print "\$foo > 100\n" }
+       default           { print "None of the above\n" }
+    }
+
+=head1 DESCRIPTION
+
+It is usually impossible to add new syntax to Perl without breaking
+some existing programs. This pragma provides a way to minimize that
+risk. New syntactic constructs can be enabled by C<use feature 'foo'>,
+and will be parsed only when the appropriate feature pragma is in
+scope.
+
+=head2 The 'switch' feature
+
+C<use feature 'switch'> tells the compiler to enable the Perl 6
+given/when construct from here to the end of the enclosing BLOCK.
+
+See L<perlsyn/"Switch statements"> for details.
+
+=head2 The '~~' feature
+
+C<use feature '~~'> tells the compiler to enable the Perl 6
+smart match C<~~> operator from here to the end of the enclosing BLOCK.
+
+See L<perlsyn/"Smart Matching in Detail"> for details.
+
+=head2 The 'say' feature
+
+C<use feature 'say'> tells the compiler to enable the Perl 6
+C<say> function from here to the end of the enclosing BLOCK.
+
+See L<perlfunc/say> for details.
+
+=cut
+
+sub import {
+    $^H |= $feature::hint_bits;        # Need this or %^H won't work
+
+    my $class = shift;
+    if (@_ == 0) {
+       require Carp;
+       Carp->import("croak");
+       croak("No features specified");
+    }
+    while (@_) {
+       my $name = shift(@_);
+       if (!exists $feature{$name}) {
+           require Carp;
+           Carp->import("croak");
+           croak(sprintf('Feature "%s" is not supported by Perl %vd',
+               $name, $^V));
+       }
+       $^H{$feature{$name}} = 1;
+    }
+}
+
+sub unimport {
+    my $class = shift;
+
+    # A bare C<no feature> should disable *all* features
+    for my $name (@_) {
+       if (!exists($feature{$name})) {
+           require Carp;
+           Carp->import("croak");
+           croak(sprintf('Feature "%s" is not supported by Perl %vd',
+               $name, $^V));
+       }
+       else {
+           delete $^H{$feature{$name}};
+       }
+    }
+
+    if(!@_) {
+       delete @^H{ values(%feature) };
+    }
+}
+
+1;
diff --git a/lib/feature.t b/lib/feature.t
new file mode 100644 (file)
index 0000000..a60644f
--- /dev/null
@@ -0,0 +1,10 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+    $ENV{PERL5LIB} = '../lib';
+}
+
+our $pragma_name = "feature";
+require "../t/lib/common.pl";
index b189044..8a07efe 100644 (file)
@@ -422,7 +422,7 @@ The dereference operators must be specified explicitly they will not be passed t
 
 =item * I<Special>
 
-    "nomethod", "fallback", "=",
+    "nomethod", "fallback", "=", "~~",
 
 see L<SPECIAL SYMBOLS FOR C<use overload>>.
 
@@ -517,6 +517,11 @@ The key C<"fallback"> governs what to do if a method for a particular
 operation is not found.  Three different cases are possible depending on
 the value of C<"fallback">:
 
+=head2 Smart Match
+
+The key C<"~~"> allows you to override the smart matching used by
+the switch construct. See L<feature>.
+
 =over 16
 
 =item * C<undef>
index f23d9e6..55e2794 100644 (file)
@@ -4,201 +4,7 @@ BEGIN {
     chdir 't' if -d 't';
     @INC = '../lib';
     $ENV{PERL5LIB} = '../lib';
-    require Config; import Config;
-    require './test.pl';
 }
 
-use File::Path;
-use File::Spec::Functions;
-
-$| = 1;
-
-my $Is_MacOS   = $^O eq 'MacOS';
-my $tmpfile = "tmp0000";
-1 while -e ++$tmpfile;
-END {  if ($tmpfile) { 1 while unlink $tmpfile} }
-
-my @prgs = () ;
-my @w_files = () ;
-
-if (@ARGV)
-  { print "ARGV = [@ARGV]\n" ;
-    if ($^O eq 'MacOS') {
-      @w_files = map { s#^#:lib:warnings:#; $_ } @ARGV
-    } else {
-      @w_files = map { s#^#./lib/warnings/#; $_ } @ARGV
-    }
-  }
-else
-  { @w_files = sort glob(catfile(curdir(), "lib", "warnings", "*")) }
-
-my $files = 0;
-foreach my $file (@w_files) {
-
-    next if $file =~ /(~|\.orig|,v)$/;
-    next if $file =~ /perlio$/ && !(find PerlIO::Layer 'perlio');
-    next if -d $file;
-
-    open F, "<$file" or die "Cannot open $file: $!\n" ;
-    my $line = 0;
-    while (<F>) {
-        $line++;
-       last if /^__END__/ ;
-    }
-
-    {
-        local $/ = undef;
-        $files++;
-        @prgs = (@prgs, $file, split "\n########\n", <F>) ;
-    }
-    close F ;
-}
-
-undef $/;
-
-plan tests => (scalar(@prgs)-$files);
-
-
-
-for (@prgs){
-    unless (/\n/)
-     {
-      print "# From $_\n";
-      next;
-     }
-    my $switch = "";
-    my @temps = () ;
-    my @temp_path = () ;
-    if (s/^\s*-\w+//){
-        $switch = $&;
-    }
-    my($prog,$expected) = split(/\nEXPECT\n/, $_);
-    my ($todo, $todo_reason);
-    $todo = $prog =~ s/^#\s*TODO(.*)\n//m and $todo_reason = $1;
-    if ( $prog =~ /--FILE--/) {
-        my(@files) = split(/\n--FILE--\s*([^\s\n]*)\s*\n/, $prog) ;
-       shift @files ;
-       die "Internal error test $test didn't split into pairs, got " .
-               scalar(@files) . "[" . join("%%%%", @files) ."]\n"
-           if @files % 2 ;
-       while (@files > 2) {
-           my $filename = shift @files ;
-           my $code = shift @files ;
-           push @temps, $filename ;
-           if ($filename =~ m#(.*)/#) {
-                mkpath($1);
-                push(@temp_path, $1);
-           }
-           open F, ">$filename" or die "Cannot open $filename: $!\n" ;
-           print F $code ;
-           close F or die "Cannot close $filename: $!\n";
-       }
-       shift @files ;
-       $prog = shift @files ;
-    }
-
-    # fix up some paths
-    if ($^O eq 'MacOS') {
-       $prog =~ s|require "./abc(d)?";|require ":abc$1";|g;
-       $prog =~ s|"\."|":"|g;
-    }
-
-    open TEST, ">$tmpfile" or die "Cannot open >$tmpfile: $!";
-    print TEST q{
-        BEGIN {
-            open(STDERR, ">&STDOUT")
-              or die "Can't dup STDOUT->STDERR: $!;";
-        }
-    };
-    print TEST "\n#line 1\n";  # So the line numbers don't get messed up.
-    print TEST $prog,"\n";
-    close TEST or die "Cannot close $tmpfile: $!";
-    my $results = runperl( switches => [$switch], stderr => 1, progfile => $tmpfile );
-    my $status = $?;
-    $results =~ s/\n+$//;
-    # allow expected output to be written as if $prog is on STDIN
-    $results =~ s/tmp\d+/-/g;
-    if ($^O eq 'VMS') {
-        # some tests will trigger VMS messages that won't be expected
-        $results =~ s/\n?%[A-Z]+-[SIWEF]-[A-Z]+,.*//;
-
-        # pipes double these sometimes
-        $results =~ s/\n\n/\n/g;
-    }
-# bison says 'parse error' instead of 'syntax error',
-# various yaccs may or may not capitalize 'syntax'.
-    $results =~ s/^(syntax|parse) error/syntax error/mig;
-    # allow all tests to run when there are leaks
-    $results =~ s/Scalars leaked: \d+\n//g;
-
-    # fix up some paths
-    if ($^O eq 'MacOS') {
-       $results =~ s|:abc\.pm\b|abc.pm|g;
-       $results =~ s|:abc(d)?\b|./abc$1|g;
-    }
-
-    $expected =~ s/\n+$//;
-    my $prefix = ($results =~ s#^PREFIX(\n|$)##) ;
-    # any special options? (OPTIONS foo bar zap)
-    my $option_regex = 0;
-    my $option_random = 0;
-    if ($expected =~ s/^OPTIONS? (.+)\n//) {
-       foreach my $option (split(' ', $1)) {
-           if ($option eq 'regex') { # allow regular expressions
-               $option_regex = 1;
-           }
-           elsif ($option eq 'random') { # all lines match, but in any order
-               $option_random = 1;
-           }
-           else {
-               die "$0: Unknown OPTION '$option'\n";
-           }
-       }
-    }
-    die "$0: can't have OPTION regex and random\n"
-        if $option_regex + option_random > 1;
-    my $ok = 1;
-    if ( $results =~ s/^SKIPPED\n//) {
-       print "$results\n" ;
-    }
-    elsif ($option_random)
-    {
-        $ok = randomMatch($results, $expected);
-    }
-    elsif (($prefix  && (( $option_regex && $results !~ /^$expected/) ||
-                        (!$option_regex && $results !~ /^\Q$expected/))) or
-          (!$prefix && (( $option_regex && $results !~ /^$expected/) ||
-                        (!$option_regex && $results ne $expected)))) {
-        my $err_line = "PROG: $switch\n$prog\n" .
-                       "EXPECTED:\n$expected\n" .
-                       "GOT:\n$results\n";
-        if ($todo) {
-            $err_line =~ s/^/# /mg;
-            print $err_line;  # Harness can't filter it out from STDERR.
-        }
-        else {
-            print STDERR $err_line;
-        }
-        $ok = 0;
-    }
-
-    $TODO = $todo ? $todo_reason : 0;
-    ok($ok);
-
-    foreach (@temps)
-       { unlink $_ if $_ }
-    foreach (@temp_path)
-       { rmtree $_ if -d $_ }
-}
-
-sub randomMatch
-{
-    my $got = shift ;
-    my $expected = shift;
-
-    my @got = sort split "\n", $got ;
-    my @expected = sort split "\n", $expected ;
-
-   return "@got" eq "@expected";
-
-}
+our $pragma_name = "warnings";
+require "../t/lib/common.pl";
diff --git a/op.c b/op.c
index 626db8f..fc1c6a8 100644 (file)
--- a/op.c
+++ b/op.c
@@ -820,6 +820,8 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_AND:
     case OP_DOR:
     case OP_COND_EXPR:
+    case OP_ENTERGIVEN:
+    case OP_ENTERWHEN:
        for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
            scalarvoid(kid);
        break;
@@ -841,6 +843,8 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_LEAVELOOP:
     case OP_LINESEQ:
     case OP_LIST:
+    case OP_LEAVEGIVEN:
+    case OP_LEAVEWHEN:
        for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
            scalarvoid(kid);
        break;
@@ -3918,6 +3922,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
            iterpflags = sv->op_private & OPpOUR_INTRO; /* for our $x () */
            sv->op_type = OP_RV2GV;
            sv->op_ppaddr = PL_ppaddr[OP_RV2GV];
+           if (cGVOPx_gv(cUNOPx(sv)->op_first) == PL_defgv)
+               iterpflags |= OPpITER_DEF;
        }
        else if (sv->op_type == OP_PADSV) { /* private variable */
            iterpflags = sv->op_private & OPpLVAL_INTRO; /* for my $x () */
@@ -3935,6 +3941,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
        }
        else
            Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]);
+       if (padoff && strEQ(PAD_COMPNAME_PV(padoff), "$_"))
+           iterpflags |= OPpITER_DEF;
     }
     else {
         const I32 offset = pad_findmy("$_");
@@ -3944,6 +3952,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
        else {
            padoff = offset;
        }
+       iterpflags |= OPpITER_DEF;
     }
     if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
        expr = mod(force_list(scalar(ref(expr, OP_ITER))), OP_GREPSTART);
@@ -4031,6 +4040,177 @@ 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, mod(cond, OP_REFGEN));
+
+    else
+       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;
+
+    NewOp(1101, enterop, 1, LOGOP);
+    enterop->op_type = enter_opcode;
+    enterop->op_ppaddr = PL_ppaddr[enter_opcode];
+    enterop->op_flags =  (U8) OPf_KIDS;
+    enterop->op_targ = ((entertarg == NOT_IN_PAD) ? 0 : entertarg);
+    enterop->op_private = 0;
+
+    o = newUNOP(leave_opcode, 0, (OP *) enterop);
+
+    if (cond) {
+       enterop->op_first = scalar(cond);
+       cond->op_sibling = block;
+
+       o->op_next = LINKLIST(cond);
+       cond->op_next = (OP *) enterop;
+    }
+    else {
+       /* This is a default {} block */
+       enterop->op_first = block;
+       enterop->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;
+}
+
+/* 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_ OP *o)
+{
+    switch(o->op_type) {
+       case OP_OR:
+           return looks_like_bool(cLOGOPo->op_first);
+
+       case OP_AND:
+           return (
+               looks_like_bool(cLOGOPo->op_first)
+            && looks_like_bool(cLOGOPo->op_first->op_sibling));
+
+       case OP_ENTERSUB:
+
+       case OP_NOT:    case OP_XOR:
+       /* Note that OP_DOR is not here */
+
+       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:
+
+           return TRUE;
+       
+       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;
+               
+       /* FALL THROUGH */
+       default:
+           return FALSE;
+    }
+}
+
+OP *
+Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off)
+{
+    assert( cond );
+    return newGIVWHENOP(
+       ref_array_or_hash(cond),
+       block,
+       OP_ENTERGIVEN, OP_LEAVEGIVEN,
+       defsv_off);
+}
+
+/* If cond is null, this is a default {} block */
+OP *
+Perl_newWHENOP(pTHX_ OP *cond, OP *block)
+{
+    bool cond_llb = (!cond || looks_like_bool(cond));
+    OP *cond_op;
+
+    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,
+       append_elem(block->op_type, block, newOP(OP_BREAK, OPf_SPECIAL)),
+       OP_ENTERWHEN, OP_LEAVEWHEN, 0);
+}
+
 /*
 =for apidoc cv_undef
 
@@ -5104,6 +5284,13 @@ Perl_ck_eval(pTHX_ OP *o)
        o = newUNOP(OP_ENTEREVAL, 0, newDEFSVOP());
     }
     o->op_targ = (PADOFFSET)PL_hints;
+    if ((PL_hints & HINT_HH_FOR_EVAL) != 0 && GvHV(PL_hintgv))
+    {
+       /* Store a copy of %^H that pp_entereval can pick up */
+       OP *hhop = newSVOP(OP_CONST, 0, (SV*)newHVhv(GvHV(PL_hintgv)));
+       cUNOPo->op_first->op_sibling = hhop;
+       o->op_private |= OPpEVAL_HAS_HH;
+    }
     return o;
 }
 
@@ -5763,6 +5950,43 @@ Perl_ck_listiob(pTHX_ OP *o)
 }
 
 OP *
+Perl_ck_say(pTHX_ OP *o)
+{
+    o = ck_listiob(o);
+    o->op_type = OP_PRINT;
+    cLISTOPo->op_last = cLISTOPo->op_last->op_sibling
+       = newSVOP(OP_CONST, 0, newSVpvn("\n", 1));
+    return o;
+}
+
+OP *
+Perl_ck_smartmatch(pTHX_ OP *o)
+{
+    if (0 == (o->op_flags & OPf_SPECIAL)) {
+       OP *first  = cBINOPo->op_first;
+       OP *second = first->op_sibling;
+       
+       /* Implicitly take a reference to an array or hash */
+       first->op_sibling = Nullop;
+       first = cBINOPo->op_first = ref_array_or_hash(first);
+       second = first->op_sibling = ref_array_or_hash(second);
+       
+       /* Implicitly take a reference to a regular expression */
+       if (first->op_type == OP_MATCH) {
+           first->op_type = OP_QR;
+           first->op_ppaddr = PL_ppaddr[OP_QR];
+       }
+       if (second->op_type == OP_MATCH) {
+           second->op_type = OP_QR;
+           second->op_ppaddr = PL_ppaddr[OP_QR];
+        }
+    }
+    
+    return o;
+}
+
+
+OP *
 Perl_ck_sassign(pTHX_ OP *o)
 {
     OP *kid = cLISTOPo->op_first;
@@ -5795,7 +6019,7 @@ Perl_ck_sassign(pTHX_ OP *o)
 OP *
 Perl_ck_match(pTHX_ OP *o)
 {
-    if (o->op_type != OP_QR) {
+    if (o->op_type != OP_QR && PL_compcv) {
        const I32 offset = pad_findmy("$_");
        if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS(offset) & SVpad_OUR)) {
            o->op_targ = offset;
diff --git a/op.h b/op.h
index caea112..e687f42 100644 (file)
--- a/op.h
+++ b/op.h
@@ -110,6 +110,9 @@ Deprecated.  Use C<GIMME_V> instead.
                                 *    (runtime property) */
                                /*  On OP_AELEMFAST, indiciates pad var */
                                /*  On OP_REQUIRE, was seen as CORE::require */
+                               /*  On OP_ENTERWHEN, there's no condition */
+                               /*  On OP_BREAK, an implicit break */
+                               /*  On OP_SMARTMATCH, an implicit smartmatch */
 
 /* old names; don't use in new code, but don't break them, either */
 #define OPf_LIST       OPf_WANT_LIST
@@ -183,6 +186,7 @@ Deprecated.  Use C<GIMME_V> instead.
 
 /* Private for OP_ENTERITER and OP_ITER */
 #define OPpITER_REVERSED       4       /* for (reverse ...) */
+#define OPpITER_DEF            8       /* for $_ or for my $_ */
 
 /* Private for OP_CONST */
 #define        OPpCONST_NOVER          2       /* no 6; */
@@ -224,7 +228,7 @@ Deprecated.  Use C<GIMME_V> instead.
 #define OPpHUSH_VMSISH         64      /* hush DCL exit msg vmsish mode*/
 #define OPpEXIT_VMSISH         128     /* exit(0) vs. exit(1) vmsish mode*/
 
-/* Private of OP_FTXXX */
+/* Private for OP_FTXXX */
 #define OPpFT_ACCESS           2       /* use filetest 'access' */
 #define OPpFT_STACKED          4       /* stacked filetest, as in "-f -x $f" */
 #define OP_IS_FILETEST_ACCESS(op)              \
@@ -238,6 +242,9 @@ Deprecated.  Use C<GIMME_V> instead.
 /* Private for OP_(MAP|GREP)(WHILE|START) */
 #define OPpGREP_LEX            2       /* iterate over lexical $_ */
     
+/* Private for OP_ENTEREVAL */
+#define OPpEVAL_HAS_HH         2       /* Does it have a copy of %^H */
+    
 struct op {
     BASEOP
 };
index 587c138..5ebe99f 100644 (file)
--- a/opcode.h
+++ b/opcode.h
@@ -386,6 +386,14 @@ EXTCONST char* const PL_op_name[] = {
        "method_named",
        "dor",
        "dorassign",
+       "entergiven",
+       "leavegiven",
+       "enterwhen",
+       "leavewhen",
+       "break",
+       "continue",
+       "smartmatch",
+       "say",
        "custom",
 };
 #endif
@@ -747,6 +755,14 @@ EXTCONST char* const PL_op_desc[] = {
        "method with known name",
        "defined or (//)",
        "defined or assignment (//=)",
+       "given()",
+       "leave given block",
+       "when()",
+       "leave when block",
+       "break",
+       "continue",
+       "smart match",
+       "say",
        "unknown custom operator",
 };
 #endif
@@ -1119,6 +1135,14 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
        MEMBER_TO_FPTR(Perl_pp_method_named),
        MEMBER_TO_FPTR(Perl_pp_defined),        /* Perl_pp_dor */
        MEMBER_TO_FPTR(Perl_pp_defined),        /* Perl_pp_dorassign */
+       MEMBER_TO_FPTR(Perl_pp_entergiven),
+       MEMBER_TO_FPTR(Perl_pp_leavegiven),
+       MEMBER_TO_FPTR(Perl_pp_enterwhen),
+       MEMBER_TO_FPTR(Perl_pp_leavewhen),
+       MEMBER_TO_FPTR(Perl_pp_break),
+       MEMBER_TO_FPTR(Perl_pp_continue),
+       MEMBER_TO_FPTR(Perl_pp_smartmatch),
+       MEMBER_TO_FPTR(Perl_pp_print),  /* Perl_pp_say */
 }
 #endif
 ;
@@ -1485,6 +1509,14 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */
        MEMBER_TO_FPTR(Perl_ck_null),   /* method_named */
        MEMBER_TO_FPTR(Perl_ck_null),   /* dor */
        MEMBER_TO_FPTR(Perl_ck_null),   /* dorassign */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* entergiven */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* leavegiven */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* enterwhen */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* leavewhen */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* break */
+       MEMBER_TO_FPTR(Perl_ck_null),   /* continue */
+       MEMBER_TO_FPTR(Perl_ck_smartmatch),     /* smartmatch */
+       MEMBER_TO_FPTR(Perl_ck_say),    /* say */
        MEMBER_TO_FPTR(Perl_ck_null),   /* custom */
 }
 #endif
@@ -1849,6 +1881,14 @@ EXT const U32 PL_opargs[] = {
        0x00000c40,     /* method_named */
        0x00000600,     /* dor */
        0x00000604,     /* dorassign */
+       0x00000640,     /* entergiven */
+       0x00000200,     /* leavegiven */
+       0x00000640,     /* enterwhen */
+       0x00000200,     /* leavewhen */
+       0x00000000,     /* break */
+       0x00000000,     /* continue */
+       0x00000404,     /* smartmatch */
+       0x0005c815,     /* say */
        0x00000000,     /* custom */
 };
 #endif
index 898a248..19030a6 100755 (executable)
--- a/opcode.pl
+++ b/opcode.pl
@@ -78,6 +78,7 @@ my @raw_alias = (
                 Perl_pp_or => ['orassign'],
                 Perl_pp_ucfirst => ['lcfirst'],
                 Perl_pp_sle => [qw(slt sgt sge)],
+                Perl_pp_print => ['say'],
                );
 
 while (my ($func, $names) = splice @raw_alias, 0, 2) {
@@ -1019,6 +1020,16 @@ method_named     method with known name  ck_null         d$
 dor            defined or (//)                 ck_null         |
 dorassign      defined or assignment (//=)     ck_null         s|
 
+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
+smartmatch     smart match             ck_smartmatch   s2
+
+say            say                     ck_say          ims@    F? L
+
 # Add new ops before this, the custom operator.
 
 custom         unknown custom operator         ck_null         0
index ba6a26b..e428e1c 100644 (file)
--- a/opnames.h
+++ b/opnames.h
@@ -367,11 +367,19 @@ typedef enum opcode {
        OP_METHOD_NAMED,/* 350 */
        OP_DOR,         /* 351 */
        OP_DORASSIGN,   /* 352 */
-       OP_CUSTOM,      /* 353 */
+       OP_ENTERGIVEN,  /* 353 */
+       OP_LEAVEGIVEN,  /* 354 */
+       OP_ENTERWHEN,   /* 355 */
+       OP_LEAVEWHEN,   /* 356 */
+       OP_BREAK,       /* 357 */
+       OP_CONTINUE,    /* 358 */
+       OP_SMARTMATCH,  /* 359 */
+       OP_SAY,         /* 360 */
+       OP_CUSTOM,      /* 361 */
        OP_max          
 } opcode;
 
-#define MAXO 354
+#define MAXO 362
 #define OP_phoney_INPUT_ONLY -1
 #define OP_phoney_OUTPUT_ONLY -2
 
diff --git a/perl.h b/perl.h
index 5da4f62..ea01dda 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -4019,6 +4019,9 @@ EXTCONST char* const PL_block_type[] = {
        "LOOP",
        "SUBST",
        "BLOCK",
+       "FORMAT",
+       "GIVEN",
+       "WHEN"
 };
 #else
 EXTCONST char* PL_block_type[];
@@ -4134,6 +4137,9 @@ enum {            /* pass one of these to get_vtbl */
 #define HINT_ASSERTING          0x01000000
 #define HINT_ASSERTIONSSEEN     0x02000000
 
+#define HINT_HH_FOR_EVAL       0x04000000 /* Squirrel a copy of %^H away
+                                           * with every eval "string" */
+
 /* The following are stored in $sort::hints, not in PL_hints */
 #define HINT_SORT_SORT_BITS    0x000000FF /* allow 256 different ones */
 #define HINT_SORT_QUICKSORT    0x00000001
@@ -4725,7 +4731,10 @@ enum {
   to_sv_amg,   to_av_amg,
   to_hv_amg,   to_gv_amg,
   to_cv_amg,   iter_amg,
-  int_amg,     DESTROY_amg,
+  int_amg,     smart_amg,
+
+  /* Note: Perl_Gv_AMupdate() assumes that DESTROY is the last entry */
+  DESTROY_amg,
   max_amg_code
   /* Do not leave a trailing comma here.  C9X allows it, C89 doesn't. */
 };
@@ -4772,7 +4781,8 @@ EXTCONST char * const PL_AMG_names[NofAMmeth] = {
   "(${}",      "(@{}",
   "(%{}",      "(*{}",
   "(&{}",      "(<>",
-  "(int",      "DESTROY",
+  "(int",      "(~~",
+  "DESTROY"
 };
 #else
 EXTCONST char * PL_AMG_names[NofAMmeth];
index bb8bc74..d0471f6 100644 (file)
@@ -5,34 +5,45 @@ use Devel::Tokenizer::C 0.05;
 use strict;
 use warnings;
 
-my @pos = qw(__DATA__ __END__ AUTOLOAD BEGIN CHECK DESTROY do delete defined
-            END else eval elsif exists for format foreach grep goto glob INIT
-            if last local m my map next no our pos print printf package
-            prototype q qr qq qw qx redo return require s scalar sort split
-            study sub tr tie tied use undef until untie unless while y);
+my @pos = qw(__DATA__ __END__ AUTOLOAD BEGIN CHECK DESTROY default defined
+           delete do END else eval elsif exists for format foreach given grep
+           goto glob INIT if last local m my map next no our pos print printf
+           package prototype q qr qq qw qx redo return require s scalar sort
+           split study sub tr tie tied use undef until untie unless when while
+           y);
 
 my @neg = qw(__FILE__ __LINE__ __PACKAGE__ and abs alarm atan2 accept bless
-            bind binmode CORE cmp chr cos chop close chdir chomp chmod chown
-            crypt chroot caller connect closedir continue die dump dbmopen
-            dbmclose eq eof err exp exit exec each endgrent endpwent
-            endnetent endhostent endservent endprotoent fork fcntl flock
-            fileno formline getppid getpgrp getpwent getpwnam getpwuid
-            getpeername getprotoent getpriority getprotobyname
-            getprotobynumber gethostbyname gethostbyaddr gethostent
-            getnetbyname getnetbyaddr getnetent getservbyname getservbyport
-            getservent getsockname getsockopt getgrent getgrnam getgrgid
-            getlogin getc gt ge gmtime hex int index ioctl join keys kill lt
-            le lc log link lock lstat length listen lcfirst localtime mkdir
-            msgctl msgget msgrcv msgsnd ne not or ord oct open opendir pop
-            push pack pipe quotemeta ref read rand recv rmdir reset rename
-            rindex reverse readdir readlink readline readpipe rewinddir seek
-            send semop select semctl semget setpgrp seekdir setpwent setgrent
-            setnetent setsockopt sethostent setservent setpriority
-            setprotoent shift shmctl shmget shmread shmwrite shutdown sin
-            sleep socket socketpair sprintf splice sqrt srand stat substr
-            system symlink syscall sysopen sysread sysseek syswrite tell time
-            times telldir truncate uc utime umask unpack unlink unshift
-            ucfirst values vec warn wait write waitpid wantarray x xor);
+           break bind binmode CORE cmp chr cos chop close chdir chomp chmod
+           chown crypt chroot caller connect closedir continue die dump
+           dbmopen dbmclose eq eof err exp exit exec each endgrent endpwent
+           endnetent endhostent endservent endprotoent fork fcntl flock fileno
+           formline getppid getpgrp getpwent getpwnam getpwuid getpeername
+           getprotoent getpriority getprotobyname getprotobynumber
+           gethostbyname gethostbyaddr gethostent getnetbyname getnetbyaddr
+           getnetent getservbyname getservbyport getservent getsockname
+           getsockopt getgrent getgrnam getgrgid getlogin getc gt ge gmtime
+           hex int index ioctl join keys kill lt le lc log link lock lstat
+           length listen lcfirst localtime mkdir msgctl msgget msgrcv msgsnd
+           ne not or ord oct open opendir pop push pack pipe quotemeta ref
+           read rand recv rmdir reset rename rindex reverse readdir readlink
+           readline readpipe rewinddir say seek send semop select semctl semget
+           setpgrp seekdir setpwent setgrent setnetent setsockopt sethostent
+           setservent setpriority setprotoent shift shmctl shmget shmread
+           shmwrite shutdown sin sleep socket socketpair sprintf splice sqrt
+           srand stat substr system symlink syscall sysopen sysread sysseek
+           syswrite tell time times telldir truncate uc utime umask unpack
+           unlink unshift ucfirst values vec warn wait write waitpid wantarray
+           x xor);
+
+my %feature_kw = (
+       given   => 'switch',
+       when    => 'switch',
+       default => 'switch',
+       # continue is already a keyword
+       break   => 'switch',
+
+       say     => 'say',
+       );
 
 my %pos = map { ($_ => 1) } @pos;
 
@@ -71,7 +82,13 @@ if(ckWARN_d(WARN_SYNTAX))
   Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "elseif should be elsif");
 END
   }
-
+  elsif (my $feature = $feature_kw{$k}) {
+    my $feature_len = length($feature);
+    $feature =~ s/([\\"])/\\$1/g;
+    return <<END;
+return (FEATURE_IS_ENABLED("$feature", $feature_len) ? ${sign}KEY_$k : 0);
+END
+  }
   return <<END;
 return ${sign}KEY_$k;
 END
index 590c0a5..817bde9 100644 (file)
--- a/perly.act
+++ b/perly.act
@@ -1,56 +1,61 @@
 case 2:
-#line 98 "perly.y"
+#line 100 "perly.y"
     { (yyval.ival) = (yyvsp[-1].ival); newPROG(block_end((yyvsp[-1].ival),(yyvsp[0].opval))); ;}
     break;
 
   case 3:
-#line 103 "perly.y"
+#line 105 "perly.y"
     { if (PL_copline > (line_t)(yyvsp[-3].ival))
                              PL_copline = (line_t)(yyvsp[-3].ival);
                          (yyval.opval) = block_end((yyvsp[-2].ival), (yyvsp[-1].opval)); ;}
     break;
 
   case 4:
-#line 109 "perly.y"
+#line 111 "perly.y"
     { (yyval.ival) = block_start(TRUE); ;}
     break;
 
   case 5:
-#line 113 "perly.y"
+#line 115 "perly.y"
+    { (yyval.ival) = (I32) allocmy("$_"); ;}
+    break;
+
+  case 6:
+#line 119 "perly.y"
     {
                    PL_expect = XSTATE; (yyval.ival) = block_start(TRUE);
                ;}
     break;
 
-  case 6:
-#line 120 "perly.y"
+  case 7:
+#line 126 "perly.y"
     { if (PL_copline > (line_t)(yyvsp[-3].ival))
                              PL_copline = (line_t)(yyvsp[-3].ival);
                          (yyval.opval) = block_end((yyvsp[-2].ival), (yyvsp[-1].opval)); ;}
     break;
 
-  case 7:
-#line 126 "perly.y"
+  case 8:
+#line 132 "perly.y"
     { (yyval.ival) = block_start(FALSE); ;}
     break;
 
-  case 8:
-#line 130 "perly.y"
+  case 9:
+#line 136 "perly.y"
     { (yyval.ival) = PL_savestack_ix; ;}
     break;
 
-  case 9:
-#line 134 "perly.y"
+  case 10:
+#line 140 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 10:
-#line 136 "perly.y"
+  case 11:
+#line 142 "perly.y"
     { (yyval.opval) = (yyvsp[-1].opval); ;}
     break;
 
-  case 11:
-#line 138 "perly.y"
+  case 12:
+#line 144 "perly.y"
     {   LEAVE_SCOPE((yyvsp[-1].ival));
                            (yyval.opval) = append_list(OP_LINESEQ,
                                (LISTOP*)(yyvsp[-2].opval), (LISTOP*)(yyvsp[0].opval));
@@ -58,13 +63,23 @@ case 2:
                            if ((yyvsp[-2].opval) && (yyvsp[0].opval)) PL_hints |= HINT_BLOCK_SCOPE; ;}
     break;
 
-  case 12:
-#line 147 "perly.y"
+  case 13:
+#line 153 "perly.y"
+    { (yyval.opval) = newSTATEOP(0, (yyvsp[-1].pval), (yyvsp[0].opval)); ;}
+    break;
+
+  case 15:
+#line 156 "perly.y"
+    { (yyval.opval) = (yyvsp[0].opval); ;}
+    break;
+
+  case 16:
+#line 158 "perly.y"
     { (yyval.opval) = newSTATEOP(0, (yyvsp[-1].pval), (yyvsp[0].opval)); ;}
     break;
 
-  case 14:
-#line 150 "perly.y"
+  case 17:
+#line 160 "perly.y"
     { if ((yyvsp[-1].pval) != Nullch) {
                              (yyval.opval) = newSTATEOP(0, (yyvsp[-1].pval), newOP(OP_NULL, 0));
                            }
@@ -75,91 +90,102 @@ case 2:
                            PL_expect = XSTATE; ;}
     break;
 
-  case 15:
-#line 159 "perly.y"
+  case 18:
+#line 169 "perly.y"
     { (yyval.opval) = newSTATEOP(0, (yyvsp[-2].pval), (yyvsp[-1].opval));
                          PL_expect = XSTATE; ;}
     break;
 
-  case 16:
-#line 165 "perly.y"
+  case 19:
+#line 175 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 17:
-#line 167 "perly.y"
+  case 20:
+#line 177 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 18:
-#line 169 "perly.y"
+  case 21:
+#line 179 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (yyvsp[0].opval), (yyvsp[-2].opval)); ;}
     break;
 
-  case 19:
-#line 171 "perly.y"
+  case 22:
+#line 181 "perly.y"
     { (yyval.opval) = newLOGOP(OP_OR, 0, (yyvsp[0].opval), (yyvsp[-2].opval)); ;}
     break;
 
-  case 20:
-#line 173 "perly.y"
+  case 23:
+#line 183 "perly.y"
     { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, scalar((yyvsp[0].opval)), (yyvsp[-2].opval)); ;}
     break;
 
-  case 21:
-#line 175 "perly.y"
+  case 24:
+#line 185 "perly.y"
     { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, (yyvsp[0].opval), (yyvsp[-2].opval));;}
     break;
 
-  case 22:
-#line 177 "perly.y"
+  case 25:
+#line 187 "perly.y"
     { (yyval.opval) = newFOROP(0, Nullch, (line_t)(yyvsp[-1].ival),
                                        Nullop, (yyvsp[0].opval), (yyvsp[-2].opval), Nullop); ;}
     break;
 
-  case 23:
-#line 183 "perly.y"
+  case 26:
+#line 193 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 24:
-#line 185 "perly.y"
+  case 27:
+#line 195 "perly.y"
     { ((yyvsp[0].opval))->op_flags |= OPf_PARENS; (yyval.opval) = scope((yyvsp[0].opval)); ;}
     break;
 
-  case 25:
-#line 187 "perly.y"
+  case 28:
+#line 197 "perly.y"
     { PL_copline = (line_t)(yyvsp[-5].ival);
                            (yyval.opval) = newCONDOP(0, (yyvsp[-3].opval), scope((yyvsp[-1].opval)), (yyvsp[0].opval));
                            PL_hints |= HINT_BLOCK_SCOPE; ;}
     break;
 
-  case 26:
-#line 194 "perly.y"
+  case 29:
+#line 204 "perly.y"
     { PL_copline = (line_t)(yyvsp[-6].ival);
                            (yyval.opval) = block_end((yyvsp[-4].ival),
                                   newCONDOP(0, (yyvsp[-3].opval), scope((yyvsp[-1].opval)), (yyvsp[0].opval))); ;}
     break;
 
-  case 27:
-#line 198 "perly.y"
+  case 30:
+#line 208 "perly.y"
     { PL_copline = (line_t)(yyvsp[-6].ival);
                            (yyval.opval) = block_end((yyvsp[-4].ival),
                                   newCONDOP(0, (yyvsp[-3].opval), scope((yyvsp[-1].opval)), (yyvsp[0].opval))); ;}
     break;
 
-  case 28:
-#line 205 "perly.y"
+  case 31:
+#line 215 "perly.y"
+    { (yyval.opval) = block_end((yyvsp[-3].ival),
+               newWHENOP((yyvsp[-2].opval), scope((yyvsp[0].opval)))); ;}
+    break;
+
+  case 32:
+#line 218 "perly.y"
+    { (yyval.opval) = newWHENOP(0, scope((yyvsp[0].opval))); ;}
+    break;
+
+  case 33:
+#line 223 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 29:
-#line 207 "perly.y"
+  case 34:
+#line 225 "perly.y"
     { (yyval.opval) = scope((yyvsp[0].opval)); ;}
     break;
 
-  case 30:
-#line 212 "perly.y"
+  case 35:
+#line 230 "perly.y"
     { PL_copline = (line_t)(yyvsp[-7].ival);
                            (yyval.opval) = block_end((yyvsp[-5].ival),
                                   newSTATEOP(0, (yyvsp[-8].pval),
@@ -167,8 +193,8 @@ case 2:
                                                (yyvsp[-7].ival), (yyvsp[-4].opval), (yyvsp[-1].opval), (yyvsp[0].opval), (yyvsp[-2].ival)))); ;}
     break;
 
-  case 31:
-#line 218 "perly.y"
+  case 36:
+#line 236 "perly.y"
     { PL_copline = (line_t)(yyvsp[-7].ival);
                            (yyval.opval) = block_end((yyvsp[-5].ival),
                                   newSTATEOP(0, (yyvsp[-8].pval),
@@ -176,27 +202,27 @@ case 2:
                                                (yyvsp[-7].ival), (yyvsp[-4].opval), (yyvsp[-1].opval), (yyvsp[0].opval), (yyvsp[-2].ival)))); ;}
     break;
 
-  case 32:
-#line 224 "perly.y"
+  case 37:
+#line 242 "perly.y"
     { (yyval.opval) = block_end((yyvsp[-6].ival),
                                 newFOROP(0, (yyvsp[-9].pval), (line_t)(yyvsp[-8].ival), (yyvsp[-5].opval), (yyvsp[-3].opval), (yyvsp[-1].opval), (yyvsp[0].opval))); ;}
     break;
 
-  case 33:
-#line 227 "perly.y"
+  case 38:
+#line 245 "perly.y"
     { (yyval.opval) = block_end((yyvsp[-4].ival),
                                 newFOROP(0, (yyvsp[-8].pval), (line_t)(yyvsp[-7].ival), mod((yyvsp[-6].opval), OP_ENTERLOOP),
                                          (yyvsp[-3].opval), (yyvsp[-1].opval), (yyvsp[0].opval))); ;}
     break;
 
-  case 34:
-#line 231 "perly.y"
+  case 39:
+#line 249 "perly.y"
     { (yyval.opval) = block_end((yyvsp[-4].ival),
                                 newFOROP(0, (yyvsp[-7].pval), (line_t)(yyvsp[-6].ival), Nullop, (yyvsp[-3].opval), (yyvsp[-1].opval), (yyvsp[0].opval))); ;}
     break;
 
-  case 35:
-#line 236 "perly.y"
+  case 40:
+#line 254 "perly.y"
     { OP *forop;
                          PL_copline = (line_t)(yyvsp[-10].ival);
                          forop = newSTATEOP(0, (yyvsp[-11].pval),
@@ -213,122 +239,131 @@ case 2:
                          (yyval.opval) = block_end((yyvsp[-8].ival), forop); ;}
     break;
 
-  case 36:
-#line 251 "perly.y"
+  case 41:
+#line 269 "perly.y"
     { (yyval.opval) = newSTATEOP(0, (yyvsp[-2].pval),
                                 newWHILEOP(0, 1, (LOOP*)Nullop,
                                            NOLINE, Nullop, (yyvsp[-1].opval), (yyvsp[0].opval), 0)); ;}
     break;
 
-  case 37:
-#line 258 "perly.y"
+  case 42:
+#line 276 "perly.y"
+    { PL_copline = (line_t) (yyvsp[-6].ival);
+                           (yyval.opval) = block_end((yyvsp[-4].ival),
+                               newSTATEOP(0, (yyvsp[-7].pval),
+                                   newGIVENOP((yyvsp[-2].opval), scope((yyvsp[0].opval)),
+                                       (PADOFFSET) (yyvsp[-3].ival)) )); ;}
+    break;
+
+  case 43:
+#line 285 "perly.y"
     { (yyval.ival) = (PL_min_intro_pending &&
                            PL_max_intro_pending >=  PL_min_intro_pending);
                          intro_my(); ;}
     break;
 
-  case 38:
-#line 264 "perly.y"
+  case 44:
+#line 291 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 40:
-#line 270 "perly.y"
+  case 46:
+#line 297 "perly.y"
     { (void)scan_num("1", &yylval); (yyval.opval) = yylval.opval; ;}
     break;
 
-  case 42:
-#line 276 "perly.y"
+  case 48:
+#line 303 "perly.y"
     { (yyval.opval) = invert(scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 43:
-#line 281 "perly.y"
+  case 49:
+#line 308 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); intro_my(); ;}
     break;
 
-  case 44:
-#line 285 "perly.y"
+  case 50:
+#line 312 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); intro_my(); ;}
     break;
 
-  case 45:
-#line 289 "perly.y"
+  case 51:
+#line 316 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); intro_my(); ;}
     break;
 
-  case 46:
-#line 294 "perly.y"
+  case 52:
+#line 321 "perly.y"
     { (yyval.pval) = Nullch; ;}
     break;
 
-  case 48:
-#line 300 "perly.y"
+  case 54:
+#line 327 "perly.y"
     { (yyval.ival) = 0; ;}
     break;
 
-  case 49:
-#line 302 "perly.y"
+  case 55:
+#line 329 "perly.y"
     { (yyval.ival) = 0; ;}
     break;
 
-  case 50:
-#line 304 "perly.y"
+  case 56:
+#line 331 "perly.y"
     { (yyval.ival) = 0; ;}
     break;
 
-  case 51:
-#line 306 "perly.y"
+  case 57:
+#line 333 "perly.y"
     { (yyval.ival) = 0; ;}
     break;
 
-  case 52:
-#line 308 "perly.y"
+  case 58:
+#line 335 "perly.y"
     { (yyval.ival) = 0; ;}
     break;
 
-  case 53:
-#line 312 "perly.y"
+  case 59:
+#line 339 "perly.y"
     { newFORM((yyvsp[-2].ival), (yyvsp[-1].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 54:
-#line 315 "perly.y"
+  case 60:
+#line 342 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 55:
-#line 316 "perly.y"
+  case 61:
+#line 343 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 56:
-#line 321 "perly.y"
+  case 62:
+#line 348 "perly.y"
     { newMYSUB((yyvsp[-4].ival), (yyvsp[-3].opval), (yyvsp[-2].opval), (yyvsp[-1].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 57:
-#line 326 "perly.y"
+  case 63:
+#line 353 "perly.y"
     { newATTRSUB((yyvsp[-4].ival), (yyvsp[-3].opval), (yyvsp[-2].opval), (yyvsp[-1].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 58:
-#line 330 "perly.y"
+  case 64:
+#line 357 "perly.y"
     { (yyval.ival) = start_subparse(FALSE, 0); ;}
     break;
 
-  case 59:
-#line 334 "perly.y"
+  case 65:
+#line 361 "perly.y"
     { (yyval.ival) = start_subparse(FALSE, CVf_ANON); ;}
     break;
 
-  case 60:
-#line 338 "perly.y"
+  case 66:
+#line 365 "perly.y"
     { (yyval.ival) = start_subparse(TRUE, 0); ;}
     break;
 
-  case 61:
-#line 342 "perly.y"
+  case 67:
+#line 369 "perly.y"
     { const char *const name = SvPV_nolen_const(((SVOP*)(yyvsp[0].opval))->op_sv);
                          if (strEQ(name, "BEGIN") || strEQ(name, "END")
                              || strEQ(name, "INIT") || strEQ(name, "CHECK"))
@@ -336,387 +371,387 @@ case 2:
                          (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 62:
-#line 351 "perly.y"
+  case 68:
+#line 378 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 64:
-#line 357 "perly.y"
+  case 70:
+#line 384 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 65:
-#line 359 "perly.y"
+  case 71:
+#line 386 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 66:
-#line 361 "perly.y"
+  case 72:
+#line 388 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 67:
-#line 366 "perly.y"
+  case 73:
+#line 393 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 68:
-#line 368 "perly.y"
+  case 74:
+#line 395 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 69:
-#line 372 "perly.y"
+  case 75:
+#line 399 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 70:
-#line 373 "perly.y"
+  case 76:
+#line 400 "perly.y"
     { (yyval.opval) = Nullop; PL_expect = XSTATE; ;}
     break;
 
-  case 71:
-#line 377 "perly.y"
+  case 77:
+#line 404 "perly.y"
     { package((yyvsp[-1].opval)); ;}
     break;
 
-  case 72:
-#line 381 "perly.y"
+  case 78:
+#line 408 "perly.y"
     { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ ;}
     break;
 
-  case 73:
-#line 383 "perly.y"
+  case 79:
+#line 410 "perly.y"
     { utilize((yyvsp[-6].ival), (yyvsp[-5].ival), (yyvsp[-3].opval), (yyvsp[-2].opval), (yyvsp[-1].opval)); ;}
     break;
 
-  case 74:
-#line 388 "perly.y"
+  case 80:
+#line 415 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 75:
-#line 390 "perly.y"
+  case 81:
+#line 417 "perly.y"
     { (yyval.opval) = newLOGOP((yyvsp[-1].ival), 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 76:
-#line 392 "perly.y"
+  case 82:
+#line 419 "perly.y"
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 78:
-#line 398 "perly.y"
+  case 84:
+#line 425 "perly.y"
     { (yyval.opval) = (yyvsp[-1].opval); ;}
     break;
 
-  case 79:
-#line 400 "perly.y"
+  case 85:
+#line 427 "perly.y"
     { (yyval.opval) = append_elem(OP_LIST, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 81:
-#line 406 "perly.y"
+  case 87:
+#line 433 "perly.y"
     { (yyval.opval) = convert((yyvsp[-2].ival), OPf_STACKED,
                                prepend_elem(OP_LIST, newGVREF((yyvsp[-2].ival),(yyvsp[-1].opval)), (yyvsp[0].opval)) ); ;}
     break;
 
-  case 82:
-#line 409 "perly.y"
+  case 88:
+#line 436 "perly.y"
     { (yyval.opval) = convert((yyvsp[-4].ival), OPf_STACKED,
                                prepend_elem(OP_LIST, newGVREF((yyvsp[-4].ival),(yyvsp[-2].opval)), (yyvsp[-1].opval)) ); ;}
     break;
 
-  case 83:
-#line 412 "perly.y"
+  case 89:
+#line 439 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, scalar((yyvsp[-5].opval)), (yyvsp[-1].opval)),
                                    newUNOP(OP_METHOD, 0, (yyvsp[-3].opval)))); ;}
     break;
 
-  case 84:
-#line 417 "perly.y"
+  case 90:
+#line 444 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST, scalar((yyvsp[-2].opval)),
                                    newUNOP(OP_METHOD, 0, (yyvsp[0].opval)))); ;}
     break;
 
-  case 85:
-#line 421 "perly.y"
+  case 91:
+#line 448 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, (yyvsp[-1].opval), (yyvsp[0].opval)),
                                    newUNOP(OP_METHOD, 0, (yyvsp[-2].opval)))); ;}
     break;
 
-  case 86:
-#line 426 "perly.y"
+  case 92:
+#line 453 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, (yyvsp[-3].opval), (yyvsp[-1].opval)),
                                    newUNOP(OP_METHOD, 0, (yyvsp[-4].opval)))); ;}
     break;
 
-  case 87:
-#line 431 "perly.y"
+  case 93:
+#line 458 "perly.y"
     { (yyval.opval) = convert((yyvsp[-1].ival), 0, (yyvsp[0].opval)); ;}
     break;
 
-  case 88:
-#line 433 "perly.y"
+  case 94:
+#line 460 "perly.y"
     { (yyval.opval) = convert((yyvsp[-3].ival), 0, (yyvsp[-1].opval)); ;}
     break;
 
-  case 89:
-#line 435 "perly.y"
+  case 95:
+#line 462 "perly.y"
     { (yyvsp[0].opval) = newANONATTRSUB((yyvsp[-1].ival), 0, Nullop, (yyvsp[0].opval)); ;}
     break;
 
-  case 90:
-#line 437 "perly.y"
+  case 96:
+#line 464 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                 append_elem(OP_LIST,
                                   prepend_elem(OP_LIST, (yyvsp[-2].opval), (yyvsp[0].opval)), (yyvsp[-4].opval))); ;}
     break;
 
-  case 93:
-#line 451 "perly.y"
+  case 99:
+#line 478 "perly.y"
     { (yyval.opval) = newBINOP(OP_GELEM, 0, (yyvsp[-4].opval), scalar((yyvsp[-2].opval)));
                            PL_expect = XOPERATOR; ;}
     break;
 
-  case 94:
-#line 454 "perly.y"
+  case 100:
+#line 481 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0, oopsAV((yyvsp[-3].opval)), scalar((yyvsp[-1].opval))); ;}
     break;
 
-  case 95:
-#line 456 "perly.y"
+  case 101:
+#line 483 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((yyvsp[-4].opval)),OP_RV2AV),
                                        scalar((yyvsp[-1].opval)));;}
     break;
 
-  case 96:
-#line 460 "perly.y"
+  case 102:
+#line 487 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((yyvsp[-3].opval)),OP_RV2AV),
                                        scalar((yyvsp[-1].opval)));;}
     break;
 
-  case 97:
-#line 464 "perly.y"
+  case 103:
+#line 491 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0, oopsHV((yyvsp[-4].opval)), jmaybe((yyvsp[-2].opval)));
                            PL_expect = XOPERATOR; ;}
     break;
 
-  case 98:
-#line 467 "perly.y"
+  case 104:
+#line 494 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((yyvsp[-5].opval)),OP_RV2HV),
                                        jmaybe((yyvsp[-2].opval)));
                            PL_expect = XOPERATOR; ;}
     break;
 
-  case 99:
-#line 472 "perly.y"
+  case 105:
+#line 499 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((yyvsp[-4].opval)),OP_RV2HV),
                                        jmaybe((yyvsp[-2].opval)));
                            PL_expect = XOPERATOR; ;}
     break;
 
-  case 100:
-#line 477 "perly.y"
+  case 106:
+#line 504 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((yyvsp[-3].opval)))); ;}
     break;
 
-  case 101:
-#line 480 "perly.y"
+  case 107:
+#line 507 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   append_elem(OP_LIST, (yyvsp[-1].opval),
                                       newCVREF(0, scalar((yyvsp[-4].opval))))); ;}
     break;
 
-  case 102:
-#line 485 "perly.y"
+  case 108:
+#line 512 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   append_elem(OP_LIST, (yyvsp[-1].opval),
                                               newCVREF(0, scalar((yyvsp[-3].opval))))); ;}
     break;
 
-  case 103:
-#line 489 "perly.y"
+  case 109:
+#line 516 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((yyvsp[-2].opval)))); ;}
     break;
 
-  case 104:
-#line 492 "perly.y"
+  case 110:
+#line 519 "perly.y"
     { (yyval.opval) = newSLICEOP(0, (yyvsp[-1].opval), (yyvsp[-4].opval)); ;}
     break;
 
-  case 105:
-#line 494 "perly.y"
+  case 111:
+#line 521 "perly.y"
     { (yyval.opval) = newSLICEOP(0, (yyvsp[-1].opval), Nullop); ;}
     break;
 
-  case 106:
-#line 499 "perly.y"
+  case 112:
+#line 526 "perly.y"
     { (yyval.opval) = newASSIGNOP(OPf_STACKED, (yyvsp[-2].opval), (yyvsp[-1].ival), (yyvsp[0].opval)); ;}
     break;
 
-  case 107:
-#line 501 "perly.y"
+  case 113:
+#line 528 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 108:
-#line 503 "perly.y"
+  case 114:
+#line 530 "perly.y"
     {   if ((yyvsp[-1].ival) != OP_REPEAT)
                                scalar((yyvsp[-2].opval));
                            (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, (yyvsp[-2].opval), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 109:
-#line 507 "perly.y"
+  case 115:
+#line 534 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 110:
-#line 509 "perly.y"
+  case 116:
+#line 536 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 111:
-#line 511 "perly.y"
+  case 117:
+#line 538 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 112:
-#line 513 "perly.y"
+  case 118:
+#line 540 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 113:
-#line 515 "perly.y"
+  case 119:
+#line 542 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 114:
-#line 517 "perly.y"
+  case 120:
+#line 544 "perly.y"
     { (yyval.opval) = newBINOP((yyvsp[-1].ival), 0, scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 115:
-#line 519 "perly.y"
+  case 121:
+#line 546 "perly.y"
     { (yyval.opval) = newRANGE((yyvsp[-1].ival), scalar((yyvsp[-2].opval)), scalar((yyvsp[0].opval)));;}
     break;
 
-  case 116:
-#line 521 "perly.y"
+  case 122:
+#line 548 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 117:
-#line 523 "perly.y"
+  case 123:
+#line 550 "perly.y"
     { (yyval.opval) = newLOGOP(OP_OR, 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 118:
-#line 525 "perly.y"
+  case 124:
+#line 552 "perly.y"
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 119:
-#line 527 "perly.y"
+  case 125:
+#line 554 "perly.y"
     { (yyval.opval) = bind_match((yyvsp[-1].ival), (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 120:
-#line 532 "perly.y"
+  case 126:
+#line 559 "perly.y"
     { (yyval.opval) = newUNOP(OP_NEGATE, 0, scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 121:
-#line 534 "perly.y"
+  case 127:
+#line 561 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 122:
-#line 536 "perly.y"
+  case 128:
+#line 563 "perly.y"
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 123:
-#line 538 "perly.y"
+  case 129:
+#line 565 "perly.y"
     { (yyval.opval) = newUNOP(OP_COMPLEMENT, 0, scalar((yyvsp[0].opval)));;}
     break;
 
-  case 124:
-#line 540 "perly.y"
+  case 130:
+#line 567 "perly.y"
     { (yyval.opval) = newUNOP(OP_POSTINC, 0,
                                        mod(scalar((yyvsp[-1].opval)), OP_POSTINC)); ;}
     break;
 
-  case 125:
-#line 543 "perly.y"
+  case 131:
+#line 570 "perly.y"
     { (yyval.opval) = newUNOP(OP_POSTDEC, 0,
                                        mod(scalar((yyvsp[-1].opval)), OP_POSTDEC)); ;}
     break;
 
-  case 126:
-#line 546 "perly.y"
+  case 132:
+#line 573 "perly.y"
     { (yyval.opval) = newUNOP(OP_PREINC, 0,
                                        mod(scalar((yyvsp[0].opval)), OP_PREINC)); ;}
     break;
 
-  case 127:
-#line 549 "perly.y"
+  case 133:
+#line 576 "perly.y"
     { (yyval.opval) = newUNOP(OP_PREDEC, 0,
                                        mod(scalar((yyvsp[0].opval)), OP_PREDEC)); ;}
     break;
 
-  case 128:
-#line 556 "perly.y"
+  case 134:
+#line 583 "perly.y"
     { (yyval.opval) = newANONLIST((yyvsp[-1].opval)); ;}
     break;
 
-  case 129:
-#line 558 "perly.y"
+  case 135:
+#line 585 "perly.y"
     { (yyval.opval) = newANONLIST(Nullop); ;}
     break;
 
-  case 130:
-#line 560 "perly.y"
+  case 136:
+#line 587 "perly.y"
     { (yyval.opval) = newANONHASH((yyvsp[-2].opval)); ;}
     break;
 
-  case 131:
-#line 562 "perly.y"
+  case 137:
+#line 589 "perly.y"
     { (yyval.opval) = newANONHASH(Nullop); ;}
     break;
 
-  case 132:
-#line 564 "perly.y"
+  case 138:
+#line 591 "perly.y"
     { (yyval.opval) = newANONATTRSUB((yyvsp[-3].ival), (yyvsp[-2].opval), (yyvsp[-1].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 133:
-#line 570 "perly.y"
+  case 139:
+#line 597 "perly.y"
     { (yyval.opval) = dofile((yyvsp[0].opval), (yyvsp[-1].ival)); ;}
     break;
 
-  case 134:
-#line 572 "perly.y"
+  case 140:
+#line 599 "perly.y"
     { (yyval.opval) = newUNOP(OP_NULL, OPf_SPECIAL, scope((yyvsp[0].opval))); ;}
     break;
 
-  case 135:
-#line 574 "perly.y"
+  case 141:
+#line 601 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
@@ -726,8 +761,8 @@ case 2:
                                )),Nullop)); dep();;}
     break;
 
-  case 136:
-#line 582 "perly.y"
+  case 142:
+#line 609 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            append_elem(OP_LIST,
@@ -738,83 +773,83 @@ case 2:
                                )))); dep();;}
     break;
 
-  case 137:
-#line 591 "perly.y"
+  case 143:
+#line 618 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
                                scalar(newCVREF(0,scalar((yyvsp[-2].opval)))), Nullop)); dep();;}
     break;
 
-  case 138:
-#line 595 "perly.y"
+  case 144:
+#line 622 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
                                (yyvsp[-1].opval),
                                scalar(newCVREF(0,scalar((yyvsp[-3].opval)))))); dep();;}
     break;
 
-  case 143:
-#line 607 "perly.y"
+  case 149:
+#line 634 "perly.y"
     { (yyval.opval) = newCONDOP(0, (yyvsp[-4].opval), (yyvsp[-2].opval), (yyvsp[0].opval)); ;}
     break;
 
-  case 144:
-#line 609 "perly.y"
+  case 150:
+#line 636 "perly.y"
     { (yyval.opval) = newUNOP(OP_REFGEN, 0, mod((yyvsp[0].opval),OP_REFGEN)); ;}
     break;
 
-  case 145:
-#line 611 "perly.y"
+  case 151:
+#line 638 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 146:
-#line 613 "perly.y"
+  case 152:
+#line 640 "perly.y"
     { (yyval.opval) = localize((yyvsp[0].opval),(yyvsp[-1].ival)); ;}
     break;
 
-  case 147:
-#line 615 "perly.y"
+  case 153:
+#line 642 "perly.y"
     { (yyval.opval) = sawparens((yyvsp[-1].opval)); ;}
     break;
 
-  case 148:
-#line 617 "perly.y"
+  case 154:
+#line 644 "perly.y"
     { (yyval.opval) = sawparens(newNULLLIST()); ;}
     break;
 
-  case 149:
-#line 619 "perly.y"
+  case 155:
+#line 646 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 150:
-#line 621 "perly.y"
+  case 156:
+#line 648 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 151:
-#line 623 "perly.y"
+  case 157:
+#line 650 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 152:
-#line 625 "perly.y"
+  case 158:
+#line 652 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 153:
-#line 627 "perly.y"
+  case 159:
+#line 654 "perly.y"
     { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((yyvsp[0].opval), OP_AV2ARYLEN));;}
     break;
 
-  case 154:
-#line 629 "perly.y"
+  case 160:
+#line 656 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 155:
-#line 631 "perly.y"
+  case 161:
+#line 658 "perly.y"
     { (yyval.opval) = prepend_elem(OP_ASLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_ASLICE, 0,
@@ -822,8 +857,8 @@ case 2:
                                        ref((yyvsp[-3].opval), OP_ASLICE))); ;}
     break;
 
-  case 156:
-#line 637 "perly.y"
+  case 162:
+#line 664 "perly.y"
     { (yyval.opval) = prepend_elem(OP_HSLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_HSLICE, 0,
@@ -832,224 +867,224 @@ case 2:
                            PL_expect = XOPERATOR; ;}
     break;
 
-  case 157:
-#line 644 "perly.y"
+  case 163:
+#line 671 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 158:
-#line 646 "perly.y"
+  case 164:
+#line 673 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 159:
-#line 648 "perly.y"
+  case 165:
+#line 675 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((yyvsp[-2].opval))); ;}
     break;
 
-  case 160:
-#line 650 "perly.y"
+  case 166:
+#line 677 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, (yyvsp[-1].opval), scalar((yyvsp[-3].opval)))); ;}
     break;
 
-  case 161:
-#line 653 "perly.y"
+  case 167:
+#line 680 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, (yyvsp[0].opval), scalar((yyvsp[-1].opval)))); ;}
     break;
 
-  case 162:
-#line 656 "perly.y"
+  case 168:
+#line 683 "perly.y"
     { (yyval.opval) = newOP((yyvsp[0].ival), OPf_SPECIAL);
                            PL_hints |= HINT_BLOCK_SCOPE; ;}
     break;
 
-  case 163:
-#line 659 "perly.y"
+  case 169:
+#line 686 "perly.y"
     { (yyval.opval) = newLOOPEX((yyvsp[-1].ival),(yyvsp[0].opval)); ;}
     break;
 
-  case 164:
-#line 661 "perly.y"
+  case 170:
+#line 688 "perly.y"
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 165:
-#line 663 "perly.y"
+  case 171:
+#line 690 "perly.y"
     { (yyval.opval) = newOP((yyvsp[0].ival), 0); ;}
     break;
 
-  case 166:
-#line 665 "perly.y"
+  case 172:
+#line 692 "perly.y"
     { (yyval.opval) = newUNOP((yyvsp[-1].ival), 0, (yyvsp[0].opval)); ;}
     break;
 
-  case 167:
-#line 667 "perly.y"
+  case 173:
+#line 694 "perly.y"
     { (yyval.opval) = newUNOP((yyvsp[-1].ival), 0, (yyvsp[0].opval)); ;}
     break;
 
-  case 168:
-#line 669 "perly.y"
+  case 174:
+#line 696 "perly.y"
     { (yyval.opval) = newOP(OP_REQUIRE, (yyvsp[0].ival) ? OPf_SPECIAL : 0); ;}
     break;
 
-  case 169:
-#line 671 "perly.y"
+  case 175:
+#line 698 "perly.y"
     { (yyval.opval) = newUNOP(OP_REQUIRE, (yyvsp[-1].ival) ? OPf_SPECIAL : 0, (yyvsp[0].opval)); ;}
     break;
 
-  case 170:
-#line 673 "perly.y"
+  case 176:
+#line 700 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, (yyvsp[0].opval), scalar((yyvsp[-1].opval)))); ;}
     break;
 
-  case 171:
-#line 676 "perly.y"
+  case 177:
+#line 703 "perly.y"
     { (yyval.opval) = newOP((yyvsp[0].ival), 0); ;}
     break;
 
-  case 172:
-#line 678 "perly.y"
+  case 178:
+#line 705 "perly.y"
     { (yyval.opval) = newOP((yyvsp[-2].ival), 0); ;}
     break;
 
-  case 173:
-#line 680 "perly.y"
+  case 179:
+#line 707 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                scalar((yyvsp[0].opval))); ;}
     break;
 
-  case 174:
-#line 683 "perly.y"
+  case 180:
+#line 710 "perly.y"
     { (yyval.opval) = (yyvsp[-2].ival) == OP_NOT ? newUNOP((yyvsp[-2].ival), 0, newSVOP(OP_CONST, 0, newSViv(0)))
                                            : newOP((yyvsp[-2].ival), OPf_SPECIAL); ;}
     break;
 
-  case 175:
-#line 686 "perly.y"
+  case 181:
+#line 713 "perly.y"
     { (yyval.opval) = newUNOP((yyvsp[-3].ival), 0, (yyvsp[-1].opval)); ;}
     break;
 
-  case 176:
-#line 688 "perly.y"
+  case 182:
+#line 715 "perly.y"
     { (yyval.opval) = pmruntime((yyvsp[-3].opval), (yyvsp[-1].opval), 1); ;}
     break;
 
-  case 179:
-#line 695 "perly.y"
+  case 185:
+#line 722 "perly.y"
     { (yyval.opval) = my_attrs((yyvsp[-1].opval),(yyvsp[0].opval)); ;}
     break;
 
-  case 180:
-#line 697 "perly.y"
+  case 186:
+#line 724 "perly.y"
     { (yyval.opval) = localize((yyvsp[0].opval),(yyvsp[-1].ival)); ;}
     break;
 
-  case 181:
-#line 702 "perly.y"
+  case 187:
+#line 729 "perly.y"
     { (yyval.opval) = sawparens((yyvsp[-1].opval)); ;}
     break;
 
-  case 182:
-#line 704 "perly.y"
+  case 188:
+#line 731 "perly.y"
     { (yyval.opval) = sawparens(newNULLLIST()); ;}
     break;
 
-  case 183:
-#line 706 "perly.y"
+  case 189:
+#line 733 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 184:
-#line 708 "perly.y"
+  case 190:
+#line 735 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 185:
-#line 710 "perly.y"
+  case 191:
+#line 737 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 186:
-#line 715 "perly.y"
+  case 192:
+#line 742 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 187:
-#line 717 "perly.y"
+  case 193:
+#line 744 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 188:
-#line 721 "perly.y"
+  case 194:
+#line 748 "perly.y"
     { (yyval.opval) = Nullop; ;}
     break;
 
-  case 189:
-#line 723 "perly.y"
+  case 195:
+#line 750 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
-  case 190:
-#line 725 "perly.y"
+  case 196:
+#line 752 "perly.y"
     { (yyval.opval) = (yyvsp[-1].opval); ;}
     break;
 
-  case 191:
-#line 731 "perly.y"
+  case 197:
+#line 758 "perly.y"
     { PL_in_my = 0; (yyval.opval) = my((yyvsp[0].opval)); ;}
     break;
 
-  case 192:
-#line 735 "perly.y"
+  case 198:
+#line 762 "perly.y"
     { (yyval.opval) = newCVREF((yyvsp[-1].ival),(yyvsp[0].opval)); ;}
     break;
 
-  case 193:
-#line 739 "perly.y"
+  case 199:
+#line 766 "perly.y"
     { (yyval.opval) = newSVREF((yyvsp[0].opval)); ;}
     break;
 
-  case 194:
-#line 743 "perly.y"
+  case 200:
+#line 770 "perly.y"
     { (yyval.opval) = newAVREF((yyvsp[0].opval)); ;}
     break;
 
-  case 195:
-#line 747 "perly.y"
+  case 201:
+#line 774 "perly.y"
     { (yyval.opval) = newHVREF((yyvsp[0].opval)); ;}
     break;
 
-  case 196:
-#line 751 "perly.y"
+  case 202:
+#line 778 "perly.y"
     { (yyval.opval) = newAVREF((yyvsp[0].opval)); ;}
     break;
 
-  case 197:
-#line 755 "perly.y"
+  case 203:
+#line 782 "perly.y"
     { (yyval.opval) = newGVREF(0,(yyvsp[0].opval)); ;}
     break;
 
-  case 198:
-#line 760 "perly.y"
+  case 204:
+#line 787 "perly.y"
     { (yyval.opval) = scalar((yyvsp[0].opval)); ;}
     break;
 
-  case 199:
-#line 762 "perly.y"
+  case 205:
+#line 789 "perly.y"
     { (yyval.opval) = scalar((yyvsp[0].opval));  ;}
     break;
 
-  case 200:
-#line 764 "perly.y"
+  case 206:
+#line 791 "perly.y"
     { (yyval.opval) = scope((yyvsp[0].opval)); ;}
     break;
 
-  case 201:
-#line 767 "perly.y"
+  case 207:
+#line 794 "perly.y"
     { (yyval.opval) = (yyvsp[0].opval); ;}
     break;
 
diff --git a/perly.h b/perly.h
index cbcebc5..7c6ec99 100644 (file)
--- a/perly.h
+++ b/perly.h
      ELSIF = 278,
      CONTINUE = 279,
      FOR = 280,
-     LOOPEX = 281,
-     DOTDOT = 282,
-     FUNC0 = 283,
-     FUNC1 = 284,
-     FUNC = 285,
-     UNIOP = 286,
-     LSTOP = 287,
-     RELOP = 288,
-     EQOP = 289,
-     MULOP = 290,
-     ADDOP = 291,
-     DOLSHARP = 292,
-     DO = 293,
-     HASHBRACK = 294,
-     NOAMP = 295,
-     LOCAL = 296,
-     MY = 297,
-     MYSUB = 298,
-     REQUIRE = 299,
-     COLONATTR = 300,
-     PREC_LOW = 301,
-     DOROP = 302,
-     OROP = 303,
-     ANDOP = 304,
-     NOTOP = 305,
-     ASSIGNOP = 306,
-     DORDOR = 307,
-     OROR = 308,
-     ANDAND = 309,
-     BITOROP = 310,
-     BITANDOP = 311,
-     SHIFTOP = 312,
-     MATCHOP = 313,
-     REFGEN = 314,
-     UMINUS = 315,
-     POWOP = 316,
-     POSTDEC = 317,
-     POSTINC = 318,
-     PREDEC = 319,
-     PREINC = 320,
-     ARROW = 321
+     GIVEN = 281,
+     WHEN = 282,
+     DEFAULT = 283,
+     LOOPEX = 284,
+     DOTDOT = 285,
+     FUNC0 = 286,
+     FUNC1 = 287,
+     FUNC = 288,
+     UNIOP = 289,
+     LSTOP = 290,
+     RELOP = 291,
+     EQOP = 292,
+     MULOP = 293,
+     ADDOP = 294,
+     DOLSHARP = 295,
+     DO = 296,
+     HASHBRACK = 297,
+     NOAMP = 298,
+     LOCAL = 299,
+     MY = 300,
+     MYSUB = 301,
+     REQUIRE = 302,
+     COLONATTR = 303,
+     PREC_LOW = 304,
+     DOROP = 305,
+     OROP = 306,
+     ANDOP = 307,
+     NOTOP = 308,
+     ASSIGNOP = 309,
+     DORDOR = 310,
+     OROR = 311,
+     ANDAND = 312,
+     BITOROP = 313,
+     BITANDOP = 314,
+     SHIFTOP = 315,
+     MATCHOP = 316,
+     REFGEN = 317,
+     UMINUS = 318,
+     POWOP = 319,
+     POSTDEC = 320,
+     POSTINC = 321,
+     PREDEC = 322,
+     PREINC = 323,
+     ARROW = 324
    };
 #endif
 /* Tokens.  */
 #define ELSIF 278
 #define CONTINUE 279
 #define FOR 280
-#define LOOPEX 281
-#define DOTDOT 282
-#define FUNC0 283
-#define FUNC1 284
-#define FUNC 285
-#define UNIOP 286
-#define LSTOP 287
-#define RELOP 288
-#define EQOP 289
-#define MULOP 290
-#define ADDOP 291
-#define DOLSHARP 292
-#define DO 293
-#define HASHBRACK 294
-#define NOAMP 295
-#define LOCAL 296
-#define MY 297
-#define MYSUB 298
-#define REQUIRE 299
-#define COLONATTR 300
-#define PREC_LOW 301
-#define DOROP 302
-#define OROP 303
-#define ANDOP 304
-#define NOTOP 305
-#define ASSIGNOP 306
-#define DORDOR 307
-#define OROR 308
-#define ANDAND 309
-#define BITOROP 310
-#define BITANDOP 311
-#define SHIFTOP 312
-#define MATCHOP 313
-#define REFGEN 314
-#define UMINUS 315
-#define POWOP 316
-#define POSTDEC 317
-#define POSTINC 318
-#define PREDEC 319
-#define PREINC 320
-#define ARROW 321
+#define GIVEN 281
+#define WHEN 282
+#define DEFAULT 283
+#define LOOPEX 284
+#define DOTDOT 285
+#define FUNC0 286
+#define FUNC1 287
+#define FUNC 288
+#define UNIOP 289
+#define LSTOP 290
+#define RELOP 291
+#define EQOP 292
+#define MULOP 293
+#define ADDOP 294
+#define DOLSHARP 295
+#define DO 296
+#define HASHBRACK 297
+#define NOAMP 298
+#define LOCAL 299
+#define MY 300
+#define MYSUB 301
+#define REQUIRE 302
+#define COLONATTR 303
+#define PREC_LOW 304
+#define DOROP 305
+#define OROP 306
+#define ANDOP 307
+#define NOTOP 308
+#define ASSIGNOP 309
+#define DORDOR 310
+#define OROR 311
+#define ANDAND 312
+#define BITOROP 313
+#define BITANDOP 314
+#define SHIFTOP 315
+#define MATCHOP 316
+#define REFGEN 317
+#define UMINUS 318
+#define POWOP 319
+#define POSTDEC 320
+#define POSTINC 321
+#define PREDEC 322
+#define PREINC 323
+#define ARROW 324
 
 
 
@@ -175,7 +181,7 @@ typedef union YYSTYPE {
     GV *gvval;
 } YYSTYPE;
 /* Line 1447 of yacc.c.  */
-#line 177 "perly.h"
+#line 183 "perly.h"
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_TRIVIAL 1
index 48ac1b3..aab8ed0 100644 (file)
--- a/perly.tab
+++ b/perly.tab
@@ -1,19 +1,19 @@
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   1993
+#define YYLAST   2047
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  86
+#define YYNTOKENS  89
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  62
+#define YYNNTS  65
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  201
+#define YYNRULES  207
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  401
+#define YYNSTATES  418
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   321
+#define YYMAXUTOK   324
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -24,16 +24,16 @@ static const unsigned char yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    64,     2,     2,    82,    84,    47,     2,
-      75,    74,    85,    81,    53,    80,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    56,    78,
-       2,     2,     2,    55,    83,     2,     2,     2,     2,     2,
+       2,     2,     2,    67,     2,     2,    85,    87,    50,     2,
+      78,    77,    88,    84,    56,    83,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    59,    81,
+       2,     2,     2,    58,    86,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    76,     2,    79,     2,     2,     2,     2,     2,     2,
+       2,    79,     2,    82,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     3,     2,    77,    65,     2,     2,     2,
+       2,     2,     2,     3,     2,    80,    68,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -51,9 +51,9 @@ static const unsigned char yytranslate[] =
       16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
       26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
       36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
-      46,    48,    49,    50,    51,    52,    54,    57,    58,    59,
-      60,    61,    62,    63,    66,    67,    68,    69,    70,    71,
-      72,    73
+      46,    47,    48,    49,    51,    52,    53,    54,    55,    57,
+      60,    61,    62,    63,    64,    65,    66,    69,    70,    71,
+      72,    73,    74,    75,    76
 };
 
 #if YYDEBUG
@@ -61,129 +61,131 @@ static const unsigned char yytranslate[] =
    YYRHS.  */
 static const unsigned short int yyprhs[] =
 {
-       0,     0,     3,     6,    11,    12,    13,    18,    19,    20,
-      21,    24,    28,    31,    33,    36,    40,    42,    44,    48,
-      52,    56,    60,    64,    65,    68,    75,    83,    91,    92,
-      95,   105,   115,   126,   136,   145,   158,   162,   163,   164,
-     166,   167,   169,   171,   173,   175,   177,   178,   180,   182,
-     184,   186,   188,   190,   195,   197,   198,   205,   212,   213,
-     214,   215,   217,   218,   220,   221,   224,   226,   229,   231,
-     233,   235,   239,   240,   248,   252,   256,   260,   262,   265,
-     269,   271,   275,   281,   288,   292,   296,   302,   305,   310,
-     311,   317,   319,   321,   327,   332,   338,   343,   349,   356,
-     362,   367,   373,   378,   382,   389,   395,   399,   403,   407,
-     411,   415,   419,   423,   427,   431,   435,   439,   443,   447,
-     451,   454,   457,   460,   463,   466,   469,   472,   475,   479,
-     482,   487,   491,   497,   500,   503,   508,   514,   519,   525,
-     527,   529,   531,   533,   539,   542,   544,   547,   551,   554,
-     556,   558,   560,   562,   564,   566,   571,   577,   579,   581,
-     585,   590,   594,   596,   599,   602,   604,   607,   610,   612,
-     615,   618,   620,   624,   626,   630,   635,   640,   642,   644,
-     648,   651,   655,   658,   660,   662,   664,   665,   667,   668,
-     670,   673,   675,   678,   681,   684,   687,   690,   693,   695,
-     697,   699
+       0,     0,     3,     6,    11,    12,    13,    14,    19,    20,
+      21,    22,    25,    29,    32,    34,    36,    39,    42,    46,
+      48,    50,    54,    58,    62,    66,    70,    71,    74,    81,
+      89,    97,   104,   107,   108,   111,   121,   131,   142,   152,
+     161,   174,   178,   187,   188,   189,   191,   192,   194,   196,
+     198,   200,   202,   203,   205,   207,   209,   211,   213,   215,
+     220,   222,   223,   230,   237,   238,   239,   240,   242,   243,
+     245,   246,   249,   251,   254,   256,   258,   260,   264,   265,
+     273,   277,   281,   285,   287,   290,   294,   296,   300,   306,
+     313,   317,   321,   327,   330,   335,   336,   342,   344,   346,
+     352,   357,   363,   368,   374,   381,   387,   392,   398,   403,
+     407,   414,   420,   424,   428,   432,   436,   440,   444,   448,
+     452,   456,   460,   464,   468,   472,   476,   479,   482,   485,
+     488,   491,   494,   497,   500,   504,   507,   512,   516,   522,
+     525,   528,   533,   539,   544,   550,   552,   554,   556,   558,
+     564,   567,   569,   572,   576,   579,   581,   583,   585,   587,
+     589,   591,   596,   602,   604,   606,   610,   615,   619,   621,
+     624,   627,   629,   632,   635,   637,   640,   643,   645,   649,
+     651,   655,   660,   665,   667,   669,   673,   676,   680,   683,
+     685,   687,   689,   690,   692,   693,   695,   698,   700,   703,
+     706,   709,   712,   715,   718,   720,   722,   724
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const short int yyrhs[] =
 {
-      87,     0,    -1,    90,    94,    -1,     3,    89,    94,    77,
-      -1,    -1,    -1,     3,    92,    94,    77,    -1,    -1,    -1,
-      -1,    94,   109,    -1,    94,    93,    95,    -1,   108,    98,
-      -1,   100,    -1,   108,    78,    -1,   108,    96,    78,    -1,
-       1,    -1,   125,    -1,   125,    21,   125,    -1,   125,    22,
-     125,    -1,   125,    19,   125,    -1,   125,    20,   104,    -1,
-     125,    26,   125,    -1,    -1,    23,    91,    -1,    24,    75,
-     105,    74,    91,    97,    -1,    21,    75,    89,   105,    74,
-      91,    97,    -1,    22,    75,    89,   107,    74,    91,    97,
-      -1,    -1,    25,    88,    -1,   108,    19,    75,    89,   103,
-      74,   101,    91,    99,    -1,   108,    20,    75,    89,   104,
-      74,   101,    91,    99,    -1,   108,    26,    43,    89,   140,
-      75,   105,    74,    91,    99,    -1,   108,    26,   142,    75,
-      89,   105,    74,    91,    99,    -1,   108,    26,    75,    89,
-     105,    74,    91,    99,    -1,   108,    26,    75,    89,   106,
-      78,   103,    78,   101,   106,    74,    91,    -1,   108,    88,
-      99,    -1,    -1,    -1,    96,    -1,    -1,   125,    -1,   125,
-      -1,   125,    -1,   102,    -1,   104,    -1,    -1,    13,    -1,
-     110,    -1,   113,    -1,   112,    -1,   122,    -1,   123,    -1,
-      14,   116,   111,    88,    -1,     4,    -1,    -1,    44,   114,
-     117,   118,   119,   121,    -1,    15,   114,   117,   118,   119,
-     121,    -1,    -1,    -1,    -1,     4,    -1,    -1,     7,    -1,
-      -1,    46,     7,    -1,    46,    -1,    46,     7,    -1,    46,
-      -1,    88,    -1,    78,    -1,    17,     4,    78,    -1,    -1,
-      18,   114,   124,     4,     4,   138,    78,    -1,   125,    51,
-     125,    -1,   125,    50,   125,    -1,   125,    49,   125,    -1,
-     126,    -1,   126,    53,    -1,   126,    53,   135,    -1,   135,
-      -1,    33,   147,   126,    -1,    31,    75,   147,   125,    74,
-      -1,   135,    73,   129,    75,   139,    74,    -1,   135,    73,
-     129,    -1,     5,   147,   138,    -1,     6,   147,    75,   139,
-      74,    -1,    33,   138,    -1,    31,    75,   139,    74,    -1,
-      -1,    12,   115,    88,   128,   138,    -1,     5,    -1,   142,
-      -1,   146,     3,   125,    78,    77,    -1,   142,    76,   125,
-      79,    -1,   135,    73,    76,   125,    79,    -1,   130,    76,
-     125,    79,    -1,   142,     3,   125,    78,    77,    -1,   135,
-      73,     3,   125,    78,    77,    -1,   130,     3,   125,    78,
-      77,    -1,   135,    73,    75,    74,    -1,   135,    73,    75,
-     125,    74,    -1,   130,    75,   125,    74,    -1,   130,    75,
-      74,    -1,    75,   125,    74,    76,   125,    79,    -1,    75,
-      74,    76,   125,    79,    -1,   135,    54,   135,    -1,   135,
-      68,   135,    -1,   135,    36,   135,    -1,   135,    37,   135,
-      -1,   135,    62,   135,    -1,   135,    34,   135,    -1,   135,
-      35,   135,    -1,   135,    61,   135,    -1,   135,    60,   135,
-      -1,   135,    28,   135,    -1,   135,    59,   135,    -1,   135,
-      58,   135,    -1,   135,    57,   135,    -1,   135,    63,   135,
-      -1,    80,   135,    -1,    81,   135,    -1,    64,   135,    -1,
-      65,   135,    -1,   135,    70,    -1,   135,    69,    -1,    72,
-     135,    -1,    71,   135,    -1,    76,   125,    79,    -1,    76,
-      79,    -1,    40,   125,    78,    77,    -1,    40,    78,    77,
-      -1,    16,   115,   118,   119,    88,    -1,    39,   135,    -1,
-      39,    88,    -1,    39,     4,    75,    74,    -1,    39,     4,
-      75,   125,    74,    -1,    39,   142,    75,    74,    -1,    39,
-     142,    75,   125,    74,    -1,   131,    -1,   132,    -1,   133,
-      -1,   134,    -1,   135,    55,   135,    56,   135,    -1,    66,
-     135,    -1,   136,    -1,    42,   135,    -1,    75,   125,    74,
-      -1,    75,    74,    -1,   142,    -1,   146,    -1,   144,    -1,
-     143,    -1,   145,    -1,   130,    -1,   143,    76,   125,    79,
-      -1,   143,     3,   125,    78,    77,    -1,     7,    -1,   141,
-      -1,   141,    75,    74,    -1,   141,    75,   125,    74,    -1,
-      41,     4,   138,    -1,    27,    -1,    27,   135,    -1,    52,
-     126,    -1,    32,    -1,    32,    88,    -1,    32,   135,    -1,
-      45,    -1,    45,   135,    -1,    11,   135,    -1,    29,    -1,
-      29,    75,    74,    -1,    10,    -1,    30,    75,    74,    -1,
-      30,    75,   125,    74,    -1,     8,    75,   126,    74,    -1,
-       4,    -1,   127,    -1,    43,   137,   120,    -1,    43,   137,
-      -1,    75,   125,    74,    -1,    75,    74,    -1,   142,    -1,
-     144,    -1,   143,    -1,    -1,   126,    -1,    -1,   125,    -1,
-     125,    53,    -1,   142,    -1,    47,   147,    -1,    82,   147,
-      -1,    83,   147,    -1,    84,   147,    -1,    38,   147,    -1,
-      85,   147,    -1,     4,    -1,   142,    -1,    88,    -1,     9,
-      -1
+      90,     0,    -1,    94,    98,    -1,     3,    92,    98,    80,
+      -1,    -1,    -1,    -1,     3,    96,    98,    80,    -1,    -1,
+      -1,    -1,    98,   115,    -1,    98,    97,    99,    -1,   114,
+     102,    -1,   105,    -1,   106,    -1,   114,   103,    -1,   114,
+      81,    -1,   114,   100,    81,    -1,     1,    -1,   131,    -1,
+     131,    21,   131,    -1,   131,    22,   131,    -1,   131,    19,
+     131,    -1,   131,    20,   110,    -1,   131,    26,   131,    -1,
+      -1,    23,    95,    -1,    24,    78,   111,    77,    95,   101,
+      -1,    21,    78,    92,   111,    77,    95,   101,    -1,    22,
+      78,    92,   113,    77,    95,   101,    -1,    28,    78,    92,
+     111,    77,    95,    -1,    29,    91,    -1,    -1,    25,    91,
+      -1,   114,    19,    78,    92,   109,    77,   107,    95,   104,
+      -1,   114,    20,    78,    92,   110,    77,   107,    95,   104,
+      -1,   114,    26,    46,    92,   146,    78,   111,    77,    95,
+     104,    -1,   114,    26,   148,    78,    92,   111,    77,    95,
+     104,    -1,   114,    26,    78,    92,   111,    77,    95,   104,
+      -1,   114,    26,    78,    92,   112,    81,   109,    81,   107,
+     112,    77,    95,    -1,   114,    91,   104,    -1,   114,    27,
+      78,    92,    93,   111,    77,    95,    -1,    -1,    -1,   100,
+      -1,    -1,   131,    -1,   131,    -1,   131,    -1,   108,    -1,
+     110,    -1,    -1,    13,    -1,   116,    -1,   119,    -1,   118,
+      -1,   128,    -1,   129,    -1,    14,   122,   117,    91,    -1,
+       4,    -1,    -1,    47,   120,   123,   124,   125,   127,    -1,
+      15,   120,   123,   124,   125,   127,    -1,    -1,    -1,    -1,
+       4,    -1,    -1,     7,    -1,    -1,    49,     7,    -1,    49,
+      -1,    49,     7,    -1,    49,    -1,    91,    -1,    81,    -1,
+      17,     4,    81,    -1,    -1,    18,   120,   130,     4,     4,
+     144,    81,    -1,   131,    54,   131,    -1,   131,    53,   131,
+      -1,   131,    52,   131,    -1,   132,    -1,   132,    56,    -1,
+     132,    56,   141,    -1,   141,    -1,    36,   153,   132,    -1,
+      34,    78,   153,   131,    77,    -1,   141,    76,   135,    78,
+     145,    77,    -1,   141,    76,   135,    -1,     5,   153,   144,
+      -1,     6,   153,    78,   145,    77,    -1,    36,   144,    -1,
+      34,    78,   145,    77,    -1,    -1,    12,   121,    91,   134,
+     144,    -1,     5,    -1,   148,    -1,   152,     3,   131,    81,
+      80,    -1,   148,    79,   131,    82,    -1,   141,    76,    79,
+     131,    82,    -1,   136,    79,   131,    82,    -1,   148,     3,
+     131,    81,    80,    -1,   141,    76,     3,   131,    81,    80,
+      -1,   136,     3,   131,    81,    80,    -1,   141,    76,    78,
+      77,    -1,   141,    76,    78,   131,    77,    -1,   136,    78,
+     131,    77,    -1,   136,    78,    77,    -1,    78,   131,    77,
+      79,   131,    82,    -1,    78,    77,    79,   131,    82,    -1,
+     141,    57,   141,    -1,   141,    71,   141,    -1,   141,    39,
+     141,    -1,   141,    40,   141,    -1,   141,    65,   141,    -1,
+     141,    37,   141,    -1,   141,    38,   141,    -1,   141,    64,
+     141,    -1,   141,    63,   141,    -1,   141,    31,   141,    -1,
+     141,    62,   141,    -1,   141,    61,   141,    -1,   141,    60,
+     141,    -1,   141,    66,   141,    -1,    83,   141,    -1,    84,
+     141,    -1,    67,   141,    -1,    68,   141,    -1,   141,    73,
+      -1,   141,    72,    -1,    75,   141,    -1,    74,   141,    -1,
+      79,   131,    82,    -1,    79,    82,    -1,    43,   131,    81,
+      80,    -1,    43,    81,    80,    -1,    16,   121,   124,   125,
+      91,    -1,    42,   141,    -1,    42,    91,    -1,    42,     4,
+      78,    77,    -1,    42,     4,    78,   131,    77,    -1,    42,
+     148,    78,    77,    -1,    42,   148,    78,   131,    77,    -1,
+     137,    -1,   138,    -1,   139,    -1,   140,    -1,   141,    58,
+     141,    59,   141,    -1,    69,   141,    -1,   142,    -1,    45,
+     141,    -1,    78,   131,    77,    -1,    78,    77,    -1,   148,
+      -1,   152,    -1,   150,    -1,   149,    -1,   151,    -1,   136,
+      -1,   149,    79,   131,    82,    -1,   149,     3,   131,    81,
+      80,    -1,     7,    -1,   147,    -1,   147,    78,    77,    -1,
+     147,    78,   131,    77,    -1,    44,     4,   144,    -1,    30,
+      -1,    30,   141,    -1,    55,   132,    -1,    35,    -1,    35,
+      91,    -1,    35,   141,    -1,    48,    -1,    48,   141,    -1,
+      11,   141,    -1,    32,    -1,    32,    78,    77,    -1,    10,
+      -1,    33,    78,    77,    -1,    33,    78,   131,    77,    -1,
+       8,    78,   132,    77,    -1,     4,    -1,   133,    -1,    46,
+     143,   126,    -1,    46,   143,    -1,    78,   131,    77,    -1,
+      78,    77,    -1,   148,    -1,   150,    -1,   149,    -1,    -1,
+     132,    -1,    -1,   131,    -1,   131,    56,    -1,   148,    -1,
+      50,   153,    -1,    85,   153,    -1,    86,   153,    -1,    87,
+     153,    -1,    41,   153,    -1,    88,   153,    -1,     4,    -1,
+     148,    -1,    91,    -1,     9,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const unsigned short int yyrline[] =
 {
-       0,    96,    96,   102,   109,   113,   119,   126,   130,   134,
-     135,   137,   146,   148,   149,   158,   164,   166,   168,   170,
-     172,   174,   176,   183,   184,   186,   193,   197,   205,   206,
-     211,   217,   223,   226,   230,   233,   250,   258,   264,   265,
-     270,   271,   275,   280,   284,   288,   294,   295,   299,   301,
-     303,   305,   307,   311,   315,   316,   320,   325,   330,   334,
-     338,   342,   351,   352,   357,   358,   360,   365,   367,   372,
-     373,   376,   381,   380,   387,   389,   391,   393,   397,   399,
-     401,   405,   408,   411,   416,   420,   425,   430,   432,   435,
-     434,   443,   444,   448,   453,   455,   459,   463,   466,   471,
-     476,   479,   484,   488,   491,   493,   498,   500,   502,   506,
-     508,   510,   512,   514,   516,   518,   520,   522,   524,   526,
-     531,   533,   535,   537,   539,   542,   545,   548,   555,   557,
-     559,   561,   563,   569,   571,   573,   581,   590,   594,   602,
-     603,   604,   605,   606,   608,   610,   612,   614,   616,   618,
-     620,   622,   624,   626,   628,   630,   636,   643,   645,   647,
-     649,   652,   655,   658,   660,   662,   664,   666,   668,   670,
-     672,   675,   677,   679,   682,   685,   687,   689,   690,   694,
-     696,   701,   703,   705,   707,   709,   714,   716,   721,   722,
-     724,   730,   734,   738,   742,   746,   750,   754,   759,   761,
-     763,   766
+       0,    98,    98,   104,   111,   115,   119,   125,   132,   136,
+     140,   141,   143,   152,   154,   155,   157,   159,   168,   174,
+     176,   178,   180,   182,   184,   186,   193,   194,   196,   203,
+     207,   214,   217,   223,   224,   229,   235,   241,   244,   248,
+     251,   268,   275,   285,   291,   292,   297,   298,   302,   307,
+     311,   315,   321,   322,   326,   328,   330,   332,   334,   338,
+     342,   343,   347,   352,   357,   361,   365,   369,   378,   379,
+     384,   385,   387,   392,   394,   399,   400,   403,   408,   407,
+     414,   416,   418,   420,   424,   426,   428,   432,   435,   438,
+     443,   447,   452,   457,   459,   462,   461,   470,   471,   475,
+     480,   482,   486,   490,   493,   498,   503,   506,   511,   515,
+     518,   520,   525,   527,   529,   533,   535,   537,   539,   541,
+     543,   545,   547,   549,   551,   553,   558,   560,   562,   564,
+     566,   569,   572,   575,   582,   584,   586,   588,   590,   596,
+     598,   600,   608,   617,   621,   629,   630,   631,   632,   633,
+     635,   637,   639,   641,   643,   645,   647,   649,   651,   653,
+     655,   657,   663,   670,   672,   674,   676,   679,   682,   685,
+     687,   689,   691,   693,   695,   697,   699,   702,   704,   706,
+     709,   712,   714,   716,   717,   721,   723,   728,   730,   732,
+     734,   736,   741,   743,   748,   749,   751,   757,   761,   765,
+     769,   773,   777,   781,   786,   788,   790,   793
 };
 #endif
 
@@ -195,24 +197,25 @@ static const char *const yytname[] =
   "$end", "error", "$undefined", "'{'", "WORD", "METHOD", "FUNCMETH",
   "THING", "PMFUNC", "PRIVATEREF", "FUNC0SUB", "UNIOPSUB", "LSTOPSUB",
   "LABEL", "FORMAT", "SUB", "ANONSUB", "PACKAGE", "USE", "WHILE", "UNTIL",
-  "IF", "UNLESS", "ELSE", "ELSIF", "CONTINUE", "FOR", "LOOPEX", "DOTDOT",
-  "FUNC0", "FUNC1", "FUNC", "UNIOP", "LSTOP", "RELOP", "EQOP", "MULOP",
-  "ADDOP", "DOLSHARP", "DO", "HASHBRACK", "NOAMP", "LOCAL", "MY", "MYSUB",
-  "REQUIRE", "COLONATTR", "'&'", "PREC_LOW", "DOROP", "OROP", "ANDOP",
-  "NOTOP", "','", "ASSIGNOP", "'?'", "':'", "DORDOR", "OROR", "ANDAND",
-  "BITOROP", "BITANDOP", "SHIFTOP", "MATCHOP", "'!'", "'~'", "REFGEN",
-  "UMINUS", "POWOP", "POSTDEC", "POSTINC", "PREDEC", "PREINC", "ARROW",
-  "')'", "'('", "'['", "'}'", "';'", "']'", "'-'", "'+'", "'$'", "'@'",
-  "'%'", "'*'", "$accept", "prog", "block", "remember", "progstart",
-  "mblock", "mremember", "savescope", "lineseq", "line", "sideff", "else",
-  "cond", "cont", "loop", "mintro", "nexpr", "texpr", "iexpr", "mexpr",
-  "mnexpr", "miexpr", "label", "decl", "format", "formname", "mysubrout",
-  "subrout", "startsub", "startanonsub", "startformsub", "subname",
-  "proto", "subattrlist", "myattrlist", "subbody", "package", "use", "@1",
-  "expr", "argexpr", "listop", "@2", "method", "subscripted", "termbinop",
-  "termunop", "anonymous", "termdo", "term", "myattrterm", "myterm",
-  "listexpr", "listexprcom", "my_scalar", "amper", "scalar", "ary", "hsh",
-  "arylen", "star", "indirob", 0
+  "IF", "UNLESS", "ELSE", "ELSIF", "CONTINUE", "FOR", "GIVEN", "WHEN",
+  "DEFAULT", "LOOPEX", "DOTDOT", "FUNC0", "FUNC1", "FUNC", "UNIOP",
+  "LSTOP", "RELOP", "EQOP", "MULOP", "ADDOP", "DOLSHARP", "DO",
+  "HASHBRACK", "NOAMP", "LOCAL", "MY", "MYSUB", "REQUIRE", "COLONATTR",
+  "'&'", "PREC_LOW", "DOROP", "OROP", "ANDOP", "NOTOP", "','", "ASSIGNOP",
+  "'?'", "':'", "DORDOR", "OROR", "ANDAND", "BITOROP", "BITANDOP",
+  "SHIFTOP", "MATCHOP", "'!'", "'~'", "REFGEN", "UMINUS", "POWOP",
+  "POSTDEC", "POSTINC", "PREDEC", "PREINC", "ARROW", "')'", "'('", "'['",
+  "'}'", "';'", "']'", "'-'", "'+'", "'$'", "'@'", "'%'", "'*'", "$accept",
+  "prog", "block", "remember", "mydefsv", "progstart", "mblock",
+  "mremember", "savescope", "lineseq", "line", "sideff", "else", "cond",
+  "case", "cont", "loop", "switch", "mintro", "nexpr", "texpr", "iexpr",
+  "mexpr", "mnexpr", "miexpr", "label", "decl", "format", "formname",
+  "mysubrout", "subrout", "startsub", "startanonsub", "startformsub",
+  "subname", "proto", "subattrlist", "myattrlist", "subbody", "package",
+  "use", "@1", "expr", "argexpr", "listop", "@2", "method", "subscripted",
+  "termbinop", "termunop", "anonymous", "termdo", "term", "myattrterm",
+  "myterm", "listexpr", "listexprcom", "my_scalar", "amper", "scalar",
+  "ary", "hsh", "arylen", "star", "indirob", 0
 };
 #endif
 
@@ -225,64 +228,64 @@ static const unsigned short int yytoknum[] =
      264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
      274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
      284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
-     294,   295,   296,   297,   298,   299,   300,    38,   301,   302,
-     303,   304,   305,    44,   306,    63,    58,   307,   308,   309,
-     310,   311,   312,   313,    33,   126,   314,   315,   316,   317,
-     318,   319,   320,   321,    41,    40,    91,   125,    59,    93,
-      45,    43,    36,    64,    37,    42
+     294,   295,   296,   297,   298,   299,   300,   301,   302,   303,
+      38,   304,   305,   306,   307,   308,    44,   309,    63,    58,
+     310,   311,   312,   313,   314,   315,   316,    33,   126,   317,
+     318,   319,   320,   321,   322,   323,   324,    41,    40,    91,
+     125,    59,    93,    45,    43,    36,    64,    37,    42
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 {
-       0,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      94,    94,    95,    95,    95,    95,    96,    96,    96,    96,
-      96,    96,    96,    97,    97,    97,    98,    98,    99,    99,
-     100,   100,   100,   100,   100,   100,   100,   101,   102,   102,
-     103,   103,   104,   105,   106,   107,   108,   108,   109,   109,
-     109,   109,   109,   110,   111,   111,   112,   113,   114,   115,
-     116,   117,   118,   118,   119,   119,   119,   120,   120,   121,
-     121,   122,   124,   123,   125,   125,   125,   125,   126,   126,
-     126,   127,   127,   127,   127,   127,   127,   127,   127,   128,
-     127,   129,   129,   130,   130,   130,   130,   130,   130,   130,
-     130,   130,   130,   130,   130,   130,   131,   131,   131,   131,
-     131,   131,   131,   131,   131,   131,   131,   131,   131,   131,
-     132,   132,   132,   132,   132,   132,   132,   132,   133,   133,
-     133,   133,   133,   134,   134,   134,   134,   134,   134,   135,
-     135,   135,   135,   135,   135,   135,   135,   135,   135,   135,
-     135,   135,   135,   135,   135,   135,   135,   135,   135,   135,
-     135,   135,   135,   135,   135,   135,   135,   135,   135,   135,
-     135,   135,   135,   135,   135,   135,   135,   135,   135,   136,
-     136,   137,   137,   137,   137,   137,   138,   138,   139,   139,
-     139,   140,   141,   142,   143,   144,   145,   146,   147,   147,
-     147,   147
+       0,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    98,    98,    99,    99,    99,    99,    99,    99,   100,
+     100,   100,   100,   100,   100,   100,   101,   101,   101,   102,
+     102,   103,   103,   104,   104,   105,   105,   105,   105,   105,
+     105,   105,   106,   107,   108,   108,   109,   109,   110,   111,
+     112,   113,   114,   114,   115,   115,   115,   115,   115,   116,
+     117,   117,   118,   119,   120,   121,   122,   123,   124,   124,
+     125,   125,   125,   126,   126,   127,   127,   128,   130,   129,
+     131,   131,   131,   131,   132,   132,   132,   133,   133,   133,
+     133,   133,   133,   133,   133,   134,   133,   135,   135,   136,
+     136,   136,   136,   136,   136,   136,   136,   136,   136,   136,
+     136,   136,   137,   137,   137,   137,   137,   137,   137,   137,
+     137,   137,   137,   137,   137,   137,   138,   138,   138,   138,
+     138,   138,   138,   138,   139,   139,   139,   139,   139,   140,
+     140,   140,   140,   140,   140,   141,   141,   141,   141,   141,
+     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
+     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
+     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
+     141,   141,   141,   141,   141,   142,   142,   143,   143,   143,
+     143,   143,   144,   144,   145,   145,   145,   146,   147,   148,
+     149,   150,   151,   152,   153,   153,   153,   153
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const unsigned char yyr2[] =
 {
-       0,     2,     2,     4,     0,     0,     4,     0,     0,     0,
-       2,     3,     2,     1,     2,     3,     1,     1,     3,     3,
-       3,     3,     3,     0,     2,     6,     7,     7,     0,     2,
-       9,     9,    10,     9,     8,    12,     3,     0,     0,     1,
-       0,     1,     1,     1,     1,     1,     0,     1,     1,     1,
-       1,     1,     1,     4,     1,     0,     6,     6,     0,     0,
-       0,     1,     0,     1,     0,     2,     1,     2,     1,     1,
-       1,     3,     0,     7,     3,     3,     3,     1,     2,     3,
-       1,     3,     5,     6,     3,     3,     5,     2,     4,     0,
-       5,     1,     1,     5,     4,     5,     4,     5,     6,     5,
-       4,     5,     4,     3,     6,     5,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       2,     2,     2,     2,     2,     2,     2,     2,     3,     2,
-       4,     3,     5,     2,     2,     4,     5,     4,     5,     1,
-       1,     1,     1,     5,     2,     1,     2,     3,     2,     1,
-       1,     1,     1,     1,     1,     4,     5,     1,     1,     3,
-       4,     3,     1,     2,     2,     1,     2,     2,     1,     2,
-       2,     1,     3,     1,     3,     4,     4,     1,     1,     3,
-       2,     3,     2,     1,     1,     1,     0,     1,     0,     1,
-       2,     1,     2,     2,     2,     2,     2,     2,     1,     1,
-       1,     1
+       0,     2,     2,     4,     0,     0,     0,     4,     0,     0,
+       0,     2,     3,     2,     1,     1,     2,     2,     3,     1,
+       1,     3,     3,     3,     3,     3,     0,     2,     6,     7,
+       7,     6,     2,     0,     2,     9,     9,    10,     9,     8,
+      12,     3,     8,     0,     0,     1,     0,     1,     1,     1,
+       1,     1,     0,     1,     1,     1,     1,     1,     1,     4,
+       1,     0,     6,     6,     0,     0,     0,     1,     0,     1,
+       0,     2,     1,     2,     1,     1,     1,     3,     0,     7,
+       3,     3,     3,     1,     2,     3,     1,     3,     5,     6,
+       3,     3,     5,     2,     4,     0,     5,     1,     1,     5,
+       4,     5,     4,     5,     6,     5,     4,     5,     4,     3,
+       6,     5,     3,     3,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,     3,     3,     2,     2,     2,     2,
+       2,     2,     2,     2,     3,     2,     4,     3,     5,     2,
+       2,     4,     5,     4,     5,     1,     1,     1,     1,     5,
+       2,     1,     2,     3,     2,     1,     1,     1,     1,     1,
+       1,     4,     5,     1,     1,     3,     4,     3,     1,     2,
+       2,     1,     2,     2,     1,     2,     2,     1,     3,     1,
+       3,     4,     4,     1,     1,     3,     2,     3,     2,     1,
+       1,     1,     0,     1,     0,     1,     2,     1,     2,     2,
+       2,     2,     2,     2,     1,     1,     1,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -290,577 +293,590 @@ static const unsigned char yyr2[] =
    means the default is an error.  */
 static const unsigned char yydefact[] =
 {
-       5,     0,     9,     1,     8,    60,    58,     0,    58,    58,
-      46,    10,    48,    50,    49,    51,    52,    55,     0,     0,
-      72,     0,    47,    11,    13,     0,    54,     0,    61,    62,
-      71,     0,    62,    16,     4,   177,     0,     0,   157,     0,
-     173,     0,    59,    59,     0,     0,     0,     0,     0,   162,
-     171,     0,     0,   165,   186,     0,     0,     0,     0,     0,
-       0,   168,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    14,     0,     0,     0,     0,     0,     0,    28,     0,
-      12,    17,    77,   178,   154,   139,   140,   141,   142,    80,
-     145,   158,   149,   152,   151,   153,   150,    53,    63,    64,
-       0,    64,     9,   198,   201,   200,   199,   186,     0,     0,
-     170,     0,    62,     4,     4,     4,     4,     4,     4,     0,
-     163,     0,     0,   188,   166,   167,   198,   187,    87,   199,
-       0,   196,   177,   134,   133,   149,     0,     0,   186,   146,
-       0,   180,   183,   185,   184,   169,   192,   164,   122,   123,
-     144,   127,   126,   148,     0,   129,     0,   120,   121,   193,
-     194,   195,   197,     0,    36,    15,     0,     0,     0,     0,
-       0,     0,     0,     0,    78,     0,     0,     0,     0,     0,
+       6,     0,    10,     1,     9,    66,    64,     0,    64,    64,
+      52,    11,    54,    56,    55,    57,    58,    61,     0,     0,
+      78,     0,    53,    12,    14,    15,     0,    60,     0,    67,
+      68,    77,     0,    68,    19,     4,   183,     0,     0,   163,
+       0,   179,     0,    65,    65,     0,     0,     0,     0,     0,
+       0,     0,     0,   168,   177,     0,     0,   171,   192,     0,
+       0,     0,     0,     0,     0,   174,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    17,     0,     0,     0,     0,
+       0,     0,    33,     0,    13,    16,    20,    83,   184,   160,
+     145,   146,   147,   148,    86,   151,   164,   155,   158,   157,
+     159,   156,    59,    69,    70,     0,    70,    10,   204,   207,
+     206,   205,   192,     0,     0,   176,     0,    68,     4,     4,
+       4,     4,     4,     4,     0,     4,     4,    32,   169,     0,
+       0,   194,   172,   173,   204,   193,    93,   205,     0,   202,
+     183,   140,   139,   155,     0,     0,   192,   152,     0,   186,
+     189,   191,   190,   175,   198,   170,   128,   129,   150,   133,
+     132,   154,     0,   135,     0,   126,   127,   199,   200,   201,
+     203,     0,    41,    18,     0,     0,     0,     0,     0,     0,
+       0,     0,    84,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   125,   124,     0,     0,     0,     0,     0,
-       0,     0,    66,     0,   186,     0,     8,    85,   188,     0,
-      89,    64,    40,     0,     0,     0,     0,     0,     4,   172,
-     174,     0,   189,     0,     0,    81,     0,     0,   131,     0,
-     161,   182,     0,    68,   179,     0,   147,   128,    29,    20,
-      21,    42,    18,    19,    22,    76,    75,    74,    79,     0,
-     103,     0,     0,   115,   111,   112,   108,   109,   106,     0,
-     118,   117,   116,   114,   113,   110,   119,   107,     0,    91,
-       0,     0,    84,    92,   159,     0,     0,     0,     0,     0,
-       0,    65,    70,    69,    57,     0,    56,     3,     0,   176,
-     186,     0,     0,    41,     0,     0,    43,    45,     0,     0,
-     191,    39,    44,     0,     0,    17,     0,   175,   190,    88,
-       0,   135,     0,   137,     0,   130,   181,    67,     0,     0,
-       0,   102,    96,     0,     0,   100,     0,     0,   188,   160,
-       0,    94,     0,   155,     0,    73,    86,    90,   132,    37,
-      37,     0,     0,     0,     0,    40,     0,    82,   136,   138,
-     105,     0,    99,   143,     0,   101,    95,     0,    97,   156,
-      93,     0,     0,     7,    23,    23,     0,    28,     0,     0,
-     104,    98,    83,    28,    28,     9,     0,     0,    26,    27,
-       0,    34,    37,    28,    30,    31,     8,    24,     0,    28,
-       0,    33,     6,     0,    32,     0,     0,     0,    23,    35,
-      25
+       0,   131,   130,     0,     0,     0,     0,     0,     0,     0,
+      72,     0,   192,     0,     9,    91,   194,     0,    95,    70,
+      46,     0,     0,     0,     0,     0,     4,     5,     0,   178,
+     180,     0,   195,     0,     0,    87,     0,     0,   137,     0,
+     167,   188,     0,    74,   185,     0,   153,   134,    34,    23,
+      24,    48,    21,    22,    25,    82,    81,    80,    85,     0,
+     109,     0,     0,   121,   117,   118,   114,   115,   112,     0,
+     124,   123,   122,   120,   119,   116,   125,   113,     0,    97,
+       0,     0,    90,    98,   165,     0,     0,     0,     0,     0,
+       0,    71,    76,    75,    63,     0,    62,     3,     0,   182,
+     192,     0,     0,    47,     0,     0,    49,    51,     0,     0,
+     197,    45,    50,     0,     0,    20,     0,     0,     0,   181,
+     196,    94,     0,   141,     0,   143,     0,   136,   187,    73,
+       0,     0,     0,   108,   102,     0,     0,   106,     0,     0,
+     194,   166,     0,   100,     0,   161,     0,    79,    92,    96,
+     138,    43,    43,     0,     0,     0,     0,    46,     0,     0,
+       0,    88,   142,   144,   111,     0,   105,   149,     0,   107,
+     101,     0,   103,   162,    99,     0,     0,     8,    26,    26,
+       0,    33,     0,     0,     0,    31,   110,   104,    89,    33,
+      33,    10,     0,     0,    29,    30,     0,    39,    43,    33,
+      42,    35,    36,     9,    27,     0,    33,     0,    38,     7,
+       0,    37,     0,     0,     0,    26,    40,    28
 };
 
 /* YYDEFGOTO[NTERM-NUM]. */
 static const short int yydefgoto[] =
 {
-      -1,     1,   105,   102,     2,   364,   375,    10,     4,    23,
-     301,   378,    80,   164,    24,   361,   302,   292,   240,   295,
-     304,   298,    25,    11,    12,    27,    13,    14,    18,   111,
-      17,    29,    99,   203,   234,   284,    15,    16,    31,   296,
-      82,    83,   290,   272,    84,    85,    86,    87,    88,    89,
-      90,   141,   128,   223,   299,    91,    92,    93,    94,    95,
-      96,   107
+      -1,     1,   110,   107,   317,     2,   378,   391,    10,     4,
+      23,   311,   394,    84,    85,   172,    24,    25,   375,   312,
+     302,   250,   305,   314,   308,    26,    11,    12,    28,    13,
+      14,    18,   116,    17,    30,   104,   211,   244,   294,    15,
+      16,    32,   306,    87,    88,   300,   282,    89,    90,    91,
+      92,    93,    94,    95,   149,   136,   233,   309,    96,    97,
+      98,    99,   100,   101,   112
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -352
+#define YYPACT_NINF -362
 static const short int yypact[] =
 {
-    -352,    27,  -352,  -352,   121,  -352,  -352,    15,  -352,  -352,
-      18,  -352,  -352,  -352,  -352,  -352,  -352,    31,    39,   -28,
-    -352,    39,  -352,  -352,  -352,   321,  -352,    64,  -352,    68,
-    -352,   102,    68,  -352,  -352,  -352,     7,     7,  -352,     8,
-    -352,  1642,  -352,  -352,    36,    49,    62,    65,   -34,  1642,
-      74,    80,    89,   657,   574,     7,   740,   822,   119,  1642,
-      79,  1642,     7,  1642,  1642,  1642,  1642,  1642,  1642,   904,
-     986,  -352,  1642,  1642,     7,     7,     7,     7,   104,    88,
-    -352,   821,   117,  -352,    34,  -352,  -352,  -352,  -352,  1860,
-    -352,   106,    10,    14,  -352,  -352,   179,  -352,  -352,   138,
-     181,   138,  -352,  -352,  -352,  -352,  -352,  1642,   114,  1642,
-     308,    64,    68,  -352,  -352,  -352,  -352,  -352,  -352,   120,
-    1860,   126,  1068,   574,  -352,   308,  1770,   117,  -352,  1709,
-    1642,  -352,   128,  -352,   308,    52,   135,   108,  1642,   308,
-    1150,   148,  -352,  -352,  -352,   308,  -352,   117,   266,   266,
-     266,    -9,    -9,   161,   -21,  -352,   118,   266,   266,  -352,
-    -352,  -352,  -352,    64,  -352,  -352,  1642,  1642,  1642,  1642,
-    1642,  1642,  1642,  1642,  1642,  1642,  1232,  1642,  1642,  1642,
-    1642,  1642,  1642,  1642,  1642,  1642,  1642,  1642,  1642,  1642,
-    1642,  1642,  1642,  -352,  -352,    37,  1314,  1642,  1642,  1642,
-    1642,  1642,   221,     4,  1642,     4,    48,  -352,  1642,   -20,
-    -352,   138,  1642,  1642,  1642,  1642,   160,   406,  -352,  -352,
-    -352,    19,   621,   170,  1642,   117,  1396,  1478,  -352,   177,
-    -352,  -352,   201,   249,  -352,  1642,   190,  -352,  -352,    67,
-    -352,    67,    67,    67,    67,   220,   220,  -352,  1860,   182,
-    -352,   592,   129,  1920,   643,   477,   859,   721,  1860,  1817,
-     227,   227,   244,   393,   560,   690,   266,   266,  1642,  -352,
-    1560,  1642,   198,  -352,  -352,   602,   306,   259,   374,   340,
-     391,  -352,  -352,  -352,  -352,   199,  -352,  -352,   208,  -352,
-    1642,    64,   209,    67,   211,   217,    67,  -352,   224,   226,
-    -352,  -352,  -352,   225,   233,   185,  1642,  -352,  -352,  -352,
-     725,  -352,   807,  -352,   827,  -352,  -352,  -352,   425,  1642,
-     238,  -352,  -352,  1642,   459,  -352,   874,   509,  1642,  -352,
-     241,  -352,   242,  -352,   246,  -352,  -352,  -352,  -352,  -352,
-    -352,   299,   299,  1642,   299,  1642,   247,  -352,  -352,  -352,
-    -352,   519,  -352,  1903,   253,  -352,  -352,   272,  -352,  -352,
-    -352,   299,   299,  -352,    54,    54,   275,   104,   289,   299,
-    -352,  -352,  -352,   104,   104,  -352,   299,   294,  -352,  -352,
-     299,  -352,  -352,   104,  -352,  -352,   116,  -352,  1642,   104,
-     491,  -352,  -352,   298,  -352,   300,   299,   299,    54,  -352,
-    -352
+    -362,    19,  -362,  -362,   123,  -362,  -362,    20,  -362,  -362,
+      40,  -362,  -362,  -362,  -362,  -362,  -362,    51,    57,    -8,
+    -362,    57,  -362,  -362,  -362,  -362,   291,  -362,    73,  -362,
+      70,  -362,    95,    70,  -362,  -362,  -362,    17,    17,  -362,
+      41,  -362,  1660,  -362,  -362,    43,    46,    50,    58,    83,
+      65,    67,    73,  1660,    68,    78,    84,   639,   553,    17,
+     725,   810,   138,  1660,   262,  1660,    17,  1660,  1660,  1660,
+    1660,  1660,  1660,   895,   980,  -362,  1660,  1660,    17,    17,
+      17,    17,   140,    86,  -362,  -362,   604,   108,  -362,    10,
+    -362,  -362,  -362,  -362,  1911,  -362,    91,    11,    14,  -362,
+    -362,   171,  -362,  -362,   128,   180,   128,  -362,  -362,  -362,
+    -362,  -362,  1660,   126,  1660,   796,    73,    70,  -362,  -362,
+    -362,  -362,  -362,  -362,   137,  -362,  -362,  -362,  1911,   109,
+    1065,   553,  -362,   796,  1794,   108,  -362,  1730,  1660,  -362,
+     161,  -362,   796,    39,   169,   160,  1660,   796,  1150,   168,
+    -362,  -362,  -362,   796,  -362,   108,   499,   499,   499,   -35,
+     -35,   172,   214,  -362,   -23,   499,   499,  -362,  -362,  -362,
+    -362,    73,  -362,  -362,  1660,  1660,  1660,  1660,  1660,  1660,
+    1660,  1660,  1660,  1660,  1235,  1660,  1660,  1660,  1660,  1660,
+    1660,  1660,  1660,  1660,  1660,  1660,  1660,  1660,  1660,  1660,
+    1660,  -362,  -362,    47,  1320,  1660,  1660,  1660,  1660,  1660,
+     211,     6,  1660,     6,    64,  -362,  1660,   -45,  -362,   128,
+    1660,  1660,  1660,  1660,   155,   379,  -362,  -362,  1660,  -362,
+    -362,   349,   149,   176,  1660,   108,  1405,  1490,  -362,   179,
+    -362,  -362,   428,   253,  -362,  1660,   182,  -362,  -362,   383,
+    -362,   383,   383,   383,   383,   227,   227,  -362,  1911,   235,
+    -362,   471,    31,  1971,   758,   625,   842,   100,  1911,  1868,
+     207,   207,   455,   540,   711,   367,   499,   499,  1660,  -362,
+    1575,  1660,   206,  -362,  -362,   514,   276,   139,   290,   204,
+     364,  -362,  -362,  -362,  -362,   201,  -362,  -362,   213,  -362,
+    1660,    73,   216,   383,   223,   229,   383,  -362,   231,   244,
+    -362,  -362,  -362,   232,   257,   378,  1660,  1660,   268,  -362,
+    -362,  -362,   600,  -362,   657,  -362,   667,  -362,  -362,  -362,
+     222,  1660,   270,  -362,  -362,  1660,   433,  -362,   686,   300,
+    1660,  -362,   271,  -362,   275,  -362,   281,  -362,  -362,  -362,
+    -362,  -362,  -362,   353,   353,  1660,   353,  1660,   311,   316,
+     353,  -362,  -362,  -362,  -362,   310,  -362,  1954,   287,  -362,
+    -362,   317,  -362,  -362,  -362,   353,   353,  -362,    16,    16,
+     319,   140,   324,   353,   353,  -362,  -362,  -362,  -362,   140,
+     140,  -362,   353,   330,  -362,  -362,   353,  -362,  -362,   140,
+    -362,  -362,  -362,   116,  -362,  1660,   140,   467,  -362,  -362,
+     333,  -362,   342,   353,   353,    16,  -362,  -362
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const short int yypgoto[] =
 {
-    -352,  -352,    -7,   -92,  -352,  -104,  -352,  -352,  -101,  -352,
-     350,  -351,  -352,   152,  -352,  -325,  -352,    38,  -177,  -211,
-     -11,  -352,  -352,  -352,  -352,  -352,  -352,  -352,    72,   337,
-    -352,   361,   -27,   -97,  -352,   189,  -352,  -352,  -352,   -25,
-     -51,  -352,  -352,  -352,  -352,  -352,  -352,  -352,  -352,    35,
-    -352,  -352,   -99,  -206,  -352,  -352,   193,   335,   338,  -352,
-    -352,    -3
+    -362,  -362,   -24,   -51,  -362,  -362,  1508,  -362,  -362,  -106,
+    -362,   402,  -361,  -362,  -362,  -183,  -362,  -362,  -342,  -362,
+      85,  -196,  -220,   -39,  -362,  -362,  -362,  -362,  -362,  -362,
+    -362,    49,   397,  -362,   423,   -17,   -99,  -362,   236,  -362,
+    -362,  -362,   -26,   -52,  -362,  -362,  -362,  -362,  -362,  -362,
+    -362,  -362,    38,  -362,  -362,  -100,  -213,  -362,  -362,   -15,
+     386,   387,  -362,  -362,   184
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -178
+#define YYTABLE_NINF -184
 static const short int yytable[] =
 {
-      81,   206,   288,   127,   205,   101,   303,    34,   207,   117,
-      34,   103,   147,   197,   379,   362,   104,   199,    78,    19,
-      97,   212,   213,   214,   215,   216,   217,     3,   171,   172,
-     173,    22,   137,   174,   108,    26,   294,   175,   297,   230,
-     268,   118,   269,    28,   154,   156,   124,   400,    74,   133,
-      30,   130,   131,   236,   289,   197,   127,   390,   209,   146,
-    -178,  -178,     5,     6,   195,     7,     8,    34,   171,   172,
-     173,   159,   160,   161,   162,    98,   110,   376,   377,   225,
-      20,    21,   282,   109,   120,   211,   198,   127,   125,    74,
-     200,   134,     9,   307,   139,   346,   145,   221,   222,   148,
-     149,   150,   151,   152,   210,   285,   100,   157,   158,   176,
-     177,   113,   270,   271,   291,   232,   171,   172,   173,    74,
-     224,    -2,   357,   138,   114,   287,   306,   227,   198,   163,
-       5,     6,   366,     7,     8,     5,     6,   115,     7,     8,
-     116,   239,   241,   242,   243,   244,   245,   246,   247,   121,
-     249,   251,   252,   127,   140,   122,   238,   171,   172,   173,
-       9,    74,    75,    76,   123,     9,   165,   171,   172,   173,
-     174,   275,   276,   277,   278,   279,   280,   393,   171,   172,
-     173,   196,   201,   222,   202,   204,   229,   293,   241,   208,
-     241,   337,   305,   392,   233,   218,   283,   237,   283,   310,
-     219,   312,   314,   226,   166,   167,   168,   169,   322,   248,
-     318,   170,   228,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   281,   106,
-     106,   171,   172,   173,   171,   172,   173,   235,   365,   127,
-     367,   119,    74,   324,   309,   326,   327,   129,   106,   135,
-     171,   172,   173,   142,   315,   106,   317,   373,   374,   -43,
-     320,   179,   180,   181,   182,   383,   319,   106,   106,   106,
-     106,   173,   387,   328,   386,   316,   389,   335,   179,   180,
-     181,   182,   336,   339,   338,   340,   187,   188,   189,   190,
-     191,   341,   398,   399,   351,   192,   193,   194,   342,   344,
-     195,   343,   363,   222,   188,   189,   190,   191,   171,   172,
-     173,   345,   192,   193,   194,   352,   129,   195,   358,   359,
-     293,   369,    33,   360,    34,    35,    36,    37,    38,    39,
-     371,    40,    41,    42,   192,   193,   194,    43,   331,   195,
-      44,    45,    46,    47,   181,   182,   372,    48,    49,   380,
-      50,    51,    52,    53,    54,   171,   172,   173,   353,    55,
-      56,    57,    58,    59,    60,    81,    61,   382,    62,   388,
-     190,   191,   396,    63,   397,    79,   192,   193,   194,   395,
-     112,   195,    32,   368,   330,    64,    65,    66,   273,   171,
-     172,   173,    67,    68,   286,   143,    69,    70,   144,    71,
-       0,    72,    73,    74,    75,    76,    77,    33,     0,   300,
-      35,    36,    37,    38,    39,     0,    40,    41,    42,   333,
-       0,     0,    43,   171,   172,   173,     0,   179,   180,   181,
-     182,     0,     0,    49,     0,    50,    51,    52,    53,    54,
-     171,   172,   173,     0,    55,    56,    57,    58,    59,    60,
-       0,    61,   332,    62,   189,   190,   191,     0,    63,     0,
-       0,   192,   193,   194,     0,     0,   195,     0,     0,   334,
-      64,    65,    66,     0,   171,   172,   173,    67,    68,     0,
-       0,    69,    70,     0,   -38,     0,    72,    73,    74,    75,
-      76,    77,    33,     0,     0,    35,    36,    37,    38,    39,
-       0,    40,    41,    42,   350,     0,     0,    43,   171,   172,
-     173,   179,  -178,   181,   182,     0,     0,     0,    49,   381,
-      50,    51,    52,    53,    54,   384,   385,     0,     0,    55,
-      56,    57,    58,    59,    60,   391,    61,   354,    62,   190,
-     191,   394,     0,    63,     0,   192,   193,   194,     0,     0,
-     195,     0,     0,     0,     0,    64,    65,    66,   171,   172,
-     173,     0,    67,    68,     0,   -38,    69,    70,   171,   172,
-     173,    72,    73,    74,    75,    76,    77,    34,   126,    36,
-      37,    38,    39,   104,    40,    41,    42,     0,   356,     0,
-      43,     0,     0,     0,   179,   180,   181,   182,   370,     0,
-       0,    49,     0,    50,    51,    52,    53,    54,     0,     0,
-       0,     0,    55,    56,    57,    58,    59,    60,     0,    61,
-       0,    62,   190,   191,     0,     0,    63,     0,   192,   193,
-     194,     0,     0,   195,     0,     0,     0,     0,    64,    65,
-      66,   171,   172,   173,     0,    67,    68,     0,     0,    69,
-      70,   171,   172,   173,    72,    73,    74,    75,    76,    77,
-      34,    35,    36,    37,    38,    39,   321,    40,    41,    42,
-     171,   172,   173,    43,   308,     0,   329,  -178,     0,   181,
-     182,     0,     0,     0,    49,     0,    50,    51,    52,    53,
-      54,     0,     0,     0,     0,    55,    56,    57,    58,    59,
-      60,     0,    61,     0,    62,   190,   191,     0,     0,    63,
-       0,   192,   193,   194,     0,     0,   195,     0,     0,     0,
-       0,    64,    65,    66,     0,     0,   181,   182,    67,    68,
-       0,     0,    69,    70,     0,     0,     0,    72,    73,    74,
-      75,    76,    77,    34,   132,    36,    37,    38,    39,     0,
-      40,    41,    42,   191,     0,     0,    43,   181,   192,   193,
-     194,     0,     0,   195,     0,     0,     0,    49,     0,    50,
-      51,    52,    53,    54,   171,   172,   173,     0,    55,    56,
-      57,    58,    59,    60,   191,    61,     0,    62,     0,   192,
-     193,   194,    63,     0,   195,     0,     0,     0,     0,   347,
-       0,     0,     0,     0,    64,    65,    66,     0,     0,     0,
-       0,    67,    68,     0,     0,    69,    70,     0,     0,     0,
-      72,    73,    74,    75,    76,    77,    35,    36,    37,    38,
-      39,     0,    40,    41,    42,     0,     0,     0,    43,     0,
-     166,   167,   168,   169,     0,     0,     0,   170,     0,    49,
-       0,    50,    51,    52,    53,    54,   171,   172,   173,     0,
-      55,    56,    57,    58,    59,    60,     0,    61,     0,    62,
-     171,   172,   173,     0,    63,     0,   171,   172,   173,     0,
-       0,   348,     0,     0,     0,     0,    64,    65,    66,     0,
-       0,     0,     0,    67,    68,     0,     0,    69,    70,     0,
-     136,   349,    72,    73,    74,    75,    76,    77,    35,    36,
-      37,    38,    39,     0,    40,    41,    42,     0,     0,     0,
-      43,     0,   191,   171,   172,   173,     0,   192,   193,   194,
-       0,    49,   195,    50,    51,    52,    53,    54,     0,     0,
-       0,     0,    55,    56,    57,    58,    59,    60,   355,    61,
-       0,    62,     0,     0,     0,     0,    63,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    64,    65,
-      66,     0,     0,     0,     0,    67,    68,     0,   153,    69,
-      70,     0,     0,     0,    72,    73,    74,    75,    76,    77,
-      35,    36,    37,    38,    39,     0,    40,    41,    42,     0,
-       0,     0,    43,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    49,     0,    50,    51,    52,    53,    54,
-       0,     0,     0,     0,    55,    56,    57,    58,    59,    60,
-       0,    61,     0,    62,     0,     0,     0,     0,    63,     0,
+      86,   214,    82,   298,   102,   313,   135,   213,   318,    35,
+     376,   182,   215,   183,   205,   155,   106,   207,   395,     3,
+      35,   108,   111,   111,    19,   304,   109,   307,   127,   179,
+     180,   181,   299,   132,   124,   145,   141,  -184,  -184,   392,
+     393,   203,   205,   137,   111,   143,   240,   162,   164,   150,
+     278,   111,   279,    22,   417,    27,   407,    20,    21,   247,
+     135,    29,   217,   111,   111,   111,   111,   220,   221,   222,
+     223,   224,   225,    31,   227,   228,    35,   103,     5,     6,
+     115,     7,     8,   179,   180,   181,   235,   292,   184,   185,
+     206,   128,   218,   208,   135,   133,   358,   359,   142,   105,
+     219,   147,    78,   153,   231,   232,   156,   157,   158,   159,
+     160,     9,   295,   334,   165,   166,   137,   237,   206,   114,
+     301,   118,   242,    -2,   119,   280,   281,   371,   120,   122,
+       5,     6,    78,     7,     8,   380,   121,     5,     6,   189,
+       7,     8,   146,   125,   297,   126,   129,   248,   249,   251,
+     252,   253,   254,   255,   256,   257,   130,   259,   261,   262,
+     135,   123,   131,     9,   182,   171,   199,   173,    78,   204,
+       9,   200,   201,   202,   209,   316,   203,   210,   285,   286,
+     287,   288,   289,   290,   212,   410,   229,   293,   283,   293,
+     232,   179,   180,   181,   303,   251,   409,   251,   397,   315,
+     349,   179,   180,   181,   216,   320,   401,   402,   322,   310,
+     324,   326,   179,   180,   181,   226,   408,   243,   291,   330,
+     258,   343,   113,   411,   263,   264,   265,   266,   267,   268,
+     269,   270,   271,   272,   273,   274,   275,   276,   277,   236,
+      78,   239,   138,   139,   187,   188,   189,   190,   135,   238,
+     154,   245,   336,   321,   338,   339,   179,   180,   181,   327,
+     329,   331,   167,   168,   169,   170,   179,   180,   181,   195,
+     196,   197,   198,   199,   179,   180,   181,   350,   200,   201,
+     202,   181,   347,   203,   340,   403,   345,   179,   180,   181,
+     348,   246,    34,   351,    35,    36,    37,    38,    39,    40,
+     352,    41,    42,    43,   364,   365,   353,    44,   354,   356,
+      45,    46,    47,    48,   232,   234,   332,    49,    50,    51,
+      52,    53,   355,    54,    55,    56,    57,    58,   179,   180,
+     181,   303,    59,    60,    61,    62,    63,    64,   357,    65,
+     148,    66,   179,   180,   181,   360,    67,    78,    79,    80,
+     366,   372,   179,   180,   181,   373,   377,   342,    68,    69,
+      70,   374,   179,   180,   181,    71,    72,   387,   412,    73,
+      74,   344,    75,   367,    76,    77,    78,    79,    80,    81,
+      34,    86,   370,    36,    37,    38,    39,    40,   383,    41,
+      42,    43,   386,   384,   388,    44,   396,   174,   175,   176,
+     177,   179,   180,   181,   178,   398,   189,   190,   405,    53,
+     413,    54,    55,    56,    57,    58,   179,   180,   181,   414,
+      59,    60,    61,    62,    63,    64,   319,    65,    83,    66,
+     179,   180,   181,   199,    67,   179,   180,   181,   200,   201,
+     202,   117,   382,   203,    33,   346,    68,    69,    70,   296,
+     151,   152,     0,    71,    72,   -49,     0,    73,    74,     0,
+     -44,     0,    76,    77,    78,    79,    80,    81,    34,     0,
+       0,    36,    37,    38,    39,    40,     0,    41,    42,    43,
+     179,   180,   181,    44,     0,   179,   180,   181,     0,     0,
+       0,     0,   187,   188,   189,   190,     0,    53,     0,    54,
+      55,    56,    57,    58,     0,   328,     0,     0,    59,    60,
+      61,    62,    63,    64,   368,    65,     0,    66,   196,   197,
+     198,   199,    67,   179,   180,   181,   200,   201,   202,     0,
+       0,   203,     0,     0,    68,    69,    70,     0,     0,     0,
+       0,    71,    72,     0,   -44,    73,    74,     0,   333,     0,
+      76,    77,    78,    79,    80,    81,    35,   134,    37,    38,
+      39,    40,   109,    41,    42,    43,   179,   180,   181,    44,
+     200,   201,   202,     0,     0,   203,     0,   187,   188,   189,
+     190,     0,     0,    53,     0,    54,    55,    56,    57,    58,
+       0,   341,     0,     0,    59,    60,    61,    62,    63,    64,
+       0,    65,     0,    66,   197,   198,   199,     0,    67,     0,
+       0,   200,   201,   202,     0,     0,   203,     0,     0,     0,
+      68,    69,    70,   174,   175,   176,   177,    71,    72,     0,
+     178,    73,    74,     0,     0,     0,    76,    77,    78,    79,
+      80,    81,    35,    36,    37,    38,    39,    40,     0,    41,
+      42,    43,   179,   180,   181,    44,   179,   180,   181,     0,
+       0,     0,   187,  -184,   189,   190,     0,     0,     0,    53,
+       0,    54,    55,    56,    57,    58,     0,   361,     0,     0,
+      59,    60,    61,    62,    63,    64,     0,    65,     0,    66,
+     198,   199,     0,     0,    67,     0,   200,   201,   202,     0,
+       0,   203,     0,     0,     0,     0,    68,    69,    70,   179,
+     180,   181,     0,    71,    72,     0,     0,    73,    74,   179,
+     180,   181,    76,    77,    78,    79,    80,    81,    35,   140,
+      37,    38,    39,    40,   362,    41,    42,    43,   179,   180,
+     181,    44,     0,     0,   363,     0,     0,     0,   187,   188,
+     189,   190,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,   369,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,   198,   199,     0,     0,
+      67,     0,   200,   201,   202,     0,     0,   203,     0,     0,
+       0,     0,    68,    69,    70,  -184,     0,   189,   190,    71,
+      72,     0,     0,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,   198,   199,     0,    44,     0,     0,   200,
+     201,   202,     0,     0,   203,   189,   190,     0,     0,     0,
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,   198,   199,     0,     0,    67,     0,   200,   201,   202,
+       0,     0,   203,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,     0,    71,    72,     0,     0,    73,    74,
+       0,   144,     0,    76,    77,    78,    79,    80,    81,    36,
+      37,    38,    39,    40,     0,    41,    42,    43,   199,     0,
+       0,    44,     0,   200,   201,   202,     0,     0,   203,     0,
+       0,     0,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,     0,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,     0,     0,     0,     0,
+      67,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    68,    69,    70,     0,     0,     0,     0,    71,
+      72,     0,   161,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,     0,     0,     0,    44,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      64,    65,    66,     0,     0,     0,     0,    67,    68,     0,
-       0,    69,    70,     0,     0,   155,    72,    73,    74,    75,
-      76,    77,    35,    36,    37,    38,    39,     0,    40,    41,
-      42,     0,     0,     0,    43,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    49,     0,    50,    51,    52,
-      53,    54,     0,     0,     0,     0,    55,    56,    57,    58,
-      59,    60,     0,    61,     0,    62,     0,     0,     0,     0,
-      63,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    64,    65,    66,     0,     0,     0,     0,    67,
-      68,     0,   220,    69,    70,     0,     0,     0,    72,    73,
-      74,    75,    76,    77,    35,    36,    37,    38,    39,     0,
-      40,    41,    42,     0,     0,     0,    43,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    49,     0,    50,
-      51,    52,    53,    54,     0,     0,     0,     0,    55,    56,
-      57,    58,    59,    60,     0,    61,     0,    62,     0,     0,
-       0,     0,    63,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    64,    65,    66,     0,     0,     0,
-       0,    67,    68,     0,   231,    69,    70,     0,     0,     0,
-      72,    73,    74,    75,    76,    77,    35,    36,    37,    38,
-      39,     0,    40,    41,    42,     0,     0,     0,    43,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    49,
-       0,    50,    51,    52,    53,    54,     0,     0,     0,     0,
-      55,    56,    57,    58,    59,    60,     0,    61,     0,    62,
-       0,     0,     0,     0,    63,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    64,    65,    66,     0,
-       0,     0,     0,    67,    68,     0,   250,    69,    70,     0,
-       0,     0,    72,    73,    74,    75,    76,    77,    35,    36,
-      37,    38,    39,     0,    40,    41,    42,     0,     0,     0,
-      43,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    49,     0,    50,    51,    52,    53,    54,     0,     0,
-       0,     0,    55,    56,    57,    58,    59,    60,     0,    61,
-       0,    62,     0,     0,     0,     0,    63,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    64,    65,
-      66,     0,     0,     0,     0,    67,    68,     0,   274,    69,
-      70,     0,     0,     0,    72,    73,    74,    75,    76,    77,
-      35,    36,    37,    38,    39,     0,    40,    41,    42,     0,
-       0,     0,    43,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    49,     0,    50,    51,    52,    53,    54,
-       0,     0,     0,     0,    55,    56,    57,    58,    59,    60,
-       0,    61,     0,    62,     0,     0,     0,     0,    63,     0,
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,     0,     0,     0,     0,    67,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,     0,    71,    72,     0,     0,    73,    74,
+       0,     0,   163,    76,    77,    78,    79,    80,    81,    36,
+      37,    38,    39,    40,     0,    41,    42,    43,     0,     0,
+       0,    44,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,     0,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,     0,     0,     0,     0,
+      67,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    68,    69,    70,     0,     0,     0,     0,    71,
+      72,     0,   230,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,     0,     0,     0,    44,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      64,    65,    66,     0,     0,     0,     0,    67,    68,     0,
-     311,    69,    70,     0,     0,     0,    72,    73,    74,    75,
-      76,    77,    35,    36,    37,    38,    39,     0,    40,    41,
-      42,     0,     0,     0,    43,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    49,     0,    50,    51,    52,
-      53,    54,     0,     0,     0,     0,    55,    56,    57,    58,
-      59,    60,     0,    61,     0,    62,     0,     0,     0,     0,
-      63,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    64,    65,    66,     0,     0,     0,     0,    67,
-      68,     0,   313,    69,    70,     0,     0,     0,    72,    73,
-      74,    75,    76,    77,    35,    36,    37,    38,    39,     0,
-      40,    41,    42,     0,     0,     0,    43,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    49,     0,    50,
-      51,    52,    53,    54,     0,     0,     0,     0,    55,    56,
-      57,    58,    59,    60,     0,    61,     0,    62,     0,     0,
-       0,     0,    63,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    64,    65,    66,     0,     0,     0,
-       0,    67,    68,     0,   325,    69,    70,     0,     0,     0,
-      72,    73,    74,    75,    76,    77,    35,    36,    37,    38,
-      39,     0,    40,    41,    42,     0,     0,     0,    43,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    49,
-       0,    50,    51,    52,    53,    54,     0,     0,     0,     0,
-      55,    56,    57,    58,    59,    60,     0,    61,     0,    62,
-       0,     0,     0,     0,    63,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    64,    65,    66,     0,
-       0,     0,   197,    67,    68,     0,     0,    69,    70,     0,
-       0,     0,    72,    73,    74,    75,    76,    77,  -149,  -149,
-    -149,  -149,     0,     0,     0,  -149,     0,  -149,     0,     0,
-       0,     0,     0,  -149,  -149,  -149,  -149,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,  -149,  -149,
-    -149,     0,  -149,  -149,  -149,  -149,  -149,  -149,  -149,  -149,
-    -149,  -149,  -149,     0,     0,     0,     0,  -149,  -149,  -149,
-       0,     0,  -149,  -149,     0,   198,     0,  -149,  -149,  -177,
-    -177,  -177,  -177,     0,     0,     0,  -177,     0,  -177,     0,
-       0,     0,     0,     0,  -177,  -177,  -177,  -177,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,  -177,
-    -177,  -177,     0,  -177,  -177,  -177,  -177,  -177,  -177,  -177,
-    -177,  -177,  -177,  -177,     0,     0,     0,     0,  -177,  -177,
-    -177,     0,     0,  -177,  -177,   178,     0,     0,  -177,  -177,
-       0,   179,   180,   181,   182,     0,     0,     0,     0,     0,
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,     0,     0,     0,     0,    67,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,     0,    71,    72,     0,   241,    73,    74,
+       0,     0,     0,    76,    77,    78,    79,    80,    81,    36,
+      37,    38,    39,    40,     0,    41,    42,    43,     0,     0,
+       0,    44,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,     0,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,     0,     0,     0,     0,
+      67,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    68,    69,    70,     0,     0,     0,     0,    71,
+      72,     0,   260,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,     0,     0,     0,    44,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   183,   184,   323,   185,   186,   187,   188,   189,   190,
-     191,     0,     0,     0,     0,   192,   193,   194,   178,     0,
-     195,     0,     0,     0,   179,   180,   181,   182,     0,     0,
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,     0,     0,     0,     0,    67,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,     0,    71,    72,     0,   284,    73,    74,
+       0,     0,     0,    76,    77,    78,    79,    80,    81,    36,
+      37,    38,    39,    40,     0,    41,    42,    43,     0,     0,
+       0,    44,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,     0,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,     0,     0,     0,     0,
+      67,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    68,    69,    70,     0,     0,     0,     0,    71,
+      72,     0,   323,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,     0,     0,     0,    44,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   183,   184,     0,   185,   186,   187,
-     188,   189,   190,   191,     0,     0,     0,     0,   192,   193,
-     194,   178,     0,   195,     0,     0,     0,   179,   180,   181,
-     182,     0,     0,     0,     0,     0,     0,     0,  -178,     0,
-       0,     0,     0,     0,   179,   180,   181,   182,   184,     0,
-     185,   186,   187,   188,   189,   190,   191,     0,     0,     0,
-       0,   192,   193,   194,     0,     0,   195,   185,   186,   187,
-     188,   189,   190,   191,     0,     0,     0,     0,   192,   193,
-     194,     0,     0,   195
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,     0,     0,     0,     0,    67,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,     0,    71,    72,     0,   325,    73,    74,
+       0,     0,     0,    76,    77,    78,    79,    80,    81,    36,
+      37,    38,    39,    40,     0,    41,    42,    43,     0,     0,
+       0,    44,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    53,     0,    54,    55,    56,
+      57,    58,     0,     0,     0,     0,    59,    60,    61,    62,
+      63,    64,     0,    65,     0,    66,     0,     0,     0,     0,
+      67,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    68,    69,    70,     0,     0,     0,     0,    71,
+      72,     0,   337,    73,    74,     0,     0,     0,    76,    77,
+      78,    79,    80,    81,    36,    37,    38,    39,    40,     0,
+      41,    42,    43,     0,     0,     0,    44,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      53,     0,    54,    55,    56,    57,    58,     0,     0,     0,
+       0,    59,    60,    61,    62,    63,    64,     0,    65,     0,
+      66,     0,     0,     0,     0,    67,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    68,    69,    70,
+       0,     0,     0,   205,    71,    72,     0,     0,    73,    74,
+       0,     0,     0,    76,    77,    78,    79,    80,    81,  -155,
+    -155,  -155,  -155,     0,     0,     0,  -155,     0,     0,     0,
+       0,  -155,     0,     0,     0,     0,     0,  -155,  -155,  -155,
+    -155,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,  -155,  -155,  -155,     0,  -155,  -155,  -155,  -155,
+    -155,  -155,  -155,  -155,  -155,  -155,  -155,     0,     0,     0,
+       0,  -155,  -155,  -155,     0,     0,  -155,  -155,     0,   206,
+       0,  -155,  -155,  -183,  -183,  -183,  -183,     0,     0,     0,
+    -183,     0,     0,     0,     0,  -183,     0,     0,     0,     0,
+       0,  -183,  -183,  -183,  -183,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,  -183,  -183,  -183,     0,
+    -183,  -183,  -183,  -183,  -183,  -183,  -183,  -183,  -183,  -183,
+    -183,     0,   379,     0,   381,  -183,  -183,  -183,   385,     0,
+    -183,  -183,     0,     0,     0,  -183,  -183,     0,     0,     0,
+       0,     0,     0,   389,   390,     0,     0,     0,     0,     0,
+       0,   399,   400,     0,     0,     0,     0,     0,     0,   186,
+     404,     0,     0,     0,   406,   187,   188,   189,   190,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   415,   416,     0,     0,   191,   192,   335,   193,   194,
+     195,   196,   197,   198,   199,     0,     0,     0,     0,   200,
+     201,   202,   186,     0,   203,     0,     0,     0,   187,   188,
+     189,   190,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   191,   192,
+       0,   193,   194,   195,   196,   197,   198,   199,     0,     0,
+       0,     0,   200,   201,   202,   186,     0,   203,     0,     0,
+       0,   187,   188,   189,   190,     0,     0,     0,     0,     0,
+       0,     0,  -184,     0,     0,     0,     0,     0,   187,   188,
+     189,   190,   192,     0,   193,   194,   195,   196,   197,   198,
+     199,     0,     0,     0,     0,   200,   201,   202,     0,     0,
+     203,   193,   194,   195,   196,   197,   198,   199,     0,     0,
+       0,     0,   200,   201,   202,     0,     0,   203
 };
 
 static const short int yycheck[] =
 {
-      25,   102,   208,    54,   101,    32,   217,     3,   107,    43,
-       3,     4,    63,     3,   365,   340,     9,     3,    25,     4,
-      27,   113,   114,   115,   116,   117,   118,     0,    49,    50,
-      51,    13,    57,    53,    37,     4,   213,     3,   215,   138,
-       3,    75,     5,     4,    69,    70,    53,   398,    82,    56,
-      78,    54,    55,    74,    74,     3,   107,   382,   109,    62,
-      69,    70,    14,    15,    73,    17,    18,     3,    49,    50,
-      51,    74,    75,    76,    77,     7,    41,    23,    24,   130,
-       8,     9,    78,    75,    49,   112,    76,   138,    53,    82,
-      76,    56,    44,    74,    59,   306,    61,   122,   123,    64,
-      65,    66,    67,    68,   111,   204,     4,    72,    73,    75,
-      76,    75,    75,    76,   211,   140,    49,    50,    51,    82,
-     123,     0,   328,     4,    75,    77,   218,    75,    76,    25,
-      14,    15,   343,    17,    18,    14,    15,    75,    17,    18,
-      75,   166,   167,   168,   169,   170,   171,   172,   173,    75,
-     175,   176,   177,   204,    75,    75,   163,    49,    50,    51,
-      44,    82,    83,    84,    75,    44,    78,    49,    50,    51,
-      53,   196,   197,   198,   199,   200,   201,   388,    49,    50,
-      51,    75,     3,   208,    46,     4,    78,   212,   213,    75,
-     215,   290,   217,    77,    46,    75,   203,    79,   205,   224,
-      74,   226,   227,    75,    19,    20,    21,    22,    79,   174,
-     235,    26,    77,   178,   179,   180,   181,   182,   183,   184,
-     185,   186,   187,   188,   189,   190,   191,   192,     7,    36,
-      37,    49,    50,    51,    49,    50,    51,    76,   342,   290,
-     344,    48,    82,   268,    74,   270,   271,    54,    55,    56,
-      49,    50,    51,    60,    77,    62,     7,   361,   362,    74,
-      78,    34,    35,    36,    37,   369,    76,    74,    75,    76,
-      77,    51,   376,    75,   375,    74,   380,    78,    34,    35,
-      36,    37,    74,    74,   291,    74,    59,    60,    61,    62,
-      63,    74,   396,   397,   319,    68,    69,    70,    74,    74,
-      73,    75,     3,   328,    60,    61,    62,    63,    49,    50,
-      51,    78,    68,    69,    70,    77,   123,    73,    77,    77,
-     345,    74,     1,    77,     3,     4,     5,     6,     7,     8,
-      77,    10,    11,    12,    68,    69,    70,    16,    79,    73,
-      19,    20,    21,    22,    36,    37,    74,    26,    27,    74,
-      29,    30,    31,    32,    33,    49,    50,    51,   323,    38,
-      39,    40,    41,    42,    43,   390,    45,    78,    47,    75,
-      62,    63,    74,    52,    74,    25,    68,    69,    70,   390,
-      43,    73,    21,   345,    78,    64,    65,    66,   195,    49,
-      50,    51,    71,    72,   205,    60,    75,    76,    60,    78,
-      -1,    80,    81,    82,    83,    84,    85,     1,    -1,   216,
-       4,     5,     6,     7,     8,    -1,    10,    11,    12,    79,
-      -1,    -1,    16,    49,    50,    51,    -1,    34,    35,    36,
-      37,    -1,    -1,    27,    -1,    29,    30,    31,    32,    33,
-      49,    50,    51,    -1,    38,    39,    40,    41,    42,    43,
-      -1,    45,    78,    47,    61,    62,    63,    -1,    52,    -1,
-      -1,    68,    69,    70,    -1,    -1,    73,    -1,    -1,    78,
-      64,    65,    66,    -1,    49,    50,    51,    71,    72,    -1,
-      -1,    75,    76,    -1,    78,    -1,    80,    81,    82,    83,
-      84,    85,     1,    -1,    -1,     4,     5,     6,     7,     8,
-      -1,    10,    11,    12,    79,    -1,    -1,    16,    49,    50,
-      51,    34,    35,    36,    37,    -1,    -1,    -1,    27,   367,
-      29,    30,    31,    32,    33,   373,   374,    -1,    -1,    38,
-      39,    40,    41,    42,    43,   383,    45,    78,    47,    62,
-      63,   389,    -1,    52,    -1,    68,    69,    70,    -1,    -1,
-      73,    -1,    -1,    -1,    -1,    64,    65,    66,    49,    50,
-      51,    -1,    71,    72,    -1,    74,    75,    76,    49,    50,
-      51,    80,    81,    82,    83,    84,    85,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    -1,    79,    -1,
-      16,    -1,    -1,    -1,    34,    35,    36,    37,    79,    -1,
-      -1,    27,    -1,    29,    30,    31,    32,    33,    -1,    -1,
-      -1,    -1,    38,    39,    40,    41,    42,    43,    -1,    45,
-      -1,    47,    62,    63,    -1,    -1,    52,    -1,    68,    69,
-      70,    -1,    -1,    73,    -1,    -1,    -1,    -1,    64,    65,
-      66,    49,    50,    51,    -1,    71,    72,    -1,    -1,    75,
-      76,    49,    50,    51,    80,    81,    82,    83,    84,    85,
-       3,     4,     5,     6,     7,     8,    74,    10,    11,    12,
-      49,    50,    51,    16,    53,    -1,    74,    34,    -1,    36,
-      37,    -1,    -1,    -1,    27,    -1,    29,    30,    31,    32,
-      33,    -1,    -1,    -1,    -1,    38,    39,    40,    41,    42,
-      43,    -1,    45,    -1,    47,    62,    63,    -1,    -1,    52,
-      -1,    68,    69,    70,    -1,    -1,    73,    -1,    -1,    -1,
-      -1,    64,    65,    66,    -1,    -1,    36,    37,    71,    72,
-      -1,    -1,    75,    76,    -1,    -1,    -1,    80,    81,    82,
-      83,    84,    85,     3,     4,     5,     6,     7,     8,    -1,
-      10,    11,    12,    63,    -1,    -1,    16,    36,    68,    69,
-      70,    -1,    -1,    73,    -1,    -1,    -1,    27,    -1,    29,
-      30,    31,    32,    33,    49,    50,    51,    -1,    38,    39,
-      40,    41,    42,    43,    63,    45,    -1,    47,    -1,    68,
-      69,    70,    52,    -1,    73,    -1,    -1,    -1,    -1,    74,
-      -1,    -1,    -1,    -1,    64,    65,    66,    -1,    -1,    -1,
-      -1,    71,    72,    -1,    -1,    75,    76,    -1,    -1,    -1,
-      80,    81,    82,    83,    84,    85,     4,     5,     6,     7,
-       8,    -1,    10,    11,    12,    -1,    -1,    -1,    16,    -1,
-      19,    20,    21,    22,    -1,    -1,    -1,    26,    -1,    27,
-      -1,    29,    30,    31,    32,    33,    49,    50,    51,    -1,
-      38,    39,    40,    41,    42,    43,    -1,    45,    -1,    47,
-      49,    50,    51,    -1,    52,    -1,    49,    50,    51,    -1,
-      -1,    74,    -1,    -1,    -1,    -1,    64,    65,    66,    -1,
-      -1,    -1,    -1,    71,    72,    -1,    -1,    75,    76,    -1,
-      78,    74,    80,    81,    82,    83,    84,    85,     4,     5,
-       6,     7,     8,    -1,    10,    11,    12,    -1,    -1,    -1,
-      16,    -1,    63,    49,    50,    51,    -1,    68,    69,    70,
-      -1,    27,    73,    29,    30,    31,    32,    33,    -1,    -1,
-      -1,    -1,    38,    39,    40,    41,    42,    43,    74,    45,
-      -1,    47,    -1,    -1,    -1,    -1,    52,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    64,    65,
-      66,    -1,    -1,    -1,    -1,    71,    72,    -1,    74,    75,
-      76,    -1,    -1,    -1,    80,    81,    82,    83,    84,    85,
-       4,     5,     6,     7,     8,    -1,    10,    11,    12,    -1,
-      -1,    -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    27,    -1,    29,    30,    31,    32,    33,
-      -1,    -1,    -1,    -1,    38,    39,    40,    41,    42,    43,
-      -1,    45,    -1,    47,    -1,    -1,    -1,    -1,    52,    -1,
+      26,   107,    26,   216,    28,   225,    58,   106,   228,     3,
+     352,    56,   112,     3,     3,    67,    33,     3,   379,     0,
+       3,     4,    37,    38,     4,   221,     9,   223,    52,    52,
+      53,    54,    77,    57,    49,    61,    60,    72,    73,    23,
+      24,    76,     3,    58,    59,    60,   146,    73,    74,    64,
+       3,    66,     5,    13,   415,     4,   398,     8,     9,    82,
+     112,     4,   114,    78,    79,    80,    81,   118,   119,   120,
+     121,   122,   123,    81,   125,   126,     3,     7,    14,    15,
+      42,    17,    18,    52,    53,    54,   138,    81,    78,    79,
+      79,    53,   116,    79,   146,    57,   316,   317,    60,     4,
+     117,    63,    85,    65,   130,   131,    68,    69,    70,    71,
+      72,    47,   212,    82,    76,    77,   131,    78,    79,    78,
+     219,    78,   148,     0,    78,    78,    79,   340,    78,    46,
+      14,    15,    85,    17,    18,   355,    78,    14,    15,    39,
+      17,    18,     4,    78,    80,    78,    78,   171,   174,   175,
+     176,   177,   178,   179,   180,   181,    78,   183,   184,   185,
+     212,    78,    78,    47,    56,    25,    66,    81,    85,    78,
+      47,    71,    72,    73,     3,   226,    76,    49,   204,   205,
+     206,   207,   208,   209,     4,   405,    77,   211,   203,   213,
+     216,    52,    53,    54,   220,   221,    80,   223,   381,   225,
+     300,    52,    53,    54,    78,    56,   389,   390,   234,   224,
+     236,   237,    52,    53,    54,    78,   399,    49,     7,   245,
+     182,    82,    38,   406,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,    78,
+      85,    81,    58,    59,    37,    38,    39,    40,   300,    80,
+      66,    79,   278,    77,   280,   281,    52,    53,    54,    80,
+       7,    79,    78,    79,    80,    81,    52,    53,    54,    62,
+      63,    64,    65,    66,    52,    53,    54,   301,    71,    72,
+      73,    54,    81,    76,    78,   391,    82,    52,    53,    54,
+      77,    77,     1,    77,     3,     4,     5,     6,     7,     8,
+      77,    10,    11,    12,    82,   331,    77,    16,    77,    77,
+      19,    20,    21,    22,   340,   131,    81,    26,    27,    28,
+      29,    30,    78,    32,    33,    34,    35,    36,    52,    53,
+      54,   357,    41,    42,    43,    44,    45,    46,    81,    48,
+      78,    50,    52,    53,    54,    77,    55,    85,    86,    87,
+      80,    80,    52,    53,    54,    80,     3,    81,    67,    68,
+      69,    80,    52,    53,    54,    74,    75,    80,   407,    78,
+      79,    81,    81,   335,    83,    84,    85,    86,    87,    88,
+       1,   407,    82,     4,     5,     6,     7,     8,    77,    10,
+      11,    12,    82,    77,    77,    16,    77,    19,    20,    21,
+      22,    52,    53,    54,    26,    81,    39,    40,    78,    30,
+      77,    32,    33,    34,    35,    36,    52,    53,    54,    77,
+      41,    42,    43,    44,    45,    46,    77,    48,    26,    50,
+      52,    53,    54,    66,    55,    52,    53,    54,    71,    72,
+      73,    44,   357,    76,    21,    81,    67,    68,    69,   213,
+      64,    64,    -1,    74,    75,    77,    -1,    78,    79,    -1,
+      81,    -1,    83,    84,    85,    86,    87,    88,     1,    -1,
+      -1,     4,     5,     6,     7,     8,    -1,    10,    11,    12,
+      52,    53,    54,    16,    -1,    52,    53,    54,    -1,    -1,
+      -1,    -1,    37,    38,    39,    40,    -1,    30,    -1,    32,
+      33,    34,    35,    36,    -1,    77,    -1,    -1,    41,    42,
+      43,    44,    45,    46,    81,    48,    -1,    50,    63,    64,
+      65,    66,    55,    52,    53,    54,    71,    72,    73,    -1,
+      -1,    76,    -1,    -1,    67,    68,    69,    -1,    -1,    -1,
+      -1,    74,    75,    -1,    77,    78,    79,    -1,    77,    -1,
+      83,    84,    85,    86,    87,    88,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    52,    53,    54,    16,
+      71,    72,    73,    -1,    -1,    76,    -1,    37,    38,    39,
+      40,    -1,    -1,    30,    -1,    32,    33,    34,    35,    36,
+      -1,    77,    -1,    -1,    41,    42,    43,    44,    45,    46,
+      -1,    48,    -1,    50,    64,    65,    66,    -1,    55,    -1,
+      -1,    71,    72,    73,    -1,    -1,    76,    -1,    -1,    -1,
+      67,    68,    69,    19,    20,    21,    22,    74,    75,    -1,
+      26,    78,    79,    -1,    -1,    -1,    83,    84,    85,    86,
+      87,    88,     3,     4,     5,     6,     7,     8,    -1,    10,
+      11,    12,    52,    53,    54,    16,    52,    53,    54,    -1,
+      -1,    -1,    37,    38,    39,    40,    -1,    -1,    -1,    30,
+      -1,    32,    33,    34,    35,    36,    -1,    77,    -1,    -1,
+      41,    42,    43,    44,    45,    46,    -1,    48,    -1,    50,
+      65,    66,    -1,    -1,    55,    -1,    71,    72,    73,    -1,
+      -1,    76,    -1,    -1,    -1,    -1,    67,    68,    69,    52,
+      53,    54,    -1,    74,    75,    -1,    -1,    78,    79,    52,
+      53,    54,    83,    84,    85,    86,    87,    88,     3,     4,
+       5,     6,     7,     8,    77,    10,    11,    12,    52,    53,
+      54,    16,    -1,    -1,    77,    -1,    -1,    -1,    37,    38,
+      39,    40,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    77,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    65,    66,    -1,    -1,
+      55,    -1,    71,    72,    73,    -1,    -1,    76,    -1,    -1,
+      -1,    -1,    67,    68,    69,    37,    -1,    39,    40,    74,
+      75,    -1,    -1,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
+      10,    11,    12,    65,    66,    -1,    16,    -1,    -1,    71,
+      72,    73,    -1,    -1,    76,    39,    40,    -1,    -1,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    65,    66,    -1,    -1,    55,    -1,    71,    72,    73,
+      -1,    -1,    76,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,    -1,    74,    75,    -1,    -1,    78,    79,
+      -1,    81,    -1,    83,    84,    85,    86,    87,    88,     4,
+       5,     6,     7,     8,    -1,    10,    11,    12,    66,    -1,
+      -1,    16,    -1,    71,    72,    73,    -1,    -1,    76,    -1,
+      -1,    -1,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    -1,    -1,    -1,    -1,
+      55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    67,    68,    69,    -1,    -1,    -1,    -1,    74,
+      75,    -1,    77,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
+      10,    11,    12,    -1,    -1,    -1,    16,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,    -1,    74,    75,    -1,    -1,    78,    79,
+      -1,    -1,    82,    83,    84,    85,    86,    87,    88,     4,
+       5,     6,     7,     8,    -1,    10,    11,    12,    -1,    -1,
+      -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    -1,    -1,    -1,    -1,
+      55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    67,    68,    69,    -1,    -1,    -1,    -1,    74,
+      75,    -1,    77,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
+      10,    11,    12,    -1,    -1,    -1,    16,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,    -1,    74,    75,    -1,    77,    78,    79,
+      -1,    -1,    -1,    83,    84,    85,    86,    87,    88,     4,
+       5,     6,     7,     8,    -1,    10,    11,    12,    -1,    -1,
+      -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    -1,    -1,    -1,    -1,
+      55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    67,    68,    69,    -1,    -1,    -1,    -1,    74,
+      75,    -1,    77,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
+      10,    11,    12,    -1,    -1,    -1,    16,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      64,    65,    66,    -1,    -1,    -1,    -1,    71,    72,    -1,
-      -1,    75,    76,    -1,    -1,    79,    80,    81,    82,    83,
-      84,    85,     4,     5,     6,     7,     8,    -1,    10,    11,
-      12,    -1,    -1,    -1,    16,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    27,    -1,    29,    30,    31,
-      32,    33,    -1,    -1,    -1,    -1,    38,    39,    40,    41,
-      42,    43,    -1,    45,    -1,    47,    -1,    -1,    -1,    -1,
-      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    64,    65,    66,    -1,    -1,    -1,    -1,    71,
-      72,    -1,    74,    75,    76,    -1,    -1,    -1,    80,    81,
-      82,    83,    84,    85,     4,     5,     6,     7,     8,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,    -1,    74,    75,    -1,    77,    78,    79,
+      -1,    -1,    -1,    83,    84,    85,    86,    87,    88,     4,
+       5,     6,     7,     8,    -1,    10,    11,    12,    -1,    -1,
+      -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    -1,    -1,    -1,    -1,
+      55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    67,    68,    69,    -1,    -1,    -1,    -1,    74,
+      75,    -1,    77,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
       10,    11,    12,    -1,    -1,    -1,    16,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    27,    -1,    29,
-      30,    31,    32,    33,    -1,    -1,    -1,    -1,    38,    39,
-      40,    41,    42,    43,    -1,    45,    -1,    47,    -1,    -1,
-      -1,    -1,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    64,    65,    66,    -1,    -1,    -1,
-      -1,    71,    72,    -1,    74,    75,    76,    -1,    -1,    -1,
-      80,    81,    82,    83,    84,    85,     4,     5,     6,     7,
-       8,    -1,    10,    11,    12,    -1,    -1,    -1,    16,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    27,
-      -1,    29,    30,    31,    32,    33,    -1,    -1,    -1,    -1,
-      38,    39,    40,    41,    42,    43,    -1,    45,    -1,    47,
-      -1,    -1,    -1,    -1,    52,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    64,    65,    66,    -1,
-      -1,    -1,    -1,    71,    72,    -1,    74,    75,    76,    -1,
-      -1,    -1,    80,    81,    82,    83,    84,    85,     4,     5,
-       6,     7,     8,    -1,    10,    11,    12,    -1,    -1,    -1,
-      16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    27,    -1,    29,    30,    31,    32,    33,    -1,    -1,
-      -1,    -1,    38,    39,    40,    41,    42,    43,    -1,    45,
-      -1,    47,    -1,    -1,    -1,    -1,    52,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    64,    65,
-      66,    -1,    -1,    -1,    -1,    71,    72,    -1,    74,    75,
-      76,    -1,    -1,    -1,    80,    81,    82,    83,    84,    85,
-       4,     5,     6,     7,     8,    -1,    10,    11,    12,    -1,
-      -1,    -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    27,    -1,    29,    30,    31,    32,    33,
-      -1,    -1,    -1,    -1,    38,    39,    40,    41,    42,    43,
-      -1,    45,    -1,    47,    -1,    -1,    -1,    -1,    52,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      64,    65,    66,    -1,    -1,    -1,    -1,    71,    72,    -1,
-      74,    75,    76,    -1,    -1,    -1,    80,    81,    82,    83,
-      84,    85,     4,     5,     6,     7,     8,    -1,    10,    11,
-      12,    -1,    -1,    -1,    16,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    27,    -1,    29,    30,    31,
-      32,    33,    -1,    -1,    -1,    -1,    38,    39,    40,    41,
-      42,    43,    -1,    45,    -1,    47,    -1,    -1,    -1,    -1,
-      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    64,    65,    66,    -1,    -1,    -1,    -1,    71,
-      72,    -1,    74,    75,    76,    -1,    -1,    -1,    80,    81,
-      82,    83,    84,    85,     4,     5,     6,     7,     8,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,    -1,    74,    75,    -1,    77,    78,    79,
+      -1,    -1,    -1,    83,    84,    85,    86,    87,    88,     4,
+       5,     6,     7,     8,    -1,    10,    11,    12,    -1,    -1,
+      -1,    16,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    30,    -1,    32,    33,    34,
+      35,    36,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    -1,    -1,    -1,    -1,
+      55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    67,    68,    69,    -1,    -1,    -1,    -1,    74,
+      75,    -1,    77,    78,    79,    -1,    -1,    -1,    83,    84,
+      85,    86,    87,    88,     4,     5,     6,     7,     8,    -1,
       10,    11,    12,    -1,    -1,    -1,    16,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    27,    -1,    29,
-      30,    31,    32,    33,    -1,    -1,    -1,    -1,    38,    39,
-      40,    41,    42,    43,    -1,    45,    -1,    47,    -1,    -1,
-      -1,    -1,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    64,    65,    66,    -1,    -1,    -1,
-      -1,    71,    72,    -1,    74,    75,    76,    -1,    -1,    -1,
-      80,    81,    82,    83,    84,    85,     4,     5,     6,     7,
-       8,    -1,    10,    11,    12,    -1,    -1,    -1,    16,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    27,
-      -1,    29,    30,    31,    32,    33,    -1,    -1,    -1,    -1,
-      38,    39,    40,    41,    42,    43,    -1,    45,    -1,    47,
-      -1,    -1,    -1,    -1,    52,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    64,    65,    66,    -1,
-      -1,    -1,     3,    71,    72,    -1,    -1,    75,    76,    -1,
-      -1,    -1,    80,    81,    82,    83,    84,    85,    19,    20,
-      21,    22,    -1,    -1,    -1,    26,    -1,    28,    -1,    -1,
-      -1,    -1,    -1,    34,    35,    36,    37,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    49,    50,
-      51,    -1,    53,    54,    55,    56,    57,    58,    59,    60,
-      61,    62,    63,    -1,    -1,    -1,    -1,    68,    69,    70,
-      -1,    -1,    73,    74,    -1,    76,    -1,    78,    79,    19,
-      20,    21,    22,    -1,    -1,    -1,    26,    -1,    28,    -1,
-      -1,    -1,    -1,    -1,    34,    35,    36,    37,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    49,
-      50,    51,    -1,    53,    54,    55,    56,    57,    58,    59,
-      60,    61,    62,    63,    -1,    -1,    -1,    -1,    68,    69,
-      70,    -1,    -1,    73,    74,    28,    -1,    -1,    78,    79,
-      -1,    34,    35,    36,    37,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    54,    55,    56,    57,    58,    59,    60,    61,    62,
-      63,    -1,    -1,    -1,    -1,    68,    69,    70,    28,    -1,
-      73,    -1,    -1,    -1,    34,    35,    36,    37,    -1,    -1,
+      30,    -1,    32,    33,    34,    35,    36,    -1,    -1,    -1,
+      -1,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
+      50,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    67,    68,    69,
+      -1,    -1,    -1,     3,    74,    75,    -1,    -1,    78,    79,
+      -1,    -1,    -1,    83,    84,    85,    86,    87,    88,    19,
+      20,    21,    22,    -1,    -1,    -1,    26,    -1,    -1,    -1,
+      -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    38,    39,
+      40,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    52,    53,    54,    -1,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    -1,    -1,    -1,
+      -1,    71,    72,    73,    -1,    -1,    76,    77,    -1,    79,
+      -1,    81,    82,    19,    20,    21,    22,    -1,    -1,    -1,
+      26,    -1,    -1,    -1,    -1,    31,    -1,    -1,    -1,    -1,
+      -1,    37,    38,    39,    40,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    52,    53,    54,    -1,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    -1,   354,    -1,   356,    71,    72,    73,   360,    -1,
+      76,    77,    -1,    -1,    -1,    81,    82,    -1,    -1,    -1,
+      -1,    -1,    -1,   375,   376,    -1,    -1,    -1,    -1,    -1,
+      -1,   383,   384,    -1,    -1,    -1,    -1,    -1,    -1,    31,
+     392,    -1,    -1,    -1,   396,    37,    38,    39,    40,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    54,    55,    -1,    57,    58,    59,
-      60,    61,    62,    63,    -1,    -1,    -1,    -1,    68,    69,
-      70,    28,    -1,    73,    -1,    -1,    -1,    34,    35,    36,
-      37,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    28,    -1,
-      -1,    -1,    -1,    -1,    34,    35,    36,    37,    55,    -1,
-      57,    58,    59,    60,    61,    62,    63,    -1,    -1,    -1,
-      -1,    68,    69,    70,    -1,    -1,    73,    57,    58,    59,
-      60,    61,    62,    63,    -1,    -1,    -1,    -1,    68,    69,
-      70,    -1,    -1,    73
+      -1,   413,   414,    -1,    -1,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    -1,    -1,    -1,    -1,    71,
+      72,    73,    31,    -1,    76,    -1,    -1,    -1,    37,    38,
+      39,    40,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    57,    58,
+      -1,    60,    61,    62,    63,    64,    65,    66,    -1,    -1,
+      -1,    -1,    71,    72,    73,    31,    -1,    76,    -1,    -1,
+      -1,    37,    38,    39,    40,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    38,
+      39,    40,    58,    -1,    60,    61,    62,    63,    64,    65,
+      66,    -1,    -1,    -1,    -1,    71,    72,    73,    -1,    -1,
+      76,    60,    61,    62,    63,    64,    65,    66,    -1,    -1,
+      -1,    -1,    71,    72,    73,    -1,    -1,    76
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const unsigned char yystos[] =
 {
-       0,    87,    90,     0,    94,    14,    15,    17,    18,    44,
-      93,   109,   110,   112,   113,   122,   123,   116,   114,     4,
-     114,   114,    13,    95,   100,   108,     4,   111,     4,   117,
-      78,   124,   117,     1,     3,     4,     5,     6,     7,     8,
-      10,    11,    12,    16,    19,    20,    21,    22,    26,    27,
-      29,    30,    31,    32,    33,    38,    39,    40,    41,    42,
-      43,    45,    47,    52,    64,    65,    66,    71,    72,    75,
-      76,    78,    80,    81,    82,    83,    84,    85,    88,    96,
-      98,   125,   126,   127,   130,   131,   132,   133,   134,   135,
-     136,   141,   142,   143,   144,   145,   146,    88,     7,   118,
-       4,   118,    89,     4,     9,    88,   142,   147,   147,    75,
-     135,   115,   115,    75,    75,    75,    75,    43,    75,   142,
-     135,    75,    75,    75,    88,   135,     4,   126,   138,   142,
-     147,   147,     4,    88,   135,   142,    78,   125,     4,   135,
-      75,   137,   142,   143,   144,   135,   147,   126,   135,   135,
-     135,   135,   135,    74,   125,    79,   125,   135,   135,   147,
-     147,   147,   147,    25,    99,    78,    19,    20,    21,    22,
-      26,    49,    50,    51,    53,     3,    75,    76,    28,    34,
-      35,    36,    37,    54,    55,    57,    58,    59,    60,    61,
-      62,    63,    68,    69,    70,    73,    75,     3,    76,     3,
-      76,     3,    46,   119,     4,   119,    94,   138,    75,   126,
-      88,   118,    89,    89,    89,    89,    89,    89,    75,    74,
-      74,   125,   125,   139,   147,   126,    75,    75,    77,    78,
-     138,    74,   125,    46,   120,    76,    74,    79,    88,   125,
-     104,   125,   125,   125,   125,   125,   125,   125,   135,   125,
-      74,   125,   125,   135,   135,   135,   135,   135,   135,   135,
-     135,   135,   135,   135,   135,   135,   135,   135,     3,     5,
-      75,    76,   129,   142,    74,   125,   125,   125,   125,   125,
-     125,     7,    78,    88,   121,   138,   121,    77,   139,    74,
-     128,   119,   103,   125,   104,   105,   125,   104,   107,   140,
-     142,    96,   102,   105,   106,   125,    89,    74,    53,    74,
-     125,    74,   125,    74,   125,    77,    74,     7,   125,    76,
-      78,    74,    79,    56,   125,    74,   125,   125,    75,    74,
-      78,    79,    78,    79,    78,    78,    74,   138,    88,    74,
-      74,    74,    74,    75,    74,    78,   105,    74,    74,    74,
-      79,   125,    77,   135,    78,    74,    79,   139,    77,    77,
-      77,   101,   101,     3,    91,    91,   105,    91,   103,    74,
-      79,    77,    74,    91,    91,    92,    23,    24,    97,    97,
-      74,    99,    78,    91,    99,    99,    94,    91,    75,    91,
-     101,    99,    77,   105,    99,   106,    74,    74,    91,    91,
-      97
+       0,    90,    94,     0,    98,    14,    15,    17,    18,    47,
+      97,   115,   116,   118,   119,   128,   129,   122,   120,     4,
+     120,   120,    13,    99,   105,   106,   114,     4,   117,     4,
+     123,    81,   130,   123,     1,     3,     4,     5,     6,     7,
+       8,    10,    11,    12,    16,    19,    20,    21,    22,    26,
+      27,    28,    29,    30,    32,    33,    34,    35,    36,    41,
+      42,    43,    44,    45,    46,    48,    50,    55,    67,    68,
+      69,    74,    75,    78,    79,    81,    83,    84,    85,    86,
+      87,    88,    91,   100,   102,   103,   131,   132,   133,   136,
+     137,   138,   139,   140,   141,   142,   147,   148,   149,   150,
+     151,   152,    91,     7,   124,     4,   124,    92,     4,     9,
+      91,   148,   153,   153,    78,   141,   121,   121,    78,    78,
+      78,    78,    46,    78,   148,    78,    78,    91,   141,    78,
+      78,    78,    91,   141,     4,   132,   144,   148,   153,   153,
+       4,    91,   141,   148,    81,   131,     4,   141,    78,   143,
+     148,   149,   150,   141,   153,   132,   141,   141,   141,   141,
+     141,    77,   131,    82,   131,   141,   141,   153,   153,   153,
+     153,    25,   104,    81,    19,    20,    21,    22,    26,    52,
+      53,    54,    56,     3,    78,    79,    31,    37,    38,    39,
+      40,    57,    58,    60,    61,    62,    63,    64,    65,    66,
+      71,    72,    73,    76,    78,     3,    79,     3,    79,     3,
+      49,   125,     4,   125,    98,   144,    78,   132,    91,   124,
+      92,    92,    92,    92,    92,    92,    78,    92,    92,    77,
+      77,   131,   131,   145,   153,   132,    78,    78,    80,    81,
+     144,    77,   131,    49,   126,    79,    77,    82,    91,   131,
+     110,   131,   131,   131,   131,   131,   131,   131,   141,   131,
+      77,   131,   131,   141,   141,   141,   141,   141,   141,   141,
+     141,   141,   141,   141,   141,   141,   141,   141,     3,     5,
+      78,    79,   135,   148,    77,   131,   131,   131,   131,   131,
+     131,     7,    81,    91,   127,   144,   127,    80,   145,    77,
+     134,   125,   109,   131,   110,   111,   131,   110,   113,   146,
+     148,   100,   108,   111,   112,   131,    92,    93,   111,    77,
+      56,    77,   131,    77,   131,    77,   131,    80,    77,     7,
+     131,    79,    81,    77,    82,    59,   131,    77,   131,   131,
+      78,    77,    81,    82,    81,    82,    81,    81,    77,   144,
+      91,    77,    77,    77,    77,    78,    77,    81,   111,   111,
+      77,    77,    77,    77,    82,   131,    80,   141,    81,    77,
+      82,   145,    80,    80,    80,   107,   107,     3,    95,    95,
+     111,    95,   109,    77,    77,    95,    82,    80,    77,    95,
+      95,    96,    23,    24,   101,   101,    77,   104,    81,    95,
+      95,   104,   104,    98,    95,    78,    95,   107,   104,    80,
+     111,   104,   112,    77,    77,    95,    95,   101
 };
diff --git a/perly.y b/perly.y
index 250176a..c81cee3 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -41,6 +41,7 @@
 %token <pval> LABEL
 %token <ival> FORMAT SUB ANONSUB PACKAGE USE
 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
+%token <ival> GIVEN WHEN DEFAULT
 %token <ival> LOOPEX DOTDOT
 %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP
 %token <ival> RELOP EQOP MULOP ADDOP
@@ -49,7 +50,7 @@
 %token COLONATTR
 
 %type <ival> prog decl format startsub startanonsub startformsub mintro
-%type <ival> progstart remember mremember '&' savescope
+%type <ival> progstart remember mremember '&' savescope mydefsv
 %type <opval> block mblock lineseq line loop cond else
 %type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
 %type <opval> argexpr nexpr texpr iexpr mexpr mnexpr miexpr
@@ -57,6 +58,7 @@
 %type <opval> formname subname proto subbody cont my_scalar
 %type <opval> subattrlist myattrlist mysubrout myattrterm myterm
 %type <opval> termbinop termunop anonymous termdo
+%type <opval> switch case
 %type <pval> label
 
 %nonassoc PREC_LOW
@@ -109,6 +111,10 @@ remember:  /* NULL */      /* start a full lexical scope */
                        { $$ = block_start(TRUE); }
        ;
 
+mydefsv:       /* NULL */      /* lexicalize $_ */
+                       { $$ = (I32) allocmy("$_"); }
+       ;
+
 progstart:
                {
                    PL_expect = XSTATE; $$ = block_start(TRUE);
@@ -146,6 +152,10 @@ lineseq    :       /* NULL */
 line   :       label cond
                        { $$ = newSTATEOP(0, $1, $2); }
        |       loop    /* loops add their own labels */
+       |       switch  /* ... and so do switches */
+                       { $$ = $1; }
+       |       label case
+                       { $$ = newSTATEOP(0, $1, $2); }
        |       label ';'
                        { if ($1 != Nullch) {
                              $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
@@ -200,6 +210,14 @@ cond       :       IF '(' remember mexpr ')' mblock else
                                   newCONDOP(0, $4, scope($6), $7)); }
        ;
 
+/* Cases for a switch statement */
+case   :       WHEN '(' remember mexpr ')' mblock
+       { $$ = block_end($3,
+               newWHENOP($4, scope($6))); }
+       |       DEFAULT block
+       { $$ = newWHENOP(0, scope($2)); }
+       ;
+
 /* Continue blocks */
 cont   :       /* NULL */
                        { $$ = Nullop; }
@@ -253,6 +271,15 @@ loop       :       label WHILE '(' remember texpr ')' mintro mblock cont
                                            NOLINE, Nullop, $2, $3, 0)); }
        ;
 
+/* Switch blocks */
+switch :       label GIVEN '(' remember mydefsv mexpr ')' mblock
+                       { PL_copline = (line_t) $2;
+                           $$ = block_end($4,
+                               newSTATEOP(0, $1,
+                                   newGIVENOP($6, scope($8),
+                                       (PADOFFSET) $5) )); }
+       ;
+
 /* determine whether there are any new my declarations */
 mintro :       /* NULL */
                        { $$ = (PL_min_intro_pending &&
index 5bc399f..8b50bd3 100644 (file)
@@ -491,6 +491,13 @@ to compress something else.  See L<perlfunc/pack>.
 (F) Only hard references may be blessed.  This is how Perl "enforces"
 encapsulation of objects.  See L<perlobj>.
 
+=item Can't "break" in a loop topicaizer
+(F) You called C<break>, but you're in a C<foreach> block rather than
+a C<given> block. You probably meant to use C<next> or C<last>.
+
+=item Can't "break" outside a given block
+(F) You called C<break>, but you're not inside a C<given> block.
+
 =item Can't call method "%s" in empty package "%s"
 
 (F) You called a method correctly, and it correctly indicated a package
@@ -566,6 +573,10 @@ but then $foo no longer contains a glob.
 (F) Certain types of SVs, in particular real symbol table entries
 (typeglobs), can't be forced to stop being what they are.
 
+=item Can't "continue" outside a when block
+(F) You called C<continue>, but you're not inside a C<when>
+or C<default> block.
+
 =item Can't create pipe mailbox
 
 (P) An error peculiar to VMS.  The process is suffering from exhausted
@@ -1144,6 +1155,12 @@ expression pattern.  Trying to do this in ordinary Perl code produces a
 value that prints out looking like SCALAR(0xdecaf).  Use the $1 form
 instead.
 
+=item Can't use "when" outside a topicalizer
+(F) You have used a when() block that is neither inside a C<foreach>
+loop nor a C<given> block. (Note that this error is issued on exit
+from the C<when> block, so you won't get the error if the match fails,
+or if you use an explicit C<continue>.)
+
 =item Can't weaken a nonreference
 
 (F) You attempted to weaken something that was not a reference.  Only
index 2cb16d0..0a87ece 100644 (file)
@@ -134,7 +134,7 @@ X<I/O> X<input> X<output> X<dbm>
 
 C<binmode>, C<close>, C<closedir>, C<dbmclose>, C<dbmopen>, C<die>, C<eof>,
 C<fileno>, C<flock>, C<format>, C<getc>, C<print>, C<printf>, C<read>,
-C<readdir>, C<rewinddir>, C<seek>, C<seekdir>, C<select>, C<syscall>,
+C<readdir>, C<rewinddir>, C<say>, C<seek>, C<seekdir>, C<select>, C<syscall>,
 C<sysread>, C<sysseek>, C<syswrite>, C<tell>, C<telldir>, C<truncate>,
 C<warn>, C<write>
 
@@ -156,6 +156,13 @@ X<control flow>
 C<caller>, C<continue>, C<die>, C<do>, C<dump>, C<eval>, C<exit>,
 C<goto>, C<last>, C<next>, C<redo>, C<return>, C<sub>, C<wantarray>
 
+=item Keywords related to switch
+
+C<break>, C<continue>
+
+(These are only available if you enable the "switch" feature.
+See L<feature> and L<perlsyn/"Switch statements">.)
+
 =item Keywords related to scoping
 
 C<caller>, C<import>, C<local>, C<my>, C<our>, C<package>, C<use>
@@ -592,6 +599,13 @@ that CLASSNAME is a true value.
 
 See L<perlmod/"Perl Modules">.
 
+=item break
+
+Break out of a C<given()> block.
+
+This keyword is enabled by the "switch" feature: see L<feature>
+for more information.
+
 =item caller EXPR
 X<caller> X<call stack> X<stack> X<stack trace>
 
@@ -890,6 +904,8 @@ L<perlipc/"Sockets: Client/Server Communication">.
 =item continue BLOCK
 X<continue>
 
+=item continue
+
 C<continue> is actually a flow control statement rather than a function.  If
 there is a C<continue> BLOCK attached to a BLOCK (typically in a C<while> or
 C<foreach>), it is always executed just before the conditional is about to
@@ -917,6 +933,12 @@ Omitting the C<continue> section is semantically equivalent to using an
 empty one, logically enough.  In that case, C<next> goes directly back
 to check the condition at the top of the loop.
 
+If the "switch" feature is enabled, C<continue> is also a
+function that will break out of the current C<when> or C<default>
+block, and fall through to the next case. See L<feature> and
+L<perlsyn/"Switch statements"> for more information.
+
+
 =item cos EXPR
 X<cos> X<cosine> X<acos> X<arccosine>
 
@@ -4666,6 +4688,20 @@ sets C<$!> (errno).  If FILENAME is omitted, uses C<$_>.
 
 The substitution operator.  See L<perlop>.
 
+=item say FILEHANDLE LIST
+X<say>
+
+=item say LIST
+
+=item say
+
+Just like C<print>, but implicitly appends a newline.
+C<say LIST> is simply an abbreviation for C<print LIST, "\n">,
+and C<say()> works just like C<print($_, "\n")>.
+
+This keyword is only available when the "say" feature is
+enabled: see L<feature>.
+
 =item scalar EXPR
 X<scalar> X<context>
 
index 84cd866..db105e3 100644 (file)
@@ -41,7 +41,7 @@ values only, not array values.
     left       << >>
     nonassoc   named unary operators
     nonassoc   < > <= >= lt gt le ge
-    nonassoc   == != <=> eq ne cmp
+    nonassoc   == != <=> eq ne cmp ~~
     left       &
     left       | ^
     left       &&
@@ -430,6 +430,12 @@ argument is stringwise less than, equal to, or greater than the right
 argument.
 X<cmp>
 
+Binary "~~" does a smart match between its arguments. Smart matching
+is described in L<perlsyn/"Smart Matching in Detail">.
+This operator is only available if you enable the "~~" feature:
+see L<feature> for more information.
+X<~~>
+
 "lt", "le", "ge", "gt" and "cmp" use the collation (sort) order specified
 by the current locale if C<use locale> is in effect.  See L<perllocale>.
 
index c819b94..cc91e31 100644 (file)
@@ -466,8 +466,8 @@ rather than merely terminating the inner one.  And it's faster because
 Perl executes a C<foreach> statement more rapidly than it would the
 equivalent C<for> loop.
 
-=head2 Basic BLOCKs and Switch Statements
-X<switch> X<block> X<case>
+=head2 Basic BLOCKs
+X<block>
 
 A BLOCK by itself (labeled or not) is semantically equivalent to a
 loop that executes once.  Thus you can use any of the loop control
@@ -476,7 +476,7 @@ I<NOT> true in C<eval{}>, C<sub{}>, or contrary to popular belief
 C<do{}> blocks, which do I<NOT> count as loops.)  The C<continue>
 block is optional.
 
-The BLOCK construct is particularly nice for doing case
+The BLOCK construct can be used to emulate case
 structures.
 
     SWITCH: {
@@ -486,133 +486,146 @@ structures.
        $nothing = 1;
     }
 
-There is no official C<switch> statement in Perl, because there are
-already several ways to write the equivalent.
+Such constructs are quite frequently used, because older versions
+of Perl had no official C<switch> statement.
 
-However, starting from Perl 5.8 to get switch and case one can use
-the Switch extension and say:
 
-       use Switch;
+=head2 Switch statements
+X<switch> X<case> X<given> X<when> X<default>
 
-after which one has switch and case.  It is not as fast as it could be
-because it's not really part of the language (it's done using source
-filters) but it is available, and it's very flexible.
+Starting from Perl 5.10, you can say 
 
-In addition to the above BLOCK construct, you could write
+       use feature "switch";
 
-    SWITCH: {
-       $abc = 1, last SWITCH  if /^abc/;
-       $def = 1, last SWITCH  if /^def/;
-       $xyz = 1, last SWITCH  if /^xyz/;
-       $nothing = 1;
+which enables a switch feature that is closely based on the
+Perl 6 proposal.
+
+The keywords C<given> and C<when> are analogous
+to C<switch> and C<case> in other languages, so the code
+above could be written as
+
+       given($_) {
+           when (/^abc/) { $abc = 1; }
+           when (/^def/) { $def = 1; }
+           when (/^xyz/) { $xyz = 1; }
+           default { $nothing = 1; }
     }
 
-(That's actually not as strange as it looks once you realize that you can
-use loop control "operators" within an expression.  That's just the binary
-comma operator in scalar context.  See L<perlop/"Comma Operator">.)
+This construct is very flexible and powerful. For example:
 
-or
+       given() {
 
-    SWITCH: {
-       /^abc/ && do { $abc = 1; last SWITCH; };
-       /^def/ && do { $def = 1; last SWITCH; };
-       /^xyz/ && do { $xyz = 1; last SWITCH; };
-       $nothing = 1;
+           xxxx
     }
 
-or formatted so it stands out more as a "proper" C<switch> statement:
+Most of its power comes from the implicit smart matching:
 
-    SWITCH: {
-       /^abc/      && do {
-                           $abc = 1;
-                           last SWITCH;
-                      };
-
-       /^def/      && do {
-                           $def = 1;
-                           last SWITCH;
-                      };
-
-       /^xyz/      && do {
-                           $xyz = 1;
-                           last SWITCH;
-                       };
-       $nothing = 1;
-    }
+       when($foo) ...
 
-or
+is exactly equivalent to
 
-    SWITCH: {
-       /^abc/ and $abc = 1, last SWITCH;
-       /^def/ and $def = 1, last SWITCH;
-       /^xyz/ and $xyz = 1, last SWITCH;
-       $nothing = 1;
-    }
+       when($_ ~~ $foo) ...
 
-or even, horrors,
-
-    if (/^abc/)
-       { $abc = 1 }
-    elsif (/^def/)
-       { $def = 1 }
-    elsif (/^xyz/)
-       { $xyz = 1 }
-    else
-       { $nothing = 1 }
-
-A common idiom for a C<switch> statement is to use C<foreach>'s aliasing to make
-a temporary assignment to C<$_> for convenient matching:
-
-    SWITCH: for ($where) {
-               /In Card Names/     && do { push @flags, '-e'; last; };
-               /Anywhere/          && do { push @flags, '-h'; last; };
-               /In Rulings/        && do {                    last; };
-               die "unknown value for form variable where: `$where'";
-           }
+(though you need to enable the "~~" feature before you
+can use the C<~~> operator directly). In fact C<when(EXPR)>
+is treated as an implicit smart match most of the time. The
+exceptions are that when EXPR is:
+
+=over 4
+
+=item o
+
+a subroutine or method call
+
+=item o
+
+a regular expression match, i.e. C</REGEX/> or C<$foo =~ /REGEX/>,
+or a negated regular expression match C<$foo !~ /REGEX/>.
+
+=item o
+
+a comparison (such as C<$_ E<lt> 10> or C<$x gt "abc">
+
+=item o
+
+C<defined(...)>, C<exists(...)>, or C<eof(...)>
+
+=item o
 
-Another interesting approach to a switch statement is arrange
-for a C<do> block to return the proper value:
+A negated expression C<!(...)> or C<not (...)>, or a logical
+exclusive-or C<(...) xor (...)>.
 
-    $amode = do {
-       if     ($flag & O_RDONLY) { "r" }       # XXX: isn't this 0?
-       elsif  ($flag & O_WRONLY) { ($flag & O_APPEND) ? "a" : "w" }
-       elsif  ($flag & O_RDWR)   {
-           if ($flag & O_CREAT)  { "w+" }
-           else                  { ($flag & O_APPEND) ? "a+" : "r+" }
+=back
+
+then the value of EXPR is used directly as a boolean.
+Furthermore:
+
+=over 4
+
+=item o
+
+If EXPR is C<... && ...> or C<... and ...>, the test
+is applied recursively to both arguments. If I<both>
+arguments pass the test, then the argument is treated
+as boolean.
+
+=item o
+
+If EXPR is C<... || ...> or C<... or ...>, the test
+is applied recursively to the first argument.
+
+=back
+
+These rules look complicated, but usually they will do what
+you want. For example you could write:
+
+       when (/^\d$/ && $_ < 75) { ... }
+
+C<default> behaves exactly like C<when(1 == 1)>, which is
+to say that it always matches.
+
+See L</"Smart matching in detail"> for more information
+on smart matching.
+
+=head3 Fall-through
+
+You can use the C<continue> keyword to fall through from one
+case to the next:
+
+       given($foo) {
+           when (/x/) { print "\$foo contains an 'x'\n"; continue }
+           when (/y/) { print "\$foo contains a 'y'\n" }
+           default    { print "\$foo contains neither an 'x' nor a 'y' }
        }
-    };
-
-Or 
-
-        print do {
-            ($flags & O_WRONLY) ? "write-only"          :
-            ($flags & O_RDWR)   ? "read-write"          :
-                                  "read-only";
-        };
-
-Or if you are certain that all the C<&&> clauses are true, you can use
-something like this, which "switches" on the value of the
-C<HTTP_USER_AGENT> environment variable.
-
-    #!/usr/bin/perl 
-    # pick out jargon file page based on browser
-    $dir = 'http://www.wins.uva.nl/~mes/jargon';
-    for ($ENV{HTTP_USER_AGENT}) { 
-       $page  =    /Mac/            && 'm/Macintrash.html'
-                || /Win(dows )?NT/  && 'e/evilandrude.html'
-                || /Win|MSIE|WebTV/ && 'm/MicroslothWindows.html'
-                || /Linux/          && 'l/Linux.html'
-                || /HP-UX/          && 'h/HP-SUX.html'
-                || /SunOS/          && 's/ScumOS.html'
-                ||                     'a/AppendixB.html';
+
+=head3 Switching in a loop
+
+Instead of using C<given()>, you can use a C<foreach()> loop.
+For example, here's one way to count how many times a particular
+string occurs in an array:
+
+       my $count = 0;
+       for (@array) {
+           when ("foo") { ++$count }
     }
-    print "Location: $dir/$page\015\012\015\012";
+       print "\@array contains $count copies of 'foo'\n";
+
+On exit from the C<when> block, there is an implicit C<next>.
+You can override that with an explicit C<last> if you're only
+interested in the first match.
+
+This doesn't work if you explicitly specify a loop variable,
+as in C<for $item (@array)>. You have to use the default
+variable C<$_>. (You can use C<for my $_ (@array)>.)
+
+=head3 Smart matching in detail
+
+
 
-That kind of switch statement only works when you know the C<&&> clauses
-will be true.  If you don't, the previous C<?:> example should be used.
+=head3 Custom matching via overloading
 
-You might also consider writing a hash of subroutine references
-instead of synthesizing a C<switch> statement.
+You can change the way that an object is matched by overloading
+the C<'~~'> operator. This trumps the usual smart match semantics.
 
 =head2 Goto
 X<goto>
diff --git a/pp.sym b/pp.sym
index 19be260..1d1b876 100644 (file)
--- a/pp.sym
+++ b/pp.sym
@@ -35,8 +35,10 @@ Perl_ck_return
 Perl_ck_rfun
 Perl_ck_rvconst
 Perl_ck_sassign
+Perl_ck_say
 Perl_ck_select
 Perl_ck_shift
+Perl_ck_smartmatch
 Perl_ck_sort
 Perl_ck_spair
 Perl_ck_split
@@ -394,5 +396,13 @@ Perl_pp_setstate
 Perl_pp_method_named
 Perl_pp_dor
 Perl_pp_dorassign
+Perl_pp_entergiven
+Perl_pp_leavegiven
+Perl_pp_enterwhen
+Perl_pp_leavewhen
+Perl_pp_break
+Perl_pp_continue
+Perl_pp_smartmatch
+Perl_pp_say
 
 # ex: set ro:
index a3f76cf..2f563ef 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1193,7 +1193,9 @@ static const char * const context_name[] = {
     "loop",
     "substitution",
     "block",
-    "format"
+    "format",
+    "given",
+    "when"
 };
 
 STATIC I32
@@ -1209,6 +1211,8 @@ S_dopoptolabel(pTHX_ const char *label)
        case CXt_FORMAT:
        case CXt_EVAL:
        case CXt_NULL:
+       case CXt_GIVEN:
+       case CXt_WHEN:
            if (ckWARN(WARN_EXITING))
                Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting %s via %s",
                        context_name[CxTYPE(cx)], OP_NAME(PL_op));
@@ -1228,6 +1232,8 @@ S_dopoptolabel(pTHX_ const char *label)
     return i;
 }
 
+
+
 I32
 Perl_dowantarray(pTHX)
 {
@@ -1336,6 +1342,45 @@ S_dopoptoloop(pTHX_ I32 startingblock)
     return i;
 }
 
+STATIC I32
+S_dopoptogiven(pTHX_ I32 startingblock)
+{
+    I32 i;
+    for (i = startingblock; i >= 0; i--) {
+       register const PERL_CONTEXT *cx = &cxstack[i];
+       switch (CxTYPE(cx)) {
+       default:
+           continue;
+       case CXt_GIVEN:
+           DEBUG_l( Perl_deb(aTHX_ "(Found given #%ld)\n", (long)i));
+           return i;
+       case CXt_LOOP:
+           if (CxFOREACHDEF(cx)) {
+               DEBUG_l( Perl_deb(aTHX_ "(Found foreach #%ld)\n", (long)i));
+               return i;
+           }
+       }
+    }
+    return i;
+}
+
+STATIC I32
+S_dopoptowhen(pTHX_ I32 startingblock)
+{
+    I32 i;
+    for (i = startingblock; i >= 0; i--) {
+       register const PERL_CONTEXT *cx = &cxstack[i];
+       switch (CxTYPE(cx)) {
+       default:
+           continue;
+       case CXt_WHEN:
+           DEBUG_l( Perl_deb(aTHX_ "(Found when #%ld)\n", (long)i));
+           return i;
+       }
+    }
+    return i;
+}
+
 void
 Perl_dounwind(pTHX_ I32 cxix)
 {
@@ -1727,7 +1772,7 @@ PP(pp_enteriter)
     register PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
     SV **svp;
-    U32 cxtype = CXt_LOOP;
+    U32 cxtype = CXt_LOOP | CXp_FOREACH;
 #ifdef USE_ITHREADS
     void *iterdata;
 #endif
@@ -1760,6 +1805,9 @@ PP(pp_enteriter)
 #endif
     }
 
+    if (PL_op->op_private & OPpITER_DEF)
+       cxtype |= CXp_FOR_DEF;
+
     ENTER;
 
     PUSHBLOCK(cx, cxtype, SP);
@@ -3388,7 +3436,7 @@ PP(pp_entereval)
 {
     dVAR; dSP;
     register PERL_CONTEXT *cx;
-    dPOPss;
+    SV *sv;
     const I32 gimme = GIMME_V;
     const I32 was = PL_sub_generation;
     char tbuf[TYPE_DIGITS(long) + 12];
@@ -3398,6 +3446,12 @@ PP(pp_entereval)
     OP *ret;
     CV* runcv;
     U32 seq;
+    HV *saved_hh = 0;
+    
+    if (PL_op->op_private & OPpEVAL_HAS_HH) {
+       saved_hh = (HV*) SvREFCNT_inc(POPs);
+    }
+    sv = POPs;
 
     if (!SvPV_nolen_const(sv))
        RETPUSHUNDEF;
@@ -3432,6 +3486,8 @@ PP(pp_entereval)
     SAVEDELETE(PL_defstash, safestr, len);
     SAVEHINTS();
     PL_hints = PL_op->op_targ;
+    if (saved_hh)
+       GvHV(PL_hintgv) = saved_hh;
     SAVESPTR(PL_compiling.cop_warnings);
     if (specialWARN(PL_curcop->cop_warnings))
         PL_compiling.cop_warnings = PL_curcop->cop_warnings;
@@ -3604,6 +3660,610 @@ PP(pp_leavetry)
     RETURN;
 }
 
+PP(pp_entergiven)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    const I32 gimme = GIMME_V;
+    
+    ENTER;
+    SAVETMPS;
+
+    if (PL_op->op_targ == 0) {
+       SV **defsv_p = &GvSV(PL_defgv);
+       *defsv_p = newSVsv(POPs);
+       SAVECLEARSV(*defsv_p);
+    }
+    else
+       sv_setsv(PAD_SV(PL_op->op_targ), POPs);
+
+    PUSHBLOCK(cx, CXt_GIVEN, SP);
+    PUSHGIVEN(cx);
+
+    RETURN;
+}
+
+PP(pp_leavegiven)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    I32 gimme;
+    SV **newsp;
+    PMOP *newpm;
+    SV **mark;
+
+    POPBLOCK(cx,newpm);
+    assert(CxTYPE(cx) == CXt_GIVEN);
+    mark = newsp;
+
+    SP = newsp;
+    PUTBACK;
+
+    PL_curpm = newpm;   /* pop $1 et al */
+
+    LEAVE;
+
+    return NORMAL;
+}
+
+/* Helper routines used by pp_smartmatch */
+STATIC
+PMOP *
+S_make_matcher(pTHX_ regexp *re)
+{
+    PMOP *matcher = (PMOP *) newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED);
+    PM_SETRE(matcher, ReREFCNT_inc(re));
+    
+    SAVEFREEOP((OP *) matcher);
+    ENTER; SAVETMPS;
+    SAVEOP();
+    return matcher;
+}
+
+STATIC
+bool
+S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv)
+{
+    dSP;
+    
+    PL_op = (OP *) matcher;
+    XPUSHs(sv);
+    PUTBACK;
+    (void) pp_match();
+    SPAGAIN;
+    return (SvTRUEx(POPs));
+}
+
+STATIC
+void
+S_destroy_matcher(pTHX_ PMOP *matcher)
+{
+    PERL_UNUSED_ARG(matcher);
+    FREETMPS;
+    LEAVE;
+}
+
+/* Do a smart match */
+PP(pp_smartmatch)
+{
+    return do_smartmatch(Nullhv, Nullhv);
+}
+
+/* This version of do_smartmatch() implements the following
+   table of smart matches:
+    
+    $a      $b        Type of Match Implied    Matching Code
+    ======  =====     =====================    =============
+    (overloading trumps everything)
+
+    Code[+] Code[+]   referential equality     match if refaddr($a) == refaddr($b)
+    Any     Code[+]   scalar sub truth         match if $b->($a)
+
+    Hash    Hash      hash keys identical      match if sort(keys(%$a)) ÃˆeqÇ sort(keys(%$b))
+    Hash    Array     hash value slice truth   match if $a->{any(@$b)}
+    Hash    Regex     hash key grep            match if any(keys(%$a)) =~ /$b/
+    Hash    Any       hash entry existence     match if exists $a->{$b}
+
+    Array   Array     arrays are identical[*]  match if $a Ãˆ~~Ç $b
+    Array   Regex     array grep               match if any(@$a) =~ /$b/
+    Array   Num       array contains number    match if any($a) == $b
+    Array   Any       array contains string    match if any($a) eq $b
+
+    Any     undef     undefined                match if !defined $a
+    Any     Regex     pattern match            match if $a =~ /$b/
+    Code()  Code()    results are equal        match if $a->() eq $b->()
+    Any     Code()    simple closure truth     match if $b->() (ignoring $a)
+    Num     numish[!] numeric equality         match if $a == $b
+    Any     Str       string equality          match if $a eq $b
+    Any     Num       numeric equality         match if $a == $b
+
+    Any     Any       string equality          match if $a eq $b
+
+
+ + - this must be a code reference whose prototype (if present) is not ""
+     (subs with a "" prototype are dealt with by the 'Code()' entry lower down)
+ * - if a circular reference is found, we fall back to referential equality
+ ! - either a real number, or a string that looks_like_number()
+
+ */
+STATIC
+OP *
+S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
+{
+    dSP;
+    
+    SV *e = TOPs;      /* e is for 'expression' */
+    SV *d = TOPm1s;    /* d is for 'default', as in PL_defgv */
+    SV *this, *other;
+    MAGIC *mg;
+    regexp *this_regex, *other_regex;
+
+#   define NOT_EMPTY_PROTO(cv) (!SvPOK(cv) || SvCUR(cv) == 0)
+
+#   define SM_REF(type) ( \
+          (SvROK(d) && (SvTYPE(this = SvRV(d)) == SVt_##type) && (other = e)) \
+       || (SvROK(e) && (SvTYPE(this = SvRV(e)) == SVt_##type) && (other = d)))
+
+#   define SM_CV_NEP   /* Find a code ref without an empty prototype */ \
+       ((SvROK(d) && (SvTYPE(this = SvRV(d)) == SVt_PVCV)              \
+           && NOT_EMPTY_PROTO(this) && (other = e))                    \
+       || (SvROK(e) && (SvTYPE(this = SvRV(e)) == SVt_PVCV)            \
+           && NOT_EMPTY_PROTO(this) && (other = d)))
+
+#   define SM_REGEX ( \
+          (SvROK(d) && SvMAGICAL(this = SvRV(d))                       \
+       && (mg = mg_find(this, PERL_MAGIC_qr))                          \
+       && (this_regex = (regexp *)mg->mg_obj)                          \
+       && (other = e))                                                 \
+    ||                                                                 \
+          (SvROK(e) && SvMAGICAL(this = SvRV(e))                       \
+       && (mg = mg_find(this, PERL_MAGIC_qr))                          \
+       && (this_regex = (regexp *)mg->mg_obj)                          \
+       && (other = d)) )
+       
+
+#   define SM_OTHER_REF(type) \
+       (SvROK(other) && SvTYPE(SvRV(other)) == SVt_##type)
+
+#   define SM_OTHER_REGEX (SvROK(other) && SvMAGICAL(SvRV(other))      \
+       && (mg = mg_find(SvRV(other), PERL_MAGIC_qr))                   \
+       && (other_regex = (regexp *)mg->mg_obj))
+       
+
+#   define SM_SEEN_THIS(sv) hv_exists_ent(seen_this, \
+       sv_2mortal(newSViv((IV) sv)), 0)
+
+#   define SM_SEEN_OTHER(sv) hv_exists_ent(seen_other, \
+       sv_2mortal(newSViv((IV) sv)), 0)
+
+    tryAMAGICbinSET(smart, 0);
+    
+    SP -= 2;   /* Pop the values */
+
+    /* 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 (SvGMAGICAL(d))
+           d = sv_mortalcopy(d);
+    }
+    else
+       d = &PL_sv_undef;
+
+    assert(e);
+    if (SvGMAGICAL(e))
+       e = sv_mortalcopy(e);
+
+    if (SM_CV_NEP) {
+       I32 c;
+       
+       if ( SM_OTHER_REF(PVCV) && NOT_EMPTY_PROTO(SvRV(other)) )
+       {
+           if (this == SvRV(other))
+               RETPUSHYES;
+           else
+               RETPUSHNO;
+       }
+       
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       PUSHs(other);
+       PUTBACK;
+       c = call_sv(this, G_SCALAR);
+       SPAGAIN;
+       if (c == 0)
+           PUSHs(&PL_sv_no);
+       else if (SvTEMP(TOPs))
+           SvREFCNT_inc(TOPs);
+       FREETMPS;
+       LEAVE;
+       RETURN;
+    }
+    else if (SM_REF(PVHV)) {
+       if (SM_OTHER_REF(PVHV)) {
+           /* Check that the key-sets are identical */
+           HE *he;
+           HV *other_hv = (HV *) SvRV(other);
+           bool tied = FALSE;
+           bool other_tied = FALSE;
+           U32 this_key_count  = 0,
+               other_key_count = 0;
+           
+           /* Tied hashes don't know how many keys they have. */
+           if (SvTIED_mg(this, PERL_MAGIC_tied)) {
+               tied = TRUE;
+           }
+           else if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied)) {
+               HV * temp = other_hv;
+               other_hv = (HV *) this;
+               this  = (SV *) temp;
+               tied = TRUE;
+           }
+           if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied))
+               other_tied = TRUE;
+           
+           if (!tied && HvUSEDKEYS((HV *) this) != HvUSEDKEYS(other_hv))
+               RETPUSHNO;
+
+           /* The hashes have the same number of keys, so it suffices
+              to check that one is a subset of the other. */
+           (void) hv_iterinit((HV *) this);
+           while ( (he = hv_iternext((HV *) this)) ) {
+               I32 key_len;
+               char *key = hv_iterkey(he, &key_len);
+               
+               ++ this_key_count;
+               
+               if(!hv_exists(other_hv, key, key_len)) {
+                   (void) hv_iterinit((HV *) this);    /* reset iterator */
+                   RETPUSHNO;
+               }
+           }
+           
+           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)
+               RETPUSHNO;
+           else
+               RETPUSHYES;
+       }
+       else if (SM_OTHER_REF(PVAV)) {
+           AV *other_av = (AV *) SvRV(other);
+           I32 other_len = av_len(other_av) + 1;
+           I32 i;
+           
+           if (HvUSEDKEYS((HV *) this) != other_len)
+               RETPUSHNO;
+           
+           for(i = 0; i < other_len; ++i) {
+               SV **svp = av_fetch(other_av, i, FALSE);
+               char *key;
+               STRLEN key_len;
+
+               if (!svp)       /* ??? When can this happen? */
+                   RETPUSHNO;
+
+               key = SvPV(*svp, key_len);
+               if(!hv_exists((HV *) this, key, key_len))
+                   RETPUSHNO;
+           }
+           RETPUSHYES;
+       }
+       else if (SM_OTHER_REGEX) {
+           PMOP *matcher = make_matcher(other_regex);
+           HE *he;
+
+           (void) hv_iterinit((HV *) this);
+           while ( (he = hv_iternext((HV *) this)) ) {
+               if (matcher_matches_sv(matcher, hv_iterkeysv(he))) {
+                   (void) hv_iterinit((HV *) this);
+                   destroy_matcher(matcher);
+                   RETPUSHYES;
+               }
+           }
+           destroy_matcher(matcher);
+           RETPUSHNO;
+       }
+       else {
+           if (hv_exists_ent((HV *) this, other, 0))
+               RETPUSHYES;
+           else
+               RETPUSHNO;
+       }
+    }
+    else if (SM_REF(PVAV)) {
+       if (SM_OTHER_REF(PVAV)) {
+           AV *other_av = (AV *) SvRV(other);
+           if (av_len((AV *) this) != av_len(other_av))
+               RETPUSHNO;
+           else {
+               I32 i;
+               I32 other_len = av_len(other_av);
+
+               if (Nullhv == seen_this) {
+                   seen_this = newHV();
+                   (void) sv_2mortal((SV *) seen_this);
+               }
+               if (Nullhv == seen_other) {
+                   seen_this = newHV();
+                   (void) sv_2mortal((SV *) seen_other);
+               }
+               for(i = 0; i <= other_len; ++i) {
+                   SV **this_elem = av_fetch((AV *)this, i, FALSE);
+                   SV **other_elem = av_fetch(other_av, i, FALSE);
+                   
+                   if (!this_elem || !other_elem) {
+                       if (this_elem || other_elem)
+                           RETPUSHNO;
+                   }
+                   else if (SM_SEEN_THIS(*this_elem)
+                        || SM_SEEN_OTHER(*other_elem))
+                   {
+                       if (*this_elem != *other_elem)
+                           RETPUSHNO;
+                   }
+                   else {
+                       hv_store_ent(seen_this,
+                           sv_2mortal(newSViv((IV) *this_elem)),
+                           &PL_sv_undef, 0);
+                       hv_store_ent(seen_other,
+                           sv_2mortal(newSViv((IV) *other_elem)),
+                           &PL_sv_undef, 0);
+                       PUSHs(*this_elem);
+                       PUSHs(*other_elem);
+                       
+                       PUTBACK;
+                       (void) do_smartmatch(seen_this, seen_other);
+                       SPAGAIN;
+                       
+                       if (!SvTRUEx(POPs))
+                           RETPUSHNO;
+                   }
+               }
+               RETPUSHYES;
+           }
+       }
+       else if (SM_OTHER_REGEX) {
+           PMOP *matcher = make_matcher(other_regex);
+           I32 i;
+           I32 this_len = av_len((AV *) this);
+
+           for(i = 0; i <= this_len; ++i) {
+               SV ** svp = av_fetch((AV *)this, i, FALSE);
+               if (svp && matcher_matches_sv(matcher, *svp)) {
+                   destroy_matcher(matcher);
+                   RETPUSHYES;
+               }
+           }
+           destroy_matcher(matcher);
+           RETPUSHNO;
+       }
+       else if (SvIOK(other) || SvNOK(other)) {
+           I32 i;
+
+           for(i = 0; i <= AvFILL((AV *) this); ++i) {
+               SV ** svp = av_fetch((AV *)this, i, FALSE);
+               if (!svp)
+                   continue;
+               
+               PUSHs(other);
+               PUSHs(*svp);
+               PUTBACK;
+               if ((PL_curcop->op_private & HINT_INTEGER) == HINT_INTEGER)
+                   (void) pp_i_eq();
+               else
+                   (void) pp_eq();
+               SPAGAIN;
+               if (SvTRUEx(POPs))
+                   RETPUSHYES;
+           }
+           RETPUSHNO;
+       }
+       else if (SvPOK(other)) {
+           I32 i;
+           I32 this_len = av_len((AV *) this);
+
+           for(i = 0; i <= this_len; ++i) {
+               SV ** svp = av_fetch((AV *)this, i, FALSE);
+               if (!svp)
+                   continue;
+               
+               PUSHs(other);
+               PUSHs(*svp);
+               PUTBACK;
+               (void) pp_seq();
+               SPAGAIN;
+               if (SvTRUEx(POPs))
+                   RETPUSHYES;
+           }
+           RETPUSHNO;
+       }
+    }
+    else if (!SvOK(d) || !SvOK(e)) {
+       if (!SvOK(d) && !SvOK(e))
+           RETPUSHYES;
+       else
+           RETPUSHNO;
+    }
+    else if (SM_REGEX) {
+       PMOP *matcher = make_matcher(this_regex);
+
+       PUTBACK;
+       PUSHs(matcher_matches_sv(matcher, other)
+           ? &PL_sv_yes
+           : &PL_sv_no);
+       destroy_matcher(matcher);
+       RETURN;
+    }
+    else if (SM_REF(PVCV)) {
+       I32 c;
+       /* This must be a null-prototyped sub, because we
+          already checked for the other kind. */
+       
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       PUTBACK;
+       c = call_sv(this, G_SCALAR);
+       SPAGAIN;
+       if (c == 0)
+           PUSHs(&PL_sv_undef);
+       else if (SvTEMP(TOPs))
+           SvREFCNT_inc(TOPs);
+
+       if (SM_OTHER_REF(PVCV)) {
+           /* This one has to be null-proto'd too.
+              Call both of 'em, and compare the results */
+           PUSHMARK(SP);
+           c = call_sv(SvRV(other), G_SCALAR);
+           SPAGAIN;
+           if (c == 0)
+               PUSHs(&PL_sv_undef);
+           else if (SvTEMP(TOPs))
+               SvREFCNT_inc(TOPs);
+           FREETMPS;
+           LEAVE;
+           PUTBACK;
+           return pp_eq();
+       }
+       
+       FREETMPS;
+       LEAVE;
+       RETURN;
+    }
+    else if ( ((SvIOK(d) || SvNOK(d)) && (this = d) && (other = e))
+         ||   ((SvIOK(e) || SvNOK(e)) && (this = e) && (other = d)) )
+    {
+       if (SvPOK(other) && !looks_like_number(other)) {
+           /* String comparison */
+           PUSHs(d); PUSHs(e);
+           PUTBACK;
+           return pp_seq();
+       }
+       /* Otherwise, numeric comparison */
+       PUSHs(d); PUSHs(e);
+       PUTBACK;
+       if ((PL_curcop->op_private & HINT_INTEGER) == HINT_INTEGER)
+           (void) pp_i_eq();
+       else
+           (void) pp_eq();
+       SPAGAIN;
+       if (SvTRUEx(POPs))
+           RETPUSHYES;
+       else
+           RETPUSHNO;
+    }
+    
+    /* As a last resort, use string comparison */
+    PUSHs(d); PUSHs(e);
+    PUTBACK;
+    return pp_seq();
+}
+
+PP(pp_enterwhen)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    const I32 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 ((0 == (PL_op->op_flags & OPf_SPECIAL)) && !SvTRUEx(POPs))
+       return cLOGOP->op_other->op_next;
+
+    ENTER;
+    SAVETMPS;
+
+    PUSHBLOCK(cx, CXt_WHEN, SP);
+    PUSHWHEN(cx);
+
+    RETURN;
+}
+
+PP(pp_leavewhen)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    I32 gimme;
+    SV **newsp;
+    PMOP *newpm;
+
+    POPBLOCK(cx,newpm);
+    assert(CxTYPE(cx) == CXt_WHEN);
+
+    SP = newsp;
+    PUTBACK;
+
+    PL_curpm = newpm;   /* pop $1 et al */
+
+    LEAVE;
+    return NORMAL;
+}
+
+PP(pp_continue)
+{
+    dVAR;   
+    I32 cxix;
+    register PERL_CONTEXT *cx;
+    I32 inner;
+    
+    cxix = dopoptowhen(cxstack_ix); 
+    if (cxix < 0)   
+       DIE(aTHX_ "Can't \"continue\" outside a when block");
+    if (cxix < cxstack_ix)
+        dounwind(cxix);
+    
+    /* clear off anything above the scope we're re-entering */
+    inner = PL_scopestack_ix;
+    TOPBLOCK(cx);
+    if (PL_scopestack_ix < inner)
+        leave_scope(PL_scopestack[PL_scopestack_ix]);
+    PL_curcop = cx->blk_oldcop;
+    return cx->blk_givwhen.leave_op;
+}
+
+PP(pp_break)
+{
+    dVAR;   
+    I32 cxix;
+    register PERL_CONTEXT *cx;
+    I32 inner;
+    
+    cxix = dopoptogiven(cxstack_ix); 
+    if (cxix < 0) {
+       if (PL_op->op_flags & OPf_SPECIAL)
+           DIE(aTHX_ "Can't use when() outside a topicalizer");
+       else
+           DIE(aTHX_ "Can't \"break\" outside a given block");
+    }
+    if (CxFOREACH(&cxstack[cxix]) && (0 == (PL_op->op_flags & OPf_SPECIAL)))
+       DIE(aTHX_ "Can't \"break\" in a loop topicalizer");
+
+    if (cxix < cxstack_ix)
+        dounwind(cxix);
+    
+    /* clear off anything above the scope we're re-entering */
+    inner = PL_scopestack_ix;
+    TOPBLOCK(cx);
+    if (PL_scopestack_ix < inner)
+        leave_scope(PL_scopestack[PL_scopestack_ix]);
+    PL_curcop = cx->blk_oldcop;
+
+    if (CxFOREACH(cx))
+       return cx->blk_loop.next_op;
+    else
+       return cx->blk_givwhen.leave_op;
+}
+
 STATIC OP *
 S_doparseform(pTHX_ SV *sv)
 {
index dddb013..a64e335 100644 (file)
@@ -34,8 +34,10 @@ PERL_CKDEF(Perl_ck_return)
 PERL_CKDEF(Perl_ck_rfun)
 PERL_CKDEF(Perl_ck_rvconst)
 PERL_CKDEF(Perl_ck_sassign)
+PERL_CKDEF(Perl_ck_say)
 PERL_CKDEF(Perl_ck_select)
 PERL_CKDEF(Perl_ck_shift)
+PERL_CKDEF(Perl_ck_smartmatch)
 PERL_CKDEF(Perl_ck_sort)
 PERL_CKDEF(Perl_ck_spair)
 PERL_CKDEF(Perl_ck_split)
@@ -395,5 +397,13 @@ PERL_PPDEF(Perl_pp_setstate)
 PERL_PPDEF(Perl_pp_method_named)
 PERL_PPDEF(Perl_pp_dor)
 PERL_PPDEF(Perl_pp_dorassign)
+PERL_PPDEF(Perl_pp_entergiven)
+PERL_PPDEF(Perl_pp_leavegiven)
+PERL_PPDEF(Perl_pp_enterwhen)
+PERL_PPDEF(Perl_pp_leavewhen)
+PERL_PPDEF(Perl_pp_break)
+PERL_PPDEF(Perl_pp_continue)
+PERL_PPDEF(Perl_pp_smartmatch)
+PERL_PPDEF(Perl_pp_say)
 
 /* ex: set ro: */
diff --git a/proto.h b/proto.h
index f8b64bb..6106bb7 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1383,6 +1383,12 @@ PERL_CALLCONV OP*        Perl_newFOROP(pTHX_ I32 flags, char* label, line_t forline, OP
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_5);
 
+PERL_CALLCONV OP*      Perl_newGIVENOP(pTHX_ OP* cond, OP* block, PADOFFSET defsv_off)
+                       __attribute__malloc__
+                       __attribute__warn_unused_result__
+                       __attribute__nonnull__(pTHX_1)
+                       __attribute__nonnull__(pTHX_2);
+
 PERL_CALLCONV OP*      Perl_newLOGOP(pTHX_ I32 optype, I32 flags, OP* left, OP* right)
                        __attribute__malloc__
                        __attribute__warn_unused_result__
@@ -1568,6 +1574,11 @@ PERL_CALLCONV OP*        Perl_newUNOP(pTHX_ I32 type, I32 flags, OP* first)
                        __attribute__malloc__
                        __attribute__warn_unused_result__;
 
+PERL_CALLCONV OP*      Perl_newWHENOP(pTHX_ OP* cond, OP* block)
+                       __attribute__malloc__
+                       __attribute__warn_unused_result__
+                       __attribute__nonnull__(pTHX_2);
+
 PERL_CALLCONV OP*      Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP* loop, I32 whileline, OP* expr, OP* block, OP* cont, I32 has_my)
                        __attribute__malloc__
                        __attribute__warn_unused_result__;
@@ -3016,6 +3027,10 @@ PERL_CALLCONV OP*        Perl_ck_sassign(pTHX_ OP *o)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_1);
 
+PERL_CALLCONV OP*      Perl_ck_say(pTHX_ OP *o)
+                       __attribute__warn_unused_result__
+                       __attribute__nonnull__(pTHX_1);
+
 PERL_CALLCONV OP*      Perl_ck_select(pTHX_ OP *o)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_1);
@@ -3124,6 +3139,13 @@ STATIC OP*       S_too_many_arguments(pTHX_ OP *o, const char* name)
                        __attribute__nonnull__(pTHX_1)
                        __attribute__nonnull__(pTHX_2);
 
+STATIC bool    S_looks_like_bool(pTHX_ OP* o)
+                       __attribute__nonnull__(pTHX_1);
+
+STATIC OP*     S_newGIVWHENOP(pTHX_ OP* cond, OP *block, I32 enter_opcode, I32 leave_opcode, PADOFFSET entertarg)
+                       __attribute__nonnull__(pTHX_2);
+
+STATIC OP*     S_ref_array_or_hash(pTHX_ OP* cond);
 #endif
 #if defined(PL_OP_SLAB_ALLOC)
 PERL_CALLCONV void*    Perl_Slab_Alloc(pTHX_ int m, size_t sz)
@@ -3265,6 +3287,9 @@ STATIC bool       S_num_overflow(NV value, I32 fldsize, I32 frcsize)
 STATIC I32     S_dopoptoeval(pTHX_ I32 startingblock)
                        __attribute__warn_unused_result__;
 
+STATIC I32     S_dopoptogiven(pTHX_ I32 startingblock)
+                       __attribute__warn_unused_result__;
+
 STATIC I32     S_dopoptolabel(pTHX_ const char *label)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_1);
@@ -3279,6 +3304,9 @@ STATIC I32        S_dopoptosub_at(pTHX_ const PERL_CONTEXT* cxstk, I32 startingblock)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_1);
 
+STATIC I32     S_dopoptowhen(pTHX_ I32 startingblock)
+                       __attribute__warn_unused_result__;
+
 STATIC void    S_save_lines(pTHX_ AV *array, SV *sv)
                        __attribute__nonnull__(pTHX_2);
 
@@ -3303,6 +3331,19 @@ STATIC I32       S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_2);
 
+STATIC PMOP*   S_make_matcher(pTHX_ regexp* re)
+                       __attribute__warn_unused_result__
+                       __attribute__nonnull__(pTHX_1);
+
+STATIC bool    S_matcher_matches_sv(pTHX_ PMOP* matcher, SV* sv)
+                       __attribute__warn_unused_result__
+                       __attribute__nonnull__(pTHX_1)
+                       __attribute__nonnull__(pTHX_2);
+
+STATIC void    S_destroy_matcher(pTHX_ PMOP* matcher)
+                       __attribute__nonnull__(pTHX_1);
+
+STATIC OP*     S_do_smartmatch(pTHX_ HV* seen_this, HV* seen_other);
 #endif
 
 #if defined(PERL_IN_PP_HOT_C) || defined(PERL_DECL_PROT)
@@ -3719,6 +3760,9 @@ STATIC void       S_checkcomma(pTHX_ char *s, const char *name, const char *what)
                        __attribute__nonnull__(pTHX_2)
                        __attribute__nonnull__(pTHX_3);
 
+STATIC bool    S_feature_is_enabled(pTHX_ char* name, STRLEN namelen)
+                       __attribute__nonnull__(pTHX_1);
+
 STATIC void    S_force_ident(pTHX_ const char *s, int kind)
                        __attribute__nonnull__(pTHX_1);
 
diff --git a/t/io/say.t b/t/io/say.t
new file mode 100644 (file)
index 0000000..62cec80
--- /dev/null
@@ -0,0 +1,49 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+}
+
+# Just a few very basic tests cribbed from t/io/print.t,
+# with some minor additions. say is actually compiled to
+# a print opcode, so it's more or less guaranteed to behave
+# the same way as print in any case.
+
+use strict 'vars';
+eval 'use Errno';
+die $@ if $@ and !$ENV{PERL_CORE_MINITEST};
+
+use feature "say";
+
+say "1..11";
+
+my $foo = 'STDOUT';
+say $foo "ok 1";
+
+say "ok 2\n","ok 3\n","ok 4";
+say STDOUT "ok 5";
+
+open(FOO,">-");
+say FOO "ok 6";
+
+open(my $bar,">-");
+say $bar "ok 7";
+
+say {"STDOUT"} "ok 8";
+
+if (!exists &Errno::EBADF) {
+    print "ok 9 # skipped: no EBADF\n";
+} else {
+    $! = 0;
+    no warnings 'unopened';
+    say NONEXISTENT "foo";
+    print "not " if ($! != &Errno::EBADF);
+    say "ok 9";
+}
+
+$_ = "ok 10";
+say;
+
+$_ = "ok 11";
+say STDOUT;
diff --git a/t/lib/feature/nonesuch b/t/lib/feature/nonesuch
new file mode 100644 (file)
index 0000000..1de44f6
--- /dev/null
@@ -0,0 +1,12 @@
+Test that non-existent features fail as expected.
+
+__END__
+use feature "nonesuch";
+EXPECT
+OPTIONS regex
+^Feature "nonesuch" is not supported by Perl [v0-9.]+ at - line 1
+########
+no feature "nonesuch";
+EXPECT
+OPTIONS regex
+^Feature "nonesuch" is not supported by Perl [v0-9.]+ at - line 1
diff --git a/t/lib/feature/say b/t/lib/feature/say
new file mode 100644 (file)
index 0000000..4b507e6
--- /dev/null
@@ -0,0 +1,64 @@
+Check the lexical scoping of the say keyword.
+(The actual behaviour is tested in t/op/say.t)
+
+__END__
+# No say; should be a syntax error.
+use warnings;
+say "Hello", "world";
+EXPECT
+Unquoted string "say" may clash with future reserved word at - line 3.
+String found where operator expected at - line 3, near "say "Hello""
+       (Do you need to predeclare say?)
+syntax error at - line 3, near "say "Hello""
+Execution of - aborted due to compilation errors.
+########
+# With say, should work
+use warnings;
+use feature "say";
+say "Hello", "world";
+EXPECT
+Helloworld
+########
+# With say, should work in eval too
+use warnings;
+use feature "say";
+eval q(say "Hello", "world");
+EXPECT
+Helloworld
+########
+# feature out of scope; should be a syntax error.
+use warnings;
+{ use feature 'say'; }
+say "Hello", "world";
+EXPECT
+Unquoted string "say" may clash with future reserved word at - line 4.
+String found where operator expected at - line 4, near "say "Hello""
+       (Do you need to predeclare say?)
+syntax error at - line 4, near "say "Hello""
+Execution of - aborted due to compilation errors.
+########
+# 'no feature' should work
+use warnings;
+use feature 'say';
+say "Hello", "world";
+no feature;
+say "Hello", "world";
+EXPECT
+Unquoted string "say" may clash with future reserved word at - line 6.
+String found where operator expected at - line 6, near "say "Hello""
+       (Do you need to predeclare say?)
+syntax error at - line 6, near "say "Hello""
+Execution of - aborted due to compilation errors.
+########
+# 'no feature "say"' should work too
+use warnings;
+use feature 'say';
+say "Hello", "world";
+no feature 'say';
+say "Hello", "world";
+EXPECT
+Unquoted string "say" may clash with future reserved word at - line 6.
+String found where operator expected at - line 6, near "say "Hello""
+       (Do you need to predeclare say?)
+syntax error at - line 6, near "say "Hello""
+Execution of - aborted due to compilation errors.
diff --git a/t/lib/feature/smartmatch b/t/lib/feature/smartmatch
new file mode 100644 (file)
index 0000000..16ea7f8
--- /dev/null
@@ -0,0 +1,45 @@
+Check the lexical scoping of the switch keywords.
+(The actual behaviour is tested in t/op/smartmatch.t)
+
+__END__
+# No ~~; should be a syntax error.
+use warnings;
+print +(2 ~~ 2);
+EXPECT
+syntax error at - line 3, near "2 ~"
+Execution of - aborted due to compilation errors.
+########
+# With ~~, should work
+use warnings;
+use feature "~~";
+print +(2 ~~ 2);
+EXPECT
+1
+########
+# ~~ out of scope; should be a syntax error.
+use warnings;
+{ use feature '~~'; }
+print +(2 ~~ 2);
+EXPECT
+syntax error at - line 4, near "2 ~"
+Execution of - aborted due to compilation errors.
+########
+# 'no feature' should work
+use warnings;
+use feature '~~';
+print +(2 ~~ 2), "\n";
+no feature;
+print +(2 ~~ 2), "\n";
+EXPECT
+syntax error at - line 6, near "2 ~"
+Execution of - aborted due to compilation errors.
+########
+# 'no feature "~~"' should work too
+use warnings;
+use feature '~~';
+print +(2 ~~ 2), "\n";
+no feature "~~";
+print +(2 ~~ 2), "\n";
+EXPECT
+syntax error at - line 6, near "2 ~"
+Execution of - aborted due to compilation errors.
diff --git a/t/lib/feature/switch b/t/lib/feature/switch
new file mode 100644 (file)
index 0000000..022cbd1
--- /dev/null
@@ -0,0 +1,158 @@
+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;
+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;
+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;
+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;
+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
+syntax error at - line 2, near "STDOUT continue"
+Execution of - aborted due to compilation errors.
+########
+# Use switch; so given is a keyword
+use feature 'switch';
+given("okay\n") { print }
+EXPECT
+okay
+########
+# Use switch; so when is a keyword
+use feature 'switch';
+given(1) { when(1) { print "okay" } }
+EXPECT
+okay
+########
+# Use switch; so default is a keyword
+use feature 'switch';
+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.
+########
+# Use switch; so continue is a keyword
+use feature 'switch';
+continue;
+EXPECT
+Can't "continue" outside a when block at - line 3.
+########
+# switch out of scope; given should be a bareword.
+use warnings;
+{ 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;
+{ 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;
+{ 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;
+{ use feature 'switch';
+  given (1) { break }  
+}
+print STDOUT break;
+EXPECT
+Unquoted string "break" may clash with future reserved word at - line 6.
+break
+########
+# switch out of scope; continue should not work
+{ use feature 'switch';
+  given (1) { default {continue} }  
+}
+print STDOUT continue;
+EXPECT
+syntax error at - line 5, near "STDOUT continue"
+Execution of - aborted due to compilation errors.
+########
+# C<no feature 'switch'> should work
+use warnings;
+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<no feature> should work too
+use warnings;
+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;
+@break = ($break = "break");
+print ${break}, ${break[0]};
+EXPECT
+breakbreak
+########
+# With the feature, we get an 'Unambiguous use of' warning:
+use warnings;
+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
index d37118e..3f3e871 100644 (file)
@@ -47,7 +47,7 @@ close (;*)
 closedir (*)
 cmp unknown
 connect (*$)
-continue unknown
+continue ()
 cos (;$)
 crypt ($$)
 dbmclose (\%)
diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t
new file mode 100644 (file)
index 0000000..6275f40
--- /dev/null
@@ -0,0 +1,163 @@
+#!./perl
+
+BEGIN {
+    chdir 't';
+    @INC = '../lib';
+    require './test.pl';
+}
+use strict;
+
+use Tie::Array;
+use Tie::Hash;
+
+# The feature mechanism is tested in t/lib/feature/smartmatch:
+# This file tests the semantics of the operator, without worrying
+# about feature issues such as scoping etc.
+
+# Predeclare vars used in the tests:
+my $deep1 = []; push @$deep1, \$deep1;
+my $deep2 = []; push @$deep2, \$deep2;
+
+{my $const = "a constant"; sub a_const () {$const}}
+
+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;
+
+# Load and run the tests
+my @tests = map [chomp and split /\t+/, $_, 3], grep !/^#/ && /\S/, <DATA>;
+plan tests => 2 * @tests;
+
+for my $test (@tests) {
+    my ($yn, $left, $right) = @$test;
+
+    match_test($yn, $left, $right);
+    match_test($yn, $right, $left);
+}
+
+sub match_test {
+    my ($yn, $left, $right) = @_;
+
+    die "Bad test spec: ($yn, $left, $right)"
+       unless $yn eq "" || $yn eq "!";
+    
+    my $tstr = "$left ~~ $right";
+    
+    my $res;
+    {
+       use feature "~~";
+       $res = eval $tstr // "";        #/ <- fix syntax colouring
+    }
+
+    die $@ if $@ ne "";
+    ok( ($yn =~ /!/ xor $res), "$tstr: $res");
+}
+
+
+
+sub foo {}
+sub bar {2}
+sub fatal {die}
+
+sub a_const() {die if @_; "a constant"}
+sub b_const() {die if @_; "a constant"}
+
+__DATA__
+# CODE ref against argument
+#  - arg is code ref
+       \&foo           \&foo
+!      \&foo           sub {}
+!      \&foo           \&bar
+
+# - arg is not code ref
+       1               sub{shift}
+!      0               sub{shift}
+       1               sub{scalar @_}
+       []              \&bar
+       {}              \&bar
+       qr//            \&bar
+
+# - null-prototyped subs
+       a_const         "a constant"
+       a_const         a_const
+       a_const         b_const
+
+# 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
+
+#  - an array ref
+       \%::            [keys %main::]
+!      \%::            []
+       {"" => 1}       [undef]
+
+#  - a regex
+       {foo => 1}      qr/^(fo[ox])$/
+!      +{0..100}       qr/[13579]$/
+
+#  - a string
+       +{foo => 1, bar => 2}   "foo"
+!      +{foo => 1, bar => 2}   "baz"
+
+
+# ARRAY ref against:
+#  - another array ref
+       []              []
+!      []              [1]
+       [["foo"], ["bar"]]      [qr/o/, qr/a/]
+       ["foo", "bar"]          [qr/o/, qr/a/]
+       $deep1          $deep1
+!      $deep1          $deep2
+
+       \@nums          \@tied_nums
+
+#  - a regex
+       [qw(foo bar baz quux)]  qr/x/
+!      [qw(foo bar baz quux)]  qr/y/
+
+# - a number
+       [qw(1foo 2bar)]         2
+
+# - a string
+!      [qw(1foo 2bar)]         "2"
+
+# Number against number
+       2               2
+!      2               3
+
+# Number against string
+       2               "2"
+       2               "2.0"
+!      2               "2bananas"
+!      2_3             "2_3"
+
+# Regex against string
+       qr/x/           "x"
+!      qr/y/           "x"
+
+# Regex against number
+       12345           qr/3/
+
+
+# Test the implicit referencing
+       @nums           7
+       @nums           \@nums
+!      @nums           \\@nums
+       @nums           [1..10]
+!      @nums           [0..9]
+
+       %hash           "foo"
+       %hash           /bar/
diff --git a/t/op/switch.t b/t/op/switch.t
new file mode 100644 (file)
index 0000000..fc88a13
--- /dev/null
@@ -0,0 +1,801 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+}
+
+use strict;
+use warnings;
+
+use Test::More tests => 107;
+
+# The behaviour of the feature pragma should be tested by lib/switch.t
+# using the tests in t/lib/switch/*. This file tests the behaviour of
+# the switch ops themselves.
+              
+
+use feature 'switch';
+no warnings "numeric";
+
+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($_, "outside", "\$_ lexically scoped") }
+
+{
+    my $_ = "outside";
+    given("inside") { check_outside2() }
+    sub check_outside2 {
+       is($_, "outside", "\$_ lexically scoped (lexical \$_)")
+    }
+}
+
+# Basic string/numeric comparisons and control flow
+
+{    
+    my $ok = 0;
+    given(3) {
+       when(2) { $ok = 0; }
+       when(3) { $ok = 1; }
+       when(4) { $ok = 0; }
+       default { $ok = 0; }
+    }
+    ok($ok, "numeric comparison");
+}
+
+{    
+    my $ok = 0;
+    use integer;
+    given(3.14159265) {
+       when(2) { $ok = 0; }
+       when(3) { $ok = 1; }
+       when(4) { $ok = 0; }
+       default { $ok = 0; }
+    }
+    ok($ok, "integer comparison");
+}
+
+{    
+    my ($ok1, $ok2) = (0, 0);
+    given(3) {
+       when(3.1)   { $ok1 = 0; }
+       when(3.0)   { $ok1 = 1; continue }
+       when("3.0") { $ok2 = 1; }
+       default     { $ok2 = 0; }
+    }
+    ok($ok1, "more numeric (pt. 1)");
+    ok($ok2, "more numeric (pt. 2)");
+}
+
+{
+    my $ok = 0;
+    given("c") {
+       when("b") { $ok = 0; }
+       when("c") { $ok = 1; }
+       when("d") { $ok = 0; }
+       default   { $ok = 0; }
+    }
+    ok($ok, "string comparison");
+}
+
+{
+    my $ok = 0;
+    given("c") {
+       when("b") { $ok = 0; }
+       when("c") { $ok = 0; continue }
+       when("c") { $ok = 1; }
+       default   { $ok = 0; }
+    }
+    ok($ok, "simple continue");
+}
+
+# Definedness
+{
+    my $ok = 1;
+    given (0) { when(undef) {$ok = 0} }
+    ok($ok, "Given(0) when(undef)");
+}
+{
+    my $undef;
+    my $ok = 1;
+    given (0) { when($undef) {$ok = 0} }
+    ok($ok, 'Given(0) when($undef)');
+}
+{
+    my $undef;
+    my $ok = 0;
+    given (0) { when($undef++) {$ok = 1} }
+    ok($ok, "Given(0) when($undef++)");
+}
+{
+    my $ok = 1;
+    given (undef) { when(0) {$ok = 0} }
+    ok($ok, "Given(undef) when(0)");
+}
+{
+    my $undef;
+    my $ok = 1;
+    given ($undef) { when(0) {$ok = 0} }
+    ok($ok, 'Given($undef) when(0)');
+}
+########
+{
+    my $ok = 1;
+    given ("") { when(undef) {$ok = 0} }
+    ok($ok, 'Given("") when(undef)');
+}
+{
+    my $undef;
+    my $ok = 1;
+    given ("") { when($undef) {$ok = 0} }
+    ok($ok, 'Given("") when($undef)');
+}
+{
+    my $ok = 1;
+    given (undef) { when("") {$ok = 0} }
+    ok($ok, 'Given(undef) when("")');
+}
+{
+    my $undef;
+    my $ok = 1;
+    given ($undef) { when("") {$ok = 0} }
+    ok($ok, 'Given($undef) when("")');
+}
+########
+{
+    my $ok = 0;
+    given (undef) { when(undef) {$ok = 1} }
+    ok($ok, "Given(undef) when(undef)");
+}
+{
+    my $undef;
+    my $ok = 0;
+    given (undef) { when($undef) {$ok = 1} }
+    ok($ok, 'Given(undef) when($undef)');
+}
+{
+    my $undef;
+    my $ok = 0;
+    given ($undef) { when(undef) {$ok = 1} }
+    ok($ok, 'Given($undef) when(undef)');
+}
+{
+    my $undef;
+    my $ok = 0;
+    given ($undef) { when($undef) {$ok = 1} }
+    ok($ok, 'Given($undef) when($undef)');
+}
+
+
+# Regular expressions
+{
+    my ($ok1, $ok2) = 0;
+    given("Hello, world!") {
+       when(/lo/)
+           { $ok1 = 1; continue}
+       when(/no/)
+           { $ok1 = 0; continue}
+       when(/^(Hello,|Goodbye cruel) world[!.?]/)
+           { $ok2 = 1; continue}
+       when(/^(Hello cruel|Goodbye,) world[!.?]/)
+           { $ok2 = 0; continue}
+    }
+    ok($ok1, "regex 1");
+    ok($ok2, "regex 2");
+}
+
+# Comparisons
+{
+    my $test = "explicit numeric comparison (<)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ < 10) { fail($test) }
+       when ($_ < 20) { fail($test) }
+       when ($_ < 30) { pass($test) }
+       when ($_ < 40) { fail($test) }
+       default        { fail($test) }
+    }
+}
+
+{
+    use integer;
+    my $test = "explicit numeric comparison (integer <)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ < 10) { fail($test) }
+       when ($_ < 20) { fail($test) }
+       when ($_ < 30) { pass($test) }
+       when ($_ < 40) { fail($test) }
+       default        { fail($test) }
+    }
+}
+
+{
+    my $test = "explicit numeric comparison (<=)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ <= 10) { fail($test) }
+       when ($_ <= 20) { fail($test) }
+       when ($_ <= 30) { pass($test) }
+       when ($_ <= 40) { fail($test) }
+       default         { fail($test) }
+    }
+}
+
+{
+    use integer;
+    my $test = "explicit numeric comparison (integer <=)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ <= 10) { fail($test) }
+       when ($_ <= 20) { fail($test) }
+       when ($_ <= 30) { pass($test) }
+       when ($_ <= 40) { fail($test) }
+       default         { fail($test) }
+    }
+}
+
+
+{
+    my $test = "explicit numeric comparison (>)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ > 40) { fail($test) }
+       when ($_ > 30) { fail($test) }
+       when ($_ > 20) { pass($test) }
+       when ($_ > 10) { fail($test) }
+       default        { fail($test) }
+    }
+}
+
+{
+    my $test = "explicit numeric comparison (>=)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ >= 40) { fail($test) }
+       when ($_ >= 30) { fail($test) }
+       when ($_ >= 20) { pass($test) }
+       when ($_ >= 10) { fail($test) }
+       default         { fail($test) }
+    }
+}
+
+{
+    use integer;
+    my $test = "explicit numeric comparison (integer >)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ > 40) { fail($test) }
+       when ($_ > 30) { fail($test) }
+       when ($_ > 20) { pass($test) }
+       when ($_ > 10) { fail($test) }
+       default        { fail($test) }
+    }
+}
+
+{
+    use integer;
+    my $test = "explicit numeric comparison (integer >=)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ >= 40) { fail($test) }
+       when ($_ >= 30) { fail($test) }
+       when ($_ >= 20) { pass($test) }
+       when ($_ >= 10) { fail($test) }
+       default         { fail($test) }
+    }
+}
+
+
+{
+    my $test = "explicit string comparison (lt)";
+    my $twenty_five = "25";
+    given($twenty_five) {
+       when ($_ lt "10") { fail($test) }
+       when ($_ lt "20") { fail($test) }
+       when ($_ lt "30") { pass($test) }
+       when ($_ lt "40") { fail($test) }
+       default         { fail($test) }
+    }
+}
+
+{
+    my $test = "explicit string comparison (le)";
+    my $twenty_five = "25";
+    given($twenty_five) {
+       when ($_ le "10") { fail($test) }
+       when ($_ le "20") { fail($test) }
+       when ($_ le "30") { pass($test) }
+       when ($_ le "40") { fail($test) }
+       default           { fail($test) }
+    }
+}
+
+{
+    my $test = "explicit string comparison (gt)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ ge "40") { fail($test) }
+       when ($_ ge "30") { fail($test) }
+       when ($_ ge "20") { pass($test) }
+       when ($_ ge "10") { fail($test) }
+       default           { fail($test) }
+    }
+}
+
+{
+    my $test = "explicit string comparison (ge)";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ ge "40") { fail($test) }
+       when ($_ ge "30") { fail($test) }
+       when ($_ ge "20") { pass($test) }
+       when ($_ ge "10") { fail($test) }
+       default           { fail($test) }
+    }
+}
+
+# Make sure it still works with a lexical $_:
+{
+    my $_;
+    my $test = "explicit comparison with lexical \$_";
+    my $twenty_five = 25;
+    given($twenty_five) {
+       when ($_ ge "40") { fail($test) }
+       when ($_ ge "30") { fail($test) }
+       when ($_ ge "20") { pass($test) }
+       when ($_ ge "10") { fail($test) }
+       default           { fail($test) }
+    }
+}
+
+# Optimized-away comparisons
+{
+    my $ok = 0;
+    given(23) {
+       when (2 + 2 == 4) { $ok = 1; continue }
+       when (2 + 2 == 5) { $ok = 0 }
+    }
+    ok($ok, "Optimized-away comparison");
+}
+
+# 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 bar {"bar"}
+{
+    my $ok = 0;
+    given("foo") {
+       when(bar()) {$ok = 1}
+    }
+    ok($ok, "Sub call acts as boolean")
+}
+
+{
+    my $ok = 0;
+    given("foo") {
+       when(main->bar()) {$ok = 1}
+    }
+    ok($ok, "Class-method call acts as boolean")
+}
+
+{
+    my $ok = 0;
+    my $obj = bless [];
+    given("foo") {
+       when($obj->bar()) {$ok = 1}
+    }
+    ok($ok, "Object-method call acts as boolean")
+}
+
+# Other things that should not be smart matched
+{
+    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 $ok = 1;
+    given(0) {
+       when((1 == $ok) || "foo") {
+           $ok = 0;
+       }
+    }
+    ok($ok, '((1 == $ok) || "foo") not 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 = "Only one FETCH (in given)";
+    my $ok = 0;
+    given($v = 23) {
+       when(undef) {}
+       when(sub{0}->()) {}
+       when(21) {}
+       when("22") {}
+       when(23) {$ok = 1}
+       when(/24/) {$ok = 0}
+    }
+    ok($ok, "precheck: $test_name");
+    is($f->count(), 1, $test_name);
+}
+
+{   my $test_name = "Only one FETCH (numeric when)";
+    my $ok = 0;
+    $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}
+    }
+    ok($ok, "precheck: $test_name");
+    is($f->count(), 1, $test_name);
+}
+
+{   my $test_name = "Only one FETCH (string when)";
+    my $ok = 0;
+    $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}
+    }
+    ok($ok, "precheck: $test_name");
+    is($f->count(), 1, $test_name);
+}
+
+{   my $test_name = "Only one FETCH (undef)";
+    my $ok = 0;
+    $v = undef;
+    is($f->count(), 0, "Sanity check: $test_name");
+    given(my $undef) {
+       when(sub{0}->()) {}
+       when("21")  {}
+       when("22")  {}
+       when($v)    {$ok = 1}
+       when(undef) {$ok = 0}
+    }
+    ok($ok, "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
+       }
+    }
+}
+
+{
+    my $first = 1;
+    my $_;
+    for (1, "two") {
+       when ("two") {
+           is($first, 0, "Implicitly lexical 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, "Implicitly lexical loop: first");
+           $first = 0;
+           # Implicit break is okay
+       }
+    }
+}
+
+{
+    my $first = 1;
+    my $_;
+    for $_ (1, "two") {
+       when ("two") {
+           is($first, 0, "Implicitly lexical, 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, "Implicitly lexical, explicit \$_: first");
+           $first = 0;
+           # Implicit break is okay
+       }
+    }
+}
+
+{
+    my $first = 1;
+    for my $_ (1, "two") {
+       when ("two") {
+           is($first, 0, "Lexical 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, "Lecical loop: first");
+           $first = 0;
+           # Implicit break is okay
+       }
+    }
+}
+
+
+# Code references
+{
+    no warnings "redefine";
+    my $called_foo = 0;
+    sub foo {$called_foo = 1}
+    my $called_bar = 0;
+    sub bar {$called_bar = 1}
+    my ($matched_foo, $matched_bar) = (0, 0);
+    given(\&foo) {
+       when(\&bar) {$matched_bar = 1}
+       when(\&foo) {$matched_foo = 1}
+    }
+    is($called_foo, 0,  "Code ref comparison: foo not called");
+    is($called_bar, 0,  "Code ref comparison: bar not called");
+    is($matched_bar, 0, "Code ref didn't match different one");
+    is($matched_foo, 1, "Code ref did match itself");
+}
+
+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 "~~" => 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");
+    is($obj->{left}, "string value of obj", "$test: left");
+    is($obj->{right}, "other arg", "$test: right");
+    ok(!$obj->{reversed}, "$test: not reversed");
+}
+
+{
+    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");
+    is($obj->{left}, "string value of obj", "$test: left");
+    is($obj->{right}, "other arg", "$test: right");
+    ok(!$obj->{reversed}, "$test: not reversed");
+}
+
+{
+    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");
+}
+
+# Okay, that'll do for now. The intricacies of the smartmatch
+# semantics are tested in t/op/smartmatch.t
+__END__
diff --git a/toke.c b/toke.c
index 820b3b8..ceb521f 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -219,6 +219,7 @@ static struct debug_tokens { const int token, type; const char *name; }
     { BITOROP,         TOKENTYPE_OPNUM,        "BITOROP" },
     { COLONATTR,       TOKENTYPE_NONE,         "COLONATTR" },
     { CONTINUE,                TOKENTYPE_NONE,         "CONTINUE" },
+    { DEFAULT,         TOKENTYPE_NONE,         "DEFAULT" },
     { DO,              TOKENTYPE_NONE,         "DO" },
     { DOLSHARP,                TOKENTYPE_NONE,         "DOLSHARP" },
     { DORDOR,          TOKENTYPE_NONE,         "DORDOR" },
@@ -234,6 +235,7 @@ static struct debug_tokens { const int token, type; const char *name; }
     { FUNC0SUB,                TOKENTYPE_OPVAL,        "FUNC0SUB" },
     { FUNC1,           TOKENTYPE_OPNUM,        "FUNC1" },
     { FUNCMETH,                TOKENTYPE_OPVAL,        "FUNCMETH" },
+    { GIVEN,           TOKENTYPE_IVAL,         "GIVEN" },
     { HASHBRACK,       TOKENTYPE_NONE,         "HASHBRACK" },
     { IF,              TOKENTYPE_IVAL,         "IF" },
     { LABEL,           TOKENTYPE_PVAL,         "LABEL" },
@@ -269,6 +271,7 @@ static struct debug_tokens { const int token, type; const char *name; }
     { UNLESS,          TOKENTYPE_IVAL,         "UNLESS" },
     { UNTIL,           TOKENTYPE_IVAL,         "UNTIL" },
     { USE,             TOKENTYPE_IVAL,         "USE" },
+    { WHEN,            TOKENTYPE_IVAL,         "WHEN" },
     { WHILE,           TOKENTYPE_IVAL,         "WHILE" },
     { WORD,            TOKENTYPE_OPVAL,        "WORD" },
     { 0,               TOKENTYPE_NONE,         0 }
@@ -454,6 +457,20 @@ S_missingterm(pTHX_ char *s)
     Perl_croak(aTHX_ "Can't find string terminator %c%s%c anywhere before EOF",q,s,q);
 }
 
+#define FEATURE_IS_ENABLED(name, namelen)                              \
+       ((0 != (PL_hints & HINT_LOCALIZE_HH))                           \
+       && feature_is_enabled(name, namelen))
+/*
+ * S_feature_is_enabled
+ * Check whether the named feature is enabled.
+ */
+STATIC bool
+S_feature_is_enabled(pTHX_ char *name, STRLEN namelen)
+{
+    HV * const hinthv = GvHV(PL_hintgv);
+    return (hinthv && hv_exists(hinthv, name, namelen));
+}
+
 /*
  * Perl_deprecate
  */
@@ -3195,6 +3212,13 @@ Perl_yylex(pTHX)
        PL_lex_brackets++;
        /* FALL THROUGH */
     case '~':
+       if (s[1] == '~'
+       && (PL_expect == XOPERATOR || PL_expect == XTERMORDORDOR)
+       && FEATURE_IS_ENABLED("~~", 2))
+       {
+           s += 2;
+           Eop(OP_SMARTMATCH);
+       }
     case ',':
        tmp = *s++;
        OPERATOR(tmp);
@@ -4552,11 +4576,31 @@ Perl_yylex(pTHX)
        case KEY_bless:
            LOP(OP_BLESS,XTERM);
 
+       case KEY_break:
+           FUN0(OP_BREAK);
+
        case KEY_chop:
            UNI(OP_CHOP);
 
        case KEY_continue:
+           /* When 'use switch' is in effect, continue has a dual
+              life as a control operator. */
+           {
+               if (!FEATURE_IS_ENABLED("switch", 6))
+                   PREBLOCK(CONTINUE);
+               else {
+                   /* 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(CONTINUE);
+                   else
+                       FUN0(OP_CONTINUE);
+               }
+           }
 
        case KEY_chdir:
            (void)gv_fetchpv("ENV",TRUE, SVt_PVHV);     /* may use HOME */
@@ -4601,6 +4645,9 @@ Perl_yylex(pTHX)
        case KEY_chroot:
            UNI(OP_CHROOT);
 
+       case KEY_default:
+           PREBLOCK(DEFAULT);
+
        case KEY_do:
            s = skipspace(s);
            if (*s == '{')
@@ -4823,6 +4870,10 @@ Perl_yylex(pTHX)
        case KEY_getlogin:
            FUN0(OP_GETLOGIN);
 
+       case KEY_given:
+           yylval.ival = CopLINE(PL_curcop);
+           OPERATOR(GIVEN);
+
        case KEY_glob:
            set_csh();
            LOP(OP_GLOB,XTERM);
@@ -5180,6 +5231,10 @@ Perl_yylex(pTHX)
            else
                TOKEN(1);       /* force error */
 
+       case KEY_say:
+           checkcomma(s,PL_tokenbuf,"filehandle");
+           LOP(OP_SAY,XREF);
+
        case KEY_chomp:
            UNI(OP_CHOMP);
        
@@ -5495,6 +5550,10 @@ Perl_yylex(pTHX)
        case KEY_vec:
            LOP(OP_VEC,XTERM);
 
+       case KEY_when:
+           yylval.ival = CopLINE(PL_curcop);
+           OPERATOR(WHEN);
+
        case KEY_while:
            yylval.ival = CopLINE(PL_curcop);
            OPERATOR(WHILE);
@@ -5871,7 +5930,7 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           goto unknown;
       }
 
-    case 3: /* 28 tokens of length 3 */
+    case 3: /* 29 tokens of length 3 */
       switch (name[0])
       {
         case 'E':
@@ -6096,6 +6155,14 @@ Perl_keyword (pTHX_ const char *name, I32 len)
         case 's':
           switch (name[1])
           {
+            case 'a':
+              if (name[2] == 'y')
+              {                                   /* say        */
+                return (FEATURE_IS_ENABLED("say", 3) ? -KEY_say : 0);
+              }
+
+              goto unknown;
+
             case 'i':
               if (name[2] == 'n')
               {                                   /* sin        */
@@ -6156,7 +6223,7 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           goto unknown;
       }
 
-    case 4: /* 40 tokens of length 4 */
+    case 4: /* 41 tokens of length 4 */
       switch (name[0])
       {
         case 'C':
@@ -6586,8 +6653,9 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           }
 
         case 'w':
-          if (name[1] == 'a')
+          switch (name[1])
           {
+            case 'a':
             switch (name[2])
             {
               case 'i':
@@ -6609,6 +6677,12 @@ Perl_keyword (pTHX_ const char *name, I32 len)
               default:
                 goto unknown;
             }
+
+            case 'h':
+              if (name[2] == 'e' &&
+                  name[3] == 'n')
+              {                                   /* when       */
+                return (FEATURE_IS_ENABLED("switch", 6) ? KEY_when : 0);
           }
 
           goto unknown;
@@ -6617,7 +6691,11 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           goto unknown;
       }
 
-    case 5: /* 36 tokens of length 5 */
+        default:
+          goto unknown;
+      }
+
+    case 5: /* 38 tokens of length 5 */
       switch (name[0])
       {
         case 'B':
@@ -6670,8 +6748,10 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           }
 
         case 'b':
-          if (name[1] == 'l' &&
-              name[2] == 'e' &&
+          switch (name[1])
+          {
+            case 'l':
+              if (name[2] == 'e' &&
               name[3] == 's' &&
               name[4] == 's')
           {                                       /* bless      */
@@ -6680,6 +6760,20 @@ Perl_keyword (pTHX_ const char *name, I32 len)
 
           goto unknown;
 
+            case 'r':
+              if (name[2] == 'e' &&
+                  name[3] == 'a' &&
+                  name[4] == 'k')
+              {                                   /* break      */
+                return (FEATURE_IS_ENABLED("switch", 6) ? -KEY_break : 0);
+              }
+
+              goto unknown;
+
+            default:
+              goto unknown;
+          }
+
         case 'c':
           switch (name[1])
           {
@@ -6793,6 +6887,17 @@ Perl_keyword (pTHX_ const char *name, I32 len)
               goto unknown;
           }
 
+        case 'g':
+          if (name[1] == 'i' &&
+              name[2] == 'v' &&
+              name[3] == 'e' &&
+              name[4] == 'n')
+          {                                       /* given      */
+            return (FEATURE_IS_ENABLED("switch", 6) ? KEY_given : 0);
+          }
+
+          goto unknown;
+
         case 'i':
           switch (name[1])
           {
@@ -7529,7 +7634,7 @@ Perl_keyword (pTHX_ const char *name, I32 len)
           goto unknown;
       }
 
-    case 7: /* 28 tokens of length 7 */
+    case 7: /* 29 tokens of length 7 */
       switch (name[0])
       {
         case 'D':
@@ -7600,9 +7705,22 @@ Perl_keyword (pTHX_ const char *name, I32 len)
               goto unknown;
 
             case 'e':
-              if (name[2] == 'f' &&
-                  name[3] == 'i' &&
-                  name[4] == 'n' &&
+              if (name[2] == 'f')
+              {
+                switch (name[3])
+                {
+                  case 'a':
+                    if (name[4] == 'u' &&
+                        name[5] == 'l' &&
+                        name[6] == 't')
+                    {                             /* default    */
+                      return (FEATURE_IS_ENABLED("switch", 6) ? KEY_default : 0);
+                    }
+
+                    goto unknown;
+
+                  case 'i':
+                    if (name[4] == 'n' &&
                   name[5] == 'e' &&
                   name[6] == 'd')
               {                                   /* defined    */
@@ -7614,6 +7732,13 @@ Perl_keyword (pTHX_ const char *name, I32 len)
             default:
               goto unknown;
           }
+              }
+
+              goto unknown;
+
+            default:
+              goto unknown;
+          }
 
         case 'f':
           if (name[1] == 'o' &&
@@ -9020,7 +9145,7 @@ S_checkcomma(pTHX_ register char *s, const char *name, const char *what)
        while (s < PL_bufend && isSPACE(*s))
            s++;
        if (*s == ',') {
-           int kw;
+           I32 kw;
            *s = '\0'; /* XXX If we didn't do this, we could const a lot of toke.c */
            kw = keyword(w, s - w) || get_cv(w, FALSE) != 0;
            *s = ',';