|
|
| version 1.202, 2001/11/01 16:27:20 | version 1.209, 2002/01/24 17:18:48 |
|---|---|
| Line 2 | Line 2 |
| Parser: executor part of request class. | Parser: executor part of request class. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru) |
| $Id$ | $Id$ |
| */ | */ |
| Line 25 | Line 25 |
| //#define DEBUG_EXECUTE | //#define DEBUG_EXECUTE |
| const uint ANTI_ENDLESS_EXECUTE_RECOURSION=200; | const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| char *opcode_name[]={ | char *opcode_name[]={ |
| // literals | // literals |
| "VALUE", "CURLY_CODE__STORE_PARAM", "EXPR_CODE__STORE_PARAM", | "VALUE", "CURLY_CODE__STORE_PARAM", "EXPR_CODE__STORE_PARAM", |
| "NESTED_CODE", | |
| // actions | // actions |
| "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE", | "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE", |
| Line 89 void debug_dump(Pool& pool, int level, c | Line 90 void debug_dump(Pool& pool, int level, c |
| case OP_CURLY_CODE__STORE_PARAM: | case OP_CURLY_CODE__STORE_PARAM: |
| case OP_EXPR_CODE__STORE_PARAM: | case OP_EXPR_CODE__STORE_PARAM: |
| case OP_CURLY_CODE__CONSTRUCT: | case OP_CURLY_CODE__CONSTRUCT: |
| case OP_NESTED_CODE: | |
| const Array *local_ops=reinterpret_cast<const Array *>(i.next()); | const Array *local_ops=reinterpret_cast<const Array *>(i.next()); |
| debug_dump(pool, level+1, *local_ops); | debug_dump(pool, level+1, *local_ops); |
| } | } |
| Line 99 void debug_dump(Pool& pool, int level, c | Line 101 void debug_dump(Pool& pool, int level, c |
| #define PUSH(value) stack.push(value) | #define PUSH(value) stack.push(value) |
| #define POP() static_cast<Value *>(stack.pop()) | #define POP() static_cast<Value *>(stack.pop()) |
| #define POP_NAME() static_cast<Value *>(stack.pop())->as_string() | #define POP_NAME() static_cast<Value *>(stack.pop())->as_string() |
| #define POP_CODE() static_cast<Array *>(stack.pop()) | |
| void Request::execute(const Array& ops) { | void Request::execute(const Array& ops) { |
| // _asm int 3; | // _asm int 3; |
| Line 118 void Request::execute(const Array& ops) | Line 121 void Request::execute(const Array& ops) |
| Value *value; | Value *value; |
| Value *a; Value *b; | Value *a; Value *b; |
| Array *b_code; | |
| switch(op.code) { | switch(op.code) { |
| // param in next instruction | // param in next instruction |
| case OP_VALUE: | case OP_VALUE: |
| Line 237 void Request::execute(const Array& ops) | Line 241 void Request::execute(const Array& ops) |
| value->set_name(name); | value->set_name(name); |
| break; | break; |
| } | } |
| case OP_NESTED_CODE: | |
| { | |
| Array *local_ops=static_cast<Array *>(i.next()); | |
| #ifdef DEBUG_EXECUTE | |
| debug_printf(pool(), " (%d)\n", local_ops->size()); | |
| debug_dump(pool(), 1, *local_ops); | |
| #endif | |
| PUSH(local_ops); | |
| break; | |
| } | |
| case OP_WRITE_VALUE: | case OP_WRITE_VALUE: |
| { | { |
| value=POP(); | value=POP(); |
| Line 292 void Request::execute(const Array& ops) | Line 306 void Request::execute(const Array& ops) |
| } | } |
| case OP_REDUCE_EWPOOL: | case OP_REDUCE_EWPOOL: |
| { | { |
| value=wcontext->result(); | value=&wcontext->result(); |
| flang=static_cast<String::Untaint_lang>(reinterpret_cast<int>(POP())); | flang=static_cast<String::Untaint_lang>(reinterpret_cast<int>(POP())); |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| PUSH(value); | PUSH(value); |
| Line 371 void Request::execute(const Array& ops) | Line 385 void Request::execute(const Array& ops) |
| // this is a constructor call | // this is a constructor call |
| if(Value *value=called_class->create_new_value(pool())) { | if(Value *value=called_class->create_new_value(pool())) { |
| // some stateless_object creatable derivates | // some stateless_class creatable derivates |
| self=value; | self=value; |
| } else { | } else |
| // stateful object | throw Exception(0, 0, |
| self=NEW VObject(pool(), *called_class); | &frame->name(), |
| } | "is not a constructor, system class '%s' can be constructed only implicitly", |
| called_class->name().cstr()); | |
| frame->write(*self, | frame->write(*self, |
| String::UL_CLEAN // not used, always an object, not string | String::UL_CLEAN // not used, always an object, not string |
| ); | ); |
| Line 423 void Request::execute(const Array& ops) | Line 439 void Request::execute(const Array& ops) |
| frame->name(), frame->numbered_params()); // execute it | frame->name(), frame->numbered_params()); // execute it |
| } else { // parser code | } else { // parser code |
| root=frame; | root=frame; |
| if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { | { // anti_endless_execute_recoursion |
| anti_endless_execute_recoursion=0; // give @exception a chance | if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { |
| throw Exception(0, 0, | anti_endless_execute_recoursion=0; // give @exception a chance |
| &frame->name(), | throw Exception(0, 0, |
| "endless recursion detected"); | &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(...) { | } catch(...) { |
| // record it to stack trace | // record it to stack trace |
| Line 445 void Request::execute(const Array& ops) | Line 462 void Request::execute(const Array& ops) |
| call_type==Method::CT_STATIC?"statically":"dynamically"); | call_type==Method::CT_STATIC?"statically":"dynamically"); |
| } | } |
| value=wcontext->result(); | value=&wcontext->result(); |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| Line 632 void Request::execute(const Array& ops) | Line 649 void Request::execute(const Array& ops) |
| } | } |
| case OP_LOG_AND: | case OP_LOG_AND: |
| { | { |
| b=POP(); a=POP(); | b_code=POP_CODE(); a=POP(); |
| value=NEW VBool(pool(), a->as_bool() && b->as_bool()); | bool result; |
| if(a->as_bool()) { | |
| execute(*b_code); | |
| b=POP(); | |
| result=b->as_bool(); | |
| } else | |
| result=false; | |
| value=NEW VBool(pool(), result); | |
| PUSH(value); | PUSH(value); |
| break; | break; |
| } | } |
| case OP_LOG_OR: | case OP_LOG_OR: |
| { | { |
| b=POP(); a=POP(); | b_code=POP_CODE(); a=POP(); |
| value=NEW VBool(pool(), a->as_bool() || b->as_bool()); | bool result; |
| if(a->as_bool()) | |
| result=true; | |
| else { | |
| execute(*b_code); | |
| b=POP(); | |
| result=b->as_bool(); | |
| } | |
| value=NEW VBool(pool(), result); | |
| PUSH(value); | PUSH(value); |
| break; | break; |
| } | } |
| Line 814 Value& Request::process(Value& value, co | Line 846 Value& Request::process(Value& value, co |
| self=&junction->self; | self=&junction->self; |
| root=junction->root; | root=junction->root; |
| rcontext=junction->rcontext; | 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) { | if(using_code_frame) { |
| // CodeFrame soul: | // CodeFrame soul: |
| // string writes were intercepted | // string writes were intercepted |
| // returning them as the result of getting code-junction | // returning them as the result of getting code-junction |
| result=NEW VString(*frame->get_string()); | result=NEW VString(*frame->get_string()); |
| } else | } else |
| result=frame->result(); | result=&frame->result(); |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| Line 839 Value& Request::process(Value& value, co | Line 882 Value& Request::process(Value& value, co |
| return *result; | return *result; |
| } | } |
| const String *Request::execute_method(Value& aself, const Method& method, | const String *Request::execute_method(Value& aself, const Method& method, |
| bool return_cstr) { | bool return_cstr) { |
| PUSH(self); | PUSH(self); |
| PUSH(root); | PUSH(root); |
| PUSH(rcontext); | PUSH(rcontext); |
| Line 854 const String *Request::execute_method(Va | Line 897 const String *Request::execute_method(Va |
| execute(*method.parser_code); | execute(*method.parser_code); |
| // result | // result |
| const String *result; | const String *result=return_cstr ? &wcontext->as_string() : 0; |
| if(return_cstr) | |
| result=&wcontext->as_string(); | wcontext=static_cast<WContext *>(POP()); |
| else | rcontext=POP(); |
| result=0; // ignore result | root=POP(); |
| self=static_cast<VAliased *>(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<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| Line 870 const String *Request::execute_method(Va | Line 934 const String *Request::execute_method(Va |
| } | } |
| const String *Request::execute_virtual_method(Value& aself, | const String *Request::execute_virtual_method(Value& aself, |
| const String& method_name, | const String& method_name) { |
| bool return_cstr) { | |
| if(Value *value=aself.get_element(method_name)) | if(Value *value=aself.get_element(method_name)) |
| if(Junction *junction=value->get_junction()) | if(Junction *junction=value->get_junction()) |
| if(const Method *method=junction->method) | if(const Method *method=junction->method) |
| return execute_method(aself, *method, return_cstr); | return execute_method(aself, *method, true /*return_cstr*/); |
| return 0; | return 0; |
| } | } |
| const String *Request::execute_nonvirtual_method(VStateless_class& aclass, | const String *Request::execute_nonvirtual_method(VStateless_class& aclass, |
| const String& method_name, | const String& method_name, |
| bool return_cstr) { | bool return_cstr) { |
| if(const Method *method=aclass.get_method(method_name)) | if(const Method *method=aclass.get_method(method_name)) |
| return execute_method(aclass, *method, return_cstr); | return execute_method(aclass, *method, return_cstr); |