|
|
| version 1.295.2.27.2.6, 2003/03/21 15:36:03 | version 1.295.2.27.2.12, 2003/04/02 09:32:11 |
|---|---|
| Line 68 void debug_printf(SAPI_Info& sapi_info, | Line 68 void debug_printf(SAPI_Info& sapi_info, |
| va_end(args); | va_end(args); |
| } | } |
| void debug_dump(SAPI_Info& sapi_info, , int level, ArrayOperation& ops) { | void debug_dump(SAPI_Info& sapi_info, int level, ArrayOperation& ops) { |
| Array_iterator<Operation> i(ops); | Array_iterator<Operation> i(ops); |
| while(i.has_next()) { | while(i.has_next()) { |
| Operation& op=i.next(); | Operation op=i.next(); |
| if(op.code==OP_VALUE || op.code==OP_STRING__WRITE) { | if(op.code==OP_VALUE || op.code==OP_STRING__WRITE) { |
| Value* value=i.next().value; | Value& value=i.next().value; |
| debug_printf(sapi_info, | debug_printf(sapi_info, |
| "%*s%s" | "%*s%s" |
| " \"%s\" %s", | " \"%s\" %s", |
| level*4, "", opcode_name[op.code], | level*4, "", opcode_name[op.code], |
| value->get_string()->cstr().get(), value->type()); | value.get_string()->cstr(), value.type()); |
| continue; | continue; |
| } | } |
| debug_printf(sapi_info, "%*s%s", level*4, "", opcode_name[op.code]); | debug_printf(sapi_info, "%*s%s", level*4, "", opcode_name[op.code]); |
| Line 93 void debug_dump(SAPI_Info& sapi_info, , | Line 93 void debug_dump(SAPI_Info& sapi_info, , |
| case OP_STRING_POOL: | case OP_STRING_POOL: |
| case OP_CALL: | case OP_CALL: |
| case OP_CALL__WRITE: | case OP_CALL__WRITE: |
| if(ArrayOperation* local_ops=i.next().ops.get()) | if(ArrayOperation* local_ops=i.next().ops) |
| debug_dump(sapi_info, level+1, *local_ops); | debug_dump(sapi_info, level+1, *local_ops); |
| } | } |
| } | } |
| Line 103 void debug_dump(SAPI_Info& sapi_info, , | Line 103 void debug_dump(SAPI_Info& sapi_info, , |
| // Request | // Request |
| void Request::execute(ArrayOperation& ops) { | void Request::execute(ArrayOperation& ops) { |
| // _asm int 3; | register Stack<StackItem>& stack=this->stack; // helps a lot on MSVC: 'esi' |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, "source----------------------------\n"); | debug_printf(sapi_info, "source----------------------------\n"); |
| debug_dump(sapi_info, 0, ops); | debug_dump(sapi_info, 0, ops); |
| debug_printf(sapi_info, "execution-------------------------\n"); | debug_printf(sapi_info, "execution-------------------------\n"); |
| #endif | #endif |
| Array_iterator<Operation> i(ops); | for(Array_iterator<Operation> i(ops); i.has_next(); ) { |
| Value* value; | |
| Value* a; Value* b; | |
| const String* name; | |
| Value* ncontext; | |
| ArrayOperation* local_ops; | |
| while(i.has_next()) { | |
| if(get_interrupted()) { | if(get_interrupted()) { |
| set_interrupted(false); | set_interrupted(false); |
| throw Exception("parser.interrupted", | throw Exception("parser.interrupted", |
| 0, | 0, |
| "execution stopped"); | "execution stopped"); |
| } | } |
| OPCODE opcode=i.next().code; | |
| Operation op=i.next(); | |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, "%d:%s", stack.top_index()+1, opcode_name[op.code]); | debug_printf(sapi_info, "%d:%s", stack.top_index()+1, opcode_name[opcode]); |
| #endif | #endif |
| switch(op.code) { | switch(opcode) { |
| // param in next instruction | // param in next instruction |
| case OP_VALUE: | case OP_VALUE: |
| { | { |
| value=i.next().value; | Value& value=*i.next().value; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " \"%s\" %s", value->get_string()->cstr().get(), value->type()); | debug_printf(sapi_info, " \"%s\" %s", value.get_string()->cstr(), value.type()); |
| #endif | #endif |
| stack.push(value); | stack.push(value); |
| break; | break; |
| Line 147 void Request::execute(ArrayOperation& op | Line 138 void Request::execute(ArrayOperation& op |
| // maybe they do ^class:method[] call, remember the fact | // maybe they do ^class:method[] call, remember the fact |
| wcontext->set_somebody_entered_some_class(); | wcontext->set_somebody_entered_some_class(); |
| name=stack.pop().string(); | const String& name=stack.pop().string(); |
| value=classes().get(*name); | Value* value=classes().get(name); |
| if(!value) | if(!value) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| name, | &name, |
| "class is undefined"); | "class is undefined"); |
| stack.push(value); | stack.push(*value); |
| break; | break; |
| } | } |
| // OP_WITH | // OP_WITH |
| case OP_WITH_ROOT: | case OP_WITH_ROOT: |
| { | { |
| stack.push(method_frame); | stack.push(*method_frame); |
| break; | break; |
| } | } |
| case OP_WITH_SELF: | case OP_WITH_SELF: |
| { | { |
| stack.push(&get_self()); | stack.push(get_self()); |
| break; | break; |
| } | } |
| case OP_WITH_READ: | case OP_WITH_READ: |
| { | { |
| stack.push(rcontext); | stack.push(*rcontext); |
| break; | break; |
| } | } |
| case OP_WITH_WRITE: | case OP_WITH_WRITE: |
| Line 181 void Request::execute(ArrayOperation& op | Line 172 void Request::execute(ArrayOperation& op |
| 0, | 0, |
| "$.name outside of $name[...]"); | "$.name outside of $name[...]"); |
| stack.push(wcontext); | stack.push(*wcontext); |
| break; | break; |
| } | } |
| // OTHER ACTIONS BUT WITHs | // OTHER ACTIONS BUT WITHs |
| case OP_CONSTRUCT_VALUE: | case OP_CONSTRUCT_VALUE: |
| { | { |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| name=stack.pop().string(); | const String& name=stack.pop().string(); |
| ncontext=stack.pop().value; | Value& ncontext=stack.pop().value(); |
| ncontext->put_element(*name, value, false); | ncontext.put_element(name, &value, false); |
| break; | break; |
| } | } |
| case OP_CONSTRUCT_EXPR: | case OP_CONSTRUCT_EXPR: |
| Line 199 void Request::execute(ArrayOperation& op | Line 190 void Request::execute(ArrayOperation& op |
| // see OP_PREPARE_TO_EXPRESSION | // see OP_PREPARE_TO_EXPRESSION |
| wcontext->set_in_expression(false); | wcontext->set_in_expression(false); |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| name=stack.pop().string(); | const String& name=stack.pop().string(); |
| ncontext=stack.pop().value; | Value& ncontext=stack.pop().value(); |
| ncontext->put_element(*name, value->as_expr_result(), false); | ncontext.put_element(name, &value.as_expr_result(), false); |
| break; | break; |
| } | } |
| case OP_CURLY_CODE__CONSTRUCT: | case OP_CURLY_CODE__CONSTRUCT: |
| { | { |
| local_ops=i.next().ops; | ArrayOperation& local_ops=*i.next().ops; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " (%d)\n", local_ops->count()); | debug_printf(sapi_info, " (%d)\n", local_ops.count()); |
| debug_dump(sapi_info, 1, *local_ops); | debug_dump(sapi_info, 1, *local_ops); |
| #endif | #endif |
| value=new VJunction(new Junction( | Value& value=*new VJunction(new Junction( |
| get_self(), 0, | get_self(), 0, |
| method_frame, | method_frame, |
| rcontext, | rcontext, |
| wcontext, | wcontext, |
| local_ops)); | &local_ops)); |
| name=stack.pop().string(); | const String& name=stack.pop().string(); |
| ncontext=stack.pop().value; | Value& ncontext=stack.pop().value(); |
| ncontext->put_element(*name, value, false); | ncontext.put_element(name, &value, false); |
| break; | break; |
| } | } |
| case OP_NESTED_CODE: | case OP_NESTED_CODE: |
| { | { |
| local_ops=i.next().ops; | ArrayOperation& local_ops=*i.next().ops; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " (%d)\n", local_ops->count()); | debug_printf(sapi_info, " (%d)\n", local_ops.count()); |
| debug_dump(sapi_info, 1, *local_ops); | debug_dump(sapi_info, 1, *local_ops); |
| #endif | #endif |
| stack.push(local_ops); | stack.push(local_ops); |
| Line 236 void Request::execute(ArrayOperation& op | Line 227 void Request::execute(ArrayOperation& op |
| } | } |
| case OP_WRITE_VALUE: | case OP_WRITE_VALUE: |
| { | { |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| write_assign_lang(*value); | write_assign_lang(value); |
| break; | break; |
| } | } |
| case OP_WRITE_EXPR_RESULT: | case OP_WRITE_EXPR_RESULT: |
| { | { |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| write_no_lang(*value->as_expr_result()); | write_no_lang(value.as_expr_result()); |
| // must be after write(result) and | // must be after write(result) and |
| // see OP_PREPARE_TO_EXPRESSION | // see OP_PREPARE_TO_EXPRESSION |
| Line 252 void Request::execute(ArrayOperation& op | Line 243 void Request::execute(ArrayOperation& op |
| } | } |
| case OP_STRING__WRITE: | case OP_STRING__WRITE: |
| { | { |
| value=i.next().value; | Value* value=i.next().value; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " \"%s\"", value->get_string()->cstr().get()); | debug_printf(sapi_info, " \"%s\"", value->get_string()->cstr()); |
| #endif | #endif |
| write_no_lang(*value->get_string()); | write_no_lang(*value->get_string()); |
| break; | break; |
| Line 262 void Request::execute(ArrayOperation& op | Line 253 void Request::execute(ArrayOperation& op |
| case OP_GET_ELEMENT_OR_OPERATOR: | case OP_GET_ELEMENT_OR_OPERATOR: |
| { | { |
| value=get_element(true); | Value& value=get_element(true); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_GET_ELEMENT: | case OP_GET_ELEMENT: |
| { | { |
| value=get_element(false); | Value& value=get_element(false); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_GET_ELEMENT__WRITE: | case OP_GET_ELEMENT__WRITE: |
| { | { |
| value=get_element(false); | Value& value=get_element(false); |
| write_assign_lang(*value); | write_assign_lang(value); |
| break; | break; |
| } | } |
| case OP_OBJECT_POOL: | case OP_OBJECT_POOL: |
| { | { |
| local_ops=i.next().ops; | ArrayOperation& local_ops=*i.next().ops; |
| WContext *saved_wcontext=wcontext; | WContext *saved_wcontext=wcontext; |
| String::Language saved_lang=flang; | String::Language saved_lang=flang; |
| Line 291 void Request::execute(ArrayOperation& op | Line 282 void Request::execute(ArrayOperation& op |
| WWrapper local(0/*empty*/, wcontext); | WWrapper local(0/*empty*/, wcontext); |
| wcontext=&local; | wcontext=&local; |
| execute(*local_ops); | execute(local_ops); |
| value=&wcontext->result().as_value(); | stack.push(wcontext->result().as_value()); |
| flang=saved_lang; | flang=saved_lang; |
| wcontext=saved_wcontext; | wcontext=saved_wcontext; |
| stack.push(value); | |
| break; | break; |
| } | } |
| case OP_STRING_POOL: | case OP_STRING_POOL: |
| { | { |
| local_ops=i.next().ops; | ArrayOperation& local_ops=*i.next().ops; |
| WContext *saved_wcontext=wcontext; | WContext *saved_wcontext=wcontext; |
| WWrapper local(0 /*empty*/, wcontext); | WWrapper local(0 /*empty*/, wcontext); |
| wcontext=&local; | wcontext=&local; |
| execute(*local_ops); | execute(local_ops); |
| Value* value; | |
| // from "$a $b" part of expression taking only string value, | // from "$a $b" part of expression taking only string value, |
| // ignoring any other content of wcontext | // ignoring any other content of wcontext |
| if(const String* string=wcontext->get_string()) | if(const String* string=wcontext->get_string()) |
| value=new VString(*string); | value=new VString(*string); |
| else | else |
| value=new VVoid; | value=new VVoid; |
| stack.push(*value); | |
| wcontext=saved_wcontext; | wcontext=saved_wcontext; |
| stack.push(value); | |
| break; | break; |
| } | } |
| // CALL | // CALL |
| case OP_STORE_PARAM: | case OP_STORE_PARAM: |
| { | { |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| VMethodFrame *frame=stack.top_value().method_frame; | VMethodFrame& frame=stack.top_value().method_frame(); |
| // this op is executed from CALL local_ops only, so may skip the check "method_frame_to_fill==0" | // this op is executed from CALL local_ops only, so may skip the check "method_frame_to_fill==0" |
| frame->store_param(*value); | frame.store_param(value); |
| break; | break; |
| } | } |
| case OP_CURLY_CODE__STORE_PARAM: | case OP_CURLY_CODE__STORE_PARAM: |
| case OP_EXPR_CODE__STORE_PARAM: | case OP_EXPR_CODE__STORE_PARAM: |
| { | { |
| // code | // code |
| local_ops=i.next().ops; | ArrayOperation& local_ops=*i.next().ops; |
| VMethodFrame *frame=stack.top_value().method_frame; | VMethodFrame& frame=stack.top_value().method_frame(); |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " (%d)\n", local_ops->count()); | debug_printf(sapi_info, " (%d)\n", local_ops.count()); |
| debug_dump(sapi_info, 1, *local_ops); | debug_dump(sapi_info, 1, *local_ops); |
| #endif | #endif |
| // when they evaluate expression parameter, | // when they evaluate expression parameter, |
| Line 348 void Request::execute(ArrayOperation& op | Line 339 void Request::execute(ArrayOperation& op |
| // hence, we zero junction.wcontext here, and later | // hence, we zero junction.wcontext here, and later |
| // in .process we would test that field | // in .process we would test that field |
| // in decision "which wwrapper to use" | // in decision "which wwrapper to use" |
| value=new VJunction(new Junction( | Value& value=*new VJunction(new Junction( |
| get_self(), 0, | get_self(), 0, |
| method_frame, | method_frame, |
| rcontext, | rcontext, |
| op.code==OP_EXPR_CODE__STORE_PARAM?0:wcontext, | opcode==OP_EXPR_CODE__STORE_PARAM?0:wcontext, |
| local_ops)); | &local_ops)); |
| // store param | // store param |
| // this op is executed from CALL local_ops only, so can not check method_frame_to_fill==0 | // this op is executed from CALL local_ops only, so can not check method_frame_to_fill==0 |
| frame->store_param(*value); | frame.store_param(value); |
| break; | break; |
| } | } |
| Line 375 void Request::execute(ArrayOperation& op | Line 366 void Request::execute(ArrayOperation& op |
| case OP_CALL: | case OP_CALL: |
| case OP_CALL__WRITE: | case OP_CALL__WRITE: |
| { | { |
| local_ops=i.next().ops; | ArrayOperation* local_ops=i.next().ops; |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| debug_printf(sapi_info, " (%d)\n", local_ops?local_ops->count():0); | debug_printf(sapi_info, " (%d)\n", local_ops?local_ops.count():0); |
| if(local_ops) | if(local_ops) |
| debug_dump(sapi_info, 1, *local_ops); | debug_dump(sapi_info, 1, *local_ops); |
| debug_printf(sapi_info, "->\n"); | debug_printf(sapi_info, "->\n"); |
| #endif | #endif |
| value=stack.pop().value; | Value& value=stack.pop().value(); |
| Junction* junction=value->get_junction(); | Junction* junction=value.get_junction(); |
| if(!junction) | if(!junction) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| 0, | 0, |
| "(%s) not a method or junction, can not call it", | "(%s) not a method or junction, can not call it", |
| value->type()); | value.type()); |
| /* no check needed, code compiled the way that that's impossible | /* no check needed, code compiled the way that that's impossible |
| // check: | // check: |
| // that this is method-junction, not a code-junction | // that this is method-junction, not a code-junction |
| Line 401 void Request::execute(ArrayOperation& op | Line 392 void Request::execute(ArrayOperation& op |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| "(%s) is code junction, can not call it", | "(%s) is code junction, can not call it", |
| value->type()); | value.type()); |
| */ | */ |
| VMethodFrame frame(*junction, method_frame/*caller*/); | VMethodFrame frame(*junction, method_frame/*caller*/); |
| if(local_ops){ // store param code goes here | if(local_ops){ // store param code goes here |
| stack.push(&frame); // argument for *STORE_PARAM ops | stack.push(frame); // argument for *STORE_PARAM ops |
| execute(*local_ops); | execute(*local_ops); |
| stack.pop().value; | stack.pop().value(); |
| } | } |
| frame.fill_unspecified_params(); | frame.fill_unspecified_params(); |
| VMethodFrame *saved_method_frame=method_frame; | VMethodFrame *saved_method_frame=method_frame; |
| Line 487 void Request::execute(ArrayOperation& op | Line 478 void Request::execute(ArrayOperation& op |
| rcontext=saved_rcontext; | rcontext=saved_rcontext; |
| method_frame=saved_method_frame; | method_frame=saved_method_frame; |
| if(op.code==OP_CALL__WRITE) { | if(opcode==OP_CALL__WRITE) { |
| write_assign_lang(result); | write_assign_lang(result); |
| } else { // OP_CALL | } else { // OP_CALL |
| stack.push(&result.as_value()); | stack.push(result.as_value()); |
| } | } |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |
| Line 502 void Request::execute(ArrayOperation& op | Line 493 void Request::execute(ArrayOperation& op |
| // expression ops: unary | // expression ops: unary |
| case OP_NEG: | case OP_NEG: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VDouble(-a->as_double()); | Value& value=*new VDouble(-a.as_double()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_INV: | case OP_INV: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VDouble(~a->as_int()); | Value& value=*new VDouble(~a.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NOT: | case OP_NOT: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VBool(!a->as_bool()); | Value& value=*new VBool(!a.as_bool()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_DEF: | case OP_DEF: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VBool(a->is_defined()); | Value& value=*new VBool(a.is_defined()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_IN: | case OP_IN: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| const String& path=a->as_string(); | const String& path=a.as_string(); |
| value=new VBool(request_info.uri && path.this_starts(request_info.uri)); | Value& value=*new VBool(request_info.uri && *request_info.uri && path.this_starts(request_info.uri)); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_FEXISTS: | case OP_FEXISTS: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VBool(file_readable(absolute(a->as_string()))); | Value& value=*new VBool(file_readable(absolute(a.as_string()))); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_DEXISTS: | case OP_DEXISTS: |
| { | { |
| a=stack.pop().value; | Value& a=stack.pop().value(); |
| value=new VBool(dir_readable(absolute(a->as_string()))); | Value& value=*new VBool(dir_readable(absolute(a.as_string()))); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| Line 554 void Request::execute(ArrayOperation& op | Line 545 void Request::execute(ArrayOperation& op |
| // expression ops: binary | // expression ops: binary |
| case OP_SUB: | case OP_SUB: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VDouble(a->as_double() - b->as_double()); | Value& value=*new VDouble(a.as_double() - b.as_double()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_ADD: | case OP_ADD: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VDouble(a->as_double() + b->as_double()); | Value& value=*new VDouble(a.as_double() + b.as_double()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_MUL: | case OP_MUL: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VDouble(a->as_double() * b->as_double()); | Value& value=*new VDouble(a.as_double() * b.as_double()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_DIV: | case OP_DIV: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double a_double=a->as_double(); | double a_double=a.as_double(); |
| double b_double=b->as_double(); | double b_double=b.as_double(); |
| if(b_double == 0) { | if(b_double == 0) { |
| //const String* problem_source=b->as_string(); | //const String* problem_source=b.as_string(); |
| throw Exception("number.zerodivision", | throw Exception("number.zerodivision", |
| 0, //problem_source, | 0, //problem_source, |
| "Division by zero"); | "Division by zero"); |
| } | } |
| value=new VDouble(a_double / b_double); | Value& value=*new VDouble(a_double / b_double); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_MOD: | case OP_MOD: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double a_double=a->as_double(); | double a_double=a.as_double(); |
| double b_double=b->as_double(); | double b_double=b.as_double(); |
| if(b_double == 0) { | if(b_double == 0) { |
| //const String* problem_source=b->as_string(); | //const String* problem_source=b.as_string(); |
| throw Exception("number.zerodivision", | throw Exception("number.zerodivision", |
| 0, //problem_source, | 0, //problem_source, |
| "Modulus by zero"); | "Modulus by zero"); |
| } | } |
| value=new VDouble(fmod(a_double, b_double)); | Value& value=*new VDouble(fmod(a_double, b_double)); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_INTDIV: | case OP_INTDIV: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| int a_int=a->as_int(); | int a_int=a.as_int(); |
| int b_int=b->as_int(); | int b_int=b.as_int(); |
| if(b_int == 0) { | if(b_int == 0) { |
| //const String* problem_source=b->as_string(); | //const String* problem_source=b.as_string(); |
| throw Exception("number.zerodivision", | throw Exception("number.zerodivision", |
| 0, //problem_source, | 0, //problem_source, |
| "Division by zero"); | "Division by zero"); |
| } | } |
| value=new VInt(a_int / b_int); | Value& value=*new VInt(a_int / b_int); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_BIN_SL: | case OP_BIN_SL: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VInt( | Value& value=*new VInt( |
| a->as_int() << | a.as_int() << |
| b->as_int()); | b.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_BIN_SR: | case OP_BIN_SR: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VInt( | Value& value=*new VInt( |
| a->as_int() >> | a.as_int() >> |
| b->as_int()); | b.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_BIN_AND: | case OP_BIN_AND: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VInt( | Value& value=*new VInt( |
| a->as_int() & | a.as_int() & |
| b->as_int()); | b.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_BIN_OR: | case OP_BIN_OR: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VInt( | Value& value=*new VInt( |
| a->as_int() | | a.as_int() | |
| b->as_int()); | b.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_BIN_XOR: | case OP_BIN_XOR: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VInt( | Value& value=*new VInt( |
| a->as_int() ^ | a.as_int() ^ |
| b->as_int()); | b.as_int()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_LOG_AND: | case OP_LOG_AND: |
| { | { |
| local_ops=stack.pop().ops; a=stack.pop().value; | ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value(); |
| bool result; | bool result; |
| if(a->as_bool()) { | if(a.as_bool()) { |
| execute(*local_ops); | execute(local_ops); |
| b=stack.pop().value; | Value& b=stack.pop().value(); |
| result=b->as_bool(); | result=b.as_bool(); |
| } else | } else |
| result=false; | result=false; |
| value=new VBool(result); | Value& value=*new VBool(result); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_LOG_OR: | case OP_LOG_OR: |
| { | { |
| local_ops=stack.pop().ops; a=stack.pop().value; | ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value(); |
| bool result; | bool result; |
| if(a->as_bool()) | if(a.as_bool()) |
| result=true; | result=true; |
| else { | else { |
| execute(*local_ops); | execute(local_ops); |
| b=stack.pop().value; | Value& b=stack.pop().value(); |
| result=b->as_bool(); | result=b.as_bool(); |
| } | } |
| value=new VBool(result); | Value& value=*new VBool(result); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_LOG_XOR: | case OP_LOG_XOR: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_bool() ^ b->as_bool()); | Value& value=*new VBool(a.as_bool() ^ b.as_bool()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_LT: | case OP_NUM_LT: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result < 0.0); | Value& value=*new VBool(result < 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_GT: | case OP_NUM_GT: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result > 0.0); | Value& value=*new VBool(result > 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_LE: | case OP_NUM_LE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result <= 0.0); | Value& value=*new VBool(result <= 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_GE: | case OP_NUM_GE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result >= 0.0); | Value& value=*new VBool(result >= 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_EQ: | case OP_NUM_EQ: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result == 0.0); | Value& value=*new VBool(result == 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_NUM_NE: | case OP_NUM_NE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| double result=a->as_double() - b->as_double(); | double result=a.as_double() - b.as_double(); |
| value=new VBool(result != 0.0); | Value& value=*new VBool(result != 0.0); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_LT: | case OP_STR_LT: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() < b->as_string()); | Value& value=*new VBool(a.as_string() < b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_GT: | case OP_STR_GT: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() > b->as_string()); | Value& value=*new VBool(a.as_string() > b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_LE: | case OP_STR_LE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() <= b->as_string()); | Value& value=*new VBool(a.as_string() <= b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_GE: | case OP_STR_GE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() >= b->as_string()); | Value& value=*new VBool(a.as_string() >= b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_EQ: | case OP_STR_EQ: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() == b->as_string()); | Value& value=*new VBool(a.as_string() == b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_STR_NE: | case OP_STR_NE: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->as_string() != b->as_string()); | Value& value=*new VBool(a.as_string() != b.as_string()); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| case OP_IS: | case OP_IS: |
| { | { |
| b=stack.pop().value; a=stack.pop().value; | Value& b=stack.pop().value(); Value& a=stack.pop().value(); |
| value=new VBool(a->is(b->as_string().cstr())); | Value& value=*new VBool(a.is(b.as_string().cstr())); |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| Line 809 void Request::execute(ArrayOperation& op | Line 800 void Request::execute(ArrayOperation& op |
| default: | default: |
| throw Exception(0, | throw Exception(0, |
| 0, | 0, |
| "invalid opcode %d", op.code); | "invalid opcode %d", opcode); |
| } | } |
| } | } |
| } | } |
| Line 818 void Request::execute(ArrayOperation& op | Line 809 void Request::execute(ArrayOperation& op |
| @todo cache|prepare junctions | @todo cache|prepare junctions |
| @bug ^superbase:method would dynamically call ^base:method if there is any | @bug ^superbase:method would dynamically call ^base:method if there is any |
| */ | */ |
| Value* Request::get_element(bool can_call_operator) { | Value& Request::get_element(bool can_call_operator) { |
| const String& name=*stack.pop().string(); //remember_name=name; | const String& name=stack.pop().string(); //remember_name=name; |
| Value* ncontext=stack.pop().value; | Value& ncontext=stack.pop().value(); |
| Value* value; | Value* value=0; |
| if(can_call_operator) { | if(can_call_operator) { |
| if(Method* method=main_class.get_method(name)) // looking operator of that name FIRST | if(Method* method=main_class.get_method(name)) // looking operator of that name FIRST |
| value=new VJunction(new Junction( | value=new VJunction(new Junction( |
| Line 830 Value* Request::get_element(bool can_cal | Line 821 Value* Request::get_element(bool can_cal |
| if(!value) { | if(!value) { |
| if(!wcontext->get_constructing() // not constructing | if(!wcontext->get_constructing() // not constructing |
| && wcontext->get_somebody_entered_some_class() ) // ^class:method | && wcontext->get_somebody_entered_some_class() ) // ^class:method |
| if(VStateless_class *called_class=ncontext->get_class()) | if(VStateless_class *called_class=ncontext.get_class()) |
| if(VStateless_class *read_class=rcontext->get_class()) | if(VStateless_class *read_class=rcontext->get_class()) |
| if(read_class->derived_from(*called_class)) // current derived from called | if(read_class->derived_from(*called_class)) // current derived from called |
| if(Value* base=get_self().base()) { // doing DYNAMIC call | if(Value* base=get_self().base()) { // doing DYNAMIC call |
| Line 840 Value* Request::get_element(bool can_cal | Line 831 Value* Request::get_element(bool can_cal |
| } | } |
| } | } |
| if(!value) | if(!value) |
| value=ncontext->get_element(name, *ncontext, false); | value=ncontext.get_element(name, ncontext, false); |
| if(value && wcontext->get_constructing()) | if(value && wcontext->get_constructing()) |
| if(Junction* junction=value->get_junction()) { | if(Junction* junction=value->get_junction()) { |
| if(junction->self.get_class()!=ncontext) | if(junction->self.get_class()!=&ncontext) |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| &name, | &name, |
| "constructor must be declared in class '%s'", | "constructor must be declared in class '%s'", |
| ncontext->get_class()->name_cstr()); | ncontext.get_class()->name_cstr()); |
| } | } |
| value_ready: | value_ready: |
| if(value) | if(value) |
| value=&process_to_value(value); // process possible code-junction | value=&process_to_value(*value); // process possible code-junction |
| else | else |
| value=new VVoid; | value=new VVoid; |
| return value; | return *value; |
| } | } |
| /** @param intercept_string | /** @param intercept_string |
| Line 871 value_ready: | Line 862 value_ready: |
| using the fact it's either string_ or value_ result requested to speed up checkes | using the fact it's either string_ or value_ result requested to speed up checkes |
| */ | */ |
| StringOrValue Request::process(Value* input_value, bool intercept_string) { | StringOrValue Request::process(Value& input_value, bool intercept_string) { |
| StringOrValue result; | StringOrValue result; |
| Junction* junction=input_value->get_junction(); | Junction* junction=input_value.get_junction(); |
| if(junction && junction->code) { // is it a code-junction? | if(junction && junction->code) { // is it a code-junction? |
| // process it | // process it |
| #ifdef DEBUG_EXECUTE | #ifdef DEBUG_EXECUTE |