--- parser3/src/classes/op.C 2016/11/01 23:10:40 1.243 +++ parser3/src/classes/op.C 2019/11/22 22:37:30 1.252 @@ -1,7 +1,7 @@ /** @file Parser: parser @b operators. - Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ @@ -18,7 +18,7 @@ #include "pa_vclass.h" #include "pa_charset.h" -volatile const char * IDENT_OP_C="$Id: op.C,v 1.243 2016/11/01 23:10:40 moko Exp $"; +volatile const char * IDENT_OP_C="$Id: op.C,v 1.252 2019/11/22 22:37:30 moko Exp $"; // defines @@ -216,10 +216,11 @@ static void _process(Request& r, MethodP // after restoring current-request-lang // maybe-execute @main[] if(main_method) { - VMethodFrame frame(*main_method, r.get_method_frame()->caller(), *target_self); - frame.empty_params(); - r.call(frame); - r.write(frame.result()); + METHOD_FRAME_ACTION(*main_method, r.get_method_frame()->caller(), *target_self, { + frame.empty_params(); + r.call(frame); + r.write(frame.result()); + }); } } @@ -247,7 +248,7 @@ static void _while(Request& r, MethodPar break; Value& sv_processed=r.process(body_code); - Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); + TempSkip4Delimiter skip(r); const String* s_processed=sv_processed.get_string(); if(s_processed && !s_processed->is_empty()) { // we have body @@ -258,7 +259,7 @@ static void _while(Request& r, MethodPar } r.write(sv_processed); - if(lskip==Request::SKIP_BREAK) + if(skip.check_break()) break; } } else { @@ -270,9 +271,8 @@ static void _while(Request& r, MethodPar break; r.process_write(body_code); - Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); - if(lskip==Request::SKIP_BREAK) + if(r.check_skip_break()) break; } } @@ -282,6 +282,7 @@ static void _use(Request& r, MethodParam Value& vfile=params.as_no_junction(0, FILE_NAME_MUST_NOT_BE_CODE); bool allow_class_replace=false; + const String* use_origin=0; if(params.count()==2) if(HashStringValue* options=params.as_hash(1)) { @@ -296,15 +297,23 @@ static void _use(Request& r, MethodParam allow_class_replace=r.process(*value).as_bool(); } - if(valid_options!=options->count()) - throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); + if(key == "origin") { + valid_options++; + use_origin=&value->as_string(); + } + + if(valid_options!=options->count()) + throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); } } + if(!use_origin) + if(VMethodFrame* caller=r.get_method_frame()->caller()) + use_origin=r.get_method_filespec(&caller->method); + Temp_class_replace class_replace(r, allow_class_replace); - // _use could be called from the parser3 method only, so caller is always defined - r.use_file(r.main_class, vfile.as_string(), r.get_method_filename(&r.get_method_frame()->caller()->method)); + r.use_file(r.main_class, vfile.as_string(), use_origin); } static void set_skip(Request& r, Request::Skip askip) { @@ -321,6 +330,13 @@ static void _continue(Request& r, Method if(!params.count() || params.as_bool(0, "condition must be expression", r)) set_skip(r, Request::SKIP_CONTINUE); } +static void _return(Request& r, MethodParams& params) { + VMethodFrame& caller=*r.get_method_frame()->caller(); + if(params.count()) + r.put_element(caller, Symbols::RESULT_SYMBOL, ¶ms[0]); + r.set_skip_return(caller); +} + static void _for(Request& r, MethodParams& params) { InCycle temp(r); @@ -344,7 +360,7 @@ static void _for(Request& r, MethodParam vint->set_int(i); Value& sv_processed=r.process(body_code); - Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); + TempSkip4Delimiter skip(r); const String* s_processed=sv_processed.get_string(); if(s_processed && !s_processed->is_empty()) { // we have body @@ -355,7 +371,7 @@ static void _for(Request& r, MethodParam } r.write(sv_processed); - if(lskip==Request::SKIP_BREAK) + if(skip.check_break()) break; } } else { @@ -363,9 +379,8 @@ static void _for(Request& r, MethodParam vint->set_int(i); r.process_write(body_code); - Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); - if(lskip==Request::SKIP_BREAK) + if(r.check_skip_break()) break; } } @@ -451,7 +466,7 @@ static void _switch(Request& r, MethodPa // because of stacked WWrapper used there as wcontext r.process(cases_code); if(Value* selected_code=data->found? data->found: data->_default) - r.write(r.process(*selected_code)); + r.process_write(*selected_code); } static void _case(Request& r, MethodParams& params) { @@ -689,20 +704,13 @@ struct Cache_get_result { static Cache_get_result cache_get(Request_charsets& charsets, const String& file_spec, time_t now) { Cache_get_result result={0, false}; - File_read_result file=file_read(charsets, file_spec, - false/*as_text*/, - 0, //no params - false/*fail_on_read_problem*/); - if(file.success && file.length/* ignore reads which are empty due to - non-unary open+lockEX conflict with lockSH */) { - - Data_string_serialized_prolog& prolog= - *reinterpret_cast(file.str); - + File_read_result file=file_read(charsets, file_spec, false /*as_text*/, 0, /*no params*/ false /*fail_on_read_problem*/); + if(file.success && file.length /*ignore reads which are empty due to non-unary open+lockEX conflict with lockSH*/) { + + Data_string_serialized_prolog& prolog = *reinterpret_cast(file.str); + String* body=new String; - if( - file.length>=sizeof(Data_string_serialized_prolog) - && prolog.version==DATA_STRING_SERIALIZED_VERSION) { + if(file.length>=sizeof(Data_string_serialized_prolog) && prolog.version==DATA_STRING_SERIALIZED_VERSION) { if(body->deserialize(sizeof(Data_string_serialized_prolog), file.str, file.length)) { result.body=body; result.expired=prolog.expires <= now; @@ -712,8 +720,8 @@ static Cache_get_result cache_get(Reques return result; } -static time_t as_expires(Request& r, MethodParams& params, - int index, time_t now) { + +static time_t as_expires(Request& r, MethodParams& params, int index, time_t now) { time_t result; if(Value* vdate=params[index].as(VDATE_TYPE)) result=(time_t)(static_cast(vdate)->get_time()); @@ -828,7 +836,7 @@ static void _try_operator(Request& r, Me // process finally code but ignore the result if(finally_code){ Temp_skip temp(r); - Value &finally_result=r.process(*finally_code); + /* Value &finally_result= */ r.process(*finally_code); } rethrow; } @@ -935,6 +943,10 @@ VClassMAIN::VClassMAIN(): VClass(MAIN_CL // ^continue(condition) add_native_method("continue", Method::CT_ANY, _continue, 0, 1, Method::CO_WITHOUT_FRAME); + // ^return[] + // ^return[result] + add_native_method("return", Method::CT_ANY, _return, 0, 1); + // ^for[i](from-number;to-number-inclusive){code}[delim] add_native_method("for", Method::CT_ANY, _for, 3+1, 3+1+1);