Annotation of parser3/src/types/pa_value.h, revision 1.91
1.22 paf 1: /** @file
1.24 paf 2: Parser: Value, Method, Junction class decls.
3:
1.78 paf 4: Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.79 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 paf 6: */
7:
8: #ifndef PA_VALUE_H
9: #define PA_VALUE_H
1.87 paf 10:
1.91 ! paf 11: static const char* IDENT_VALUE_H="$Date: 2002/08/12 10:32:53 $";
1.1 paf 12:
13: #include "pa_pool.h"
14: #include "pa_string.h"
15: #include "pa_array.h"
16: #include "pa_exception.h"
1.13 paf 17: #include "pa_globals.h"
1.1 paf 18:
1.9 paf 19: class VStateless_class;
1.1 paf 20: class WContext;
21: class Request;
1.35 paf 22: class Table;
1.17 paf 23: class Junction;
24: class Method;
1.20 paf 25: class Hash;
1.42 paf 26: class VFile;
1.64 parser 27: class MethodParams;
1.1 paf 28:
1.31 paf 29: /// grandfather of all @a values in @b Parser
1.1 paf 30: class Value : public Pooled {
31: public: // Value
32:
1.53 paf 33: /// all: value type, used for error reporting and 'is' expression operator
1.1 paf 34: virtual const char *type() const =0;
1.89 paf 35:
1.91 ! paf 36: /** remember derived class instance
! 37: - VObject: the only client
! 38: */
! 39: virtual void set_derived(Value& /*aderived*/) { /*do nothing*/ }
! 40:
1.89 paf 41: /**
42: all except derived class: this if @atype eq type()
43: derived class: can locate parent class by it's type
44: */
45: virtual Value *as(const char *atype) {
46: return atype && strcmp(type(), atype)==0?this:0;
47: }
1.59 parser 48:
1.23 paf 49: /** is this value defined?
1.22 paf 50: @return for
1.63 parser 51: - VVoid: false
1.69 parser 52: - VString: eq ''=false, ne ''=true
1.72 parser 53: - VHash: count!=0
1.71 parser 54: - VTable: count!=0
1.22 paf 55: - others: true
56: */
1.38 paf 57: virtual bool is_defined() const { return true; }
1.59 parser 58:
1.35 paf 59: /** is this value string?
60: @return for
61: - VString: true
62: - others: false
63: */
1.38 paf 64: virtual bool is_string() const { return false; }
1.59 parser 65:
1.23 paf 66: /** what's the meaning of this value in context of expression?
1.22 paf 67: @return for
1.34 paf 68: - VString: fstring as VDouble or this depending on return_string_as_is
1.70 parser 69: - VBool: clone
70: - VDouble: clone
71: - VInt: clone
1.63 parser 72: - VVoid: this
1.27 paf 73: - VFile: this
1.45 paf 74: - VImage: this
1.64 parser 75: - VDate: ftime -> float days
1.72 parser 76: - VTable: count
77: - VHash: count
1.22 paf 78: */
1.75 parser 79: virtual Value *as_expr_result(bool /*return_string_as_is*/=false) {
1.34 paf 80: bark("(%s) can not be used in expression"); return 0;
81: }
1.59 parser 82:
1.23 paf 83: /** extract Hash
1.22 paf 84: @return for
1.25 paf 85: - VHash: fhash
86: - VResponse: ffields
1.22 paf 87: */
1.76 parser 88: virtual Hash *get_hash(const String * /*source*/) { return 0; }
1.59 parser 89:
1.23 paf 90: /** extract const String
1.22 paf 91: @return for
1.25 paf 92: - VString: value
1.63 parser 93: - VVoid: ""
1.25 paf 94: - VDouble: value
1.66 parser 95: - VInt: value
1.25 paf 96: - VBool: must be 0: so in ^if(1>2) it would'nt become "FALSE" string which is 'true'
1.22 paf 97: - others: 0
98: - WContext: accumulated fstring
99: */
1.1 paf 100: virtual const String *get_string() { return 0; }
1.59 parser 101:
1.23 paf 102: /** extract double
1.22 paf 103: @return for
1.25 paf 104: - VString: value
105: - VDouble: value
1.59 parser 106: - VInt: value
1.25 paf 107: - VBool: value
1.63 parser 108: - VVoid: 0
1.64 parser 109: - VDate: ftime -> float days
1.22 paf 110: */
1.72 parser 111: virtual double as_double() const { bark("(%s) does not have numerical (double) value"); return 0; }
1.59 parser 112:
113: /** extract integer
114: - VString: value
115: - VDouble: value
116: - VInt: value
117: - VBool: value
1.63 parser 118: - VVoid: 0
1.73 parser 119: - VTable: count
120: - VHash: count
1.59 parser 121: */
1.72 parser 122: virtual int as_int () const { bark("(%s) does not have numerical (int) value"); return 0; }
1.59 parser 123:
1.23 paf 124: /** extract bool
1.22 paf 125: @return for
1.63 parser 126: - VVoid: false
1.25 paf 127: - VBool: value
128: - VInt: 0 or !0
129: - VDouble: 0 or !0
1.27 paf 130: - VFile: true
1.64 parser 131: - VDate: 0 or !0
1.73 parser 132: - VTable: count
133: - VHash: count
1.22 paf 134: */
1.72 parser 135: virtual bool as_bool() const { bark("(%s) does not have logical value"); return 0; }
1.59 parser 136:
1.42 paf 137: /** extract file
138: @return for
139: - VFile: this
140: - VString: vfile
1.45 paf 141: - VImage: true
1.42 paf 142: */
1.75 parser 143: virtual VFile *as_vfile(String::Untaint_lang /*lang*/=String::UL_UNSPECIFIED,
144: bool /*origins_mode*/=false) {
1.42 paf 145: bark("(%s) does not have file value"); return 0;
146: }
1.59 parser 147:
1.23 paf 148: /** extract Junction
1.22 paf 149: @return for
150: - junction: itself
151: */
1.1 paf 152: virtual Junction *get_junction() { return 0; }
1.59 parser 153:
1.23 paf 154: /** extract Value element
1.22 paf 155: @return for
1.25 paf 156: - VHash: (key)=value
1.29 paf 157: - VStateless_class: +$method
158: - VStateless_object: +$method
1.58 paf 159: - VClass: (field)=STATIC value;(method)=method_ref with self=object_class
1.51 paf 160: - VCodeFrame: wcontext_transparent
161: - VMethodFrame: my or self_transparent
1.52 paf 162: - VTable: columns,methods
1.28 paf 163: - VEnv: field
1.67 parser 164: - VForm: CLASS,method,field
1.45 paf 165: - VString: $method
1.30 paf 166: - VRequest: fields
1.45 paf 167: - VResponse: method,fields
1.28 paf 168: - VCookie: field
1.45 paf 169: - VFile: method,field
1.67 parser 170: - VDate: CLASS,method,field
1.26 paf 171: */
1.75 parser 172: virtual Value *get_element(const String& /*name*/) { bark("(%s) has no elements"); return 0; }
1.59 parser 173:
1.31 paf 174: /** store Value element under @a name
1.22 paf 175: @return for
1.25 paf 176: - VHash: (key)=value
1.67 parser 177: - VStateless_object: (CLASS)=vclass;(method)=method_ref
1.26 paf 178: - VStateless_class: (field)=value - static values only
179: - VStateless_object: (field)=value
1.51 paf 180: - VCodeFrame: wcontext_transparent
181: - VMethodFrame: my or self_transparent
1.25 paf 182: - VResponse: (attribute)=value
183: - VCookie: field
1.22 paf 184: */
1.75 parser 185: virtual void put_element(const String& name, Value * /*value*/) {
1.65 parser 186: // to prevent modification of system classes,
187: // created at system startup, and not having exception
188: // handler installed, we neet to bark using request.pool
189: bark("(%s) does not accept elements",
190: "element can not be stored to %s", &name);
191: }
1.59 parser 192:
1.23 paf 193: /** extract VStateless_class
1.22 paf 194: @return for
1.85 paf 195: - VX: x_class
1.25 paf 196: - VStateless_class: this
1.91 ! paf 197: - VObject: class of derived or fclass
1.26 paf 198: - WContext: none yet | transparent
1.85 paf 199: these are methodless classes:
200: - VBool: 0
201: - VJunction: 0
202: - VEnv: 0
203: - VRequest: 0
204: - VCookie: 0
1.22 paf 205: */
1.85 paf 206: virtual VStateless_class *get_class()=0;
1.32 paf 207:
208: /** extract VTable
209: @return for
1.35 paf 210: - VTable: ftable
1.32 paf 211: */
1.35 paf 212: virtual Table *get_table() { return 0; }
1.1 paf 213:
214: public: // usage
215:
1.84 paf 216: Value(Pool& apool) : Pooled(apool) {
1.68 parser 217: }
1.1 paf 218:
1.26 paf 219: /// @return sure String. if it doesn't have string value barks
1.1 paf 220: const String& as_string() {
221: const String *result=get_string();
222: if(!result)
1.35 paf 223: bark("(%s) has no string representation");
1.6 paf 224:
1.1 paf 225: return *result;
226: }
227:
1.6 paf 228: protected:
1.1 paf 229:
1.22 paf 230: /// throws exception specifying bark-reason and name() type() of problematic value
1.65 parser 231: void bark(char *reason,
232: const char *alt_reason=0, const String *problem_source=0) const {
1.80 paf 233: throw Exception("parser.runtime",
1.84 paf 234: problem_source,
235: alt_reason?alt_reason:reason, type());
1.1 paf 236: }
237:
1.17 paf 238: };
239:
1.23 paf 240: /** \b junction is some code joined with context of it's evaluation.
1.22 paf 241:
242: there are code-junctions and method-junctions
243: - code-junctions are used when some parameter passed in cury brackets
244: - method-junctions used in ^method[] calls or $method references
245: */
1.17 paf 246: class Junction : public Pooled {
247: public:
248:
249: Junction(Pool& apool,
250: Value& aself,
251: VStateless_class *avclass, const Method *amethod,
252: Value *aroot,
253: Value *arcontext,
254: WContext *awcontext,
255: const Array *acode) : Pooled(apool),
256:
257: self(aself),
258: vclass(avclass), method(amethod),
259: root(aroot),
260: rcontext(arcontext),
261: wcontext(awcontext),
262: code(acode) {
1.81 paf 263: }
264:
265: void change_context(Junction *source) {
266: if(source) {
267: root=source->root;
268: rcontext=source->rcontext;
269: wcontext=source->wcontext;
270: } else {
271: root=rcontext=0;
272: wcontext=0;
273: }
1.17 paf 274: }
275:
1.22 paf 276: /// always present
1.17 paf 277: Value& self;
1.22 paf 278: //@{
279: /// @name either these // so called 'method-junction'
1.17 paf 280: VStateless_class *vclass; const Method *method;
1.22 paf 281: //@}
282: //@{
283: /// @name or these are present // so called 'code-junction'
1.17 paf 284: Value *root;
285: Value *rcontext;
286: WContext *wcontext;
287: const Array *code;
1.22 paf 288: //@}
1.48 paf 289: };
290:
291: /**
292: native code method
293: params can be NULL when
1.53 paf 294: method min&max params (see VStateless_class::add_native_method)
1.48 paf 295: counts are zero.
296: */
1.39 paf 297: typedef void (*Native_code_ptr)(Request& request,
298: const String& method_name,
1.48 paf 299: MethodParams *params);
1.39 paf 300:
1.23 paf 301: /**
1.22 paf 302: class method.
303:
304: methods can have
305: - named or
306: - numbered parameters
307:
308: methods can be
309: - parser or
310: - native onces
311:
1.40 paf 312: holds
1.22 paf 313: - parameter names or number limits
314: - local names
315: - code [parser or native]
316: */
1.17 paf 317: class Method : public Pooled {
318: public:
1.39 paf 319:
1.41 paf 320: /// allowed method call types
1.39 paf 321: enum Call_type {
1.41 paf 322: CT_ANY, ///< method can be called either statically or dynamically
323: CT_STATIC, ///< method can be called only statically
324: CT_DYNAMIC ///< method can be called only dynamically
1.39 paf 325: };
326:
327: /// name for error reporting
1.17 paf 328: const String& name;
1.39 paf 329: ///
330: Call_type call_type;
1.22 paf 331: //@{
332: /// @name either numbered params // for native-code methods = operators
1.17 paf 333: int min_numbered_params_count, max_numbered_params_count;
1.22 paf 334: //@}
335: //@{
336: /// @name or named params&locals // for parser-code methods
1.17 paf 337: Array *params_names; Array *locals_names;
1.22 paf 338: //@}
339: //@{
340: /// @name the Code
1.17 paf 341: const Array *parser_code;/*OR*/Native_code_ptr native_code;
1.22 paf 342: //@}
1.17 paf 343:
344: Method(
345: Pool& apool,
346: const String& aname,
1.39 paf 347: Call_type call_type,
1.17 paf 348: int amin_numbered_params_count, int amax_numbered_params_count,
349: Array *aparams_names, Array *alocals_names,
350: const Array *aparser_code, Native_code_ptr anative_code) :
351:
352: Pooled(apool),
353: name(aname),
1.39 paf 354: call_type(call_type),
1.17 paf 355: min_numbered_params_count(amin_numbered_params_count),
356: max_numbered_params_count(amax_numbered_params_count),
357: params_names(aparams_names), locals_names(alocals_names),
358: parser_code(aparser_code), native_code(anative_code) {
359: }
360:
1.22 paf 361: /// call this before invoking to ensure proper actual numbered params count
1.75 parser 362: void check_actual_numbered_params(
1.84 paf 363: Value& self, const String& actual_name, Array *actual_numbered_params) const;
1.86 paf 364: };
365:
366: /// Auto-object used for temporarily substituting/removing elements
367: class Temp_value_element {
368: Value& fwhere;
369: const String& fname;
370: Value *saved;
371: public:
372: Temp_value_element(Value& awhere, const String& aname, Value *awhat) :
373: fwhere(awhere),
374: fname(aname),
375: saved(awhere.get_element(aname)) {
376: fwhere.put_element(aname, awhat);
377: }
378: ~Temp_value_element() {
379: fwhere.put_element(fname, saved);
380: }
1.1 paf 381: };
382:
383: #endif
E-mail: