|
|
| version 1.241, 2002/06/12 11:40:32 | version 1.253, 2002/08/14 14:18:28 |
|---|---|
| Line 3 | Line 3 |
| Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | |
| */ | */ |
| static const char* IDENT_EXECUTE_C="$Date$"; | |
| #include "pa_opcode.h" | #include "pa_opcode.h" |
| #include "pa_array.h" | #include "pa_array.h" |
| #include "pa_request.h" | #include "pa_request.h" |
| Line 231 void Request::execute(const Array& ops) | Line 231 void Request::execute(const Array& ops) |
| value=POP(); | value=POP(); |
| const String& name=POP_NAME(); | const String& name=POP_NAME(); |
| Value *ncontext=POP(); | Value *ncontext=POP(); |
| ncontext->put_element(name, value); | ncontext->put_element(name, value, false); |
| break; | break; |
| } | } |
| case OP_CONSTRUCT_EXPR: | case OP_CONSTRUCT_EXPR: |
| Line 242 void Request::execute(const Array& ops) | Line 242 void Request::execute(const Array& ops) |
| value=POP(); | value=POP(); |
| const String& name=POP_NAME(); | const String& name=POP_NAME(); |
| Value *ncontext=POP(); | Value *ncontext=POP(); |
| ncontext->put_element(name, value->as_expr_result()); | ncontext->put_element(name, value->as_expr_result(), false); |
| break; | break; |
| } | } |
| case OP_CURLY_CODE__CONSTRUCT: | case OP_CURLY_CODE__CONSTRUCT: |
| Line 263 void Request::execute(const Array& ops) | Line 263 void Request::execute(const Array& ops) |
| value=NEW VJunction(j); | value=NEW VJunction(j); |
| const String& name=POP_NAME(); | const String& name=POP_NAME(); |
| Value *ncontext=POP(); | Value *ncontext=POP(); |
| ncontext->put_element(name, value); | ncontext->put_element(name, value, false); |
| break; | break; |
| } | } |
| case OP_NESTED_CODE: | case OP_NESTED_CODE: |
| Line 304 void Request::execute(const Array& ops) | Line 304 void Request::execute(const Array& ops) |
| case OP_GET_ELEMENT_OR_OPERATOR: | case OP_GET_ELEMENT_OR_OPERATOR: |
| { | { |
| // maybe they do ^object.method[] call, remember the fact | |
| wcontext->set_somebody_entered_some_object(true); | |
| //_asm int 3; | //_asm int 3; |
| value=get_element(last_get_element_name, true); | value=get_element(last_get_element_name, true); |
| PUSH(value); | PUSH(value); |
| Line 314 void Request::execute(const Array& ops) | Line 311 void Request::execute(const Array& ops) |
| } | } |
| case OP_GET_ELEMENT: | case OP_GET_ELEMENT: |
| { | { |
| // maybe they do ^object.method[] call, remember the fact | |
| wcontext->set_somebody_entered_some_object(true); | |
| //_asm int 3; | //_asm int 3; |
| value=get_element(last_get_element_name, false); | value=get_element(last_get_element_name, false); |
| PUSH(value); | PUSH(value); |
| Line 482 void Request::execute(const Array& ops) | Line 476 void Request::execute(const Array& ops) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| &frame.name(), | &frame.name(), |
| "method is static and can not be used as constructor"); | "method is static and can not be used as constructor"); |
| } else { | } else |
| // this is not constructor call | self=&frame.junction.self; |
| // not ^name.method call, name:method call; and | |
| // is context object or class & is it my class or my parent's class and? | |
| VStateless_class *read_class=rcontext->get_class(); | |
| if( | |
| !(wcontext->get_somebody_entered_some_object() && | |
| !wcontext->get_somebody_entered_some_class()) && | |
| read_class && read_class->is_or_derived_from(*called_class)) // yes | |
| self=rcontext; // dynamic call | |
| else // no, not me or relative of mine (=total stranger) | |
| self=&frame.junction.self; // static call | |
| } | |
| frame.set_self(*self); | frame.set_self(*self); |
| Line 504 void Request::execute(const Array& ops) | Line 486 void Request::execute(const Array& ops) |
| rcontext=wcontext=&frame; | rcontext=wcontext=&frame; |
| { | { |
| // take object or class from any wrappers | |
| // and substitute class alias to the class they are called AS | |
| Temp_alias temp_alias(*self->get_aliased(), *frame.junction.vclass); | |
| const Method& method=*frame.junction.method; | const Method& method=*frame.junction.method; |
| Method::Call_type call_type= | Method::Call_type call_type= |
| called_class==self ? Method::CT_STATIC : Method::CT_DYNAMIC; | called_class==self ? Method::CT_STATIC : Method::CT_DYNAMIC; |
| Line 545 void Request::execute(const Array& ops) | Line 523 void Request::execute(const Array& ops) |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| root=POP(); | root=POP(); |
| self=static_cast<VAliased *>(POP()); | self=static_cast<Value *>(POP()); |
| #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS | #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS |
| if(const String *s=value->get_string()) | if(const String *s=value->get_string()) |
| Line 554 void Request::execute(const Array& ops) | Line 532 void Request::execute(const Array& ops) |
| if(op.code==OP_CALL__WRITE) { | if(op.code==OP_CALL__WRITE) { |
| write_assign_lang(result, last_get_element_name); | write_assign_lang(result, last_get_element_name); |
| // forget the fact they've entered some ^object.method[]. | |
| // see OP_GET_ELEMENT | |
| wcontext->set_somebody_entered_some_object(false); | |
| } else { // OP_CALL | } else { // OP_CALL |
| PUSH(&result.as_value()); | PUSH(&result.as_value()); |
| } | } |
| Line 848 void Request::execute(const Array& ops) | Line 823 void Request::execute(const Array& ops) |
| } | } |
| case OP_IS: | case OP_IS: |
| { | { |
| //_asm int 3; | |
| b=POP(); a=POP(); | b=POP(); a=POP(); |
| value=NEW VBool(pool(), b->as_string() == a->type()); | value=NEW VBool(pool(), a->is(b->as_string().cstr(), false)); |
| PUSH(value); | PUSH(value); |
| break; | break; |
| } | } |
| Line 868 Value *Request::get_element(const String | Line 842 Value *Request::get_element(const String |
| const String& name=POP_NAME(); remember_name=&name; | const String& name=POP_NAME(); remember_name=&name; |
| Value *ncontext=POP(); | Value *ncontext=POP(); |
| Value *value=0; | Value *value=0; |
| if(can_call_operator) | if(can_call_operator) { |
| if(Method* method=OP.get_method(name)) { // looking operator of that name FIRST | if(Method* method=OP.get_method(name)) { // looking operator of that name FIRST |
| // as if that method were in self and we have normal dynamic method here | // as if that method were in self and we have normal dynamic method here |
| Junction& junction=*NEW Junction(pool(), | Junction& junction=*NEW Junction(pool(), |
| *root, self->get_class(), method, 0,0,0,0); | *root, self->get_class(), method, 0,0,0,0); |
| value=NEW VJunction(junction); | value=NEW VJunction(junction); |
| } | } |
| } | |
| if(!value) { | |
| if(!wcontext->get_constructing() // not constructing | |
| && wcontext->get_somebody_entered_some_class() ) // ^class:method | |
| if(VStateless_class *called_class=ncontext->get_class()) | |
| if(VStateless_class *read_class=rcontext->get_class()) | |
| if(read_class->derived_from(*called_class)) // current derived from called | |
| if(Value *base_object=self->base_object()) { // doing DYNAMIC call | |
| Temp_derived(*base_object, 0); // temporarily prevent go-back-down virtual calls | |
| value=base_object->get_element(name, base_object, false); // virtual-up lookup starting from parent | |
| goto _void; | |
| } | |
| } | |
| if(!value) | if(!value) |
| value=ncontext->get_element(name); | value=ncontext->get_element(name, ncontext, false); |
| _void: | |
| if(value) | if(value) |
| value=&process_to_value(*value); // process possible code-junction | value=&process_to_value(*value); // process possible code-junction |
| else | else |
| Line 950 StringOrValue Request::process(Value& in | Line 939 StringOrValue Request::process(Value& in |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| root=POP(); | root=POP(); |
| self=static_cast<VAliased *>(POP()); | self=static_cast<Value *>(POP()); |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(pool(), "<-ja returned"); | debug_printf(pool(), "<-ja returned"); |
| Line 961 StringOrValue Request::process(Value& in | Line 950 StringOrValue Request::process(Value& in |
| return result; | return result; |
| } | } |
| void Request::execute_method(Value& aself, const Method& method, | const String& Request::execute_method(VMethodFrame& amethodFrame, const Method& method) { |
| const String **return_string) { | |
| PUSH(self); | PUSH(self); |
| PUSH(root); | PUSH(root); |
| PUSH(rcontext); | PUSH(rcontext); |
| PUSH(wcontext); | PUSH(wcontext); |
| // initialize contexts | // initialize contexts |
| root=rcontext=self=&aself; | root=rcontext=self=&amethodFrame; |
| WWrapper local(pool(), &aself); | wcontext=&amethodFrame; |
| wcontext=&local; | |
| // execute! | // execute! |
| execute(*method.parser_code); | execute(*method.parser_code); |
| // result | // result |
| const String *result=0; | const String& result=wcontext->result().as_string(); |
| if(return_string) { | |
| if(Value *result_var_value=wcontext->get_element(*result_var_name)) | |
| *return_string=&result_var_value->as_string(); | |
| else | |
| *return_string=&wcontext->as_string(); | |
| } | |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| root=POP(); | root=POP(); |
| self=static_cast<VAliased *>(POP()); | self=static_cast<Value *>(POP()); |
| // return | |
| return result; | |
| } | } |
| const String& Request::execute_method(VMethodFrame& amethodFrame, const Method& method) { | void Request::execute_method(Value& aself, |
| const Method& method, VString *optional_param, | |
| const String **return_string) { | |
| PUSH(self); | PUSH(self); |
| PUSH(root); | PUSH(root); |
| PUSH(rcontext); | PUSH(rcontext); |
| PUSH(wcontext); | PUSH(wcontext); |
| // initialize contexts | // initialize contexts |
| root=rcontext=self=&amethodFrame; | //root=rcontext=self=&aself; |
| wcontext=&amethodFrame; | self=&aself; |
| // WWrapper local(pool(), &aself); | |
| // wcontext=&local; | |
| Junction local_junction(pool(), *self, self->get_class(), &method, 0,0,0,0); | |
| VMethodFrame local_frame(pool(), method.name, local_junction); | |
| if(optional_param && local_frame.can_store_param()) { | |
| local_frame.store_param(optional_param); | |
| local_frame.fill_unspecified_params(); | |
| } | |
| local_frame.set_self(*self); | |
| root=rcontext=wcontext=&local_frame; | |
| // prevent non-string writes for better error reporting | |
| if(return_string) | |
| wcontext->write(local_frame); | |
| // execute! | // execute! |
| execute(*method.parser_code); | execute(*method.parser_code); |
| // result | // result |
| const String& result=wcontext->result().as_string(); | const String *result=0; |
| if(return_string) | |
| *return_string=&wcontext->result().as_string(); | |
| wcontext=static_cast<WContext *>(POP()); | wcontext=static_cast<WContext *>(POP()); |
| rcontext=POP(); | rcontext=POP(); |
| root=POP(); | root=POP(); |
| self=static_cast<VAliased *>(POP()); | self=static_cast<Value *>(POP()); |
| // return | |
| return result; | |
| } | |
| 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) { | |
| const String *result; | |
| execute_method(aself, *method, &result); | |
| return result; | |
| } | |
| return 0; | |
| } | } |
| void Request::execute_nonvirtual_method(VStateless_class& aclass, | void Request::execute_nonvirtual_method(VStateless_class& aclass, |
| const String& method_name, | const String& method_name, VString *optional_param, |
| const String **return_string, | const String **return_string, |
| const Method **return_method) { | const Method **return_method) { |
| const Method *method=aclass.get_method(method_name); | const Method *method=aclass.get_method(method_name); |
| if(return_string) | if(return_string) |
| *return_string=0; | *return_string=0; |
| Line 1040 void Request::execute_nonvirtual_method( | Line 1027 void Request::execute_nonvirtual_method( |
| *return_method=method; | *return_method=method; |
| if(method) | if(method) |
| execute_method(aclass, *method, return_string); | execute_method(aclass, *method, optional_param, return_string); |
| } | |
| const String *Request::execute_virtual_method(Value& aself, | |
| const String& method_name) { | |
| if(Value *value=aself.get_element(method_name, &aself, false)) | |
| if(Junction *junction=value->get_junction()) | |
| if(const Method *method=junction->method) { | |
| const String *result; | |
| execute_method(aself, *method, 0/*no params*/, &result); | |
| return result; | |
| } | |
| return 0; | |
| } | } |