|
|
| version 1.198, 2001/10/22 12:30:24 | version 1.203.2.1, 2001/11/14 07:32:00 |
|---|---|
| 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 47 char *opcode_name[]={ | Line 47 char *opcode_name[]={ |
| // expression ops: unary | // expression ops: unary |
| "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS", | "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS", |
| // expression ops: binary | // expression ops: binary |
| "SUB", "ADD", "MUL", "DIV", "MOD", | "SUB", "ADD", "MUL", "DIV", "MOD", "INTDIV", |
| "BIN_AND", "BIN_OR", "BIN_XOR", | "BIN_AND", "BIN_OR", "BIN_XOR", |
| "LOG_AND", "LOG_OR", "LOG_XOR", | "LOG_AND", "LOG_OR", "LOG_XOR", |
| "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE", | "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE", |
| Line 244 void Request::execute(const Array& ops) | Line 244 void Request::execute(const Array& ops) |
| // forget the fact they've entered some ^object.method[]. | // forget the fact they've entered some ^object.method[]. |
| // see OP_GET_ELEMENT | // see OP_GET_ELEMENT |
| wcontext->clear_somebody_entered_some_object(); | wcontext->set_somebody_entered_some_object(false); |
| break; | break; |
| } | } |
| case OP_WRITE_EXPR_RESULT: | case OP_WRITE_EXPR_RESULT: |
| Line 266 void Request::execute(const Array& ops) | Line 266 void Request::execute(const Array& ops) |
| case OP_GET_ELEMENT: | case OP_GET_ELEMENT: |
| { | { |
| // maybe they do ^object.method[] call, remember the fact | // maybe they do ^object.method[] call, remember the fact |
| wcontext->inc_somebody_entered_some_object(); | wcontext->set_somebody_entered_some_object(true); |
| //_asm int 3; | //_asm int 3; |
| value=get_element(); | value=get_element(); |
| Line 349 void Request::execute(const Array& ops) | Line 349 void Request::execute(const Array& ops) |
| case OP_PREPARE_TO_CONSTRUCT_OBJECT: | case OP_PREPARE_TO_CONSTRUCT_OBJECT: |
| { | { |
| wcontext->constructing(true); | wcontext->set_constructing(true); |
| break; | break; |
| } | } |
| case OP_CALL: | case OP_CALL: |
| Line 365 void Request::execute(const Array& ops) | Line 365 void Request::execute(const Array& ops) |
| PUSH(wcontext); | PUSH(wcontext); |
| VStateless_class *called_class=frame->junction.self.get_class(); | VStateless_class *called_class=frame->junction.self.get_class(); |
| if(wcontext->constructing()) { | if(wcontext->get_constructing()) { |
| wcontext->constructing(false); | wcontext->set_constructing(false); |
| if(frame->junction.method->call_type!=Method::CT_STATIC) { | if(frame->junction.method->call_type!=Method::CT_STATIC) { |
| // 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 391 void Request::execute(const Array& ops) | Line 393 void Request::execute(const Array& ops) |
| // is context object or class & is it my class or my parent's class and? | // is context object or class & is it my class or my parent's class and? |
| VStateless_class *read_class=rcontext->get_class(); | VStateless_class *read_class=rcontext->get_class(); |
| if( | if( |
| !(wcontext->somebody_entered_some_object() && | !(wcontext->get_somebody_entered_some_object() && |
| !wcontext->somebody_entered_some_class()) && | !wcontext->get_somebody_entered_some_class()) && |
| read_class && read_class->is_or_derived_from(*called_class)) // yes | read_class && read_class->is_or_derived_from(*called_class)) // yes |
| self=rcontext; // dynamic call | self=rcontext; // dynamic call |
| else // no, not me or relative of mine (=total stranger) | else // no, not me or relative of mine (=total stranger) |
| Line 400 void Request::execute(const Array& ops) | Line 402 void Request::execute(const Array& ops) |
| } | } |
| frame->set_self(*self); | frame->set_self(*self); |
| root=rcontext=wcontext=frame; | rcontext=wcontext=frame; |
| { | { |
| // take object or class from any wrappers | // take object or class from any wrappers |
| // and substitute class alias to the class they are called AS | // and substitute class alias to the class they are called AS |
| Line 414 void Request::execute(const Array& ops) | Line 416 void Request::execute(const Array& ops) |
| method.call_type==call_type) { // allowed call type? | method.call_type==call_type) { // allowed call type? |
| try { | try { |
| if(method.native_code) { // native code? | if(method.native_code) { // native code? |
| // root unchanged, so that ^for ^foreach & co may write to locals | |
| method.check_actual_numbered_params( | method.check_actual_numbered_params( |
| frame->junction.self, | frame->junction.self, |
| frame->name(), frame->numbered_params()); | frame->name(), frame->numbered_params()); |
| Line 421 void Request::execute(const Array& ops) | Line 424 void Request::execute(const Array& ops) |
| *this, | *this, |
| frame->name(), frame->numbered_params()); // execute it | frame->name(), frame->numbered_params()); // execute it |
| } else { // parser code | } else { // parser code |
| root=frame; | |
| if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { | if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { |
| anti_endless_execute_recoursion=0; // give @exception a chance | anti_endless_execute_recoursion=0; // give @exception a chance |
| throw Exception(0, 0, | throw Exception(0, 0, |
| Line 488 void Request::execute(const Array& ops) | Line 492 void Request::execute(const Array& ops) |
| } | } |
| case OP_IN: | case OP_IN: |
| { | { |
| /// @test String::cmp | |
| Value *operand=POP(); | Value *operand=POP(); |
| const char *path=operand->as_string().cstr(); | const char *path=operand->as_string().cstr(); |
| value=NEW VBool(pool(), | value=NEW VBool(pool(), |
| Line 578 void Request::execute(const Array& ops) | Line 583 void Request::execute(const Array& ops) |
| PUSH(value); | PUSH(value); |
| break; | break; |
| } | } |
| case OP_INTDIV: | |
| { | |
| b=POP(); a=POP(); | |
| int a_int=a->as_int(); | |
| int b_int=b->as_int(); | |
| if(b_int == 0) { | |
| const String *problem_source=&b->as_string(); | |
| #ifndef NO_STRING_ORIGIN | |
| if(!problem_source->origin().file) | |
| problem_source=&b->name(); | |
| #endif | |
| throw Exception(0, 0, | |
| problem_source, | |
| "Division by zero"); | |
| } | |
| value=NEW VInt(pool(), a_int / b_int); | |
| PUSH(value); | |
| break; | |
| } | |
| case OP_BIN_AND: | case OP_BIN_AND: |
| { | { |
| b=POP(); a=POP(); | b=POP(); a=POP(); |
| Line 735 Value *Request::get_element() { | Line 762 Value *Request::get_element() { |
| if(Method* method=OP.get_method(name)) { // maybe operator? | if(Method* method=OP.get_method(name)) { // maybe operator? |
| // 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*/, 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(value) |