From: Robin Houston Date: Sat, 17 Dec 2005 20:44:31 +0000 (+0000) Subject: latest switch/say/~~ X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=0d863452f5cac86322a90184dc68dbf446006ed7;p=p5sagit%2Fp5-mst-13.2.git latest switch/say/~~ Message-Id: <20051217204431.GB28940@rpc142.cs.man.ac.uk> p4raw-id: //depot/perl@26400 --- diff --git a/MANIFEST b/MANIFEST index 8c53662..7260b76 100644 --- 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 --- 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())) diff --git a/embed.fnc b/embed.fnc index 958672d..eb19e98 100644 --- 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 --- a/embed.h +++ b/embed.h @@ -520,6 +520,7 @@ #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 @@ -563,6 +564,7 @@ #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 @@ -1097,6 +1099,7 @@ #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 @@ -1126,6 +1129,9 @@ #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) @@ -1192,16 +1198,22 @@ #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) @@ -1368,6 +1380,7 @@ #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 @@ -1707,8 +1720,10 @@ #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 @@ -1739,6 +1754,7 @@ #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 @@ -1754,6 +1770,7 @@ #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 @@ -1773,10 +1790,12 @@ #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 @@ -1886,10 +1905,12 @@ #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 @@ -1979,6 +2000,7 @@ #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 @@ -2009,6 +2031,7 @@ #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 @@ -2542,6 +2565,7 @@ #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) @@ -2584,6 +2608,7 @@ #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) @@ -3108,6 +3133,7 @@ #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) @@ -3137,6 +3163,9 @@ #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) @@ -3203,16 +3232,22 @@ #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) @@ -3380,6 +3415,7 @@ #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) @@ -3719,8 +3755,10 @@ #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) @@ -3751,6 +3789,7 @@ #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) @@ -3766,6 +3805,7 @@ #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) @@ -3785,10 +3825,12 @@ #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) @@ -3898,10 +3940,12 @@ #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) @@ -3991,6 +4035,7 @@ #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) @@ -4021,6 +4066,7 @@ #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) diff --git a/ext/B/B/Deparse.pm b/ext/B/B/Deparse.pm index 218ab9c..958b137 100644 --- a/ext/B/B/Deparse.pm +++ b/ext/B/B/Deparse.pm @@ -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. diff --git a/ext/B/t/concise-xs.t b/ext/B/t/concise-xs.t index acce386..fe45773e 100644 --- a/ext/B/t/concise-xs.t +++ b/ext/B/t/concise-xs.t @@ -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"); diff --git a/ext/B/t/f_map.t b/ext/B/t/f_map.t index 25bed73..8e614a6 100644 --- a/ext/B/t/f_map.t +++ b/ext/B/t/f_map.t @@ -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 diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t index 4f0d782..c7a8152 100644 --- a/ext/B/t/optree_samples.t +++ b/ext/B/t/optree_samples.t @@ -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 diff --git a/ext/IO/lib/IO/Handle.pm b/ext/IO/lib/IO/Handle.pm index 329d26a..551988b 100644 --- a/ext/IO/lib/IO/Handle.pm +++ b/ext/IO/lib/IO/Handle.pm @@ -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; diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index 9394734..9a1c92b 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -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 diff --git a/global.sym b/global.sym index 1d86272..eb73405 100644 --- a/global.sym +++ b/global.sym @@ -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 diff --git a/keywords.h b/keywords.h index 3af51b8..c4834ac 100644 --- a/keywords.h +++ b/keywords.h @@ -33,231 +33,236 @@ #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: */ diff --git a/keywords.pl b/keywords.pl index fe745d4..2f3a95a 100755 --- a/keywords.pl +++ b/keywords.pl @@ -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 index 0000000..e0981d0 --- /dev/null +++ b/lib/feature.pm @@ -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 +# no longer throws the error C. +# 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, +and will be parsed only when the appropriate feature pragma is in +scope. + +=head2 The 'switch' feature + +C tells the compiler to enable the Perl 6 +given/when construct from here to the end of the enclosing BLOCK. + +See L for details. + +=head2 The '~~' feature + +C tells the compiler to enable the Perl 6 +smart match C<~~> operator from here to the end of the enclosing BLOCK. + +See L for details. + +=head2 The 'say' feature + +C tells the compiler to enable the Perl 6 +C function from here to the end of the enclosing BLOCK. + +See L 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 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 index 0000000..a60644f --- /dev/null +++ b/lib/feature.t @@ -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"; diff --git a/lib/overload.pm b/lib/overload.pm index b189044..8a07efe 100644 --- a/lib/overload.pm +++ b/lib/overload.pm @@ -422,7 +422,7 @@ The dereference operators must be specified explicitly they will not be passed t =item * I - "nomethod", "fallback", "=", + "nomethod", "fallback", "=", "~~", see L>. @@ -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. + =over 16 =item * C diff --git a/lib/warnings.t b/lib/warnings.t index f23d9e6..55e2794 100644 --- a/lib/warnings.t +++ b/lib/warnings.t @@ -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 () { - $line++; - last if /^__END__/ ; - } - - { - local $/ = undef; - $files++; - @prgs = (@prgs, $file, split "\n########\n", ) ; - } - 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 --- 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 --- a/op.h +++ b/op.h @@ -110,6 +110,9 @@ Deprecated. Use C 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 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 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 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 }; diff --git a/opcode.h b/opcode.h index 587c138..5ebe99f 100644 --- 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 diff --git a/opcode.pl b/opcode.pl index 898a248..19030a6 100755 --- 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 diff --git a/opnames.h b/opnames.h index ba6a26b..e428e1c 100644 --- 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 --- 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]; diff --git a/perl_keyword.pl b/perl_keyword.pl index bb8bc74..d0471f6 100644 --- a/perl_keyword.pl +++ b/perl_keyword.pl @@ -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 < (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 --- a/perly.h +++ b/perly.h @@ -53,47 +53,50 @@ 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. */ @@ -120,47 +123,50 @@ #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 diff --git a/perly.tab b/perly.tab index 48ac1b3..aab8ed0 100644 --- 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 --- a/perly.y +++ b/perly.y @@ -41,6 +41,7 @@ %token LABEL %token FORMAT SUB ANONSUB PACKAGE USE %token WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR +%token GIVEN WHEN DEFAULT %token LOOPEX DOTDOT %token FUNC0 FUNC1 FUNC UNIOP LSTOP %token RELOP EQOP MULOP ADDOP @@ -49,7 +50,7 @@ %token COLONATTR %type prog decl format startsub startanonsub startformsub mintro -%type progstart remember mremember '&' savescope +%type progstart remember mremember '&' savescope mydefsv %type block mblock lineseq line loop cond else %type expr term subscripted scalar ary hsh arylen star amper sideff %type argexpr nexpr texpr iexpr mexpr mnexpr miexpr @@ -57,6 +58,7 @@ %type formname subname proto subbody cont my_scalar %type subattrlist myattrlist mysubrout myattrterm myterm %type termbinop termunop anonymous termdo +%type switch case %type 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 && diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 5bc399f..8b50bd3 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -491,6 +491,13 @@ to compress something else. See L. (F) Only hard references may be blessed. This is how Perl "enforces" encapsulation of objects. See L. +=item Can't "break" in a loop topicaizer +(F) You called C, but you're in a C block rather than +a C block. You probably meant to use C or C. + +=item Can't "break" outside a given block +(F) You called C, but you're not inside a C block. + =item Can't call 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, but you're not inside a C +or C 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 +loop nor a C block. (Note that this error is issued on exit +from the C block, so you won't get the error if the match fails, +or if you use an explicit C.) + =item Can't weaken a nonreference (F) You attempted to weaken something that was not a reference. Only diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 2cb16d0..0a87ece 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -134,7 +134,7 @@ X X X X C, C, C, C, C, C, C, C, C, C, C, C, C, C, -C, C, C, C, C, C, C, C, C, C, C, C, C, C @@ -156,6 +156,13 @@ X C, C, C, C, C, C, C, C, C, C, C, C, C, C +=item Keywords related to switch + +C, C + +(These are only available if you enable the "switch" feature. +See L and L.) + =item Keywords related to scoping C, C, C, C, C, C, C @@ -592,6 +599,13 @@ that CLASSNAME is a true value. See L. +=item break + +Break out of a C block. + +This keyword is enabled by the "switch" feature: see L +for more information. + =item caller EXPR X X X X @@ -890,6 +904,8 @@ L. =item continue BLOCK X +=item continue + C is actually a flow control statement rather than a function. If there is a C BLOCK attached to a BLOCK (typically in a C or C), it is always executed just before the conditional is about to @@ -917,6 +933,12 @@ Omitting the C section is semantically equivalent to using an empty one, logically enough. In that case, C goes directly back to check the condition at the top of the loop. +If the "switch" feature is enabled, C is also a +function that will break out of the current C or C +block, and fall through to the next case. See L and +L for more information. + + =item cos EXPR X X X X @@ -4666,6 +4688,20 @@ sets C<$!> (errno). If FILENAME is omitted, uses C<$_>. The substitution operator. See L. +=item say FILEHANDLE LIST +X + +=item say LIST + +=item say + +Just like C, but implicitly appends a newline. +C is simply an abbreviation for C, +and C works just like C. + +This keyword is only available when the "say" feature is +enabled: see L. + =item scalar EXPR X X diff --git a/pod/perlop.pod b/pod/perlop.pod index 84cd866..db105e3 100644 --- a/pod/perlop.pod +++ b/pod/perlop.pod @@ -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 +Binary "~~" does a smart match between its arguments. Smart matching +is described in L. +This operator is only available if you enable the "~~" feature: +see L for more information. +X<~~> + "lt", "le", "ge", "gt" and "cmp" use the collation (sort) order specified by the current locale if C is in effect. See L. diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index c819b94..cc91e31 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -466,8 +466,8 @@ rather than merely terminating the inner one. And it's faster because Perl executes a C statement more rapidly than it would the equivalent C loop. -=head2 Basic BLOCKs and Switch Statements -X X X +=head2 Basic BLOCKs +X 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 true in C, C, or contrary to popular belief C blocks, which do I count as loops.) The C 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 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 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 X X X X -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 and C are analogous +to C and C 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.) +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 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 statement is to use C'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 +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 or C<$foo =~ /REGEX/>, +or a negated regular expression match C<$foo !~ /REGEX/>. + +=item o + +a comparison (such as C<$_ E 10> or C<$x gt "abc"> + +=item o + +C, C, or C + +=item o -Another interesting approach to a switch statement is arrange -for a C block to return the proper value: +A negated expression C or C, 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 +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 behaves exactly like C, which is +to say that it always matches. + +See L for more information +on smart matching. + +=head3 Fall-through + +You can use the C 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 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, you can use a C 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 block, there is an implicit C. +You can override that with an explicit C if you're only +interested in the first match. + +This doesn't work if you explicitly specify a loop variable, +as in C. You have to use the default +variable C<$_>. (You can use C.) + +=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 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 diff --git a/pp.sym b/pp.sym index 19be260..1d1b876 100644 --- 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: diff --git a/pp_ctl.c b/pp_ctl.c index a3f76cf..2f563ef 100644 --- 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) { diff --git a/pp_proto.h b/pp_proto.h index dddb013..a64e335 100644 --- a/pp_proto.h +++ b/pp_proto.h @@ -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 --- 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 index 0000000..62cec80 --- /dev/null +++ b/t/io/say.t @@ -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 index 0000000..1de44f6 --- /dev/null +++ b/t/lib/feature/nonesuch @@ -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 index 0000000..4b507e6 --- /dev/null +++ b/t/lib/feature/say @@ -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 index 0000000..16ea7f8 --- /dev/null +++ b/t/lib/feature/smartmatch @@ -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 index 0000000..022cbd1 --- /dev/null +++ b/t/lib/feature/switch @@ -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 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 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 diff --git a/t/op/cproto.t b/t/op/cproto.t index d37118e..3f3e871 100644 --- a/t/op/cproto.t +++ b/t/op/cproto.t @@ -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 index 0000000..6275f40 --- /dev/null +++ b/t/op/smartmatch.t @@ -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/, ; +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 index 0000000..fc88a13 --- /dev/null +++ b/t/op/switch.t @@ -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 --- 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 = ',';