--- parser3/src/classes/op.C 2005/11/22 15:40:17 1.161 +++ parser3/src/classes/op.C 2006/04/09 13:38:46 1.164 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_OP_C="$Date: 2005/11/22 15:40:17 $"; +static const char * const IDENT_OP_C="$Date: 2006/04/09 13:38:46 $"; #include "classes.h" #include "pa_vmethod_frame.h" @@ -22,7 +22,7 @@ static const char * const IDENT_OP_C="$D // limits -#define MAX_LOOPS 10000 +#define MAX_LOOPS 20000 // defines @@ -38,10 +38,20 @@ public: VClassMAIN(); }; +// defines for globals + +#define CYCLE_DATA_NAME "CYCLE-DATA" + +// globals + +//^for & co +String cycle_data_name(CYCLE_DATA_NAME); + // defines for statics #define SWITCH_DATA_NAME "SWITCH-DATA" #define CACHE_DATA_NAME "CACHE-DATA" + #define EXCEPTION_VAR_NAME "exception" // statics @@ -53,6 +63,7 @@ static const String cache_data_name(CACH static const String exception_var_name(EXCEPTION_VAR_NAME); + // local defines #define CACHE_EXCEPTION_HANDLED_CACHE_NAME "cache" @@ -229,11 +240,16 @@ static void _rem(Request&, MethodParams& } static void _while(Request& r, MethodParams& params) { + Temp_hash_value + cycle_data_setter(r.classes_conf, cycle_data_name, /*any not null flag*/&r); + Value& vcondition=params.as_junction(0, "condition must be expression"); - Value& body=params.as_junction(1, "body must be code"); + Value& body_code=params.as_junction(1, "body must be code"); + Value* delim_maybe_code=params.count()>2?¶ms[2]:0; // while... int endless_loop_count=0; + bool need_delim=false; while(true) { if(++endless_loop_count>=MAX_LOOPS) // endless loop? throw Exception("parser.runtime", @@ -245,8 +261,18 @@ static void _while(Request& r, MethodPar if(!condition) // ...condition is true break; - // write processed body - r.write_pass_lang(r.process(body)); + StringOrValue sv_processed=r.process(body_code); + Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); + const String* s_processed=sv_processed.get_string(); + if(delim_maybe_code && s_processed && s_processed->length()) { // delimiter set and we have body + if(need_delim) // need delim & iteration produced string? + r.write_pass_lang(r.process(*delim_maybe_code)); + need_delim=true; + } + r.write_pass_lang(sv_processed); + + if(lskip==Request::SKIP_BREAK) + break; } } @@ -255,7 +281,28 @@ static void _use(Request& r, MethodParam r.use_file(r.main_class, vfile.as_string()); } +static void set_skip(Request& r, Request::Skip askip) { + void* data=r.classes_conf.get(cycle_data_name); + if(!data) + throw Exception("parser.runtime", + 0, + "without cycle"); + + r.set_skip(askip); +} + +static void _break(Request& r, MethodParams&) { + set_skip(r, Request::SKIP_BREAK); +} + +static void _continue(Request& r, MethodParams&) { + set_skip(r, Request::SKIP_CONTINUE); +} + static void _for(Request& r, MethodParams& params) { + Temp_hash_value + cycle_data_setter(r.classes_conf, cycle_data_name, /*any not null flag*/&r); + const String& var_name=params.as_string(0, "var name must be string"); int from=params.as_int(1, "from must be int", r); int to=params.as_int(2, "to must be int", r); @@ -276,6 +323,7 @@ static void _for(Request& r, MethodParam vint->set_int(i); StringOrValue sv_processed=r.process(body_code); + Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); const String* s_processed=sv_processed.get_string(); if(delim_maybe_code && s_processed && s_processed->length()) { // delimiter set and we have body if(need_delim) // need delim & iteration produced string? @@ -283,6 +331,9 @@ static void _for(Request& r, MethodParam need_delim=true; } r.write_pass_lang(sv_processed); + + if(lskip==Request::SKIP_BREAK) + break; } } @@ -379,6 +430,8 @@ static void _case(Request& r, MethodPara int count=params.count(); Value& code=params.as_junction(--count, "case result must be code"); + Value& searching=data->searching; + bool we_are_searching_string_or_void=searching.is_string() || searching.is_void(); for(int i=0; isearching.is_string()) - matches=data->searching.as_string() == value.as_string(); + if(we_are_searching_string_or_void) + matches=searching.as_string() == value.as_string(); else - matches=data->searching.as_double() == value.as_double(); + matches=searching.as_double() == value.as_double(); if(matches) { if(data->found) @@ -810,11 +863,15 @@ VClassMAIN::VClassMAIN(): VClass() { add_native_method("rem", Method::CT_ANY, _rem, 1, 10000); // ^while(condition){code} - add_native_method("while", Method::CT_ANY, _while, 2, 2); + add_native_method("while", Method::CT_ANY, _while, 2, 3); // ^use[file] add_native_method("use", Method::CT_ANY, _use, 1, 1); + // ^break[] + add_native_method("break", Method::CT_ANY, _break, 0, 0); + // ^continue[] + add_native_method("continue", Method::CT_ANY, _continue, 0, 0); // ^for[i](from-number;to-number-inclusive){code}[delim] add_native_method("for", Method::CT_ANY, _for, 3+1, 3+1+1);