Annotation of parser3/src/classes/reflection.C, revision 1.1

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: 
        !             8: static const char * const IDENT_REFLECTION_C="$Date: 2005/08/09 08:14:48 $";
        !             9: 
        !            10: #include "pa_vmethod_frame.h"
        !            11: #include "pa_request.h"
        !            12: #include "pa_vbool.h"
        !            13: 
        !            14: // class
        !            15: 
        !            16: class MReflection: public Methoded {
        !            17: public:
        !            18:        MReflection();
        !            19: public: // Methoded
        !            20:        bool used_directly() { return true; }
        !            21: };
        !            22: 
        !            23: // global variable
        !            24: 
        !            25: DECLARE_CLASS_VAR(reflection, new MReflection, 0);
        !            26: 
        !            27: // methods
        !            28: 
        !            29: static void _construct(Request& r, MethodParams& params) {
        !            30:        const String& class_name=params.as_string(0, "class_name must be string");
        !            31:        Value* class_value=r.classes().get(class_name);
        !            32: 
        !            33:        if(!class_value)
        !            34:                throw Exception(PARSER_RUNTIME,
        !            35:                        &class_name,
        !            36:                        "class is undefined");
        !            37: 
        !            38:        const String& constructor_name=params.as_string(1, "constructor_name must be string");
        !            39:        Value* constructor_value=class_value->get_element(constructor_name, *class_value, true);
        !            40: 
        !            41:        if(!constructor_value || !constructor_value->get_junction())
        !            42:                throw Exception(PARSER_RUNTIME,
        !            43:                        &constructor_name,
        !            44:                        "constructor must be declared in class '%s'",
        !            45:                        class_name.cstr());
        !            46: 
        !            47:        Junction* junction=constructor_value->get_junction();
        !            48: 
        !            49:        VMethodFrame frame(*junction, r.get_method_frame());
        !            50: 
        !            51:        size_t nparams=params.count()-2;
        !            52:     Value* v[100];
        !            53: 
        !            54:        if(nparams>0){
        !            55:                for(size_t i=0; i<nparams; i++)
        !            56:                        v[i]=&r.process_to_value(params[i+2]);
        !            57:                frame.store_params((Value**)&v, nparams);
        !            58:        } else {
        !            59:                frame.empty_params();
        !            60:        }
        !            61:        r.op_call(frame, true/*constructing*/);
        !            62:        r.write_pass_lang(frame.result());
        !            63: }
        !            64: 
        !            65: static void _class(Request& r, MethodParams& params) {
        !            66:        if(Value* lclass=params[0].get_class())
        !            67:                r.write_no_lang(*lclass);
        !            68:        else
        !            69:                throw Exception(PARSER_RUNTIME,
        !            70:                        0,
        !            71:                        "class was not defined");
        !            72: }
        !            73: 
        !            74: static void _class_name(Request& r, MethodParams& params) {
        !            75:        r.write_no_lang(String(params[0].type()));
        !            76: }
        !            77: 
        !            78: static void store_method_info(
        !            79:                HashString<Method*>::key_type key, 
        !            80:                HashString<Method*>::value_type value,
        !            81:                HashStringValue* result
        !            82: ) {
        !            83:        VHash* method_info=new VHash;
        !            84:        HashStringValue* method_hash=method_info->get_hash();
        !            85:        bool native=false;
        !            86: 
        !            87:        if(value->native_code){
        !            88:                // native code
        !            89:                native=true;
        !            90:                if(value->min_numbered_params_count)
        !            91:                        method_hash->put(String("min_params"), new VInt(value->min_numbered_params_count));
        !            92: 
        !            93:                if(value->max_numbered_params_count)
        !            94:                        method_hash->put(String("max_params"), new VInt(value->max_numbered_params_count));
        !            95:        } else {
        !            96:                // parser code
        !            97:                if(value->params_names){
        !            98:                        VHash* params=new VHash;
        !            99:                        method_hash->put(String("params"), params);
        !           100:                        HashStringValue* params_hash=params->get_hash();
        !           101: 
        !           102:                        for(size_t i=0; i<value->params_names->count(); i++)
        !           103:                                params_hash->put(String::Body::Format(i), new VString(*value->params_names->get(i)));
        !           104:                }
        !           105: 
        !           106:                if(value->locals_names){
        !           107:                        VHash* locals=new VHash;
        !           108:                        method_hash->put(String("locals"), locals);
        !           109:                        HashStringValue* locals_hash=locals->get_hash();
        !           110:        
        !           111:                        for(size_t i=0; i<value->locals_names->count(); i++)
        !           112:                                locals_hash->put(String::Body::Format(i), new VString(*value->locals_names->get(i)));
        !           113:                }
        !           114:        }
        !           115: 
        !           116:        method_hash->put(String("native"), &VBool::get(native));
        !           117:        result->put(key, method_info);
        !           118: }
        !           119: 
        !           120: static void _methods(Request& r, MethodParams& params) {
        !           121:        const String& class_name=params.as_string(0, "class_name must be string");
        !           122:        Value* class_value=r.classes().get(class_name);
        !           123: 
        !           124:        if(!class_value)
        !           125:                throw Exception(PARSER_RUNTIME,
        !           126:                        &class_name,
        !           127:                        "class is undefined");
        !           128: 
        !           129:        VHash& result=*new VHash;
        !           130:        if(VStateless_class* lclass=class_value->get_class()){
        !           131:                HashString<Method*> methods=lclass->get_methods();
        !           132:                methods.for_each(store_method_info, result.get_hash());
        !           133:        } else {
        !           134:                // exception?
        !           135:        }
        !           136:        r.write_no_lang(result);
        !           137: }
        !           138: 
        !           139: // constructor
        !           140: MReflection::MReflection(): Methoded("reflection") {
        !           141:        // ^reflection:construct[class;constructor;params[;]]
        !           142:        add_native_method("construct", Method::CT_STATIC, _construct, 2, 102);
        !           143: 
        !           144:        // ^reflection:class[object]
        !           145:        add_native_method("class", Method::CT_STATIC, _class, 1, 1);
        !           146: 
        !           147:        // ^reflection:class_name[object]
        !           148:        add_native_method("class_name", Method::CT_STATIC, _class_name, 1, 1);
        !           149: 
        !           150:        // ^reflection:get_methods[object]
        !           151:        add_native_method("methods", Method::CT_STATIC, _methods, 1, 1);
        !           152: }

E-mail: