--- parser3/src/classes/reflection.C 2016/11/30 21:30:24 1.71 +++ parser3/src/classes/reflection.C 2016/12/08 21:05:43 1.78 @@ -10,7 +10,7 @@ #include "pa_vbool.h" #include "pa_vobject.h" -volatile const char * IDENT_REFLECTION_C="$Id: reflection.C,v 1.71 2016/11/30 21:30:24 moko Exp $"; +volatile const char * IDENT_REFLECTION_C="$Id: reflection.C,v 1.78 2016/12/08 21:05:43 moko Exp $"; static const String class_type_methoded("methoded"); @@ -42,40 +42,78 @@ DECLARE_CLASS_VAR(reflection, new MRefle // methods +const int MAX_CREATE_PARAMS = 100; static void _create(Request& r, MethodParams& params) { - const String& class_name=params.as_string(0, "class_name must be string"); - VStateless_class* vclass=r.get_class(class_name); + int params_offset; + HashStringValue* params_hash=0; - if(!vclass) - throw Exception(PARSER_RUNTIME, &class_name, "class is undefined"); + const String* class_name=0; + const String* constructor_name=0; + + Value& voptions=params.as_no_junction(0, "param must not be code"); + if(HashStringValue* options=voptions.get_hash()) { + int valid_options=0; + if(Value* vclass_name=options->get("class")) { + valid_options++; + class_name=&vclass_name->as_string(); + } + if(Value* vconstructor_name=options->get("constructor")) { + valid_options++; + constructor_name=&vconstructor_name->as_string(); + } + if(Value* vparams_hash=options->get("arguments")) { + valid_options++; + params_hash=vparams_hash->as_hash("arguments"); + if(params.count()>1) + throw Exception(PARSER_RUNTIME, 0, "agruments should not be specified as hash and as create params"); + } + if(valid_options!=options->count()) + throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); - const String& constructor_name=params.as_string(1, "constructor_name must be string"); - Value* constructor_value=vclass->get_element(constructor_name); + if(!class_name) + throw Exception(PARSER_RUNTIME, 0, "class name must be specified"); + if(!constructor_name) + throw Exception(PARSER_RUNTIME, 0, "constructor name must be specified"); - if(!constructor_value || !constructor_value->get_junction()) - throw Exception(PARSER_RUNTIME, &constructor_name, "constructor must be declared in class '%s'", vclass->type()); + params_offset=1; + } else { + class_name=¶ms.as_string(0, "param must not be code"); - Junction* junction=constructor_value->get_junction(); - const Method* method=junction->method; + if(params.count()==1) + throw Exception(PARSER_RUNTIME, 0, "constructor name must be specified"); - int nparams=params.count()-2; - int max_params_count; + constructor_name=¶ms.as_string(1, "constructor name must be string"); - if(method->native_code){ - max_params_count=method->max_numbered_params_count; - } else { - max_params_count=method->params_count; + params_offset=2; } + VStateless_class* vclass=r.get_class(*class_name); + if(!vclass) + throw Exception(PARSER_RUNTIME, class_name, "class is undefined"); + + const Method* method=vclass->get_method(*constructor_name); + if(!method) + throw Exception(PARSER_RUNTIME, constructor_name, "constructor not found in class '%s'", vclass->type()); + Value &object = r.construct(*vclass, *method); + int nparams=params_hash ? params_hash->count() : (params.count()-params_offset); + if(nparams>MAX_CREATE_PARAMS) + throw Exception(PARSER_RUNTIME, 0, "arguments count should not exceed %d", MAX_CREATE_PARAMS); + + Value* args[MAX_CREATE_PARAMS]; CONSTRUCTOR_FRAME_ACTION(*method, r.get_method_frame(), object, { - Value* v[100]; if(nparams>0){ - for(int i=0; i