--- parser3/src/main/compile.tab.C 2007/10/25 10:52:48 1.115 +++ parser3/src/main/compile.tab.C 2012/05/30 03:09:07 1.155 @@ -129,12 +129,14 @@ /** @file Parser: compiler(lexical parser and grammar). - Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexander Petrosyan (http://design.ru/paf) - $Id: compile.tab.C,v 1.115 2007/10/25 10:52:48 misha Exp $ + */ +volatile const char * IDENT_COMPILE_Y = "$Id: compile.tab.C,v 1.155 2012/05/30 03:09:07 misha Exp $"; + /** @todo parser4: - cache compiled code from request to request. to do that... @@ -162,12 +164,15 @@ #include "pa_vobject.h" #include "pa_vdouble.h" #include "pa_globals.h" -#include "pa_vvoid.h" #include "pa_vmethod_frame.h" // defines #define USE_CONTROL_METHOD_NAME "USE" +#define OPTIONS_CONTROL_METHOD_NAME "OPTIONS" +#define OPTION_ALL_VARS_LOCAL_NAME "locals" +#define OPTION_PARTIAL_CLASS "partial" +#define REM_OPERATOR_NAME "rem" // forwards @@ -177,7 +182,7 @@ static int yylex(YYSTYPE* lvalp, void* p static const VBool vfalse(false); static const VBool vtrue(true); -static const VVoid vvoid; +static const VString vempty; // local convinient inplace typecast & var #undef PC @@ -213,7 +218,7 @@ typedef int YYSTYPE; /* Line 214 of yacc.c. */ -#line 217 "compile.tab.C" +#line 222 "compile.tab.C" #if ! defined (yyoverflow) || YYERROR_VERBOSE @@ -452,24 +457,24 @@ static const short int yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { - 0, 128, 128, 135, 137, 137, 138, 140, 140, 142, - 214, 214, 215, 215, 216, 217, 217, 219, 219, 263, - 263, 264, 265, 265, 266, 266, 268, 268, 272, 272, - 274, 274, 275, 275, 276, 276, 276, 280, 287, 288, - 288, 289, 291, 292, 293, 315, 316, 316, 320, 325, - 326, 327, 328, 345, 350, 353, 354, 355, 357, 360, - 357, 368, 376, 383, 384, 385, 387, 393, 394, 394, - 398, 404, 407, 404, 423, 425, 425, 427, 428, 429, - 431, 434, 431, 437, 438, 440, 441, 444, 445, 448, - 449, 451, 455, 470, 475, 476, 477, 482, 482, 484, - 484, 485, 486, 494, 499, 502, 503, 504, 505, 507, - 511, 520, 523, 520, 531, 536, 536, 537, 543, 544, - 546, 558, 570, 572, 573, 574, 575, 576, 577, 578, - 579, 581, 582, 583, 584, 585, 586, 587, 588, 590, - 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, - 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, - 611, 612, 613, 614, 615, 616, 619, 624, 633, 638, - 639, 640, 642 + 0, 133, 133, 140, 142, 142, 143, 145, 145, 147, + 256, 256, 257, 257, 258, 259, 259, 261, 261, 309, + 309, 310, 311, 311, 312, 312, 314, 314, 318, 318, + 320, 320, 321, 321, 322, 322, 322, 326, 367, 368, + 368, 369, 371, 372, 373, 426, 427, 427, 431, 444, + 445, 446, 447, 473, 478, 481, 482, 483, 485, 488, + 485, 496, 504, 511, 512, 513, 515, 521, 522, 522, + 526, 538, 541, 538, 586, 588, 588, 590, 591, 592, + 594, 597, 594, 600, 601, 603, 604, 607, 608, 611, + 612, 614, 617, 631, 636, 637, 638, 643, 643, 645, + 645, 646, 647, 655, 660, 663, 664, 665, 666, 668, + 672, 681, 684, 681, 692, 697, 697, 698, 704, 705, + 707, 720, 732, 734, 735, 736, 737, 738, 739, 740, + 741, 743, 744, 745, 746, 747, 748, 749, 750, 752, + 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, + 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, + 773, 774, 775, 776, 777, 778, 781, 786, 807, 812, + 813, 814, 816 }; #endif @@ -512,7 +517,7 @@ static const char *const yytname[] = "subvar_ref_name_rdive", "subvar_get_writes", "subvar__get_write", "class_prefix", "class_static_prefix", "class_constructor_prefix", "expr_value", "expr", "double_or_STRING", "string_inside_quotes_value", - "write_string", "void_value", "true_value", "false_value", "empty", 0 + "write_string", "empty_value", "true_value", "false_value", "empty", 0 }; #endif @@ -1424,20 +1429,20 @@ yyreduce: switch (yyn) { case 2: -#line 128 "compile.y" +#line 133 "compile.y" { - Method& method=*new Method(Method::CT_ANY, + Method* method=new Method(Method::CT_ANY, 0, 0, /*min, max numbered_params_count*/ 0/*param_names*/, 0/*local_names*/, yyvsp[0]/*parser_code*/, 0/*native_code*/); - PC.cclass->add_method(PC.alias_method(main_method_name), method); + PC.cclass->set_method(PC.alias_method(main_method_name), method); ;} break; case 9: -#line 143 "compile.y" +#line 148 "compile.y" { - const String& command=*LA2S(*yyvsp[-2]); + const String& command=LA2S(*yyvsp[-2])->trim(String::TRIM_END); YYSTYPE strings_code=yyvsp[0]; if(strings_code->count()<1*OPERATIONS_PER_OPVALUE) { strcpy(PC.error, "@"); @@ -1446,38 +1451,39 @@ yyreduce: YYERROR; } if(command==CLASS_NAME) { - if(PC.cclass->base_class()) { // already changed from default? - strcpy(PC.error, "class already have a name '"); - strncat(PC.error, PC.cclass->name().cstr(), 100); - strcat(PC.error, "'"); - YYERROR; - } if(strings_code->count()==1*OPERATIONS_PER_OPVALUE) { + PC.class_add(); // new class' name - const String& name=*LA2S(*strings_code); + const String& name=LA2S(*strings_code)->trim(String::TRIM_END); // creating the class VStateless_class* cclass=new VClass; - PC.cclass=cclass; - PC.cclass->set_name(name); - // append to request's classes - PC.request.classes().put(name, cclass); + PC.cclass_new=cclass; + PC.cclass_new->set_name(name); } else { strcpy(PC.error, "@"CLASS_NAME" must contain only one line with class name (contains more then one)"); YYERROR; } } else if(command==USE_CONTROL_METHOD_NAME) { + PC.class_add(); for(size_t i=0; icount(); i+=OPERATIONS_PER_OPVALUE) - PC.request.use_file(PC.request.main_class, *LA2S(*strings_code, i)); + PC.request.use_file(PC.request.main_class, LA2S(*strings_code, i)->trim(String::TRIM_END), PC.request.get_used_filename(PC.file_no)); } else if(command==BASE_NAME) { + if(PC.append){ + strcpy(PC.error, "can't set base while appending methods to class '"); + strncat(PC.error, PC.cclass->name().cstr(), MAX_STRING/2); + strcat(PC.error, "'"); + YYERROR; + } + PC.class_add(); if(PC.cclass->base_class()) { // already changed from default? strcpy(PC.error, "class already have a base '"); - strncat(PC.error, PC.cclass->base_class()->name().cstr(), 100); + strncat(PC.error, PC.cclass->base_class()->name().cstr(), MAX_STRING/2); strcat(PC.error, "'"); YYERROR; } if(strings_code->count()==1*OPERATIONS_PER_OPVALUE) { - const String& base_name=*LA2S(*strings_code); - if(Value* base_class_value=PC.request.classes().get(base_name)) { + const String& base_name=LA2S(*strings_code)->trim(String::TRIM_END); + if(Value* base_class_value=PC.request.get_class(base_name)) { // @CLASS == @BASE sanity check if(VStateless_class *base_class=base_class_value->get_class()) { if(PC.cclass==base_class) { @@ -1499,26 +1505,62 @@ yyreduce: strcpy(PC.error, "@"BASE_NAME" must contain sole name"); YYERROR; } + } else if(command==OPTIONS_CONTROL_METHOD_NAME) { + for(size_t i=0; icount(); i+=OPERATIONS_PER_OPVALUE) { + const String& option=LA2S(*strings_code, i)->trim(String::TRIM_END); + if(option==OPTION_ALL_VARS_LOCAL_NAME){ + PC.set_all_vars_local(); + } else if(option==OPTION_PARTIAL_CLASS){ + if(PC.cclass_new){ + if(VStateless_class* existed=PC.get_existed_class(PC.cclass_new)){ + if(!PC.reuse_existed_class(existed)){ + strcpy(PC.error, "can't append methods to '"); + strncat(PC.error, PC.cclass_new->name().cstr(), MAX_STRING/2); + strcat(PC.error, "' - the class wasn't marked as partial"); + YYERROR; + } + } else { + // marks the new class as partial. we will be able to add methods here later. + PC.cclass_new->set_partial(); + } + } else { + strcpy(PC.error, "'"OPTION_PARTIAL_CLASS"' option should be used straight after @"CLASS_NAME); + YYERROR; + } + } else if(option==method_call_type_static){ + PC.set_methods_call_type(Method::CT_STATIC); + } else if(option==method_call_type_dynamic){ + PC.set_methods_call_type(Method::CT_DYNAMIC); + } else { + strcpy(PC.error, "'"); + strncat(PC.error, option.cstr(), MAX_STRING/2); + strcat(PC.error, "' invalid option. valid options are " + "'"OPTION_PARTIAL_CLASS"', '"OPTION_ALL_VARS_LOCAL_NAME"'" + ", '"METHOD_CALL_TYPE_STATIC"' and '"METHOD_CALL_TYPE_DYNAMIC"'" + ); + YYERROR; + } + } } else { strcpy(PC.error, "'"); strncat(PC.error, command.cstr(), MAX_STRING/2); strcat(PC.error, "' invalid special name. valid names are " - "'"CLASS_NAME"', '"USE_CONTROL_METHOD_NAME"' and '"BASE_NAME"'"); + "'"CLASS_NAME"', '"USE_CONTROL_METHOD_NAME"', '"BASE_NAME"' and '"OPTIONS_CONTROL_METHOD_NAME"'."); YYERROR; } ;} break; case 13: -#line 215 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 257 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 17: -#line 219 "compile.y" +#line 261 "compile.y" { + PC.class_add(); PC.explicit_result=false; -// const String& name=*LA2S(*$2); YYSTYPE params_names_code=yyvsp[-3]; ArrayString* params_names=0; @@ -1530,137 +1572,223 @@ yyreduce: YYSTYPE locals_names_code=yyvsp[-2]; ArrayString* locals_names=0; + bool all_vars_local=false; if(int size=locals_names_code->count()) { locals_names=new ArrayString; for(int i=0; iis_vars_local()) + all_vars_local=true; Method* method=new Method( //name, - Method::CT_ANY, + GetMethodCallType(PC, *yyvsp[-4]), 0, 0/*min,max numbered_params_count*/, params_names, locals_names, - 0/*to be filled later in next {} */, 0); + 0/*to be filled later in next {} */, 0, all_vars_local); *reinterpret_cast(&yyval)=method; - - // todo: check [][;result;] ;} break; case 18: -#line 254 "compile.y" +#line 299 "compile.y" { - Method& method=*reinterpret_cast(yyvsp[-1]); - // fill in the code - method.parser_code=yyvsp[0]; - // register in class - const String& name=*LA2S(*yyvsp[-6]); - PC.cclass->add_method(PC.alias_method(name), method); + Method* method=reinterpret_cast(yyvsp[-1]); + // fill in the code + method->parser_code=yyvsp[0]; + + // register in class + const String& name=*LA2S(*yyvsp[-6]); + PC.cclass->set_method(PC.alias_method(name), method); ;} break; case 21: -#line 264 "compile.y" - {yyval=yyvsp[-1];} +#line 310 "compile.y" + {yyval=yyvsp[-1];;} break; case 25: -#line 266 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]) ;} +#line 312 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); ;} break; case 31: -#line 274 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 320 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 37: -#line 280 "compile.y" +#line 326 "compile.y" { - yyval=yyvsp[0]; /* stack: resulting value */ - changetail_or_append(*yyval, - OP_GET_ELEMENT, false, /*->*/OP_GET_ELEMENT__WRITE, - /*or */OP_WRITE_VALUE - ); /* value=pop; wcontext.write(value) */ + yyval=N(); + YYSTYPE code=yyvsp[0]; + size_t count=code->count(); + +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT + if( + count!=3 + || !maybe_change_first_opcode(*code, OP::OP_VALUE__GET_ELEMENT, /*=>*/OP::OP_VALUE__GET_ELEMENT__WRITE) + ) +#endif + +#ifdef OPTIMIZE_BYTECODE_GET_SELF_ELEMENT + if( + count!=3 + || !maybe_change_first_opcode(*code, OP::OP_WITH_SELF__VALUE__GET_ELEMENT, /*=>*/OP::OP_WITH_SELF__VALUE__GET_ELEMENT__WRITE) + ) +#endif + +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT + if( + count!=5 + || !maybe_change_first_opcode(*code, OP::OP_GET_OBJECT_ELEMENT, /*=>*/OP::OP_GET_OBJECT_ELEMENT__WRITE) + ) +#endif + +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT + if( + count!=5 + || !maybe_change_first_opcode(*code, OP::OP_GET_OBJECT_VAR_ELEMENT, /*=>*/OP::OP_GET_OBJECT_VAR_ELEMENT__WRITE) + ) +#endif + { + changetail_or_append(*code, + OP::OP_GET_ELEMENT, false, /*=>*/OP::OP_GET_ELEMENT__WRITE, + /*or */OP::OP_WRITE_VALUE + ); /* value=pop; wcontext.write(value) */ + } + + P(*yyval, *code); ;} break; case 38: -#line 287 "compile.y" - { yyval=yyvsp[0] ;} +#line 367 "compile.y" + { yyval=yyvsp[0]; ;} break; case 41: -#line 289 "compile.y" - { yyval=yyvsp[-1] ;} +#line 369 "compile.y" + { yyval=yyvsp[-1]; ;} break; case 44: -#line 293 "compile.y" +#line 373 "compile.y" { yyval=N(); - ArrayOperation* diving_code=yyvsp[0]; - const String* first_name=LA2S(*diving_code); - // self.xxx... -> xxx... - // OP_VALUE+origin+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... - if(first_name && *first_name==SELF_ELEMENT_NAME) { - O(*yyval, OP_WITH_SELF); /* stack: starting context */ - P(*yyval, *diving_code, - /* skip over... */ - diving_code->count()>=4?4/*OP_VALUE+origin+string+OP_GET_ELEMENTx*/:3/*OP_+origin+string*/); + YYSTYPE diving_code=yyvsp[0]; + size_t count=diving_code->count(); + + if(maybe_make_self(*yyval, *diving_code, count)) { + // $self. + } else + +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT + if(maybe_make_get_object_element(*yyval, *diving_code, count)){ + // optimization for $object.field + ^object.method[ + } else +#endif + +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT + if(maybe_make_get_object_var_element(*yyval, *diving_code, count)){ + // optimization for $object.$var + } else +#endif + +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT + if( + count>=4 + && (*diving_code)[0].code==OP::OP_VALUE + && (*diving_code)[3].code==OP::OP_GET_ELEMENT + ){ + // optimization + O(*yyval, + (PC.in_call_value && count==4) + ? OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR // ^object[ : OP_VALUE+origin+string+OP_GET_ELEMENT => OP_VALUE__GET_ELEMENT_OR_OPERATOR+origin+string + : OP::OP_VALUE__GET_ELEMENT // $object : OP_VALUE+origin+string+OP_GET_ELEMENT => OP_VALUE__GET_ELEMENT+origin+string + ); + P(*yyval, *diving_code, 1/*offset*/, 2/*limit*/); // copy origin+value + if(count>4) + P(*yyval, *diving_code, 4); // copy tail } else { - O(*yyval, OP_WITH_READ); /* stack: starting context */ + O(*yyval, OP::OP_WITH_READ); /* stack: starting context */ + P(*yyval, *diving_code); + } +#else + { + O(*yyval, OP::OP_WITH_READ); /* stack: starting context */ - // ^if ELEMENT -> ^if ELEMENT_OR_OPERATOR - // OP_VALUE+origin+string+OP_GET_ELEMENT. -> OP_VALUE+origin+string+OP_GET_ELEMENT_OR_OPERATOR. - if(PC.in_call_value && diving_code->count()==4) - diving_code->put(4-1, OP_GET_ELEMENT_OR_OPERATOR); + // ^if OP_ELEMENT => ^if OP_ELEMENT_OR_OPERATOR + // optimized OP_VALUE+origin+string+OP_GET_ELEMENT. => OP_VALUE+origin+string+OP_GET_ELEMENT_OR_OPERATOR. + if(PC.in_call_value && count==4) + diving_code->put(count-1, OP::OP_GET_ELEMENT_OR_OPERATOR); P(*yyval, *diving_code); } +#endif /* diving code; stack: current context */ ;} break; case 45: -#line 315 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 426 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 47: -#line 316 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 427 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 48: -#line 320 "compile.y" +#line 431 "compile.y" { - yyval=yyvsp[-1]; /* stack: context,name */ - P(*yyval, *yyvsp[0]); /* stack: context,name,constructor_value */ + yyval=N(); +#ifdef OPTIMIZE_BYTECODE_CONSTRUCT + if(maybe_optimize_construct(*yyval, *yyvsp[-1], *yyvsp[0])){ + // $a(expr), $.a(expr), $a[value], $.a[value], $self.a[value], $self.a(expr) + } else +#endif + { + P(*yyval, *yyvsp[-1]); /* stack: context,name */ + P(*yyval, *yyvsp[0]); /* stack: context,name,constructor_value */ + } ;} break; case 52: -#line 328 "compile.y" +#line 447 "compile.y" { yyval=N(); - ArrayOperation* diving_code=yyvsp[0]; - const String* first_name=LA2S(*diving_code); - // $self.xxx... -> $xxx... - // OP_VALUE+origin+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... - if(first_name && *first_name==SELF_ELEMENT_NAME) { - O(*yyval, OP_WITH_SELF); /* stack: starting context */ - P(*yyval, *diving_code, - /* skip over... */ - diving_code->count()>=4?4/*OP_VALUE+origin+string+OP_GET_ELEMENTx*/:3/*OP_+origin+string*/); - } else { - O(*yyval, OP_WITH_ROOT); /* stack: starting context */ + YYSTYPE diving_code=yyvsp[0]; + size_t count=diving_code->count(); + + if(maybe_make_self(*yyval, *diving_code, count)) { + // $self. + } else +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT + if( + count>=4 + && (*diving_code)[0].code==OP::OP_VALUE + && (*diving_code)[3].code==OP::OP_GET_ELEMENT + ){ + O(*yyval, OP::OP_WITH_ROOT__VALUE__GET_ELEMENT); + P(*yyval, *diving_code, 1/*offset*/, 2/*limit*/); // copy origin+value + if(count>4) + P(*yyval, *diving_code, 4); // tail + } else +#endif + { + O(*yyval, OP::OP_WITH_ROOT); /* stack: starting context */ P(*yyval, *diving_code); } /* diving code; stack: current context */ @@ -1668,21 +1796,21 @@ yyreduce: break; case 53: -#line 345 "compile.y" +#line 473 "compile.y" { yyval=N(); - O(*yyval, OP_WITH_WRITE); /* stack: starting context */ + O(*yyval, OP::OP_WITH_WRITE); /* stack: starting context */ P(*yyval, *yyvsp[0]); /* diving code; stack: context,name */ ;} break; case 54: -#line 350 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 478 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 58: -#line 357 "compile.y" +#line 485 "compile.y" { // allow $result_or_other_variable[ letters here any time ] *reinterpret_cast(&yyval)=PC.explicit_result; PC.explicit_result=false; @@ -1690,103 +1818,138 @@ yyreduce: break; case 59: -#line 360 "compile.y" +#line 488 "compile.y" { PC.explicit_result=*reinterpret_cast(&yyvsp[-1]); ;} break; case 60: -#line 362 "compile.y" +#line 490 "compile.y" { // stack: context, name yyval=yyvsp[-2]; // stack: context, name, value - O(*yyval, OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ + O(*yyval, OP::OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ ;} break; case 61: -#line 368 "compile.y" +#line 496 "compile.y" { yyval=N(); - O(*yyval, OP_PREPARE_TO_EXPRESSION); + O(*yyval, OP::OP_PREPARE_TO_EXPRESSION); // stack: context, name P(*yyval, *yyvsp[-1]); // stack: context, name, value - O(*yyval, OP_CONSTRUCT_EXPR); /* value=pop->as_expr_result; name=pop; context=pop; construct(context,name,value) */ + O(*yyval, OP::OP_CONSTRUCT_EXPR); /* value=pop->as_expr_result; name=pop; context=pop; construct(context,name,value) */ ;} break; case 62: -#line 376 "compile.y" +#line 504 "compile.y" { // stack: context, name yyval=N(); - OA(*yyval, OP_CURLY_CODE__CONSTRUCT, yyvsp[-1]); /* code=pop; name=pop; context=pop; construct(context,name,junction(code)) */ + OA(*yyval, OP::OP_CURLY_CODE__CONSTRUCT, yyvsp[-1]); /* code=pop; name=pop; context=pop; construct(context,name,junction(code)) */ ;} break; case 66: -#line 387 "compile.y" +#line 515 "compile.y" { yyval=N(); - OA(*yyval, OP_OBJECT_POOL, yyvsp[0]); /* stack: empty write context */ + OA(*yyval, OP::OP_OBJECT_POOL, yyvsp[0]); /* stack: empty write context */ /* some code that writes to that context */ /* context=pop; stack: context.value() */ ;} break; case 69: -#line 394 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 522 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 70: -#line 398 "compile.y" +#line 526 "compile.y" { - yyval=yyvsp[0]; /* stack: value */ - changetail_or_append(*yyval, - OP_CALL, true, /*->*/ OP_CALL__WRITE, - /*or */OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ +#ifdef OPTIMIZE_BYTECODE_CUT_REM_OPERATOR + if((*yyvsp[0]).count()) +#endif + { + yyval=yyvsp[0]; /* stack: value */ + if(!maybe_change_first_opcode(*yyval, OP::OP_CONSTRUCT_OBJECT, /*=>*/OP::OP_CONSTRUCT_OBJECT__WRITE)) + changetail_or_append(*yyval, + OP::OP_CALL, true, /*=>*/ OP::OP_CALL__WRITE, + /*or */OP::OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ + } ;} break; case 71: -#line 404 "compile.y" +#line 538 "compile.y" { PC.in_call_value=true; ;} break; case 72: -#line 407 "compile.y" +#line 541 "compile.y" { PC.in_call_value=false; ;} break; case 73: -#line 410 "compile.y" +#line 544 "compile.y" { /* ^field.$method{vasya} */ - yyval=yyvsp[-3]; /* with_xxx,diving code; stack: context,method_junction */ +#ifdef OPTIMIZE_BYTECODE_CUT_REM_OPERATOR +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT + const String* operator_name=LA2S(*yyvsp[-3], 0, OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR); +#else + const String* operator_name=LA2S(*yyvsp[-3], 1); +#endif + if(operator_name && *operator_name==REM_OPERATOR_NAME){ + yyval=N(); + } else +#endif + { + YYSTYPE params_code=yyvsp[-1]; + if(params_code->count()==3) { // probably [] case. [OP::OP_VALUE+origin+Void] + if(Value* value=LA2V(*params_code)) // it is OP_VALUE+origin+value? + if(const String * string=value->get_string()) + if(string->is_empty()) // value is empty string? + params_code=0; // ^zzz[] case. don't append lone empty param. + } + /* stack: context, method_junction */ - YYSTYPE params_code=yyvsp[-1]; - if(params_code->count()==4) { // probably [] case. [OP_VALUE+origin+Void+STORE_PARAM] - if(Value* value=LA2V(*params_code)) // it is OP_VALUE+origin+value? - if(value->is_void()) // value is VVoid? - params_code=0; // ^zzz[] case. don't append lone empty param. - } - /* stack: context, method_junction */ - OA(*yyval, OP_CALL, params_code); // method_frame=make frame(pop junction); ncontext=pop; call(ncontext,method_frame) stack: value + YYSTYPE var_code=yyvsp[-3]; + if( + var_code->count()==8 + && (*var_code)[0].code==OP::OP_VALUE__GET_CLASS + && (*var_code)[3].code==OP::OP_PREPARE_TO_CONSTRUCT_OBJECT + && (*var_code)[4].code==OP::OP_VALUE + && (*var_code)[7].code==OP::OP_GET_ELEMENT + ){ + yyval=N(); + O(*yyval, OP::OP_CONSTRUCT_OBJECT); + P(*yyval, *var_code, 1/*offset*/, 2/*limit*/); // class name + P(*yyval, *var_code, 5/*offset*/, 2/*limit*/); // constructor name + OA(*yyval, params_code); + } else + { + yyval=var_code; /* with_xxx,diving code; stack: context,method_junction */ + OA(*yyval, OP::OP_CALL, params_code); // method_frame=make frame(pop junction); ncontext=pop; call(ncontext,method_frame) stack: value + } + } ;} break; case 76: -#line 425 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 588 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 80: -#line 431 "compile.y" +#line 594 "compile.y" { // allow ^call[ letters here any time ] *reinterpret_cast(&yyval)=PC.explicit_result; PC.explicit_result=false; @@ -1794,131 +1957,129 @@ yyreduce: break; case 81: -#line 434 "compile.y" +#line 597 "compile.y" { PC.explicit_result=*reinterpret_cast(&yyvsp[-1]); ;} break; case 82: -#line 436 "compile.y" - {yyval=yyvsp[-2];} +#line 599 "compile.y" + {yyval=yyvsp[-2];;} break; case 83: -#line 437 "compile.y" - {yyval=yyvsp[-1];} +#line 600 "compile.y" + {yyval=yyvsp[-1];;} break; case 84: -#line 438 "compile.y" - {yyval=yyvsp[-1];} +#line 601 "compile.y" + {yyval=yyvsp[-1];;} break; case 86: -#line 441 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]) ;} +#line 604 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); ;} break; case 88: -#line 445 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]) ;} +#line 608 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); ;} break; case 90: -#line 449 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]) ;} +#line 612 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); ;} break; case 91: -#line 451 "compile.y" +#line 614 "compile.y" { yyval=yyvsp[0]; - O(*yyval, OP_STORE_PARAM); ;} break; case 92: -#line 455 "compile.y" +#line 617 "compile.y" { YYSTYPE expr_code=yyvsp[0]; if(expr_code->count()==3 - && (*expr_code)[0].code==OP_VALUE) { // optimizing (double/bool/incidently 'string' too) case. [OP_VALUE+origin+Double] + && (*expr_code)[0].code==OP::OP_VALUE) { // optimizing (double/bool/incidently 'string' too) case. [OP::OP_VALUE+origin+Double]. no evaluating yyval=expr_code; - O(*yyval, OP_STORE_PARAM); // no evaluating } else { - ArrayOperation* code=N(); - O(*code, OP_PREPARE_TO_EXPRESSION); + YYSTYPE code=N(); + O(*code, OP::OP_PREPARE_TO_EXPRESSION); P(*code, *expr_code); - O(*code, OP_WRITE_EXPR_RESULT); + O(*code, OP::OP_WRITE_EXPR_RESULT); yyval=N(); - OA(*yyval, OP_EXPR_CODE__STORE_PARAM, code); + OA(*yyval, OP::OP_EXPR_CODE__STORE_PARAM, code); } ;} break; case 93: -#line 470 "compile.y" +#line 631 "compile.y" { yyval=N(); - OA(*yyval, OP_CURLY_CODE__STORE_PARAM, yyvsp[0]); + OA(*yyval, OP::OP_CURLY_CODE__STORE_PARAM, yyvsp[0]); ;} break; case 98: -#line 482 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 643 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 100: -#line 484 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 645 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 102: -#line 486 "compile.y" +#line 647 "compile.y" { // we know that name_advance1 not called from ^xxx context // so we'll not check for operator call possibility as we do in name_advance2 /* stack: context */ yyval=yyvsp[0]; /* stack: context,name */ - O(*yyval, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */ + O(*yyval, OP::OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */ ;} break; case 103: -#line 494 "compile.y" +#line 655 "compile.y" { /* stack: context */ yyval=yyvsp[0]; /* stack: context,name */ - O(*yyval, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */ + O(*yyval, OP::OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */ ;} break; case 109: -#line 507 "compile.y" +#line 668 "compile.y" { yyval=yyvsp[0]; - O(*yyval, OP_GET_ELEMENT); + O(*yyval, OP::OP_GET_ELEMENT); ;} break; case 110: -#line 511 "compile.y" +#line 672 "compile.y" { - ArrayOperation* code; + YYSTYPE code; { change_string_literal_to_write_string_literal(*(code=yyvsp[-1])); P(*code, *yyvsp[0]); } yyval=N(); - OA(*yyval, OP_STRING_POOL, code); + OA(*yyval, OP::OP_STRING_POOL, code); ;} break; case 111: -#line 520 "compile.y" +#line 681 "compile.y" { // allow $result_or_other_variable[ letters here any time ] *reinterpret_cast(&yyval)=PC.explicit_result; PC.explicit_result=false; @@ -1926,46 +2087,46 @@ yyreduce: break; case 112: -#line 523 "compile.y" +#line 684 "compile.y" { PC.explicit_result=*reinterpret_cast(&yyvsp[-1]); ;} break; case 113: -#line 525 "compile.y" +#line 686 "compile.y" { yyval=N(); - OA(*yyval, OP_OBJECT_POOL, yyvsp[-2]); /* stack: empty write context */ + OA(*yyval, OP::OP_OBJECT_POOL, yyvsp[-2]); /* stack: empty write context */ /* some code that writes to that context */ /* context=pop; stack: context.value() */ ;} break; case 114: -#line 531 "compile.y" +#line 692 "compile.y" { yyval=N(); - O(*yyval, OP_WITH_READ); + O(*yyval, OP::OP_WITH_READ); P(*yyval, *yyvsp[0]); ;} break; case 116: -#line 536 "compile.y" - { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]) ;} +#line 697 "compile.y" + { yyval=yyvsp[-1]; P(*yyval, *yyvsp[0]); ;} break; case 117: -#line 537 "compile.y" +#line 698 "compile.y" { yyval=yyvsp[0]; - O(*yyval, OP_GET_ELEMENT__WRITE); + O(*yyval, OP::OP_GET_ELEMENT__WRITE); ;} break; case 120: -#line 546 "compile.y" +#line 707 "compile.y" { yyval=yyvsp[-1]; // stack: class name string if(*LA2S(*yyval) == BASE_NAME) { // pseudo BASE class @@ -1976,263 +2137,276 @@ yyreduce: YYERROR; } } - O(*yyval, OP_GET_CLASS); + // optimized OP_VALUE+origin+string+OP_GET_CLASS => OP_VALUE__GET_CLASS+origin+string + maybe_change_first_opcode(*yyval, OP::OP_VALUE, OP::OP_VALUE__GET_CLASS); ;} break; case 121: -#line 558 "compile.y" +#line 720 "compile.y" { yyval=yyvsp[-1]; if(!PC.in_call_value) { strcpy(PC.error, ":: not allowed here"); YYERROR; } - O(*yyval, OP_PREPARE_TO_CONSTRUCT_OBJECT); + O(*yyval, OP::OP_PREPARE_TO_CONSTRUCT_OBJECT); ;} break; case 128: -#line 577 "compile.y" - { yyval = yyvsp[-1] ;} +#line 739 "compile.y" + { yyval = yyvsp[-1]; ;} break; case 129: -#line 578 "compile.y" - { yyval = yyvsp[-1] ;} +#line 740 "compile.y" + { yyval = yyvsp[-1]; ;} break; case 130: -#line 579 "compile.y" +#line 741 "compile.y" { yyval = yyvsp[-1]; ;} break; case 131: -#line 581 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_NEG) ;} +#line 743 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_NEG); ;} break; case 132: -#line 582 "compile.y" - { yyval=yyvsp[0] ;} +#line 744 "compile.y" + { yyval=yyvsp[0]; ;} break; case 133: -#line 583 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_INV) ;} +#line 745 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_INV); ;} break; case 134: -#line 584 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_NOT) ;} +#line 746 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_NOT); ;} break; case 135: -#line 585 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_DEF) ;} +#line 747 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_DEF); ;} break; case 136: -#line 586 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_IN) ;} +#line 748 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_IN); ;} break; case 137: -#line 587 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_FEXISTS) ;} +#line 749 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_FEXISTS); ;} break; case 138: -#line 588 "compile.y" - { yyval=yyvsp[0]; O(*yyval, OP_DEXISTS) ;} +#line 750 "compile.y" + { yyval=yyvsp[0]; O(*yyval, OP::OP_DEXISTS); ;} break; case 139: -#line 590 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_SUB) ;} +#line 752 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_SUB); ;} break; case 140: -#line 591 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_ADD) ;} +#line 753 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_ADD); ;} break; case 141: -#line 592 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_MUL) ;} +#line 754 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_MUL); ;} break; case 142: -#line 593 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_DIV) ;} +#line 755 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_DIV); ;} break; case 143: -#line 594 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_MOD) ;} +#line 756 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_MOD); ;} break; case 144: -#line 595 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_INTDIV) ;} +#line 757 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_INTDIV); ;} break; case 145: -#line 596 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_BIN_SL) ;} +#line 758 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_BIN_SL); ;} break; case 146: -#line 597 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_BIN_SR) ;} +#line 759 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_BIN_SR); ;} break; case 147: -#line 598 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_BIN_AND) ;} +#line 760 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_BIN_AND); ;} break; case 148: -#line 599 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_BIN_OR) ;} +#line 761 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_BIN_OR); ;} break; case 149: -#line 600 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_BIN_XOR) ;} +#line 762 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_BIN_XOR); ;} break; case 150: -#line 601 "compile.y" - { yyval=yyvsp[-2]; OA(*yyval, OP_NESTED_CODE, yyvsp[0]); O(*yyval, OP_LOG_AND) ;} +#line 763 "compile.y" + { yyval=yyvsp[-2]; OA(*yyval, OP::OP_NESTED_CODE, yyvsp[0]); O(*yyval, OP::OP_LOG_AND); ;} break; case 151: -#line 602 "compile.y" - { yyval=yyvsp[-2]; OA(*yyval, OP_NESTED_CODE, yyvsp[0]); O(*yyval, OP_LOG_OR) ;} +#line 764 "compile.y" + { yyval=yyvsp[-2]; OA(*yyval, OP::OP_NESTED_CODE, yyvsp[0]); O(*yyval, OP::OP_LOG_OR); ;} break; case 152: -#line 603 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_LOG_XOR) ;} +#line 765 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_LOG_XOR); ;} break; case 153: -#line 604 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_LT) ;} +#line 766 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_LT); ;} break; case 154: -#line 605 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_GT) ;} +#line 767 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_GT); ;} break; case 155: -#line 606 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_LE) ;} +#line 768 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_LE); ;} break; case 156: -#line 607 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_GE) ;} +#line 769 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_GE); ;} break; case 157: -#line 608 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_EQ) ;} +#line 770 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_EQ); ;} break; case 158: -#line 609 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_NUM_NE) ;} +#line 771 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_NUM_NE); ;} break; case 159: -#line 610 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_LT) ;} +#line 772 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_LT); ;} break; case 160: -#line 611 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_GT) ;} +#line 773 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_GT); ;} break; case 161: -#line 612 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_LE) ;} +#line 774 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_LE); ;} break; case 162: -#line 613 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_GE) ;} +#line 775 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_GE); ;} break; case 163: -#line 614 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_EQ) ;} +#line 776 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_EQ); ;} break; case 164: -#line 615 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_STR_NE) ;} +#line 777 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_STR_NE); ;} break; case 165: -#line 616 "compile.y" - { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP_IS) ;} +#line 778 "compile.y" + { yyval=yyvsp[-2]; P(*yyval, *yyvsp[0]); O(*yyval, OP::OP_IS); ;} break; case 166: -#line 619 "compile.y" +#line 781 "compile.y" { - // optimized from OP_STRING->OP_VALUE for doubles + // optimized OP_STRING => OP_VALUE for doubles maybe_change_string_literal_to_double_literal(*(yyval=yyvsp[0])); ;} break; case 167: -#line 624 "compile.y" +#line 786 "compile.y" { +#ifdef OPTIMIZE_BYTECODE_STRING_POOL + // it brakes ^if(" 09 "){...} + YYSTYPE code=yyvsp[0]; + yyval=N(); + if(code->count()==3 && maybe_change_first_opcode(*code, OP::OP_STRING__WRITE, OP::OP_VALUE)){ + // optimized OP_STRING__WRITE+origin+value => OP_VALUE+origin+value without starting OP_STRING_POOL + P(*yyval, *code); + } else { + OA(*yyval, OP::OP_STRING_POOL, code); /* stack: empty write context */ + } +#else yyval=N(); - OA(*yyval, OP_STRING_POOL, yyvsp[0]); /* stack: empty write context */ + OA(*yyval, OP::OP_STRING_POOL, yyvsp[0]); /* stack: empty write context */ +#endif /* some code that writes to that context */ /* context=pop; stack: context.get_string() */ ;} break; case 168: -#line 633 "compile.y" +#line 807 "compile.y" { - // optimized from OP_STRING+OP_WRITE_VALUE to OP_STRING__WRITE - change_string_literal_to_write_string_literal(*(yyval=yyvsp[0])) + // optimized OP_STRING+OP_WRITE_VALUE => OP_STRING__WRITE + change_string_literal_to_write_string_literal(*(yyval=yyvsp[0])); ;} break; case 169: -#line 638 "compile.y" - { yyval=VL(/*we know that we will not change it*/const_cast(&vvoid), 0, 0, 0) ;} +#line 812 "compile.y" + { yyval=VL(/*we know that we will not change it*/const_cast(&vempty), 0, 0, 0); ;} break; case 170: -#line 639 "compile.y" - { yyval = VL(/*we know that we will not change it*/const_cast(&vtrue), 0, 0, 0) ;} +#line 813 "compile.y" + { yyval = VL(/*we know that we will not change it*/const_cast(&vtrue), 0, 0, 0); ;} break; case 171: -#line 640 "compile.y" - { yyval = VL(/*we know that we will not change it*/const_cast(&vfalse), 0, 0, 0) ;} +#line 814 "compile.y" + { yyval = VL(/*we know that we will not change it*/const_cast(&vfalse), 0, 0, 0); ;} break; case 172: -#line 642 "compile.y" - { yyval=N() ;} +#line 816 "compile.y" + { yyval=N(); ;} break; } /* Line 1010 of yacc.c. */ -#line 2236 "compile.tab.C" +#line 2410 "compile.tab.C" yyvsp -= yylen; yyssp -= yylen; @@ -2457,7 +2631,7 @@ yyreturn: } -#line 644 "compile.y" +#line 818 "compile.y" #endif @@ -2550,7 +2724,7 @@ case LS_DEF_COMMENT: default: switch(*pc.source) { // ^escaping some punctuators - case '^': case '$': case ';': + case '^': case '$': case ';': case '@': case '(': case ')': case '[': case ']': case '{': case '}': @@ -2578,7 +2752,7 @@ default: pc.string.append_strdup_know_length(begin, end-begin); } // #HH ? - if(pc.source[0]=='#' && pc.source[1] && pc.source[2]) { + if(pc.source[1] && isxdigit(pc.source[1]) && pc.source[2] && isxdigit(pc.source[2])) { char c=(char)( hex_value[(unsigned char)pc.source[1]]*0x10+ hex_value[(unsigned char)pc.source[2]]); @@ -2597,7 +2771,14 @@ default: // skip analysis = forced literal continue; } - break; + // just escaped char + // reset piece 'begin' position & line + begin=pc.source; + begin_pos=pc.pos; + // skip over _ after ^ + pc.source++; pc.pos.col++; + // skip analysis = forced literal + continue; } break; } @@ -2894,14 +3075,18 @@ default: case 'd': if(end==begin) // right after whitespace if(pc.source[0]=='e' && pc.source[1]=='f') { // def - skip_analized=2; - result=DEF; - goto break2; + switch(pc.source[2]){ + case ' ': case '\t': case '\n': case '"': case '\'': case '^': case '$': // non-quoted string without whitespace after 'def' is not allowed + skip_analized=2; + result=DEF; + goto break2; + } + // error: incorrect char after 'def' } break; case 't': if(end==begin) // right after whitespace - if(pc.source[0]=='r' && pc.source[1]=='u' && pc.source[2]=='e') { // def + if(pc.source[0]=='r' && pc.source[1]=='u' && pc.source[2]=='e') { // true skip_analized=3; result=LITERAL_TRUE; goto break2; @@ -2909,7 +3094,7 @@ default: break; case 'f': if(end==begin) // right after whitespace - if(pc.source[0]=='a' && pc.source[1]=='l' && pc.source[2]=='s' && pc.source[3]=='e') { // def + if(pc.source[0]=='a' && pc.source[1]=='l' && pc.source[2]=='s' && pc.source[3]=='e') { // false skip_analized=4; result=LITERAL_FALSE; goto break2; @@ -2986,7 +3171,7 @@ default: case ']': case '}': case ')': case '"': case '\'': case '<': case '>': // these stand for HTML brackets AND expression binary ops - case '+': case '*': case '/': case '%': + case '+': case '*': case '/': case '\\': case '%': case '&': case '|': case '=': case '!': // common delimiters @@ -3216,12 +3401,9 @@ default: break2: if(end!=begin) { // there is last piece? - if((c=='@' || c==0) && end[-1]=='\n') { // we are before LS_DEF_NAME or EOF? - // strip last \n - end--; - if(end!=begin && end[-1]=='\n') // allow one empty line before LS_DEF_NAME + if(c=='@' || c==0) // we are before LS_DEF_NAME or EOF? + while(end!=begin && end[-1]=='\n') // trim all empty lines before LS_DEF_NAME and EOF end--; - } if(end!=begin && pc.ls!=LS_USER_COMMENT) { // last piece still alive and not comment? if(!pc.string_start) pc.string_start=begin_pos;