Annotation of parser3/src/classes/reflection.C, revision 1.4
1.1 misha 1: /** @file
2: Parser: @b reflection parser class.
3:
4: Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com)
5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
6: */
7:
1.4 ! misha 8: static const char * const IDENT_REFLECTION_C="$Date: 2009-07-28 08:03:05 $";
1.1 misha 9:
10: #include "pa_vmethod_frame.h"
11: #include "pa_request.h"
12: #include "pa_vbool.h"
13:
1.3 misha 14: static const String class_type_methoded("methoded");
1.2 misha 15:
1.3 misha 16: static const String method_type_native("native");
17: static const String method_type_parser("parser");
1.2 misha 18:
1.3 misha 19: static const String method_call_type_static("static");
20: static const String method_call_type_dynamic("dynamic");
1.2 misha 21:
1.3 misha 22: static const String method_min_params("min_params");
23: static const String method_max_params("max_params");
1.2 misha 24:
1.1 misha 25: // class
26:
27: class MReflection: public Methoded {
28: public:
29: MReflection();
30: public: // Methoded
31: bool used_directly() { return true; }
32: };
33:
34: // global variable
35:
36: DECLARE_CLASS_VAR(reflection, new MReflection, 0);
37:
38: // methods
39:
1.2 misha 40:
41: static void _create(Request& r, MethodParams& params) {
1.1 misha 42: const String& class_name=params.as_string(0, "class_name must be string");
43: Value* class_value=r.classes().get(class_name);
44:
45: if(!class_value)
46: throw Exception(PARSER_RUNTIME,
47: &class_name,
48: "class is undefined");
49:
50: const String& constructor_name=params.as_string(1, "constructor_name must be string");
51: Value* constructor_value=class_value->get_element(constructor_name, *class_value, true);
52:
1.2 misha 53: if(!constructor_value || !constructor_value->get_junction() || constructor_value->get_junction()->self.get_class()!=class_value)
1.1 misha 54: throw Exception(PARSER_RUNTIME,
55: &constructor_name,
56: "constructor must be declared in class '%s'",
1.2 misha 57: class_value->get_class()->name_cstr());
1.1 misha 58:
59: Junction* junction=constructor_value->get_junction();
1.2 misha 60: const Method* method=junction->method;
61:
62: int nparams=params.count()-2;
63: int max_params_count;
64:
65: if(method->native_code){
66: if(method->call_type==Method::CT_STATIC)
67: throw Exception(PARSER_RUNTIME,
68: &constructor_name,
69: "native method of class '%s' (%s) is not allowed to be called dynamically",
70: class_value->get_class()->name_cstr(),
71: class_value->type());
72:
73: if(nparams<method->min_numbered_params_count)
74: throw Exception(PARSER_RUNTIME,
75: &constructor_name,
76: "native method of class '%s' (%s) accepts minimum %d parameter(s) (%d passed)",
77: class_value->get_class()->name_cstr(),
78: class_value->type(),
79: method->min_numbered_params_count,
80: nparams);
81:
82: max_params_count=method->max_numbered_params_count;
83: } else {
84: max_params_count=method->params_names->count();
85: }
86:
87: if(nparams>max_params_count)
88: throw Exception(PARSER_RUNTIME,
89: &constructor_name,
90: "method of class '%s' (%s) accepts maximum %d parameter(s) (%d passed)",
91: class_value->get_class()->name_cstr(),
92: class_value->type(),
93: max_params_count,
94: nparams);
1.1 misha 95:
96: VMethodFrame frame(*junction, r.get_method_frame());
97:
1.3 misha 98: Value* v[100];
1.1 misha 99: if(nparams>0){
1.2 misha 100: for(int i=0; i<nparams; i++)
1.1 misha 101: v[i]=&r.process_to_value(params[i+2]);
102: frame.store_params((Value**)&v, nparams);
103: } else {
104: frame.empty_params();
105: }
106: r.op_call(frame, true/*constructing*/);
107: r.write_pass_lang(frame.result());
108: }
109:
1.2 misha 110:
1.3 misha 111: static void store_vlass_info(
112: HashStringValue::key_type key,
113: HashStringValue::value_type value,
114: HashStringValue* result
115: ){
116: Value* v;
117: if(value->get_class())
118: v=new VString(class_type_methoded);
119: else
120: v=VVoid::get();
121: result->put(key, v);
122: }
123:
124: static void _classes(Request& r, MethodParams&) {
125: VHash& result=*new VHash;
126: r.classes().for_each(store_vlass_info, result.get_hash());
127: r.write_no_lang(result);
128: }
129:
130:
131: static Value* get_class(Value* value){
132: if(VStateless_class* result=value->get_class())
133: return result;
134: else
135: // classes with fields only, like env & console
136: return value;
137: }
138:
139: static const String* get_class_name(Value* value){
140: if(VStateless_class* lclass=value->get_class())
141: return &lclass->name();
142: else
143: // classes with fields only, like env & console
144: return new String(value->type());
145: }
146:
147:
1.1 misha 148: static void _class(Request& r, MethodParams& params) {
1.3 misha 149: r.write_no_lang(*get_class(¶ms[0]));
1.1 misha 150: }
151:
1.2 misha 152:
1.1 misha 153: static void _class_name(Request& r, MethodParams& params) {
1.3 misha 154: r.write_no_lang(*get_class_name(¶ms[0]));
1.1 misha 155: }
156:
157:
1.2 misha 158: static void _base(Request& r, MethodParams& params) {
1.3 misha 159: if(VStateless_class* lclass=params[0].get_class())
160: if(Value* base=lclass->base()){
161: r.write_no_lang(*get_class(base));
162: return;
163: }
164:
165: // classes with fields only, like env & console or without base
166: r.write_no_lang(*VVoid::get());
1.2 misha 167: }
1.1 misha 168:
169:
1.2 misha 170: static void _base_name(Request& r, MethodParams& params) {
1.3 misha 171: if(VStateless_class* lclass=params[0].get_class())
1.2 misha 172: if(Value* base=lclass->base())
1.3 misha 173: r.write_no_lang(*get_class_name(base));
1.2 misha 174: }
1.1 misha 175:
176:
1.2 misha 177: static void store_method_info(
178: HashString<Method*>::key_type key,
179: HashString<Method*>::value_type method,
180: HashStringValue* result
181: ) {
182: result->put(key, new VString(method->native_code?method_type_native:method_type_parser));
1.1 misha 183: }
184:
185: static void _methods(Request& r, MethodParams& params) {
186: const String& class_name=params.as_string(0, "class_name must be string");
187: Value* class_value=r.classes().get(class_name);
188: if(!class_value)
189: throw Exception(PARSER_RUNTIME,
190: &class_name,
191: "class is undefined");
192:
193: VHash& result=*new VHash;
194: if(VStateless_class* lclass=class_value->get_class()){
195: HashString<Method*> methods=lclass->get_methods();
196: methods.for_each(store_method_info, result.get_hash());
197: } else {
1.3 misha 198: // class which does not have methods (env, console, etc)
1.1 misha 199: }
200: r.write_no_lang(result);
201: }
202:
1.2 misha 203:
204: static void _method_params(Request& r, MethodParams& params) {
205: const String& class_name=params.as_string(0, "class_name must be string");
206: Value* class_value=r.classes().get(class_name);
207: if(!class_value)
208: throw Exception(PARSER_RUNTIME,
209: &class_name,
210: "class is undefined");
211:
212: VStateless_class* lclass=class_value->get_class();
213: if(!lclass)
214: throw Exception(PARSER_RUNTIME,
215: &class_name,
216: "class does not have methods");
217:
218: const String& method_name=params.as_string(1, "method_name must be string");
219: Method* method=lclass->get_method(method_name);
220: if(!method)
221: throw Exception(PARSER_RUNTIME,
222: &method_name,
223: "method not found in class %s",
224: class_name.cstr());
225:
226: VHash& result=*new VHash;
227: HashStringValue* hash=result.get_hash();
228: if(method->native_code){
229: // native code
230: hash->put(method_min_params, new VInt(method->min_numbered_params_count));
231: hash->put(method_max_params, new VInt(method->max_numbered_params_count));
1.4 ! misha 232: Value* call_type;
1.2 misha 233: switch(method->call_type){
234: case Method::CT_DYNAMIC:
1.4 ! misha 235: call_type=new VString(method_call_type_dynamic);
1.2 misha 236: break;
237: case Method::CT_STATIC:
1.4 ! misha 238: call_type=new VString(method_call_type_static);
1.2 misha 239: break;
240: default:
1.4 ! misha 241: call_type=VVoid::get();
1.2 misha 242: }
1.4 ! misha 243: hash->put(String("call_type"), call_type);
1.2 misha 244:
245: } else {
246: // parser code
247: if(method->params_names)
248: for(size_t i=0; i<method->params_names->count(); i++)
249: hash->put(String::Body::Format(i), new VString(*method->params_names->get(i)));
250: }
251:
252: r.write_no_lang(result);
253: }
254:
1.1 misha 255: // constructor
256: MReflection::MReflection(): Methoded("reflection") {
1.2 misha 257: // ^reflection:create[class_name;constructor_name[;param1[;param2[;...]]]]
258: add_native_method("create", Method::CT_STATIC, _create, 2, 102);
1.1 misha 259:
1.3 misha 260: // ^reflection:classes[]
261: add_native_method("classes", Method::CT_STATIC, _classes, 0, 0);
262:
1.1 misha 263: // ^reflection:class[object]
264: add_native_method("class", Method::CT_STATIC, _class, 1, 1);
265:
266: // ^reflection:class_name[object]
267: add_native_method("class_name", Method::CT_STATIC, _class_name, 1, 1);
268:
1.2 misha 269: // ^reflection:base_class[object]
270: add_native_method("base", Method::CT_STATIC, _base, 1, 1);
271:
272: // ^reflection:base_class_name[object]
273: add_native_method("base_name", Method::CT_STATIC, _base_name, 1, 1);
274:
275: // ^reflection:methods[class_name]
1.1 misha 276: add_native_method("methods", Method::CT_STATIC, _methods, 1, 1);
1.2 misha 277:
278: // ^reflection:method_params[class_name;method_name]
279: add_native_method("method_params", Method::CT_STATIC, _method_params, 2, 2);
1.1 misha 280: }
E-mail: