Annotation of parser3/src/types/pa_vmethod_frame.h, revision 1.43.4.1
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.43.4.1! paf 11: static const char* IDENT_VMETHOD_FRAME_H="$Date: 2002/10/15 14:28:57 $";
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.40 paf 18: // defines
19:
1.42 paf 20: #define CALLER_ELEMENT_NAME "caller"
21: #define SELF_ELEMENT_NAME "self"
1.40 paf 22:
1.4 paf 23: /** Method frame write context
24: accepts values written by method code
25: also handles method parameters and local variables
1.3 paf 26: */
1.1 paf 27: class VMethodFrame : public WContext {
28: public: // Value
29:
30: const char *type() const { return "method_frame"; }
1.20 paf 31:
32: /// VMethodFrame: $result | parent get_string(=accumulated fstring)
33: const String *get_string() {
34: // check the $result value
35: Value *result=get_result_variable();
36: // if we have one, return it's string value, else return as usual: accumulated fstring or fvalue
37: return result ? result->get_string() : WContext::get_string();
38: }
39:
1.40 paf 40: /// VMethodFrame: my or self_transparent or $caller
1.43.4.1! paf 41: Value *get_element(const String& aname, Value& aself, bool looking_up) {
1.25 paf 42: if(junction.method->max_numbered_params_count==0) {
1.32 paf 43: if(Value *result=static_cast<Value *>(my.get(aname)))
1.1 paf 44: return result;
45: }
1.41 paf 46: if(Value *result=self().get_element(aname, aself, looking_up))
1.40 paf 47: return result;
48:
1.42 paf 49: if(aname==CALLER_ELEMENT_NAME)
1.40 paf 50: return caller();
1.42 paf 51:
52: if(aname==SELF_ELEMENT_NAME)
53: return &self();
1.40 paf 54:
55: return 0;
1.1 paf 56: }
1.4 paf 57: /// VMethodFrame: my or self_transparent
1.32 paf 58: /*override*/ bool put_element(const String& aname, Value *avalue, bool replace) {
59: if(junction.method->max_numbered_params_count==0 && my.put_replace(aname, avalue))
60: return true;
61:
1.41 paf 62: return self().put_element(aname, avalue, replace);
1.1 paf 63: }
64:
1.4 paf 65: /// VMethodFrame: self_transparent
1.43.4.1! paf 66: /*override*/ VStateless_class* get_class() { return self().get_class(); }
! 67:
! 68: /// VMethodFrame: self_transparent
! 69: /*override*/ Value& get_last_derived() { return self().get_last_derived(); }
! 70:
! 71: /// VMethodFrame: self_transparent
! 72: /*override*/ Value *base() { return self().base(); }
1.1 paf 73:
1.30 paf 74: public: // WContext
1.1 paf 75:
1.35 paf 76: /* override */ StringOrValue result() {
1.1 paf 77: // check the $result value
1.24 paf 78: Value *result_value=get_result_variable();
1.1 paf 79: // if we have one, return it, else return as usual: accumulated fstring or fvalue
1.24 paf 80: return result_value ? StringOrValue(0, result_value) : WContext::result();
1.1 paf 81: }
82:
83: public: // usage
84:
85: VMethodFrame(Pool& apool,
1.25 paf 86: const String& aname,
1.40 paf 87: const Junction& ajunction/*info: always method-junction*/,
88: VMethodFrame *acaller) :
1.36 paf 89: WContext(apool, 0 /* empty */, 0 /* no parent, junctions can be reattached only up to VMethodFrame */ ),
1.1 paf 90:
1.25 paf 91: fname(aname),
1.1 paf 92: junction(ajunction),
1.40 paf 93: fcaller(acaller),
1.1 paf 94: store_param_index(0),
1.25 paf 95:
96: my(apool),
97: fnumbered_params(apool, aname),
98:
1.15 parser 99: fself(0),
1.36 paf 100: fresult_initial_void(0) {
1.1 paf 101:
1.25 paf 102: if(has_my()) { // this method uses named params?
103: const Method &method=*junction.method;
1.1 paf 104: if(method.locals_names) { // are there any local var names?
105: // remember them
1.25 paf 106: // those are flags that fname is local == to be looked up in 'my'
1.1 paf 107: for(int i=0; i<method.locals_names->size(); i++) {
1.25 paf 108: // speedup: not checking for clash with "result" fname
1.12 parser 109: Value *value=NEW VVoid(pool());
1.25 paf 110: const String& fname=*method.locals_names->get_string(i);
111: set_my_variable(fname, value);
1.1 paf 112: }
113: }
114: { // always there is one local: $result
1.15 parser 115: fresult_initial_void=NEW VVoid(pool());
1.18 paf 116: set_my_variable(*result_var_name, fresult_initial_void);
1.1 paf 117: }
118: }
119: }
120:
1.25 paf 121: const String& name() { return fname; }
1.40 paf 122: VMethodFrame *caller() { return fcaller; }
1.25 paf 123:
1.38 paf 124: void set_self(Value& aself) { fself=&aself; }
1.41 paf 125: /// we sure that someone already set our self with VMethodFrame::set_self(Value&)
126: Value& self() { return *fself; }
1.1 paf 127:
1.27 paf 128: bool can_store_param() {
129: const Method& method=*junction.method;
130: return method.params_names && store_param_index<method.params_names->size();
131: }
1.26 paf 132: void store_param(Value *value) {
1.1 paf 133: const Method& method=*junction.method;
134: int max_params=
135: method.max_numbered_params_count?method.max_numbered_params_count:
136: method.params_names?method.params_names->size():
137: 0;
138: if(store_param_index==max_params)
1.23 paf 139: throw Exception("parser.runtime",
1.26 paf 140: &name(),
1.7 paf 141: "method of %s (%s) accepts maximum %d parameter(s)",
1.38 paf 142: junction.self.get_class()->name_cstr(),
143: junction.self.type(),
1.1 paf 144: max_params);
145:
146: if(method.max_numbered_params_count) { // are this method params numbered?
1.25 paf 147: fnumbered_params+=value;
1.1 paf 148: } else { // named param
1.25 paf 149: // speedup: not checking for clash with "result" fname
150: const String& fname=*method.params_names->get_string(store_param_index);
151: set_my_variable(fname, value);
1.1 paf 152: }
153: store_param_index++;
154: }
155: void fill_unspecified_params() {
156: const Method &method=*junction.method;
157: if(method.params_names) // there are any named parameters might need filling?
158: for(; store_param_index<method.params_names->size(); store_param_index++) {
1.25 paf 159: const String& fname=*method.params_names->get_string(store_param_index);
160: my.put(fname, NEW VVoid(pool()));
1.1 paf 161: }
162: }
163:
1.25 paf 164: MethodParams *numbered_params() { return &fnumbered_params; }
1.18 paf 165:
166: private:
167:
1.25 paf 168: bool has_my() {
169: return junction.method->max_numbered_params_count==0;
170: }
171:
172: void set_my_variable(const String& fname, Value *value) {
173: my.put(fname, value); // remember param
1.20 paf 174: }
175:
176: Value *get_result_variable() {
1.25 paf 177: Value *result=has_my()?static_cast<Value*>(my.get(*result_var_name)):0;
1.20 paf 178: return result && result!=fresult_initial_void ? result : 0;
1.18 paf 179: }
1.1 paf 180:
181: public:
182:
183: const Junction& junction;
184:
185: private:
1.35 paf 186:
1.25 paf 187: const String& fname;
1.40 paf 188: VMethodFrame *fcaller;
1.25 paf 189:
1.1 paf 190: int store_param_index;
1.25 paf 191: Hash my;/*OR*/MethodParams fnumbered_params;
1.1 paf 192: Value *fself;
1.15 parser 193:
194: private:
1.35 paf 195:
1.15 parser 196: Value *fresult_initial_void;
1.1 paf 197:
1.41 paf 198: };
199:
200: /// Auto-object used for temporary changing VMethod_frame::fself.
201: class Temp_method_frame_self {
202: VMethodFrame& fmethod_frame;
203: Value& saved_self;
204: public:
205: Temp_method_frame_self(VMethodFrame& amethod_frame, Value& aself) :
206: fmethod_frame(amethod_frame),
207: saved_self(amethod_frame.self()) {
208: fmethod_frame.set_self(aself);
209: }
210: ~Temp_method_frame_self() {
211: fmethod_frame.set_self(saved_self);
212: }
1.1 paf 213: };
214:
215: #endif
E-mail: