Annotation of parser3/src/types/pa_vmethod_frame.h, revision 1.37

1.3       paf         1: /** @file
1.5       paf         2:        Parser: @b method_frame write context
1.3       paf         3: 
1.21      paf         4:        Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.22      paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       paf         6: */
                      7: 
                      8: #ifndef PA_VMETHOD_FRAME_H
                      9: #define PA_VMETHOD_FRAME_H
1.28      paf        10: 
1.37    ! paf        11: static const char* IDENT_VMETHOD_FRAME_H="$Date: 2002/09/10 12:02:24 $";
1.1       paf        12: 
                     13: #include "pa_wcontext.h"
1.12      parser     14: #include "pa_vvoid.h"
1.1       paf        15: #include "pa_vjunction.h"
1.35      paf        16: #include "pa_request.h"
1.1       paf        17: 
1.4       paf        18: /**    Method frame write context
                     19:        accepts values written by method code
                     20:        also handles method parameters and local variables
1.3       paf        21: */
1.1       paf        22: class VMethodFrame : public WContext {
                     23: public: // Value
                     24: 
                     25:        const char *type() const { return "method_frame"; }
1.20      paf        26: 
                     27:        /// VMethodFrame: $result | parent get_string(=accumulated fstring)
                     28:        const String *get_string() { 
                     29:                // check the $result value
                     30:                Value *result=get_result_variable();
                     31:                // if we have one, return it's string value, else return as usual: accumulated fstring or fvalue
                     32:                return result ? result->get_string() : WContext::get_string();
                     33:        }
                     34:        
1.4       paf        35:        /// VMethodFrame: my or self_transparent
1.34      paf        36:        Value *get_element(const String& aname, Value *aself, bool looking_up) { 
1.25      paf        37:                if(junction.method->max_numbered_params_count==0) {
1.32      paf        38:                        if(Value *result=static_cast<Value *>(my.get(aname)))
1.1       paf        39:                                return result;
                     40:                }
1.37    ! paf        41:                return self(&aname).get_element(aname, aself, looking_up); 
1.1       paf        42:        }
1.4       paf        43:        /// VMethodFrame: my or self_transparent
1.32      paf        44:        /*override*/ bool put_element(const String& aname, Value *avalue, bool replace) { 
                     45:                if(junction.method->max_numbered_params_count==0 && my.put_replace(aname, avalue))
                     46:                        return true;
                     47: 
1.37    ! paf        48:                return self(&aname).put_element(aname, avalue, replace);
1.1       paf        49:        }
                     50: 
1.4       paf        51:        /// VMethodFrame: self_transparent
1.37    ! paf        52:        VStateless_class* get_class() { return fself?fself->get_class():0; }
1.1       paf        53: 
1.30      paf        54: public: // WContext
1.1       paf        55: 
1.35      paf        56:        /* override */ StringOrValue result() {
1.1       paf        57:                // check the $result value
1.24      paf        58:                Value *result_value=get_result_variable();
1.1       paf        59:                // if we have one, return it, else return as usual: accumulated fstring or fvalue
1.24      paf        60:                return result_value ? StringOrValue(0, result_value) : WContext::result();
1.1       paf        61:        }
                     62: 
                     63: public: // usage
                     64: 
                     65:        VMethodFrame(Pool& apool, 
1.25      paf        66:                const String& aname,
1.13      parser     67:                const Junction& ajunction/*info: always method-junction*/) : 
1.36      paf        68:                WContext(apool, 0 /* empty */, 0 /* no parent, junctions can be reattached only up to VMethodFrame */ ),
1.1       paf        69: 
1.25      paf        70:                fname(aname),
1.1       paf        71:                junction(ajunction),
                     72:                store_param_index(0),
1.25      paf        73: 
                     74:                my(apool),
                     75:                fnumbered_params(apool, aname),
                     76: 
1.15      parser     77:                fself(0),
1.36      paf        78:                fresult_initial_void(0) {
1.1       paf        79: 
1.25      paf        80:                if(has_my()) { // this method uses named params?
                     81:                        const Method &method=*junction.method;
1.1       paf        82:                        if(method.locals_names) { // are there any local var names?
                     83:                                // remember them
1.25      paf        84:                                // those are flags that fname is local == to be looked up in 'my'
1.1       paf        85:                                for(int i=0; i<method.locals_names->size(); i++) {
1.25      paf        86:                                        // speedup: not checking for clash with "result" fname
1.12      parser     87:                                        Value *value=NEW VVoid(pool());
1.25      paf        88:                                        const String& fname=*method.locals_names->get_string(i);
                     89:                                        set_my_variable(fname, value);
1.1       paf        90:                                }
                     91:                        }
                     92:                        { // always there is one local: $result
1.15      parser     93:                                fresult_initial_void=NEW VVoid(pool());
1.18      paf        94:                                set_my_variable(*result_var_name, fresult_initial_void);
1.1       paf        95:                        }
                     96:                }
                     97:        }
                     98: 
1.25      paf        99:        const String& name() { return fname; }
                    100: 
1.37    ! paf       101:        void set_self(Value *aself) { fself=aself; }
        !           102:        Value& self(const String *source) { 
        !           103:                if(!fself)
        !           104:                        throw Exception("parser.runtime",
        !           105:                                source,
        !           106:                                "you can not access nonlocal variables here");
        !           107:                return *fself; 
        !           108:        }
1.1       paf       109: 
1.27      paf       110:        bool can_store_param() {
                    111:                const Method& method=*junction.method;
                    112:                return method.params_names && store_param_index<method.params_names->size();
                    113:        }
1.26      paf       114:        void store_param(Value *value) {
1.1       paf       115:                const Method& method=*junction.method;
                    116:                int max_params=
                    117:                        method.max_numbered_params_count?method.max_numbered_params_count:
                    118:                        method.params_names?method.params_names->size():
                    119:                        0;
                    120:                if(store_param_index==max_params)
1.23      paf       121:                        throw Exception("parser.runtime",
1.26      paf       122:                                &name(),
1.7       paf       123:                                "method of %s (%s) accepts maximum %d parameter(s)", 
1.37    ! paf       124:                                        junction.self?junction.self->get_class()->name_cstr():"<unknown class>",
        !           125:                                        junction.self?junction.self->type():"<unknown type>",
1.1       paf       126:                                        max_params);
                    127:                
                    128:                if(method.max_numbered_params_count) { // are this method params numbered?
1.25      paf       129:                        fnumbered_params+=value;
1.1       paf       130:                } else { // named param
1.25      paf       131:                        // speedup: not checking for clash with "result" fname
                    132:                        const String& fname=*method.params_names->get_string(store_param_index);
                    133:                        set_my_variable(fname, value);
1.1       paf       134:                }
                    135:                store_param_index++;
                    136:        }
                    137:        void fill_unspecified_params() {
                    138:                const Method &method=*junction.method;
                    139:                if(method.params_names) // there are any named parameters might need filling?
                    140:                        for(; store_param_index<method.params_names->size(); store_param_index++) {
1.25      paf       141:                                const String& fname=*method.params_names->get_string(store_param_index);
                    142:                                my.put(fname, NEW VVoid(pool()));
1.1       paf       143:                        }
                    144:        }
                    145: 
1.25      paf       146:        MethodParams *numbered_params() { return &fnumbered_params; }
1.18      paf       147: 
                    148: private:
                    149: 
1.25      paf       150:        bool has_my() {
                    151:                return junction.method->max_numbered_params_count==0;
                    152:        }
                    153: 
                    154:        void set_my_variable(const String& fname, Value *value) {
                    155:                my.put(fname, value); // remember param
1.20      paf       156:        }
                    157: 
                    158:        Value *get_result_variable() {
1.25      paf       159:                Value *result=has_my()?static_cast<Value*>(my.get(*result_var_name)):0;
1.20      paf       160:                return result && result!=fresult_initial_void ? result : 0;
1.18      paf       161:        }
1.1       paf       162: 
                    163: public:
                    164:        
                    165:        const Junction& junction;
                    166: 
                    167: private:
1.35      paf       168: 
1.25      paf       169:        const String& fname;
                    170: 
1.1       paf       171:        int store_param_index;
1.25      paf       172:        Hash my;/*OR*/MethodParams fnumbered_params;
1.1       paf       173:        Value *fself;
1.15      parser    174: 
                    175: private:
1.35      paf       176: 
1.15      parser    177:        Value *fresult_initial_void;
1.1       paf       178: 
                    179: };
                    180: 
                    181: #endif

E-mail: