|
|
| version 1.359, 2010/03/19 12:12:31 | version 1.366, 2010/10/09 23:17:26 |
|---|---|
| Line 33 char *opcode_name[]={ | Line 33 char *opcode_name[]={ |
| // actions | // actions |
| "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE", | "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE", |
| #ifdef OPTIMIZE_BYTECODE_GET_CLASS | |
| "VALUE__GET_CLASS", | "VALUE__GET_CLASS", |
| #else | |
| "GET_CLASS", | |
| #endif | |
| "CONSTRUCT_VALUE", "CONSTRUCT_EXPR", "CURLY_CODE__CONSTRUCT", | "CONSTRUCT_VALUE", "CONSTRUCT_EXPR", "CURLY_CODE__CONSTRUCT", |
| "WRITE_VALUE", "WRITE_EXPR_RESULT", "STRING__WRITE", | "WRITE_VALUE", "WRITE_EXPR_RESULT", "STRING__WRITE", |
| #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT | #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT |
| Line 167 void debug_dump(SAPI_Info& sapi_info, in | Line 163 void debug_dump(SAPI_Info& sapi_info, in |
| if( | if( |
| opcode==OP::OP_VALUE | opcode==OP::OP_VALUE |
| || opcode==OP::OP_STRING__WRITE | || opcode==OP::OP_STRING__WRITE |
| #ifdef OPTIMIZE_BYTECODE_GET_CLASS | |
| || opcode==OP::OP_VALUE__GET_CLASS | || opcode==OP::OP_VALUE__GET_CLASS |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT | #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT |
| || opcode==OP::OP_VALUE__GET_ELEMENT | || opcode==OP::OP_VALUE__GET_ELEMENT |
| || opcode==OP::OP_VALUE__GET_ELEMENT__WRITE | || opcode==OP::OP_VALUE__GET_ELEMENT__WRITE |
| Line 263 void Request::execute(ArrayOperation& op | Line 257 void Request::execute(ArrayOperation& op |
| stack.push(value); | stack.push(value); |
| break; | break; |
| } | } |
| #ifdef OPTIMIZE_BYTECODE_GET_CLASS | |
| case OP::OP_VALUE__GET_CLASS: | case OP::OP_VALUE__GET_CLASS: |
| { | { |
| // maybe they do ^class:method[] call, remember the fact | // maybe they do ^class:method[] call, remember the fact |
| Line 272 void Request::execute(ArrayOperation& op | Line 264 void Request::execute(ArrayOperation& op |
| debug_origin=i.next().origin; | debug_origin=i.next().origin; |
| Value& value=*i.next().value; | Value& value=*i.next().value; |
| const String& name=*value.get_string(); | const String& name=*value.get_string(); debug_name=&name; |
| DEBUG_PRINT_STRING(name) | DEBUG_PRINT_STRING(name) |
| Line 285 void Request::execute(ArrayOperation& op | Line 277 void Request::execute(ArrayOperation& op |
| stack.push(*class_value); | stack.push(*class_value); |
| break; | break; |
| } | } |
| #else | |
| case OP::OP_GET_CLASS: | |
| { | |
| // maybe they do ^class:method[] call, remember the fact | |
| wcontext->set_somebody_entered_some_class(); | |
| const String& name=stack.pop().string(); | |
| Value* value=get_class(name); | |
| if(!value) | |
| throw Exception(PARSER_RUNTIME, | |
| &name, | |
| "class is undefined"); | |
| stack.push(*value); | |
| break; | |
| } | |
| #endif | |
| // OP_WITH | // OP_WITH |
| case OP::OP_WITH_ROOT: | case OP::OP_WITH_ROOT: |
| { | { |
| Line 748 void Request::execute(ArrayOperation& op | Line 723 void Request::execute(ArrayOperation& op |
| value.type()); | value.type()); |
| } | } |
| VMethodFrame frame(*junction, method_frame); | VMethodFrame frame(*junction->method, method_frame, junction->self); |
| METHOD_FRAME_ACTION(op_call(frame, false)); | METHOD_FRAME_ACTION(op_call(frame)); |
| stack.push(frame.result().as_value()); | stack.push(frame.result().as_value()); |
| DEBUG_PRINT_STR("<-returned") | DEBUG_PRINT_STR("<-returned") |
| Line 806 void Request::execute(ArrayOperation& op | Line 781 void Request::execute(ArrayOperation& op |
| method.native_code(*this, method_params); // execute it | method.native_code(*this, method_params); // execute it |
| } | } |
| } else if(method.call_optimization==Method::CO_WITHOUT_WCONTEXT){ | } else if(method.call_optimization==Method::CO_WITHOUT_WCONTEXT){ |
| VMethodFrame frame(*junction, method_frame); | VMethodFrame frame(method, method_frame, junction->self); |
| METHOD_FRAME_ACTION(op_call_write(frame)); | METHOD_FRAME_ACTION(op_call_write(frame)); |
| } else | } else |
| #endif // OPTIMIZE_CALL | #endif // OPTIMIZE_CALL |
| { | { |
| VMethodFrame frame(*junction, method_frame); | VMethodFrame frame(method, method_frame, junction->self); |
| METHOD_FRAME_ACTION(op_call(frame, false)); | METHOD_FRAME_ACTION(op_call(frame)); |
| write_pass_lang(frame.result()); | write_pass_lang(frame.result()); |
| } | } |
| Line 834 void Request::execute(ArrayOperation& op | Line 809 void Request::execute(ArrayOperation& op |
| { | { |
| debug_origin=i.next().origin; | debug_origin=i.next().origin; |
| Value& vclass_name=*i.next().value; | Value& vclass_name=*i.next().value; |
| const String& class_name=*vclass_name.get_string(); | const String& class_name=*vclass_name.get_string(); debug_name=&class_name; |
| DEBUG_PRINT_STRING(class_name) | DEBUG_PRINT_STRING(class_name) |
| Line 850 void Request::execute(ArrayOperation& op | Line 825 void Request::execute(ArrayOperation& op |
| DEBUG_PRINT_STRING(constructor_name) | DEBUG_PRINT_STRING(constructor_name) |
| Value& constructor_value=get_element(*class_value, constructor_name); | Junction* constructor_junction=get_element(*class_value, constructor_name).get_junction(); |
| if(!constructor_junction) | |
| Junction* junction=constructor_value.get_junction(); | |
| if(!junction) | |
| throw Exception(PARSER_RUNTIME, | throw Exception(PARSER_RUNTIME, |
| &constructor_name, | &constructor_name, |
| "constructor must be declared in class '%s'", | "constructor must be declared in class '%s'", |
| Line 863 void Request::execute(ArrayOperation& op | Line 836 void Request::execute(ArrayOperation& op |
| DEBUG_PRINT_OPS(local_ops) | DEBUG_PRINT_OPS(local_ops) |
| DEBUG_PRINT_STR("->\n") | DEBUG_PRINT_STR("->\n") |
| Junction casted=Junction(*class_value, junction->method); | Value &object=construct(*class_value, *constructor_junction->method); |
| VConstructorFrame frame(casted, method_frame); | VConstructorFrame frame(*constructor_junction->method, method_frame, object); |
| METHOD_FRAME_ACTION(op_call(frame)); | |
| object.enable_default_setter(); | |
| METHOD_FRAME_ACTION(op_call(frame, true /* constructing */)); | |
| if(opcode==OP::OP_CONSTRUCT_OBJECT) | if(opcode==OP::OP_CONSTRUCT_OBJECT) |
| stack.push(frame.result().as_value()); | stack.push(frame.result().as_value()); |
| else | else |
| Line 1207 void Request::execute(ArrayOperation& op | Line 1181 void Request::execute(ArrayOperation& op |
| rcontext=saved_rcontext; \ | rcontext=saved_rcontext; \ |
| method_frame=saved_method_frame; | method_frame=saved_method_frame; |
| void Request::op_call(VMethodFrame& frame, bool constructing){ | |
| const Junction &junction=frame.junction; | |
| VStateless_class& called_class=*junction.self.get_class(); | |
| Value* new_self; | |
| if(constructing) { | |
| if(junction.method->call_type!=Method::CT_STATIC) { | |
| // this is a constructor call | |
| if(new_self=called_class.create_new_value(fpool)) { | |
| // some stateless_class creatable derivates | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, //&frame.name(), | |
| "is not a constructor, system class '%s' can be constructed only implicitly", | |
| called_class.name().cstr()); | |
| frame.write(*new_self); | Value& Request::construct(Value &class_value, const Method &method){ |
| } else | VStateless_class& called_class=*class_value.get_class(); |
| if(method.call_type!=Method::CT_STATIC) { | |
| // this is a constructor call | |
| if(Value* result=called_class.create_new_value(fpool)) { | |
| // some stateless_class creatable derivates | |
| return *result; | |
| } else | |
| throw Exception(PARSER_RUNTIME, | throw Exception(PARSER_RUNTIME, |
| 0, //&frame.name(), | 0, //&frame.name(), |
| "is not a constructor, system class '%s' can be constructed only implicitly", | |
| called_class.name().cstr()); | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, //&frame.name(), | |
| "method is static and can not be used as constructor"); | "method is static and can not be used as constructor"); |
| } else | } |
| new_self=&junction.self; | |
| frame.set_self(*new_self); | |
| void Request::op_call(VMethodFrame& frame){ | |
| // see OP_PREPARE_TO_EXPRESSION | // see OP_PREPARE_TO_EXPRESSION |
| frame.set_in_expression(wcontext->get_in_expression()); | frame.set_in_expression(wcontext->get_in_expression()); |
| SAVE_CONTEXT | SAVE_CONTEXT |
| rcontext=wcontext=&frame; | rcontext=wcontext=method_frame=&frame; |
| method_frame=&frame; | |
| const Method& method=*junction.method; | Value& self=frame.self(); |
| Method::Call_type call_type=&called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC; | const Method& method=frame.method; |
| Method::Call_type call_type=self.get_class()==&self ? Method::CT_STATIC : Method::CT_DYNAMIC; | |
| if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type? | if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type? |
| if(method.native_code) { // native code? | if(method.native_code) { // native code? |
| method.check_actual_numbered_params(junction.self, frame.numbered_params()); | method.check_actual_numbered_params(self, frame.numbered_params()); |
| method.native_code(*this, *frame.numbered_params()); // execute it | method.native_code(*this, *frame.numbered_params()); // execute it |
| } else // parser code, execute it | } else // parser code, execute it |
| recoursion_checked_execute(*method.parser_code); | recoursion_checked_execute(*method.parser_code); |
| Line 1257 void Request::op_call(VMethodFrame& fram | Line 1226 void Request::op_call(VMethodFrame& fram |
| call_type==Method::CT_STATIC?"statically":"dynamically"); | call_type==Method::CT_STATIC?"statically":"dynamically"); |
| RESTORE_CONTEXT | RESTORE_CONTEXT |
| //return &frame; | |
| } | } |
| void Request::op_call_write(VMethodFrame& frame){ | void Request::op_call_write(VMethodFrame& frame){ |
| const Junction &junction=frame.junction; | |
| frame.set_self(junction.self); | |
| VMethodFrame *saved_method_frame=method_frame; | VMethodFrame *saved_method_frame=method_frame; |
| Value* saved_rcontext=rcontext; | Value* saved_rcontext=rcontext; |
| rcontext=&frame; | rcontext=&frame; |
| method_frame=&frame; | method_frame=&frame; |
| const Method& method=*junction.method; | Value& self=frame.self(); |
| Method::Call_type call_type=junction.self.get_class()==&junction.self ? Method::CT_STATIC : Method::CT_DYNAMIC; | const Method& method=frame.method; |
| Method::Call_type call_type=self.get_class()==&self ? Method::CT_STATIC : Method::CT_DYNAMIC; | |
| if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type? | if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type? |
| if(method.native_code) { // native code? | if(method.native_code) { // native code? |
| method.check_actual_numbered_params(junction.self, frame.numbered_params()); | method.check_actual_numbered_params(self, frame.numbered_params()); |
| method.native_code(*this, *frame.numbered_params()); // execute it | method.native_code(*this, *frame.numbered_params()); // execute it |
| } else // parser code, execute it | } else // parser code, execute it |
| recoursion_checked_execute(*method.parser_code); | recoursion_checked_execute(*method.parser_code); |
| Line 1308 void Request::put_element(Value& ncontex | Line 1273 void Request::put_element(Value& ncontex |
| // put_element can return property-setting-junction | // put_element can return property-setting-junction |
| if(const VJunction* vjunction=ncontext.put_element(name, value, false)) | if(const VJunction* vjunction=ncontext.put_element(name, value, false)) |
| if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) { | if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) { |
| // process it | const Junction& junction = vjunction->junction(); |
| VMethodFrame frame(vjunction->junction(), method_frame/*caller*/); | VConstructorFrame frame(*junction.method, method_frame /*caller*/, junction.self); |
| size_t param_count=frame.method_params_count(); | size_t param_count=frame.method_params_count(); |
| if(param_count!=1) | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "setter method must have ONE parameter (has %d parameters)", param_count); | |
| frame.store_params(&value, 1); | if(junction.auto_name){ |
| frame.set_self(frame.junction.self); | // default setter |
| if(param_count!=2) | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "default setter method must have TWO parameters (has %d parameters)", param_count); | |
| Value* params[2] = { new VString(*junction.auto_name), value }; | |
| frame.store_params(params, 2); | |
| Temp_disable_default_setter temp(junction.self); | |
| execute_method(frame); | |
| } else { | |
| // setter | |
| if(param_count!=1) | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "setter method must have ONE parameter (has %d parameters)", param_count); | |
| SAVE_CONTEXT | frame.store_params(&value, 1); |
| execute_method(frame); | |
| } | |
| } | |
| } | |
| rcontext=wcontext=&frame; | StringOrValue Request::process_getter(Junction& junction) { |
| method_frame=&frame; | VMethodFrame frame(*junction.method, method_frame/*caller*/, junction.self); |
| size_t param_count=frame.method_params_count(); | |
| if(junction.auto_name){ | |
| // default getter | |
| Value *param; | |
| // prevent non-string writes for better error reporting [setters are not expected to return anything] | if(param_count){ |
| wcontext->write(*method_frame); | if(param_count>1) |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "default getter method can't have more then 1 parameter (has %d parameters)", param_count); | |
| param=new VString(*junction.auto_name); | |
| frame.store_params(¶m, 1); | |
| } // no need for else frame.empty_params() | |
| recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it | Temp_disable_default_getter temp(junction.self); |
| // we don't need it StringOrValue result=wcontext->result(); | execute_method(frame); |
| } else { | |
| // getter | |
| if(param_count!=0) | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "getter method must have no parameters (has %d parameters)", param_count); | |
| // no need for frame.empty_params() | |
| execute_method(frame); | |
| } | |
| RESTORE_CONTEXT | return frame.result(); |
| } | |
| } | } |
| /** @param intercept_string | /** @param intercept_string |
| Line 1346 void Request::put_element(Value& ncontex | Line 1347 void Request::put_element(Value& ncontex |
| 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) { |
| Junction* junction=input_value.get_junction(); | Junction* junction=input_value.get_junction(); |
| if(junction) { | if(junction) { |
| if(junction->is_getter) { // is it a getter-junction? | if(junction->is_getter) { // is it a getter-junction? |
| VMethodFrame frame(*junction, method_frame/*caller*/); | return process_getter(*junction); |
| Value *param; | |
| if(size_t param_count=frame.method_params_count()){ | |
| if(junction->auto_name){ // default getter | |
| if(param_count==1){ | |
| param=new VString(*junction->auto_name); | |
| frame.store_params(¶m, 1); | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "default getter method can't have more then 1 parameter (has %d parameters)", param_count); | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "getter method must have no parameters (has %d parameters)", param_count); | |
| } // no need for else frame.empty_params() | |
| frame.set_self(frame.junction.self); | |
| SAVE_CONTEXT | |
| rcontext=wcontext=&frame; | |
| method_frame=&frame; | |
| recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it | |
| RESTORE_CONTEXT | |
| return frame.result(); | |
| } | } |
| if(junction->code) { // is it a code-junction? | if(junction->code) { // is it a code-junction? |
| Line 1442 void Request::process_write(Value& input | Line 1415 void Request::process_write(Value& input |
| Junction* junction=input_value.get_junction(); | Junction* junction=input_value.get_junction(); |
| if(junction) { | if(junction) { |
| if(junction->is_getter) { // is it a getter-junction? | if(junction->is_getter) { // is it a getter-junction? |
| VMethodFrame frame(*junction, method_frame/*caller*/); | write_pass_lang(process_getter(*junction)); |
| Value *param; | |
| if(size_t param_count=frame.method_params_count()){ | |
| if(junction->auto_name){ // default getter | |
| if(param_count==1){ | |
| param=new VString(*junction->auto_name); | |
| frame.store_params(¶m, 1); | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "default getter method can't have more then 1 parameter (has %d parameters)", param_count); | |
| } else | |
| throw Exception(PARSER_RUNTIME, | |
| 0, | |
| "getter method must have no parameters (has %d parameters)", param_count); | |
| } // no need for else frame.empty_params() | |
| frame.set_self(frame.junction.self); | |
| SAVE_CONTEXT | |
| rcontext=wcontext=&frame; | |
| method_frame=&frame; | |
| recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it | |
| RESTORE_CONTEXT | |
| write_pass_lang(frame.result()); | |
| return; | return; |
| } | } |
| Line 1533 void Request::process_write(Value& input | Line 1477 void Request::process_write(Value& input |
| write_pass_lang(input_value); | write_pass_lang(input_value); |
| } | } |
| StringOrValue Request::execute_method(VMethodFrame& amethod_frame, const Method& method) { | void Request::execute_method(VMethodFrame& aframe) { |
| SAVE_CONTEXT | SAVE_CONTEXT |
| // initialize contexts | // initialize contexts |
| rcontext=wcontext=method_frame=&amethod_frame; | rcontext=wcontext=method_frame=&aframe; |
| // execute! | // execute! |
| execute(*method.parser_code); | recoursion_checked_execute(*aframe.method.parser_code); |
| // result | |
| StringOrValue result=wcontext->result(); | |
| RESTORE_CONTEXT | RESTORE_CONTEXT |
| // return | |
| return result; | |
| } | } |
| const String* Request::execute_method(Value& aself, | const String* Request::execute_method(Value& aself, |
| const Method& method, Value* optional_param, | const Method& method, Value* optional_param, |
| bool do_return_string) { | bool do_return_string) { |
| SAVE_CONTEXT | VMethodFrame local_frame(method, method_frame/*caller*/, aself); |
| Junction local_junction(aself, &method); | |
| VMethodFrame local_frame(local_junction, method_frame/*caller*/); | |
| if(optional_param && local_frame.method_params_count()>0) { | if(optional_param && local_frame.method_params_count()>0) { |
| local_frame.store_params(&optional_param, 1); | local_frame.store_params(&optional_param, 1); |
| } else { | } else { |
| local_frame.empty_params(); | local_frame.empty_params(); |
| } | } |
| local_frame.set_self(aself); | |
| rcontext=wcontext=method_frame=&local_frame; | |
| // prevent non-string writes for better error reporting | // prevent non-string writes for better error reporting |
| if(do_return_string) | if(do_return_string) |
| local_frame.write(local_frame); | local_frame.write(local_frame); |
| // execute! | execute_method(local_frame); |
| execute(*method.parser_code); | |
| // result | |
| const String* result=do_return_string ? local_frame.get_string() : 0; | |
| RESTORE_CONTEXT | return do_return_string ? local_frame.get_string() : 0; |
| return result; | |
| } | } |
| Request::Execute_nonvirtual_method_result | Request::Execute_nonvirtual_method_result |
| Line 1603 const String* Request::execute_virtual_m | Line 1531 const String* Request::execute_virtual_m |
| return 0; | return 0; |
| } | } |
| const String* Request::get_method_filename(const Method* method){ | |
| if(ArrayOperation* code=method->parser_code) | |
| if(code){ | |
| Operation::Origin origin={0, 0, 0}; | |
| Array_iterator<Operation> i(*code); | |
| while( i.has_next() ){ | |
| switch( i.next().code ){ | |
| case OP::OP_CURLY_CODE__STORE_PARAM: | |
| case OP::OP_EXPR_CODE__STORE_PARAM: | |
| case OP::OP_CURLY_CODE__CONSTRUCT: | |
| case OP::OP_NESTED_CODE: | |
| case OP::OP_OBJECT_POOL: | |
| case OP::OP_STRING_POOL: | |
| case OP::OP_CALL: | |
| case OP::OP_CALL__WRITE: | |
| { | |
| i.next(); // skip local ops | |
| i.next(); // skip next opcode | |
| // continue execution | |
| } | |
| case OP::OP_CONSTRUCT_OBJECT: | |
| case OP::OP_CONSTRUCT_OBJECT__WRITE: | |
| case OP::OP_VALUE: | |
| case OP::OP_STRING__WRITE: | |
| case OP::OP_VALUE__GET_CLASS: | |
| #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT | |
| case OP::OP_GET_OBJECT_ELEMENT: | |
| case OP::OP_GET_OBJECT_ELEMENT__WRITE: | |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT | |
| case OP::OP_GET_OBJECT_VAR_ELEMENT: | |
| case OP::OP_GET_OBJECT_VAR_ELEMENT__WRITE: | |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT | |
| case OP::OP_VALUE__GET_ELEMENT: | |
| case OP::OP_VALUE__GET_ELEMENT__WRITE: | |
| case OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR: | |
| case OP::OP_WITH_ROOT__VALUE__GET_ELEMENT: | |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_GET_SELF_ELEMENT | |
| case OP::OP_WITH_SELF__VALUE__GET_ELEMENT: | |
| case OP::OP_WITH_SELF__VALUE__GET_ELEMENT__WRITE: | |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_CONSTRUCT | |
| case OP::OP_WITH_ROOT__VALUE__CONSTRUCT_EXPR: | |
| case OP::OP_WITH_ROOT__VALUE__CONSTRUCT_VALUE: | |
| case OP::OP_WITH_WRITE__VALUE__CONSTRUCT_EXPR: | |
| case OP::OP_WITH_WRITE__VALUE__CONSTRUCT_VALUE: | |
| case OP::OP_WITH_SELF__VALUE__CONSTRUCT_EXPR: | |
| case OP::OP_WITH_SELF__VALUE__CONSTRUCT_VALUE: | |
| #endif | |
| { | |
| origin=i.next().origin; | |
| break; | |
| } | |
| } | |
| if(origin.file_no) | |
| return get_used_filename(origin.file_no); | |
| } | |
| } | |
| return 0; | |
| } | |