Diff for /parser3/src/classes/reflection.C between versions 1.96 and 1.105

version 1.96, 2024/12/11 02:52:50 version 1.105, 2026/09/25 17:03:52
Line 1 Line 1
 /** @file  /** @file
         Parser: @b reflection parser class.          Parser: @b reflection parser class.
   
         Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
         Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
 */  */
   
Line 10 Line 10
 #include "pa_vbool.h"  #include "pa_vbool.h"
 #include "pa_varray.h"  #include "pa_varray.h"
 #include "pa_vobject.h"  #include "pa_vobject.h"
   #include "pa_vtable.h"
   
 volatile const char * IDENT_REFLECTION_C="$Id$";  volatile const char * IDENT_REFLECTION_C="$Id$";
   
Line 126  static void _create(Request& r, MethodPa Line 127  static void _create(Request& r, MethodPa
   
 static void _classes(Request& r, MethodParams&) {  static void _classes(Request& r, MethodParams&) {
         VHash& result=*new VHash;          VHash& result=*new VHash;
         for(HashString<VStateless_class*>::Iterator i(r.classes()); i; i.next()){          for(OrderedHashString<VStateless_class*>::Iterator i(r.classes()); i; i.next()){
                 result.hash().put(i.key(), i.value()->get_methods().count()>0 ? new VString(class_type_methoded) : VVoid::get() );                  result.hash().put(i.key(), i.value()->get_methods().count()>0 ? new VString(class_type_methoded) : VVoid::get() );
         }          }
         r.write(result);          r.write(result);
Line 161  static void _class_name(Request& r, Meth Line 162  static void _class_name(Request& r, Meth
 }  }
   
 static void _class_by_name(Request& r, MethodParams& params) {  static void _class_by_name(Request& r, MethodParams& params) {
         const String& class_name=params.as_string(0, "class_name must be string");          const String& class_name=params.as_string(0, "class name must be string");
         r.write(r.get_class_ref(class_name));          r.write(r.get_class_ref(class_name));
 }  }
   
Line 361  static void _method_info(Request& r, Met Line 362  static void _method_info(Request& r, Met
                 // parser code                  // parser code
                 const String* filespec = r.get_method_filespec(method);                  const String* filespec = r.get_method_filespec(method);
                 if( filespec )                  if( filespec )
                         hash->put("file", new VString(*filespec));                          HASH_PUT_CSTR(*hash, "file", new VString(*filespec));
   
                 hash->put(method_max_params, new VInt(method->params_count + (method->named_params ? 1 : 0)));                  hash->put(method_max_params, new VInt(method->params_count + (method->named_params ? 1 : 0)));
   
                 if(method->params_names)                  if(method->params_names)
                         for(size_t i=0; i<method->params_names->count(); i++)                          for(size_t i=0; i<method->params_names->count(); i++)
                                 hash->put(pa_uitoa(i), new VString(*method->params_names->get(i)));                                  hash->put(String::Body::uitoa(i), new VString(*method->params_names->get(i)));
   
                 if(method->extra_params)                  if(method->extra_params)
                         hash->put(method_extra_param, new VString(*method->extra_params));                          hash->put(method_extra_param, new VString(*method->extra_params));
Line 376  static void _method_info(Request& r, Met Line 377  static void _method_info(Request& r, Met
                         VArray& named_params=*new VArray(named_count);                          VArray& named_params=*new VArray(named_count);
                         ArrayValue &array=named_params.array();                          ArrayValue &array=named_params.array();
   
                         for(int i=0; i<named_count; i++) {                          for(size_t i=0; i<named_count; i++) {
                                 const String& fname=*(*method->named_params)[i];                                  const String& fname=*(*method->named_params)[i];
                                 array+=new VString(fname);                                  array+=new VString(fname);
                         }                          }
Line 475  static void _mixin(Request& r, MethodPar Line 476  static void _mixin(Request& r, MethodPar
   
         if(params.count()>1)          if(params.count()>1)
                 if(HashStringValue* options=params.as_hash(1, "mixin options")) {                  if(HashStringValue* options=params.as_hash(1, "mixin options")) {
                         int valid_options=0;  
                         for(HashStringValue::Iterator i(*options); i; i.next() ){                          for(HashStringValue::Iterator i(*options); i; i.next() ){
                                 String::Body key=i.key();                                  String::Body key=i.key();
                                 Value* value=i.value();                                  Value* value=i.value();
                                 if(key == "to") {                                  if(key == "to") {
                                         vtarget=value;                                          vtarget=value;
                                         valid_options++;  
                                 } else if(key == "name") {                                  } else if(key == "name") {
                                         name=&value->as_string();                                          name=&value->as_string();
                                         valid_options++;  
                                 } else if(key == "methods") {                                  } else if(key == "methods") {
                                         copy_methods=r.process(*value).as_bool();                                          copy_methods=r.process(*value).as_bool();
                                         valid_options++;  
                                 } else if(key == "fields") {                                  } else if(key == "fields") {
                                         copy_fields=r.process(*value).as_bool();                                          copy_fields=r.process(*value).as_bool();
                                         valid_options++;  
                                 } else if(key == "overwrite") {                                  } else if(key == "overwrite") {
                                         overwrite=r.process(*value).as_bool();                                          overwrite=r.process(*value).as_bool();
                                         valid_options++;                                  } else
                                 }                                          throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                         }                          }
                         if(valid_options!=options->count())  
                                 throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);  
                 }                  }
   
         if(!vtarget)          if(!vtarget)
Line 538  static void _mixin(Request& r, MethodPar Line 532  static void _mixin(Request& r, MethodPar
         }          }
 }  }
   
   static void _override(Request& r, MethodParams& params) {
           Junction *j=params[0].get_junction();
           const Method* method=j ? j->method : 0;
           if(!method)
                   throw Exception(PARSER_RUNTIME, 0, "param must be method junction");
           if(method->native_code)
                   throw Exception(PARSER_RUNTIME, 0, "param must not be native method");
   
           const String *name=method->name;
           Value* vtarget=0;
           if(params.count()>1)
                   if(HashStringValue* options=params.as_hash(1, "override options")) {
                           for(HashStringValue::Iterator i(*options); i; i.next() ){
                                   if(i.key() == "to") {
                                           vtarget=i.value();
                                   } else if(i.key() == "name") {
                                           name=&i.value()->as_string();
                                   } else
                                           throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                           }
                   }
   
           if(!vtarget)
                   vtarget=&r.get_method_frame()->caller()->self();
   
           VClass* target=dynamic_cast<VClass*>(vtarget->get_class());
   
           if(!target)
                   throw Exception(PARSER_RUNTIME, 0, "destination must be parser object or class");
   
           target->set_method(*name, new Method(*method));
   }
   
 String::Language get_untaint_lang(const String& lang_name); // op.C  String::Language get_untaint_lang(const String& lang_name); // op.C
   
 static void _tainting(Request& r, MethodParams& params) {  static void _tainting(Request& r, MethodParams& params) {
Line 572  static void _tainting(Request& r, Method Line 599  static void _tainting(Request& r, Method
         }          }
 }  }
   
   struct LocalsInfo { HashStringValue* args; HashStringValue* locals; };
   
   static void collect_local(const String::Body& key, Value* value, LocalsInfo* info) {
           if(!info->args->contains(key) && (key != "result"))
                   info->locals->put(key, value->get_junction() ? VVoid::get() : value);
   }
   
 static void _stack(Request& r, MethodParams& params) {  static void _stack(Request& r, MethodParams& params) {
           if(params.count())
                   if(VException* exception=dynamic_cast<VException*>(&params[0])) {
                           r.write(*new VTable(&exception->stack(r)));
                           return;
                   }
   
         bool show_args=false;          bool show_args=false;
         bool show_locals=false;          bool show_locals=false;
   
Line 581  static void _stack(Request& r, MethodPar Line 621  static void _stack(Request& r, MethodPar
   
         if(params.count()>0)          if(params.count()>0)
                 if(HashStringValue* options=params.as_hash(0, "stack options")) {                  if(HashStringValue* options=params.as_hash(0, "stack options")) {
                         int valid_options=0;  
                         for(HashStringValue::Iterator i(*options); i; i.next() ){                          for(HashStringValue::Iterator i(*options); i; i.next() ){
                                 String::Body key=i.key();                                  String::Body key=i.key();
                                 Value* value=i.value();                                  Value* value=i.value();
   
                                 if(key == "args") {                                  if(key == "args") {
                                         show_args=r.process(*value).as_bool();                                          show_args=r.process(*value).as_bool();
                                         valid_options++;  
                                 } else if(key == "locals") {                                  } else if(key == "locals") {
                                         show_locals=r.process(*value).as_bool();                                          show_locals=r.process(*value).as_bool();
                                         valid_options++;  
                                 } else if(key == "limit") {                                  } else if(key == "limit") {
                                         limit=r.process(*value).as_int();                                          limit=r.process(*value).as_int();
                                         valid_options++;  
                                 } else if(key == "offset") {                                  } else if(key == "offset") {
                                         offset=r.process(*value).as_int();                                          offset=r.process(*value).as_int();
                                         valid_options++;                                  } else
                                 }                                          throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                         }                          }
   
                         if(valid_options!=options->count())  
                                 throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);  
                 }                  }
   
         limit+=offset;          limit+=offset;
Line 625  static void _stack(Request& r, MethodPar Line 657  static void _stack(Request& r, MethodPar
                         if(!method.native_code){                          if(!method.native_code){
                                 Operation::Origin origin=r.get_method_origin(&method);                                  Operation::Origin origin=r.get_method_origin(&method);
                                 if(origin.file_no){                                  if(origin.file_no){
                                         current->put("file", new VString(*r.get_used_filespec(origin.file_no)));                                          HASH_PUT_CSTR(*current, "file", new VString(*r.get_used_filespec(origin.file_no)));
                                         current->put("line", new VInt(origin.line)); // no +1 as declaration before first command                                          HASH_PUT_CSTR(*current, "line", new VInt(origin.line)); // no +1 as declaration before first command
                                 }                                  }
   
                                 if(show_args || show_locals){                                  if(show_args || show_locals){
Line 645  static void _stack(Request& r, MethodPar Line 677  static void _stack(Request& r, MethodPar
                                                 args->put(*method.extra_params, caller->get_element(*method.extra_params));                                                  args->put(*method.extra_params, caller->get_element(*method.extra_params));
   
                                         if(show_args)                                          if(show_args)
                                                 current->put("args", &vargs);                                                  HASH_PUT_CSTR(*current, "args", &vargs);
   
                                         if(show_locals){                                          if(show_locals){
                                                 VHash& vlocals=*new VHash;                                                  VHash& vlocals=*new VHash;
                                                 HashStringValue* locals=vlocals.get_hash();                                                  HashStringValue* locals=vlocals.get_hash();
   
                                                 if(VParserMethodFrame* frame=dynamic_cast<VParserMethodFrame*>(caller))                                                  if(VParserMethodFrame* frame=dynamic_cast<VParserMethodFrame*>(caller)){
                                                         for(HashString<Value*>::Iterator h(frame->my); h; h.next()){                                                          LocalsInfo linfo = { args, locals };
                                                                 String::Body key=h.key();                                                          frame->my.for_each(collect_local, &linfo);
                                                                 Value* value=h.value();                                                  }
                                                                 if(!args->contains(key) && (key != "result")){  
                                                                         locals->put(key, value->get_junction() ? VVoid::get() : value);  
                                                                 }  
                                                         }  
   
                                                 current->put("locals", &vlocals);                                                  HASH_PUT_CSTR(*current, "locals", &vlocals);
                                         }                                          }
                                 }                                  }
                         }                          }
   
                         result->put(pa_uitoa(index), &vcurrent);                          result->put(String::Body::uitoa(index), &vcurrent);
                 }                  }
                 caller=caller->caller();                  caller=caller->caller();
                 index++;                  index++;
Line 745  MReflection::MReflection(): Methoded("re Line 773  MReflection::MReflection(): Methoded("re
         // ^reflection:mixin[object or class or junction;options]          // ^reflection:mixin[object or class or junction;options]
         add_native_method("mixin", Method::CT_STATIC, _mixin, 1, 2);          add_native_method("mixin", Method::CT_STATIC, _mixin, 1, 2);
   
           // ^reflection:override[method junction[;$.to[class] $.name[another_name]]]
           add_native_method("override", Method::CT_STATIC, _override, 1, 2);
   
         // ^reflection:tainting[[language or 'tainted' or 'optimized';]string]          // ^reflection:tainting[[language or 'tainted' or 'optimized';]string]
         add_native_method("tainting", Method::CT_STATIC, _tainting, 1, 2);          add_native_method("tainting", Method::CT_STATIC, _tainting, 1, 2);
   

Removed from v.1.96  
changed lines
  Added in v.1.105


E-mail: