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