Annotation of parser3/src/types/pa_vmethod_frame.h, revision 1.77
1.3 paf 1: /** @file
1.5 paf 2: Parser: @b method_frame write context
1.3 paf 3:
1.68 misha 4: Copyright (c) 2001-2009 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.77 ! misha 11: static const char * const IDENT_VMETHOD_FRAME_H="$Date: 2009-04-18 00:34:14 $";
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"
16:
1.40 paf 17: // defines
18:
1.42 paf 19: #define CALLER_ELEMENT_NAME "caller"
20: #define SELF_ELEMENT_NAME "self"
1.50 paf 21: #define RESULT_VAR_NAME "result"
1.40 paf 22:
1.46 paf 23: // forwards
24:
25: class Request;
26:
27: /**
28: @b method parameters passed in this array.
29: contains handy typecast ad junction/not junction ensurers
30:
31: */
32: class MethodParams: public Array<Value*> {
33: public:
1.77 ! misha 34: void store_params(Value **params, size_t count){
! 35: expand(count);
! 36: memcpy(felements, params, sizeof(Value *)*count);
! 37: fused=count;
! 38: }
! 39:
! 40: inline Value& operator[] (size_t index) { return *get(index); }
1.46 paf 41:
42: Value& last() { return *get(count()-1); }
43:
44: /// handy is-value-a-junction ensurer
45: Value& as_junction(int index, const char* msg) {
1.56 paf 46: Value* value=get(index);
47: return as_junction(value, msg, index);
48: }
49: /// handy is-value-a-junction ensurer
50: Value& as_junction(Value* value, const char* msg, int index) {
51: return get_as(value, true, msg, index);
1.46 paf 52: }
53: /// handy value-is-not-a-junction ensurer
54: Value& as_no_junction(int index, const char* msg) {
1.56 paf 55: Value* value=get(index);
56: return as_no_junction(value, msg, index);
57: }
58: /// handy value-is-not-a-junction ensurer
59: Value& as_no_junction(Value* value, const char* msg, int index) {
60: return get_as(value, false, msg, index);
1.46 paf 61: }
1.62 misha 62: /// handy is-value-a-junction ensurer or can be auto-processed
63: Value& as_expression(int index, const char* msg) {
64: Value* value=get(index);
65: if(value->is_evaluated_expr()){
66: return *value;
67: } else {
68: return get_as(value, true, msg, index);
69: }
70: }
1.46 paf 71: /// handy expression auto-processing to double
72: double as_double(int index, const char* msg, Request& r) {
1.56 paf 73: Value* value=get(index);
1.60 paf 74: if(!value->is_evaluated_expr())
1.57 paf 75: value=&get_processed(value, msg, index, r);
76: return value->as_double();
1.46 paf 77: }
78: /// handy expression auto-processing to int
79: int as_int(int index, const char* msg, Request& r) {
1.56 paf 80: Value* value=get(index);
1.60 paf 81: if(!value->is_evaluated_expr())
1.57 paf 82: value=&get_processed(value, msg, index, r);
83: return value->as_int();
1.46 paf 84: }
85: /// handy expression auto-processing to bool
86: bool as_bool(int index, const char* msg, Request& r) {
1.56 paf 87: Value* value=get(index);
1.60 paf 88: if(!value->is_evaluated_expr())
1.59 paf 89: value=&get_processed(value, msg, index, r);
90: return value->as_bool();
1.46 paf 91: }
92: /// handy string ensurer
93: const String& as_string(int index, const char* msg) {
94: return as_no_junction(index, msg).as_string();
95: }
96: private:
97:
98: /// handy value-is/not-a-junction ensurer
1.56 paf 99: Value& get_as(Value* value, bool as_junction, const char* msg, int index) {
100: if((value->get_junction()!=0) ^ as_junction)
1.61 misha 101: throw Exception(PARSER_RUNTIME,
1.46 paf 102: 0,
103: "%s (parameter #%d)", msg, 1+index);
104:
1.56 paf 105: return *value;
1.46 paf 106: }
107:
1.56 paf 108: Value& get_processed(Value* value, const char* msg, int index, Request& r);
1.46 paf 109:
110: };
111:
1.4 paf 112: /** Method frame write context
113: accepts values written by method code
114: also handles method parameters and local variables
1.3 paf 115: */
1.46 paf 116: class VMethodFrame: public WContext {
1.63 misha 117: protected:
1.46 paf 118: VMethodFrame *fcaller;
119:
1.72 misha 120: HashStringValue* my; /*OR*/ MethodParams fnumbered_params;
1.46 paf 121: Value* fself;
122:
1.64 misha 123: typedef const VJunction* (VMethodFrame::*put_element_t)(const String& aname, Value* avalue);
124: put_element_t put_element_impl;
1.46 paf 125:
1.1 paf 126: public: // Value
127:
1.46 paf 128: override const char* type() const { return "method_frame"; }
1.20 paf 129:
130: /// VMethodFrame: $result | parent get_string(=accumulated fstring)
1.46 paf 131: override const String* get_string() {
1.20 paf 132: // check the $result value
1.46 paf 133: Value* result=get_result_variable();
1.20 paf 134: // if we have one, return it's string value, else return as usual: accumulated fstring or fvalue
135: return result ? result->get_string() : WContext::get_string();
136: }
137:
1.40 paf 138: /// VMethodFrame: my or self_transparent or $caller
1.51 paf 139: override Value* get_element(const String& aname, Value& /*aself*/, bool looking_up) {
1.42 paf 140: if(aname==CALLER_ELEMENT_NAME)
1.40 paf 141: return caller();
1.42 paf 142:
1.67 misha 143: if(aname==SELF_ELEMENT_NAME)
144: return &self();
145:
1.66 misha 146: Value* result;
147: if(my && (result=my->get(aname)))
148: return result;
149:
150: if(result=self().get_element(aname, self(), looking_up))
151: return result;
1.40 paf 152:
153: return 0;
1.1 paf 154: }
155:
1.4 paf 156: /// VMethodFrame: self_transparent
1.46 paf 157: override VStateless_class* get_class() { return self().get_class(); }
1.44 paf 158:
159: /// VMethodFrame: self_transparent
1.46 paf 160: override Value* base() { return self().base(); }
1.1 paf 161:
1.64 misha 162: /// VMethodFrame: my or self_transparent
163: override const VJunction* put_element(Value& /*aself*/, const String& aname, Value* avalue, bool /*areplace*/) {
164: return (this->*put_element_impl)(aname, avalue);
165: }
166:
1.69 misha 167: /// VMethodFrame: appends a fstring to result
168: override void write(const String& astring, String::Language alang) {
1.74 misha 169: if(!junction.method->allways_use_result){
1.73 misha 170: if(!get_result_variable()){
171: WContext::write(astring, alang);
172: } else {
1.74 misha 173: ((Method *)junction.method)->allways_use_result=true;
1.73 misha 174: }
1.69 misha 175: }
176: }
177:
1.64 misha 178: private:
179:
180: const VJunction* put_element_local(const String& aname, Value* avalue){
181: set_my_variable(aname, *avalue);
182: return PUT_ELEMENT_REPLACED_ELEMENT;
183: }
184:
185: const VJunction* put_element_global(const String& aname, Value* avalue){
186: if(my && my->put_replaced(aname, avalue))
187: return PUT_ELEMENT_REPLACED_ELEMENT;
188: return self().put_element(self(), aname, avalue, false/*=always, areplace*/);
189: }
190:
1.30 paf 191: public: // WContext
1.1 paf 192:
1.46 paf 193: override StringOrValue result() {
1.1 paf 194: // check the $result value
1.46 paf 195: Value* result_value=get_result_variable();
1.1 paf 196: // if we have one, return it, else return as usual: accumulated fstring or fvalue
1.52 paf 197: return result_value ? StringOrValue(*result_value) : WContext::result();
1.1 paf 198: }
199:
1.46 paf 200: void write(Value& avalue, String::Language alang) {
201: WContext::write(avalue, alang);
202: }
203:
1.1 paf 204: public: // usage
205:
1.46 paf 206: VMethodFrame(
1.40 paf 207: const Junction& ajunction/*info: always method-junction*/,
1.46 paf 208: VMethodFrame *acaller);
1.1 paf 209:
1.40 paf 210: VMethodFrame *caller() { return fcaller; }
1.25 paf 211:
1.76 misha 212: #ifdef USE_DESTRUCTORS
1.75 misha 213: ~VMethodFrame(){
214: if(my){
215: delete my;
216: }
217: }
1.76 misha 218: #endif
1.75 misha 219:
1.38 paf 220: void set_self(Value& aself) { fself=&aself; }
1.41 paf 221: /// we sure that someone already set our self with VMethodFrame::set_self(Value&)
222: Value& self() { return *fself; }
1.1 paf 223:
1.77 ! misha 224: size_t method_params_count() {
1.27 paf 225: const Method& method=*junction.method;
1.77 ! misha 226: return method.params_names ? method.params_names->count():0;
1.27 paf 227: }
1.77 ! misha 228:
! 229: void store_params(Value **params, size_t count) {
1.1 paf 230: const Method& method=*junction.method;
1.46 paf 231: size_t max_params=
1.1 paf 232: method.max_numbered_params_count?method.max_numbered_params_count:
1.46 paf 233: method.params_names?method.params_names->count():
1.1 paf 234: 0;
1.77 ! misha 235:
! 236: if(count>max_params)
1.61 misha 237: throw Exception(PARSER_RUNTIME,
1.46 paf 238: 0, //&name(),
1.7 paf 239: "method of %s (%s) accepts maximum %d parameter(s)",
1.38 paf 240: junction.self.get_class()->name_cstr(),
241: junction.self.type(),
1.1 paf 242: max_params);
243:
1.77 ! misha 244: if(my) {
! 245: size_t i=0;
! 246:
! 247: for (; i<count; i++){
! 248: const String& fname=*(*method.params_names)[i];
! 249: set_my_variable(fname, *params[i]);
! 250: }
! 251:
1.46 paf 252: size_t param_count=method.params_names->count();
1.77 ! misha 253: for(; i<param_count; i++) {
! 254: const String& fname=*(*method.params_names)[i];
1.68 misha 255: my->put(fname, VVoid::get());
1.1 paf 256: }
1.77 ! misha 257: } else {
! 258: fnumbered_params.store_params(params,count);
1.46 paf 259: }
1.1 paf 260: }
261:
1.72 misha 262: MethodParams* numbered_params() { return &fnumbered_params; }
1.18 paf 263:
1.63 misha 264: protected:
1.18 paf 265:
1.46 paf 266: void set_my_variable(const String& fname, Value& value) {
267: my->put(fname, &value); // remember param
1.25 paf 268: }
269:
1.46 paf 270: Value* get_result_variable();
1.1 paf 271:
272: public:
273:
274: const Junction& junction;
275:
1.41 paf 276: };
277:
278: /// Auto-object used for temporary changing VMethod_frame::fself.
279: class Temp_method_frame_self {
280: VMethodFrame& fmethod_frame;
1.46 paf 281: Value* saved_self;
1.41 paf 282: public:
283: Temp_method_frame_self(VMethodFrame& amethod_frame, Value& aself) :
284: fmethod_frame(amethod_frame),
1.46 paf 285: saved_self(&amethod_frame.self()) {
1.41 paf 286: fmethod_frame.set_self(aself);
287: }
288: ~Temp_method_frame_self() {
1.46 paf 289: fmethod_frame.set_self(*saved_self);
1.41 paf 290: }
1.1 paf 291: };
292:
293: #endif
E-mail: