Diff for /parser3/src/main/execute.C between versions 1.315 and 1.320

version 1.315, 2006/04/09 13:38:47 version 1.320, 2008/06/05 13:32:43
Line 14  static const char * const IDENT_EXECUTE_ Line 14  static const char * const IDENT_EXECUTE_
 #include "pa_vhash.h"  #include "pa_vhash.h"
 #include "pa_vvoid.h"  #include "pa_vvoid.h"
 #include "pa_vcode_frame.h"  #include "pa_vcode_frame.h"
 #include "pa_vmethod_frame.h"  #include "pa_vmethod_frame_local.h"
   #include "pa_vmethod_frame_global.h"
 #include "pa_vobject.h"  #include "pa_vobject.h"
 #include "pa_vdouble.h"  #include "pa_vdouble.h"
 #include "pa_vbool.h"  #include "pa_vbool.h"
Line 147  void Request::execute(ArrayOperation& op Line 148  void Request::execute(ArrayOperation& op
                                 const String& name=stack.pop().string();                                  const String& name=stack.pop().string();
                                 Value* 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"); 
   
Line 174  void Request::execute(ArrayOperation& op Line 175  void Request::execute(ArrayOperation& op
                 case OP_WITH_WRITE:                   case OP_WITH_WRITE: 
                         {                          {
                                 if(wcontext==method_frame)                                  if(wcontext==method_frame)
                                         throw Exception("parser.runtime",                                          throw Exception(PARSER_RUNTIME,
                                                 0,                                                  0,
                                                 "$.name outside of $name[...]");                                                  "$.name outside of $name[...]");
   
Line 222  void Request::execute(ArrayOperation& op Line 223  void Request::execute(ArrayOperation& op
                                 Value& ncontext=stack.pop().value();                                  Value& ncontext=stack.pop().value();
                                 if(const VJunction* vjunction=ncontext.put_element(ncontext, name, &value, false))                                  if(const VJunction* vjunction=ncontext.put_element(ncontext, name, &value, false))
                                         if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT)                                          if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT)
                                                 throw Exception("parser.runtime",                                                  throw Exception(PARSER_RUNTIME,
                                                         0,                                                          0,
                                                         "property value can not be code, use [] or () brackets");                                                          "property value can not be code, use [] or () brackets");
                                                                                   
Line 400  void Request::execute(ArrayOperation& op Line 401  void Request::execute(ArrayOperation& op
                                 Junction* junction=value.get_junction();                                  Junction* junction=value.get_junction();
                                 if(!junction) {                                  if(!junction) {
                                         if(value.is("void"))                                          if(value.is("void"))
                                                 throw Exception("parser.runtime",                                                  throw Exception(PARSER_RUNTIME,
                                                         0,                                                          0,
                                                         "undefined method");                                                          "undefined method");
                                         else                                          else
                                                 throw Exception("parser.runtime",                                                  throw Exception(PARSER_RUNTIME,
                                                         0,                                                          0,
                                                         "is '%s', not a method or junction, can not call it",                                                          "is '%s', not a method or junction, can not call it",
                                                                 value.type());                                                                  value.type());
Line 416  void Request::execute(ArrayOperation& op Line 417  void Request::execute(ArrayOperation& op
                                 // $junction{code}                                  // $junction{code}
                                 //  ^junction[]                                  //  ^junction[]
                                 if(!junction->method)                                  if(!junction->method)
                                         throw Exception("parser.runtime",                                          throw Exception(PARSER_RUNTIME,
                                                   
                                                 "is '%s', it is code junction, can not call it",                                                  "is '%s', it is code junction, can not call it",
                                                         value.type());                                                          value.type());
                                 */                                  */
   
                                 VMethodFrame frame(*junction, method_frame/*caller*/);                                  if(junction->method->all_vars_local){
                                 if(local_ops){ // store param code goes here                                          VMethodFrameLocal frame(*junction, method_frame);
                                         stack.push(frame); // argument for *STORE_PARAM ops                                          if(local_ops){ // store param code goes here
                                         execute(*local_ops);                                                  stack.push(frame); // argument for *STORE_PARAM ops
                                         stack.pop().value();                                                  execute(*local_ops);
                                                   stack.pop().value();
                                           }
                                           WContext* result_wcontext=op_call(frame);
                                           if(opcode==OP_CALL__WRITE) {
                                                   write_assign_lang(result_wcontext->result());
                                           } else { // OP_CALL
                                                   stack.push(result_wcontext->result().as_value());
                                           }
                                   } else {
                                           VMethodFrameGlobal frame(*junction, method_frame);
                                           if(local_ops){ // store param code goes here
                                                   stack.push(frame); // argument for *STORE_PARAM ops
                                                   execute(*local_ops);
                                                   stack.pop().value();
                                           }
                                           WContext* result_wcontext=op_call(frame);
                                           if(opcode==OP_CALL__WRITE) {
                                                   write_assign_lang(result_wcontext->result());
                                           } else { // OP_CALL
                                                   stack.push(result_wcontext->result().as_value());
                                           }
                                 }                                  }
                                 frame.fill_unspecified_params();  
                                 VMethodFrame *saved_method_frame=method_frame;  
                                 Value* saved_rcontext=rcontext;  
                                 WContext *saved_wcontext=wcontext;  
                                   
                                 VStateless_class& called_class=*frame.junction.self.get_class();  
                                 Value* new_self;  
                                 if(wcontext->get_constructing()) {  
                                         wcontext->set_constructing(false);  
                                         new_self=&get_self();  
                                         if(frame.junction.method->call_type!=Method::CT_STATIC) {  
                                                 // this is a constructor call  
   
                                                 HashStringValue& new_object_fields=*new HashStringValue();  
                                                 if(Value* value=called_class.create_new_value(fpool, new_object_fields)) {  
                                                         // some stateless_class creatable derivates  
                                                         new_self=value;  
                                                 } 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,   
                                                         String::L_CLEAN  // not used, always an object, not string  
                                                 );  
                                         } else  
                                                 throw Exception("parser.runtime",  
                                                         0, //&frame.name(),  
                                                         "method is static and can not be used as constructor");  
                                 } else  
                                         new_self=&frame.junction.self;  
   
                                 frame.set_self(*new_self);  
   
                                 // see OP_PREPARE_TO_EXPRESSION  
                                 frame.set_in_expression(wcontext->get_in_expression());  
                                   
                                 rcontext=wcontext=&frame;  
                                 {  
                                         const Method& method=*frame.junction.method;  
                                         Method::Call_type call_type=  
                                                 &called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC;  
                                         if(  
                                                 method.call_type==Method::CT_ANY ||  
                                                 method.call_type==call_type) { // allowed call type?  
                                                 method_frame=&frame;  
                                                 if(method.native_code) { // native code?  
                                                         method.check_actual_numbered_params(  
                                                                 frame.junction.self,   
                                                                 /*frame.name(), */frame.numbered_params());  
                                                         method.native_code(  
                                                                 *this,   
                                                                 *frame.numbered_params()); // execute it  
                                                 } else // parser code, execute it  
                                                         recoursion_checked_execute(*method.parser_code);  
                                         } else  
                                                 throw Exception("parser.runtime",  
                                                         0, //&frame.name(),  
                                                         "is not allowed to be called %s",   
                                                                 call_type==Method::CT_STATIC?"statically":"dynamically");  
   
                                 }  
                                 StringOrValue result=wcontext->result();  
   
                                 wcontext=saved_wcontext;  
                                 rcontext=saved_rcontext;  
                                 method_frame=saved_method_frame;  
   
                                 if(opcode==OP_CALL__WRITE) {  
                                         write_assign_lang(result);  
                                 } else { // OP_CALL  
                                         stack.push(result.as_value());  
                                 }  
                                   
 #ifdef DEBUG_EXECUTE  #ifdef DEBUG_EXECUTE
                                 debug_printf(sapi_info, "<-returned");                                  debug_printf(sapi_info, "<-returned");
 #endif  #endif
Line 831  void Request::execute(ArrayOperation& op Line 778  void Request::execute(ArrayOperation& op
         }          }
 }  }
   
   WContext* Request::op_call(VMethodFrame& frame){
           frame.fill_unspecified_params();
           VMethodFrame *saved_method_frame=method_frame;
           Value* saved_rcontext=rcontext;
           WContext *saved_wcontext=wcontext;
                           
           VStateless_class& called_class=*frame.junction.self.get_class();
           Value* new_self;
           if(wcontext->get_constructing()) {
                   wcontext->set_constructing(false);
                   new_self=&get_self();
                   if(frame.junction.method->call_type!=Method::CT_STATIC) {
                           // this is a constructor call
                           HashStringValue& new_object_fields=*new HashStringValue();
                           if(Value* value=called_class.create_new_value(fpool, new_object_fields)) {
                                   // some stateless_class creatable derivates
                                   new_self=value;
                           } 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, 
                                   String::L_CLEAN  // not used, always an object, not string
                           );
                   } else
                           throw Exception(PARSER_RUNTIME,
                                   0, //&frame.name(),
                                   "method is static and can not be used as constructor");
           } else
                   new_self=&frame.junction.self;
   
           frame.set_self(*new_self);
   
           // see OP_PREPARE_TO_EXPRESSION
           frame.set_in_expression(wcontext->get_in_expression());
                                   
           rcontext=wcontext=&frame;
           {
                   const Method& method=*frame.junction.method;
                   Method::Call_type call_type=&called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC;
                   if(
                           method.call_type==Method::CT_ANY ||
                           method.call_type==call_type) { // allowed call type?
                           method_frame=&frame;
                           if(method.native_code) { // native code?
                                   method.check_actual_numbered_params(
                                           frame.junction.self, 
                                           /*frame.name(), */frame.numbered_params());
                                   method.native_code(
                                           *this, 
                                           *frame.numbered_params()); // execute it
                           } else // parser code, execute it
                                   recoursion_checked_execute(*method.parser_code);
                   } else
                           throw Exception(PARSER_RUNTIME,
                                   0, //&frame.name(),
                                   "is not allowed to be called %s", 
                                           call_type==Method::CT_STATIC?"statically":"dynamically");
           }
   
           WContext *result_wcontext=wcontext;
           // StringOrValue result=wcontext->result();
   
           wcontext=saved_wcontext;
           rcontext=saved_rcontext;
           method_frame=saved_method_frame;
   
           return result_wcontext;
   }
   
   
 /**  /**
         @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
Line 849  Value& Request::get_element(Value& ncont Line 869  Value& Request::get_element(Value& ncont
                                         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
                                                         Temp_derived temp_derived(*base, 0); // temporarily prevent go-back-down virtual calls                                                          Temp_derived temp_derived(*base, 0); // temporarily prevent go-back-down virtual calls
                                                         value=base->get_element(name, *base, false); // virtual-up lookup starting from parent                                                          value=base->get_element(name, *base, true); // virtual-up lookup starting from parent
                                                         goto value_ready;                                                          goto value_ready;
                                                 }                                                  }
         }          }
         if(!value)          if(!value)
                 value=ncontext.get_element(name, ncontext, false);                  value=ncontext.get_element(name, ncontext, true);
   
         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());
Line 883  void Request::put_element(Value& ncontex Line 903  void Request::put_element(Value& ncontex
                         ArrayString* params_names=junction.method->params_names;                          ArrayString* params_names=junction.method->params_names;
                         int param_count=params_names? params_names->count(): 0;                          int param_count=params_names? params_names->count(): 0;
                         if(param_count!=1)                          if(param_count!=1)
                                 throw Exception("parser.runtime",                                  throw Exception(PARSER_RUNTIME,
                                         0,                                          0,
                                         "setter method must have ONE parameter (has %d parameters)", param_count);                                          "setter method must have ONE parameter (has %d parameters)", param_count);
   
                         VMethodFrame frame(junction, method_frame/*caller*/);                          VMethodFrameGlobal frame(junction, method_frame/*caller*/);
                         frame.store_param(value);                          frame.store_param(value);
   
                         frame.set_self(frame.junction.self);                          frame.set_self(frame.junction.self);
Line 926  StringOrValue Request::process(Value& in Line 946  StringOrValue Request::process(Value& in
         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?
                         // process it                          int param_count=junction->method->params_names?junction->method->params_names->count():0;
                           if(junction->auto_name){ // default getter
                         VMethodFrame frame(*junction, method_frame/*caller*/);                                  if(param_count>1)
                         if(junction->method->params_names)                                          throw Exception(PARSER_RUNTIME,
                                 throw Exception("parser.runtime",                                                  0,
                                                   "default getter method can't have more then 1 parameter (has %d parameters)", param_count);
                           } else if(param_count)
                                   throw Exception(PARSER_RUNTIME,
                                         0,                                          0,
                                         "getter method must have no parameters");                                          "getter method must have no parameters (has %d parameters)", param_count);
   
                           VMethodFrameGlobal frame(*junction, method_frame/*caller*/);
   
                           if(junction->auto_name && param_count)
                                   frame.store_param(*new VString(*junction->auto_name));
   
                         frame.set_self(frame.junction.self);                          frame.set_self(frame.junction.self);
   
Line 961  StringOrValue Request::process(Value& in Line 989  StringOrValue Request::process(Value& in
 #endif  #endif
   
                         if(!junction->method_frame)                          if(!junction->method_frame)
                                 throw Exception("parser.runtime",                                  throw Exception(PARSER_RUNTIME,
                                 0,                                  0,
                                 "junction used outside of context");                                  "junction used outside of context");
   
Line 977  StringOrValue Request::process(Value& in Line 1005  StringOrValue Request::process(Value& in
                         // using the fact in decision "which wwrapper to use"                          // using the fact in decision "which wwrapper to use"
                         bool using_code_frame=intercept_string && junction->wcontext;                          bool using_code_frame=intercept_string && junction->wcontext;
                         if(using_code_frame) {                          if(using_code_frame) {
                                 // almost plain wwrapper about junction wcontext,                                   // almost plain wwrapper about junction wcontext 
                                 // BUT intercepts string writes  
                                 VCodeFrame local(*junction->wcontext, junction->wcontext);                                  VCodeFrame local(*junction->wcontext);
                                 wcontext=&local;                                  wcontext=&local;
   
                                 // execute it                                  // execute it
                                 recoursion_checked_execute(*junction->code);                                  recoursion_checked_execute(*junction->code);
   
                                 // CodeFrame soul:                                  // CodeFrame soul:
                                 //   string writes were intercepted                                  result=wcontext->result();
                                 //   returning them as the result of getting code-junction  
                                 result.set_string(*wcontext->get_string());  
                         } else {                          } else {
                                 // plain wwrapper                                  // plain wwrapper
                                 WWrapper local(0/*empty*/, wcontext);                                  WWrapper local(0/*empty*/, wcontext);
Line 1042  StringOrValue Request::execute_method(VM Line 1068  StringOrValue Request::execute_method(VM
 const String* Request::execute_method(Value& aself,   const String* Request::execute_method(Value& aself, 
                                       const Method& method, VString* optional_param,                                        const Method& method, VString* optional_param,
                                       bool do_return_string) {                                        bool do_return_string) {
   
         VMethodFrame *saved_method_frame=method_frame;            VMethodFrame *saved_method_frame=method_frame;  
         Value* saved_rcontext=rcontext;            Value* saved_rcontext=rcontext;  
         WContext *saved_wcontext=wcontext;          WContext *saved_wcontext=wcontext;
                   
         Junction local_junction(aself, &method);          Junction local_junction(aself, &method);
         VMethodFrame local_frame(local_junction, method_frame/*caller*/);          VMethodFrameGlobal local_frame(local_junction, method_frame/*caller*/);
         if(optional_param && local_frame.can_store_param()) {          if(optional_param && local_frame.can_store_param()) {
                 local_frame.store_param(*optional_param);                  local_frame.store_param(*optional_param);
                 local_frame.fill_unspecified_params();                  local_frame.fill_unspecified_params();
Line 1076  const String* Request::execute_method(Va Line 1103  const String* Request::execute_method(Va
   
 Request::Execute_nonvirtual_method_result   Request::Execute_nonvirtual_method_result 
 Request::execute_nonvirtual_method(VStateless_class& aclass,   Request::execute_nonvirtual_method(VStateless_class& aclass, 
                                    const String& method_name, VString* optional_param,                                     const String& method_name,
                                      VString* optional_param,
                                    bool do_return_string) {                                     bool do_return_string) {
         Execute_nonvirtual_method_result result;          Execute_nonvirtual_method_result result;
         result.method=aclass.get_method(method_name);          result.method=aclass.get_method(method_name);
         if(result.method)          if(result.method)
                 result.string=execute_method(aclass, *result.method, optional_param,                   result.string=execute_method(aclass, *result.method, optional_param, do_return_string);
                         do_return_string);  
         return result;          return result;
 }  }
   

Removed from v.1.315  
changed lines
  Added in v.1.320


E-mail: