--- parser3/src/main/execute.C 2001/10/31 13:07:35 1.201 +++ parser3/src/main/execute.C 2001/12/21 12:47:56 1.208 @@ -2,9 +2,9 @@ Parser: executor part of request class. Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + Author: Alexander Petrosyan (http://paf.design.ru) - $Id: execute.C,v 1.201 2001/10/31 13:07:35 paf Exp $ + $Id: execute.C,v 1.208 2001/12/21 12:47:56 paf Exp $ */ #include "pa_opcode.h" @@ -25,7 +25,7 @@ //#define DEBUG_EXECUTE -const uint ANTI_ENDLESS_EXECUTE_RECOURSION=200; +const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500; #ifdef DEBUG_EXECUTE char *opcode_name[]={ @@ -292,7 +292,7 @@ void Request::execute(const Array& ops) } case OP_REDUCE_EWPOOL: { - value=wcontext->result(); + value=&wcontext->result(); flang=static_cast(reinterpret_cast(POP())); wcontext=static_cast(POP()); PUSH(value); @@ -371,12 +371,14 @@ void Request::execute(const Array& ops) // this is a constructor call if(Value *value=called_class->create_new_value(pool())) { - // some stateless_object creatable derivates + // some stateless_class creatable derivates self=value; - } else { - // stateful object - self=NEW VObject(pool(), *called_class); - } + } else + throw Exception(0, 0, + &frame->name(), + "is not a constructor, system class '%s' can be constructed only implicitly", + called_class->name().cstr()); + frame->write(*self, String::UL_CLEAN // not used, always an object, not string ); @@ -400,7 +402,7 @@ void Request::execute(const Array& ops) } frame->set_self(*self); - root=rcontext=wcontext=frame; + rcontext=wcontext=frame; { // take object or class from any wrappers // and substitute class alias to the class they are called AS @@ -414,6 +416,7 @@ void Request::execute(const Array& ops) method.call_type==call_type) { // allowed call type? try { if(method.native_code) { // native code? + // root unchanged, so that ^for ^foreach & co may write to locals method.check_actual_numbered_params( frame->junction.self, frame->name(), frame->numbered_params()); @@ -421,15 +424,17 @@ void Request::execute(const Array& ops) *this, frame->name(), frame->numbered_params()); // execute it } else { // parser code - if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { - anti_endless_execute_recoursion=0; // give @exception a chance - throw Exception(0, 0, - &frame->name(), - "endless recursion detected"); + root=frame; + { // anti_endless_execute_recoursion + if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { + anti_endless_execute_recoursion=0; // give @exception a chance + throw Exception(0, 0, + &frame->name(), + "call canceled - endless recursion detected"); + } + execute(*method.parser_code); // execute it + anti_endless_execute_recoursion--; } - - execute(*method.parser_code); // execute it - anti_endless_execute_recoursion--; } } catch(...) { // record it to stack trace @@ -443,7 +448,7 @@ void Request::execute(const Array& ops) call_type==Method::CT_STATIC?"statically":"dynamically"); } - value=wcontext->result(); + value=&wcontext->result(); wcontext=static_cast(POP()); rcontext=POP(); @@ -758,7 +763,7 @@ Value *Request::get_element() { if(Method* method=OP.get_method(name)) { // maybe operator? // as if that method were in self and we have normal dynamic method here Junction& junction=*NEW Junction(pool(), - *root/*self*/, self->get_class(), method, 0,0,0,0); + *root, self->get_class(), method, 0,0,0,0); value=NEW VJunction(junction); } if(value) @@ -812,14 +817,25 @@ Value& Request::process(Value& value, co self=&junction->self; root=junction->root; rcontext=junction->rcontext; - execute(*junction->code); + + { // anti_endless_execute_recoursion + if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { + anti_endless_execute_recoursion=0; // give @exception a chance + throw Exception(0, 0, + name, + "junction evaluation canceled - endless recursion detected"); + } + execute(*junction->code); + anti_endless_execute_recoursion--; + } + if(using_code_frame) { // CodeFrame soul: // string writes were intercepted // returning them as the result of getting code-junction result=NEW VString(*frame->get_string()); } else - result=frame->result(); + result=&frame->result(); wcontext=static_cast(POP()); rcontext=POP(); @@ -837,8 +853,8 @@ Value& Request::process(Value& value, co return *result; } -const String *Request::execute_method(Value& aself, const Method& method, - bool return_cstr) { +const String *Request::execute_method(Value& aself, const Method& method, + bool return_cstr) { PUSH(self); PUSH(root); PUSH(rcontext); @@ -852,11 +868,32 @@ const String *Request::execute_method(Va execute(*method.parser_code); // result - const String *result; - if(return_cstr) - result=&wcontext->as_string(); - else - result=0; // ignore result + const String *result=return_cstr ? &wcontext->as_string() : 0; + + wcontext=static_cast(POP()); + rcontext=POP(); + root=POP(); + self=static_cast(POP()); + + // return + return result; +} + +const String& Request::execute_method(VMethodFrame& amethodFrame, const Method& method) { + PUSH(self); + PUSH(root); + PUSH(rcontext); + PUSH(wcontext); + + // initialize contexts + root=rcontext=self=&amethodFrame; + wcontext=&amethodFrame; + + // execute! + execute(*method.parser_code); + + // result + const String& result=wcontext->as_string(); wcontext=static_cast(POP()); rcontext=POP(); @@ -868,18 +905,17 @@ const String *Request::execute_method(Va } const String *Request::execute_virtual_method(Value& aself, - const String& method_name, - bool return_cstr) { + 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, return_cstr); + return execute_method(aself, *method, true /*return_cstr*/); return 0; } const String *Request::execute_nonvirtual_method(VStateless_class& aclass, - const String& method_name, + const String& method_name, bool return_cstr) { if(const Method *method=aclass.get_method(method_name)) return execute_method(aclass, *method, return_cstr);