--- parser3/src/main/execute.C 2017/01/13 13:50:28 1.403 +++ parser3/src/main/execute.C 2020/12/31 12:08:35 1.413 @@ -1,7 +1,7 @@ /** @file Parser: executor part of request class. - Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2020 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ @@ -21,7 +21,7 @@ #include "pa_vimage.h" #include "pa_wwrapper.h" -volatile const char * IDENT_EXECUTE_C="$Id: execute.C,v 1.403 2017/01/13 13:50:28 moko Exp $" IDENT_PA_OPCODE_H IDENT_PA_OPERATION_H IDENT_PA_VCODE_FRAME_H IDENT_PA_WWRAPPER_H; +volatile const char * IDENT_EXECUTE_C="$Id: execute.C,v 1.413 2020/12/31 12:08:35 moko Exp $" IDENT_PA_OPCODE_H IDENT_PA_OPERATION_H IDENT_PA_VCODE_FRAME_H IDENT_PA_WWRAPPER_H; //#define DEBUG_EXECUTE @@ -280,11 +280,7 @@ void Request::execute(ArrayOperation& op DEBUG_PRINT_STRING(name) - VStateless_class* vclass=get_class(name); - if(!vclass) - throw Exception(PARSER_RUNTIME, &name, "class is undefined"); - - stack.push(*vclass); + stack.push(get_class_ref(name)); break; } @@ -297,11 +293,7 @@ void Request::execute(ArrayOperation& op DEBUG_PRINT_STRING(name) - VStateless_class* vclass=get_class(name); - if(!vclass) - throw Exception(PARSER_RUNTIME, &name, "class is undefined"); - - stack.push(*new VBaseClassWrapper(*vclass, get_self())); + stack.push(*new VBaseClassWrapper(get_class_ref(name), get_self())); break; } @@ -450,7 +442,6 @@ void Request::execute(ArrayOperation& op const String& name=stack.pop().string(); debug_name=&name; Value& ncontext=stack.pop().value(); if(const VJunction* vjunction=ncontext.put_element(name, &value)) - if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) throw Exception(PARSER_RUNTIME, 0, "property value can not be code, use [] or () brackets"); break; @@ -672,6 +663,8 @@ void Request::execute(ArrayOperation& op case OP::OP_OBJECT_POOL: { + debug_name=0; + ArrayOperation& local_ops=*i.next().ops; WContext *saved_wcontext=wcontext; @@ -849,9 +842,7 @@ void Request::execute(ArrayOperation& op DEBUG_PRINT_STRING(class_name) - VStateless_class* vclass=get_class(class_name); - if(!vclass) - throw Exception(PARSER_RUNTIME, &class_name, "class is undefined"); + VStateless_class& vclass=get_class_ref(class_name); debug_origin=i.next().origin; Value& vconstructor_name=*i.next().value; @@ -859,9 +850,9 @@ void Request::execute(ArrayOperation& op DEBUG_PRINT_STRING(constructor_name) - Junction* constructor_junction=get_element(*vclass, constructor_name).get_junction(); + Junction* constructor_junction=get_element(vclass, constructor_name).get_junction(); if(!constructor_junction) - throw Exception(PARSER_RUNTIME, &constructor_name, "constructor must be declared in class '%s'", vclass->type()); + throw Exception(PARSER_RUNTIME, &constructor_name, "constructor must be declared in class '%s'", vclass.type()); ArrayOperation* local_ops=i.next().ops; DEBUG_PRINT_OPS(local_ops) @@ -869,7 +860,7 @@ void Request::execute(ArrayOperation& op Value *result; { - Value& object=construct(*vclass, *constructor_junction->method); + Value& object=construct(vclass, *constructor_junction->method); CONSTRUCTOR_FRAME_ACTION(*constructor_junction->method, method_frame, object, { METHOD_PARAMS_ACTION(call(frame)); object.enable_default_setter(); @@ -927,14 +918,14 @@ void Request::execute(ArrayOperation& op case OP::OP_FEXISTS: { Value& a=stack.pop().value(); - Value& value=VBool::get(file_exist(absolute(a.as_string()))); + Value& value=VBool::get(file_exist(full_disk_path(a.as_string()))); stack.push(value); break; } case OP::OP_DEXISTS: { Value& a=stack.pop().value(); - Value& value=VBool::get(dir_exists(absolute(a.as_string()))); + Value& value=VBool::get(dir_exists(full_disk_path(a.as_string()))); stack.push(value); break; } @@ -1250,34 +1241,33 @@ Value& Request::get_element4call(Value& void Request::put_element(Value& ncontext, const String& name, Value* value) { // put_element can return property-setting-junction - if(const VJunction* vjunction=ncontext.put_element(name, value)) - if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) { - const Junction& junction = vjunction->junction(); - int param_count=junction.method->params_count; - - if(junction.auto_name){ - // default setter - if(param_count!=2) - throw Exception(PARSER_RUNTIME, 0, "default setter method must have TWO parameters (has %d parameters)", param_count); - - Value* params[2] = { new VString(*junction.auto_name), value }; - - CONSTRUCTOR_FRAME_ACTION(*junction.method, method_frame /*caller*/, junction.self, { - frame.store_params(params, 2); - Temp_disable_default_setter temp(junction.self); - call(frame); - }); - } else { - // setter - if(param_count!=1) - throw Exception(PARSER_RUNTIME, 0, "setter method must have ONE parameter (has %d parameters)", param_count); - - CONSTRUCTOR_FRAME_ACTION(*junction.method, method_frame /*caller*/, junction.self, { - frame.store_params(&value, 1); - call(frame); - }); - } + if(const VJunction* vjunction=ncontext.put_element(name, value)) { + const Junction& junction = vjunction->junction(); + int param_count=junction.method->params_count; + + if(junction.auto_name) { + // default setter + if(param_count!=2) + throw Exception(PARSER_RUNTIME, 0, "default setter method must have TWO parameters (has %d parameters)", param_count); + + Value* params[2] = { new VString(*junction.auto_name), value }; + + CONSTRUCTOR_FRAME_ACTION(*junction.method, method_frame /*caller*/, junction.self, { + frame.store_params(params, 2); + Temp_disable_default_setter temp(junction.self); + call(frame); + }); + } else { + // setter + if(param_count!=1) + throw Exception(PARSER_RUNTIME, 0, "setter method must have ONE parameter (has %d parameters)", param_count); + + CONSTRUCTOR_FRAME_ACTION(*junction.method, method_frame /*caller*/, junction.self, { + frame.store_params(&value, 1); + call(frame); + }); } + } } Value& Request::process_getter(Junction& junction) { @@ -1432,47 +1422,58 @@ void Request::process_write(Value& input write(input_value); } -const String* Request::execute_method(Value& aself, const Method& method, Value* optional_param, bool do_return_string) { - METHOD_FRAME_ACTION(method, method_frame/*caller*/, aself, { +const String* Request::execute_method(VStateless_class& aclass, const String& method_name, Value* optional_param) { + if(const Method *method=aclass.get_method(method_name)){ + METHOD_FRAME_ACTION(*method, method_frame/*caller*/, aclass, { - if(optional_param && method.params_count>0) { - frame.store_params(&optional_param, 1); - } else { - frame.empty_params(); - } + if(optional_param && method->params_count>0) { + frame.store_params(&optional_param, 1); + } else { + frame.empty_params(); + } - // prevent non-string writes for better error reporting - if(do_return_string) + // prevent non-string writes for better error reporting frame.write(frame); + + call(frame); - call(frame); - - return do_return_string ? frame.get_string() : 0; - }); + Value &result=frame.result(); + if(const String* sresult=result.get_string()){ + return sresult; + } + result.bark("is '%s', it has no string representation", &method_name); + }); + } + return 0; } -Request::Execute_nonvirtual_method_result -Request::execute_nonvirtual_method(VStateless_class& aclass, const String& method_name, VString* optional_param, bool do_return_string) { - Execute_nonvirtual_method_result result; - result.method=aclass.get_method(method_name); - if(result.method) - result.string=execute_method(aclass, *result.method, optional_param, do_return_string); - return result; -} +bool Request::execute_method_if_exists(VStateless_class& aclass, const String& method_name, Value* optional_param) { + if(const Method *method=aclass.get_method(method_name)){ + METHOD_FRAME_ACTION(*method, method_frame/*caller*/, aclass, { -const String* Request::execute_virtual_method(Value& aself, const String& method_name) { - if(Value* value=aself.get_element(method_name)) - if(Junction* junction=value->get_junction()) - if(const Method *method=junction->method) - return execute_method(aself, *method, 0/*no params*/, true); - - return 0; + if(optional_param && method->params_count>0) { + frame.store_params(&optional_param, 1); + } else { + frame.empty_params(); + } + + call(frame); + }); + return true; + } + return false; } const String* Request::get_method_filespec(const Method* method){ + Operation::Origin origin=get_method_origin(method); + return origin.file_no ? get_used_filespec(origin.file_no) : NULL; +} + +const Operation::Origin Request::get_method_origin(const Method* method){ + Operation::Origin origin={0, 0, 0}; + if(ArrayOperation* code=method->parser_code) if(code){ - Operation::Origin origin={0, 0, 0}; Array_iterator i(*code); while( i.has_next() ){ switch( i.next().code ){ @@ -1539,9 +1540,9 @@ const String* Request::get_method_filesp default: break; } if(origin.file_no) - return get_used_filespec(origin.file_no); + return origin; } } - return 0; + return origin; }