|
|
1.117 paf 1: /** @file
1.118 paf 2: Parser: executor part of request class.
3:
1.88 paf 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.118 paf 5:
1.89 paf 6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.1 paf 7: */
1.186 ! parser 8: static const char *RCSId="$Id: execute.C,v 1.185 2001/07/26 10:47:02 parser Exp $";
1.1 paf 9:
1.152 paf 10: #include "pa_opcode.h"
1.8 paf 11: #include "pa_array.h"
1.11 paf 12: #include "pa_request.h"
1.15 paf 13: #include "pa_vstring.h"
1.22 paf 14: #include "pa_vhash.h"
1.167 parser 15: #include "pa_vvoid.h"
1.145 paf 16: #include "pa_vcode_frame.h"
17: #include "pa_vmethod_frame.h"
1.38 paf 18: #include "pa_vobject.h"
1.49 paf 19: #include "pa_vdouble.h"
1.54 paf 20: #include "pa_vbool.h"
1.94 paf 21: #include "pa_vtable.h"
1.132 paf 22: #include "pa_vfile.h"
1.144 paf 23: #include "pa_vimage.h"
1.1 paf 24:
1.157 parser 25: //#define DEBUG_EXECUTE
26:
1.159 parser 27: const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500;
1.24 paf 28:
1.157 parser 29: #ifdef DEBUG_EXECUTE
1.1 paf 30: char *opcode_name[]={
1.49 paf 31: // literals
1.109 paf 32: "VALUE", "CURLY_CODE__STORE_PARAM", "EXPR_CODE__STORE_PARAM",
1.49 paf 33:
34: // actions
1.185 parser 35: "WITH_SELF", "WITH_READ", "WITH_WRITE",
1.66 paf 36: "GET_CLASS",
1.182 parser 37: "CONSTRUCT_VALUE", "CONSTRUCT_EXPR", "CURLY_CODE__CONSTRUCT",
1.108 paf 38: "WRITE_VALUE", "WRITE_EXPR_RESULT", "STRING__WRITE",
1.18 paf 39: "GET_ELEMENT", "GET_ELEMENT__WRITE",
1.1 paf 40: "CREATE_EWPOOL", "REDUCE_EWPOOL",
1.49 paf 41: "CREATE_SWPOOL", "REDUCE_SWPOOL",
1.1 paf 42: "GET_METHOD_FRAME",
43: "STORE_PARAM",
1.186 ! parser 44: "PREPARE_TO_CONSTRUCT_OBJECT", "CALL",
1.49 paf 45:
46: // expression ops: unary
1.148 paf 47: "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS",
1.49 paf 48: // expression ops: binary
49: "SUB", "ADD", "MUL", "DIV", "MOD",
1.56 paf 50: "BIN_AND", "BIN_OR", "BIN_XOR",
51: "LOG_AND", "LOG_OR", "LOG_XOR",
1.49 paf 52: "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE",
1.103 paf 53: "STR_LT", "STR_GT", "STR_LE", "STR_GE", "STR_EQ", "STR_NE",
54: "IS"
1.1 paf 55: };
56:
1.158 parser 57: void va_debug_printf(Pool& pool, const char *fmt,va_list args) {
1.127 paf 58: char buf[MAX_STRING];
59: vsnprintf(buf, MAX_STRING, fmt, args);
60: SAPI::log(pool, "%s", buf);
1.107 paf 61: }
62:
1.158 parser 63: void debug_printf(Pool& pool, const char *fmt, ...) {
1.107 paf 64: va_list args;
65: va_start(args,fmt);
1.158 parser 66: va_debug_printf(pool,fmt,args);
1.107 paf 67: va_end(args);
1.105 paf 68: }
69:
1.158 parser 70: void debug_dump(Pool& pool, int level, const Array& ops) {
1.181 parser 71: /* {
1.135 paf 72: int size=ops.quick_size();
1.158 parser 73: //debug_printf(pool, "size=%d\n", size);
1.23 paf 74: for(int i=0; i<size; i++) {
75: Operation op;
76: op.cast=ops.quick_get(i);
1.158 parser 77: debug_printf(pool, "%8X\n", op.cast);
1.23 paf 78: }
1.181 parser 79: }*/
1.23 paf 80:
1.135 paf 81: int size=ops.quick_size();
1.158 parser 82: //debug_printf(pool, "size=%d\n", size);
1.1 paf 83: for(int i=0; i<size; i++) {
1.23 paf 84: Operation op;
85: op.cast=ops.quick_get(i);
1.1 paf 86:
1.86 paf 87: if(op.code==OP_VALUE || op.code==OP_STRING__WRITE) {
1.52 paf 88: Value *value=static_cast<Value *>(ops.quick_get(++i));
1.158 parser 89: debug_printf(pool,
1.133 paf 90: "%*s%s"
91: " \"%s\" %s",
92: level*4, "", opcode_name[op.code],
93: value->get_string()->cstr(), value->type());
94: continue;
1.15 paf 95: }
1.158 parser 96: debug_printf(pool, "%*s%s", level*4, "", opcode_name[op.code]);
1.1 paf 97:
1.184 parser 98: switch(op.code) {
99: case OP_CURLY_CODE__STORE_PARAM:
100: case OP_EXPR_CODE__STORE_PARAM:
101: case OP_CURLY_CODE__CONSTRUCT:
1.10 paf 102: const Array *local_ops=reinterpret_cast<const Array *>(ops.quick_get(++i));
1.158 parser 103: debug_dump(pool, level+1, *local_ops);
1.1 paf 104: }
105: }
106: }
1.157 parser 107: #endif
1.1 paf 108:
1.159 parser 109: #define PUSH(value) stack.push(value)
110: #define POP() static_cast<Value *>(stack.pop())
111: #define POP_NAME() static_cast<Value *>(stack.pop())->as_string()
112:
1.32 paf 113: void Request::execute(const Array& ops) {
1.157 parser 114: #ifdef DEBUG_EXECUTE
1.158 parser 115: debug_printf(pool(), "source----------------------------\n");
116: debug_dump(pool(), 0, ops);
117: debug_printf(pool(), "execution-------------------------\n");
1.157 parser 118: #endif
1.12 paf 119:
1.135 paf 120: int size=ops.quick_size();
1.158 parser 121: //debug_printf(pool(), "size=%d\n", size);
1.11 paf 122: for(int i=0; i<size; i++) {
1.23 paf 123: Operation op;
124: op.cast=ops.quick_get(i);
1.157 parser 125: #ifdef DEBUG_EXECUTE
1.158 parser 126: debug_printf(pool(), "%d:%s", stack.top_index()+1, opcode_name[op.code]);
1.157 parser 127: #endif
1.11 paf 128:
1.23 paf 129: switch(op.code) {
1.51 paf 130: // param in next instruction
1.52 paf 131: case OP_VALUE:
1.32 paf 132: {
1.52 paf 133: Value *value=static_cast<Value *>(ops.quick_get(++i));
1.157 parser 134: #ifdef DEBUG_EXECUTE
1.158 parser 135: debug_printf(pool(), " \"%s\" %s", value->get_string()->cstr(), value->type());
1.157 parser 136: #endif
1.52 paf 137: PUSH(value);
1.32 paf 138: break;
139: }
1.109 paf 140: case OP_CURLY_CODE__STORE_PARAM:
141: case OP_EXPR_CODE__STORE_PARAM:
1.32 paf 142: {
1.73 paf 143: VMethodFrame *frame=static_cast<VMethodFrame *>(stack.top_value());
1.65 paf 144: // code
1.32 paf 145: const Array *local_ops=reinterpret_cast<const Array *>(ops.quick_get(++i));
1.157 parser 146: #ifdef DEBUG_EXECUTE
1.158 parser 147: debug_printf(pool(), " (%d)\n", local_ops->size());
148: debug_dump(pool(), 1, *local_ops);
1.157 parser 149: #endif
1.109 paf 150: // when they evaluate expression parameter,
151: // the object expression result
152: // does not need to be written into calling frame
153: // it must go into any expressions using that parameter
1.146 paf 154: // hence, we zero junction.wcontext here, and later
155: // in .process we would test that field
1.109 paf 156: // in decision "which wwrapper to use"
1.32 paf 157: Junction& j=*NEW Junction(pool(),
1.45 paf 158: *self, 0, 0,
1.130 paf 159: root,
1.149 paf 160: rcontext,
161: op.code==OP_EXPR_CODE__STORE_PARAM?0:wcontext,
1.130 paf 162: local_ops);
1.32 paf 163:
164: Value *value=NEW VJunction(j);
1.65 paf 165:
166: // store param
1.92 paf 167: frame->store_param(frame->name(), value);
1.32 paf 168: break;
169: }
1.66 paf 170: case OP_GET_CLASS:
1.38 paf 171: {
1.130 paf 172: // maybe they do ^class:method[] call, remember the fact
1.98 paf 173: wcontext->set_somebody_entered_some_class();
174:
1.82 paf 175: const String& name=POP_NAME();
1.120 paf 176: Value *value=static_cast<Value *>(classes().get(name));
177: if(!value)
1.66 paf 178: THROW(0,0,
179: &name,
1.143 paf 180: "class is undefined");
1.66 paf 181:
1.120 paf 182: PUSH(value);
1.38 paf 183: break;
184: }
1.32 paf 185:
1.51 paf 186: // OP_WITH
1.37 paf 187: case OP_WITH_SELF:
188: {
189: PUSH(self);
190: break;
191: }
1.15 paf 192: case OP_WITH_READ:
193: {
1.24 paf 194: PUSH(rcontext);
1.20 paf 195: break;
196: }
1.37 paf 197: case OP_WITH_WRITE:
1.20 paf 198: {
1.37 paf 199: PUSH(wcontext);
1.20 paf 200: break;
201: }
1.37 paf 202:
1.51 paf 203: // OTHER ACTIONS BUT WITHs
1.80 paf 204: case OP_CONSTRUCT_VALUE:
1.20 paf 205: {
1.37 paf 206: Value *value=POP();
1.82 paf 207: const String& name=POP_NAME();
1.37 paf 208: Value *ncontext=POP();
1.81 paf 209: ncontext->put_element(name, value);
1.37 paf 210: value->set_name(name);
1.15 paf 211: break;
212: }
1.80 paf 213: case OP_CONSTRUCT_EXPR:
214: {
215: Value *value=POP();
1.82 paf 216: const String& name=POP_NAME();
1.80 paf 217: Value *ncontext=POP();
1.128 paf 218: ncontext->put_element(name, value->as_expr_result());
1.80 paf 219: value->set_name(name);
220: break;
221: }
1.182 parser 222: case OP_CURLY_CODE__CONSTRUCT:
223: {
224: const Array *local_ops=reinterpret_cast<const Array *>(ops.quick_get(++i));
225: #ifdef DEBUG_EXECUTE
226: debug_printf(pool(), " (%d)\n", local_ops->size());
227: debug_dump(pool(), 1, *local_ops);
228: #endif
229: Junction& j=*NEW Junction(pool(),
230: *self, 0, 0,
231: root,
232: rcontext,
233: wcontext,
234: local_ops);
235:
236: Value *value=NEW VJunction(j);
237: const String& name=POP_NAME();
238: Value *ncontext=POP();
239: ncontext->put_element(name, value);
240: value->set_name(name);
241: break;
242: }
1.108 paf 243: case OP_WRITE_VALUE:
1.13 paf 244: {
1.24 paf 245: Value *value=POP();
1.92 paf 246: write_assign_lang(*value);
1.150 paf 247:
248: // forget the fact they've entered some ^object.method[].
249: // see OP_GET_ELEMENT
250: wcontext->clear_somebody_entered_some_object();
1.86 paf 251: break;
252: }
1.108 paf 253: case OP_WRITE_EXPR_RESULT:
254: {
255: Value *value=POP();
1.128 paf 256: write_expr_result(*value->as_expr_result());
1.108 paf 257: break;
258: }
1.86 paf 259: case OP_STRING__WRITE:
260: {
261: VString *vstring=static_cast<VString *>(ops.quick_get(++i));
1.157 parser 262: #ifdef DEBUG_EXECUTE
1.158 parser 263: debug_printf(pool(), " \"%s\"", vstring->string().cstr());
1.157 parser 264: #endif
1.122 paf 265: write_no_lang(vstring->string());
1.13 paf 266: break;
1.14 paf 267: }
1.13 paf 268:
1.15 paf 269: case OP_GET_ELEMENT:
1.11 paf 270: {
1.150 paf 271: // maybe they do ^object.method[] call, remember the fact
272: wcontext->inc_somebody_entered_some_object();
273:
1.174 parser 274: //_asm int 3;
1.17 paf 275: Value *value=get_element();
1.24 paf 276: PUSH(value);
1.17 paf 277: break;
278: }
279:
1.18 paf 280: case OP_GET_ELEMENT__WRITE:
1.17 paf 281: {
282: Value *value=get_element();
1.92 paf 283: write_assign_lang(*value);
1.17 paf 284: break;
285: }
286:
1.32 paf 287:
1.17 paf 288: case OP_CREATE_EWPOOL:
289: {
1.24 paf 290: PUSH(wcontext);
1.137 paf 291: PUSH((void *)flang);
292: flang=String::UL_PASS_APPENDED;
1.186 ! parser 293: wcontext=NEW WWrapper(pool(), 0 /*empty*/);
1.17 paf 294: break;
295: }
296: case OP_REDUCE_EWPOOL:
297: {
1.36 paf 298: Value *value=wcontext->result();
1.137 paf 299: flang=static_cast<String::Untaint_lang>(reinterpret_cast<int>(POP()));
1.25 paf 300: wcontext=static_cast<WContext *>(POP());
1.24 paf 301: PUSH(value);
1.13 paf 302: break;
1.15 paf 303: }
1.13 paf 304:
1.49 paf 305: case OP_CREATE_SWPOOL:
306: {
307: PUSH(wcontext);
1.186 ! parser 308: wcontext=NEW WWrapper(pool(), 0 /*empty*/);
1.49 paf 309: break;
310: }
311: case OP_REDUCE_SWPOOL:
312: {
313: // from "$a $b" part of expression taking only string value,
314: // ignoring any other content of wcontext
1.82 paf 315: const String *string=wcontext->get_string();
1.80 paf 316: Value *value;
317: if(string)
318: value=NEW VString(*string);
319: else
1.167 parser 320: NEW VVoid(pool());
1.50 paf 321: wcontext=static_cast<WContext *>(POP());
1.49 paf 322: PUSH(value);
323: break;
324: }
325:
1.51 paf 326: // CALL
1.28 paf 327: case OP_GET_METHOD_FRAME:
328: {
1.32 paf 329: Value *value=POP();
1.138 paf 330:
1.111 paf 331: // info:
332: // code compiled so that this one's always method-junction,
333: // not a code-junction
1.32 paf 334: Junction *junction=value->get_junction();
1.31 paf 335: if(!junction)
1.185 parser 336: THROW(0, 0,
1.42 paf 337: &value->name(),
1.111 paf 338: "(%s) not a method or junction, can not call it",
1.38 paf 339: value->type());
1.70 paf 340:
1.185 parser 341: VMethodFrame *frame=NEW VMethodFrame(pool(), value->name(), *junction);
1.28 paf 342: PUSH(frame);
343: break;
344: }
345: case OP_STORE_PARAM:
346: {
347: Value *value=POP();
1.73 paf 348: VMethodFrame *frame=static_cast<VMethodFrame *>(stack.top_value());
1.92 paf 349: frame->store_param(frame->name(), value);
1.29 paf 350: break;
351: }
352:
1.186 ! parser 353: case OP_PREPARE_TO_CONSTRUCT_OBJECT:
! 354: {
! 355: wcontext->constructing(true);
! 356: break;
! 357: }
! 358: case OP_CALL:
1.29 paf 359: {
1.157 parser 360: #ifdef DEBUG_EXECUTE
1.158 parser 361: debug_printf(pool(), "->\n");
1.157 parser 362: #endif
1.34 paf 363: VMethodFrame *frame=static_cast<VMethodFrame *>(POP());
364: frame->fill_unspecified_params();
1.45 paf 365: PUSH(self);
366: PUSH(root);
367: PUSH(rcontext);
368: PUSH(wcontext);
369:
1.100 paf 370: VStateless_class *called_class=frame->junction.self.get_class();
1.186 ! parser 371: if(wcontext->constructing()) {
! 372: wcontext->constructing(false);
1.185 parser 373: if(frame->junction.method->call_type!=Method::CT_STATIC) {
1.138 paf 374: // this is a constructor call
1.185 parser 375:
376: if(Value *value=called_class->create_new_value(pool())) {
377: // some stateless_object creatable derivates
1.149 paf 378: self=value;
1.185 parser 379: } else {
380: // stateful object
1.94 paf 381: self=NEW VObject(pool(), *called_class);
1.185 parser 382: }
1.83 paf 383: frame->write(*self,
1.136 paf 384: String::UL_CLEAN // not used, always an object, not string
1.83 paf 385: );
1.185 parser 386: } else
387: THROW(0, 0,
388: &frame->name(),
389: "method is static and can not be used as constructor");
390: } else {
391: // this is not constructor call
392:
393: // not ^name.method call, name:method call; and
394: // is context object or class & is it my class or my parent's class and?
395: VStateless_class *read_class=rcontext->get_class();
396: if(
397: !(wcontext->somebody_entered_some_object() &&
398: !wcontext->somebody_entered_some_class()) &&
399: read_class && read_class->is_or_derived_from(*called_class)) // yes
400: self=rcontext; // dynamic call
401: else // no, not me or relative of mine (=total stranger)
402: self=&frame->junction.self; // static call
403: }
1.75 paf 404:
1.45 paf 405: frame->set_self(*self);
1.29 paf 406: root=rcontext=wcontext=frame;
1.47 paf 407: {
1.48 paf 408: // take object or class from any wrappers
1.102 paf 409: // and substitute class alias to the class they are called AS
410: Temp_alias temp_alias(*self->get_aliased(), *frame->junction.vclass);
1.68 paf 411:
1.99 paf 412: const Method& method=*frame->junction.method;
1.134 paf 413: Method::Call_type call_type=
414: called_class==self ? Method::CT_STATIC : Method::CT_DYNAMIC;
415: if(
416: method.call_type==Method::CT_ANY ||
417: method.call_type==call_type) // allowed call type?
418: if(method.native_code) { // native code?
1.154 paf 419: method.check_actual_numbered_params(pool(),
1.134 paf 420: frame->junction.self,
421: frame->name(), frame->numbered_params());
1.160 parser 422: method.native_code(
1.134 paf 423: *this,
424: frame->name(), frame->numbered_params()); // execute it
1.159 parser 425: } else { // parser code
426: if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) {
427: anti_endless_execute_recoursion=0; // give @exception a chance
428: THROW(0, 0,
1.160 parser 429: &frame->name(),
1.159 parser 430: "endless recursion detected");
431: }
432:
1.134 paf 433: execute(*method.parser_code); // execute it
1.159 parser 434: anti_endless_execute_recoursion--;
435: }
1.134 paf 436: else
437: THROW(0, 0,
438: &frame->name(),
439: "is not allowed to be called %s",
440: call_type==Method::CT_STATIC?"statically":"dynamically");
441:
1.47 paf 442: }
1.36 paf 443: Value *value=wcontext->result();
1.45 paf 444:
445: wcontext=static_cast<WContext *>(POP());
446: rcontext=POP();
447: root=POP();
448: self=static_cast<VAliased *>(POP());
1.62 paf 449:
1.61 paf 450: PUSH(value);
1.157 parser 451: #ifdef DEBUG_EXECUTE
1.158 parser 452: debug_printf(pool(), "<-returned");
1.157 parser 453: #endif
1.49 paf 454: break;
455: }
456:
1.55 paf 457: // expression ops: unary
458: case OP_NEG:
459: {
460: Value *operand=POP();
1.128 paf 461: Value *value=NEW VDouble(pool(), -operand->as_double());
1.55 paf 462: PUSH(value);
463: break;
464: }
465: case OP_INV:
466: {
467: Value *operand=POP();
1.155 parser 468: Value *value=NEW VDouble(pool(), ~operand->as_int());
1.55 paf 469: PUSH(value);
470: break;
471: }
472: case OP_NOT:
473: {
474: Value *operand=POP();
1.128 paf 475: Value *value=NEW VBool(pool(), !operand->as_bool());
1.55 paf 476: PUSH(value);
477: break;
478: }
1.62 paf 479: case OP_DEF:
480: {
481: Value *operand=POP();
1.128 paf 482: Value *value=NEW VBool(pool(), operand->is_defined());
1.62 paf 483: PUSH(value);
484: break;
485: }
486: case OP_IN:
487: {
488: Value *operand=POP();
1.110 paf 489: const char *path=operand->as_string().cstr();
1.151 paf 490: Value *value=NEW VBool(pool(),
491: info.uri && strncmp(path, info.uri, strlen(path))==0);
1.62 paf 492: PUSH(value);
493: break;
494: }
495: case OP_FEXISTS:
496: {
497: Value *operand=POP();
1.127 paf 498: Value *value=NEW VBool(pool(),
499: file_readable(absolute(operand->as_string())));
1.148 paf 500: PUSH(value);
501: break;
502: }
503: case OP_DEXISTS:
504: {
505: Value *operand=POP();
506: Value *value=NEW VBool(pool(),
507: dir_readable(absolute(operand->as_string())));
1.62 paf 508: PUSH(value);
509: break;
510: }
1.55 paf 511:
512: // expression ops: binary
513: case OP_SUB:
1.53 paf 514: {
1.61 paf 515: Value *b=POP(); Value *a=POP();
1.128 paf 516: Value *value=NEW VDouble(pool(), a->as_double() - b->as_double());
1.53 paf 517: PUSH(value);
518: break;
519: }
1.55 paf 520: case OP_ADD:
1.53 paf 521: {
1.61 paf 522: Value *b=POP(); Value *a=POP();
1.128 paf 523: Value *value=NEW VDouble(pool(), a->as_double() + b->as_double());
1.53 paf 524: PUSH(value);
525: break;
526: }
1.49 paf 527: case OP_MUL:
528: {
1.61 paf 529: Value *b=POP(); Value *a=POP();
1.128 paf 530: Value *value=NEW VDouble(pool(), a->as_double() * b->as_double());
1.53 paf 531: PUSH(value);
532: break;
533: }
534: case OP_DIV:
535: {
1.61 paf 536: Value *b=POP(); Value *a=POP();
1.170 parser 537:
538: double a_double=a->as_double();
539: double b_double=b->as_double();
540:
1.171 parser 541: if(b_double == 0) {
542: const String *problem_source=&b->as_string();
543: #ifndef NO_STRING_ORIGIN
544: if(!problem_source->origin().file)
1.172 parser 545: problem_source=&b->name();
1.171 parser 546: #endif
1.170 parser 547: THROW(0, 0,
1.171 parser 548: problem_source,
1.170 parser 549: "Division by zero");
1.171 parser 550: }
1.170 parser 551:
1.171 parser 552: Value *value=NEW VDouble(pool(), a_double / b_double);
1.54 paf 553: PUSH(value);
554: break;
555: }
1.55 paf 556: case OP_MOD:
557: {
1.61 paf 558: Value *b=POP(); Value *a=POP();
1.170 parser 559:
1.173 parser 560: double a_double=a->as_double();
561: double b_double=b->as_double();
1.170 parser 562:
1.173 parser 563: if(b_double == 0) {
1.171 parser 564: const String *problem_source=&b->as_string();
565: #ifndef NO_STRING_ORIGIN
566: if(!problem_source->origin().file)
1.172 parser 567: problem_source=&b->name();
1.171 parser 568: #endif
1.170 parser 569: THROW(0, 0,
1.171 parser 570: problem_source,
1.170 parser 571: "Modulus by zero");
1.171 parser 572: }
1.170 parser 573:
1.173 parser 574: Value *value=NEW VDouble(pool(), fmod(a_double, b_double));
1.55 paf 575: PUSH(value);
576: break;
577: }
578: case OP_BIN_AND:
1.54 paf 579: {
1.61 paf 580: Value *b=POP(); Value *a=POP();
1.78 paf 581: Value *value=NEW VDouble(pool(),
1.155 parser 582: a->as_int() &
583: b->as_int());
1.54 paf 584: PUSH(value);
585: break;
586: }
1.55 paf 587: case OP_BIN_OR:
1.54 paf 588: {
1.61 paf 589: Value *b=POP(); Value *a=POP();
1.78 paf 590: Value *value=NEW VDouble(pool(),
1.155 parser 591: a->as_int() |
592: b->as_int());
1.55 paf 593: PUSH(value);
594: break;
595: }
1.56 paf 596: case OP_BIN_XOR:
597: {
1.61 paf 598: Value *b=POP(); Value *a=POP();
1.78 paf 599: Value *value=NEW VDouble(pool(),
1.155 parser 600: a->as_int() ^
601: b->as_int());
1.56 paf 602: PUSH(value);
603: break;
604: }
1.55 paf 605: case OP_LOG_AND:
606: {
1.61 paf 607: Value *b=POP(); Value *a=POP();
1.128 paf 608: Value *value=NEW VBool(pool(), a->as_bool() && b->as_bool());
1.55 paf 609: PUSH(value);
610: break;
611: }
612: case OP_LOG_OR:
613: {
1.61 paf 614: Value *b=POP(); Value *a=POP();
1.128 paf 615: Value *value=NEW VBool(pool(), a->as_bool() || b->as_bool());
1.56 paf 616: PUSH(value);
617: break;
618: }
619: case OP_LOG_XOR:
620: {
1.61 paf 621: Value *b=POP(); Value *a=POP();
1.128 paf 622: Value *value=NEW VBool(pool(), a->as_bool() ^ b->as_bool());
1.55 paf 623: PUSH(value);
624: break;
625: }
626: case OP_NUM_LT:
627: {
1.61 paf 628: Value *b=POP(); Value *a=POP();
1.128 paf 629: Value *value=NEW VBool(pool(), a->as_double() < b->as_double());
1.55 paf 630: PUSH(value);
631: break;
632: }
633: case OP_NUM_GT:
634: {
1.61 paf 635: Value *b=POP(); Value *a=POP();
1.128 paf 636: Value *value=NEW VBool(pool(), a->as_double() > b->as_double());
1.55 paf 637: PUSH(value);
638: break;
639: }
640: case OP_NUM_LE:
641: {
1.61 paf 642: Value *b=POP(); Value *a=POP();
1.128 paf 643: Value *value=NEW VBool(pool(), a->as_double() <= b->as_double());
1.55 paf 644: PUSH(value);
645: break;
646: }
647: case OP_NUM_GE:
648: {
1.61 paf 649: Value *b=POP(); Value *a=POP();
1.128 paf 650: Value *value=NEW VBool(pool(), a->as_double() >= b->as_double());
1.55 paf 651: PUSH(value);
652: break;
653: }
654: case OP_NUM_EQ:
655: {
1.61 paf 656: Value *b=POP(); Value *a=POP();
1.128 paf 657: Value *value=NEW VBool(pool(), a->as_double() == b->as_double());
1.55 paf 658: PUSH(value);
659: break;
660: }
661: case OP_NUM_NE:
662: {
1.61 paf 663: Value *b=POP(); Value *a=POP();
1.128 paf 664: Value *value=NEW VBool(pool(), a->as_double() != b->as_double());
1.54 paf 665: PUSH(value);
666: break;
667: }
1.58 paf 668: case OP_STR_LT:
669: {
1.61 paf 670: Value *b=POP(); Value *a=POP();
1.78 paf 671: Value *value=NEW VBool(pool(), a->as_string() < b->as_string());
1.58 paf 672: PUSH(value);
673: break;
674: }
675: case OP_STR_GT:
676: {
1.61 paf 677: Value *b=POP(); Value *a=POP();
1.78 paf 678: Value *value=NEW VBool(pool(), a->as_string() > b->as_string());
1.58 paf 679: PUSH(value);
680: break;
681: }
1.55 paf 682: case OP_STR_LE:
1.58 paf 683: {
1.61 paf 684: Value *b=POP(); Value *a=POP();
1.78 paf 685: Value *value=NEW VBool(pool(), a->as_string() <= b->as_string());
1.58 paf 686: PUSH(value);
687: break;
688: }
1.55 paf 689: case OP_STR_GE:
1.54 paf 690: {
1.61 paf 691: Value *b=POP(); Value *a=POP();
1.78 paf 692: Value *value=NEW VBool(pool(), a->as_string() >= b->as_string());
1.58 paf 693: PUSH(value);
694: break;
695: }
696: case OP_STR_EQ:
697: {
1.61 paf 698: Value *b=POP(); Value *a=POP();
1.78 paf 699: Value *value=NEW VBool(pool(), a->as_string() == b->as_string());
1.58 paf 700: PUSH(value);
701: break;
702: }
703: case OP_STR_NE:
704: {
1.61 paf 705: Value *b=POP(); Value *a=POP();
1.78 paf 706: Value *value=NEW VBool(pool(), a->as_string() != b->as_string());
1.103 paf 707: PUSH(value);
708: break;
709: }
710: case OP_IS:
711: {
712: Value *b=POP(); Value *a=POP();
713: Value *value=NEW VBool(pool(), b->as_string() == a->type());
1.49 paf 714: PUSH(value);
1.28 paf 715: break;
716: }
717:
1.11 paf 718: default:
1.67 paf 719: THROW(0,0,
720: 0,
1.139 paf 721: "invalid opcode %d", op.code);
1.11 paf 722: }
723: }
1.1 paf 724: }
1.17 paf 725:
726: Value *Request::get_element() {
1.82 paf 727: const String& name=POP_NAME();
1.24 paf 728: Value *ncontext=POP();
1.181 parser 729: Value *value=ncontext->get_element(name);
730: if(!value)
731: if(Method* method=OP.get_method(name)) { // maybe operator?
732: // as if that method were in self and we have normal dynamic method here
733: Junction& junction=*NEW Junction(pool(),
734: *self, self->get_class(), method, 0,0,0,0);
735: value=NEW VJunction(junction);
736: }
1.76 paf 737: if(value)
1.92 paf 738: value=&process(*value, &name); // process possible code-junction
1.76 paf 739: else {
1.167 parser 740: value=NEW VVoid(pool());
1.76 paf 741: value->set_name(name);
742: }
1.63 paf 743:
1.17 paf 744: return value;
1.34 paf 745: }
1.70 paf 746:
1.162 parser 747: /** @param intercept_string
1.116 paf 748: - true:
749: they want result=string value,
750: possible object result goes to wcontext
751: - false:
752: they want any result[string|object]
753: nothing goes to wcontext.
1.125 paf 754: used in @c (expression) params evaluation
1.116 paf 755: */
1.92 paf 756: Value& Request::process(Value& value, const String *name, bool intercept_string) {
1.91 paf 757: Value *result;
1.70 paf 758: Junction *junction=value.get_junction();
759: if(junction && junction->code) { // is it a code-junction?
1.92 paf 760: // process it
1.157 parser 761: #ifdef DEBUG_EXECUTE
1.158 parser 762: debug_printf(pool(), "ja->\n");
1.157 parser 763: #endif
1.70 paf 764: PUSH(self);
765: PUSH(root);
766: PUSH(rcontext);
1.129 paf 767: PUSH(wcontext);
1.70 paf 768:
1.71 paf 769: WContext *frame;
1.109 paf 770: // for expression method params
771: // wcontext is set 0
772: // using the fact in decision "which wwrapper to use"
773: bool using_code_frame=intercept_string && junction->wcontext;
774: if(using_code_frame) {
1.71 paf 775: // almost plain wwrapper about junction wcontext,
776: // BUT intercepts string writes
777: frame=NEW VCodeFrame(pool(), *junction->wcontext);
778: } else {
779: // plain wwrapper
1.186 ! parser 780: frame=NEW WWrapper(pool(), 0/*empty*/);
1.71 paf 781: }
782:
1.183 parser 783: //frame->set_name(value.name());
1.71 paf 784: wcontext=frame;
1.70 paf 785: self=&junction->self;
786: root=junction->root;
787: rcontext=junction->rcontext;
788: execute(*junction->code);
1.109 paf 789: if(using_code_frame) {
1.71 paf 790: // CodeFrame soul:
791: // string writes were intercepted
792: // returning them as the result of getting code-junction
793: result=NEW VString(*frame->get_string());
794: } else
795: result=frame->result();
1.70 paf 796:
797: wcontext=static_cast<WContext *>(POP());
798: rcontext=POP();
799: root=POP();
800: self=static_cast<VAliased *>(POP());
801:
1.157 parser 802: #ifdef DEBUG_EXECUTE
1.158 parser 803: debug_printf(pool(), "<-ja returned");
1.157 parser 804: #endif
1.70 paf 805: } else
1.91 paf 806: result=&value;
807:
808: if(name)
809: result->set_name(*name);
810: return *result;
1.85 paf 811: }
812:
1.176 parser 813: const String *Request::execute_method(Value& aself, const Method& method,
814: bool return_cstr) {
1.99 paf 815: PUSH(self);
816: PUSH(root);
817: PUSH(rcontext);
818: PUSH(wcontext);
819:
820: // initialize contexts
821: root=rcontext=self=&aself;
1.186 ! parser 822: wcontext=NEW WWrapper(pool(), &aself);
1.99 paf 823:
824: // execute!
825: execute(*method.parser_code);
826:
827: // result
1.114 paf 828: const String *result;
1.99 paf 829: if(return_cstr)
1.114 paf 830: result=&wcontext->as_string();
1.99 paf 831: else
832: result=0; // ignore result
833:
834: wcontext=static_cast<WContext *>(POP());
835: rcontext=POP();
836: root=POP();
837: self=static_cast<VAliased *>(POP());
838:
839: // return
840: return result;
841: }
842:
1.176 parser 843: const String *Request::execute_virtual_method(Value& aself,
844: const String& method_name,
845: bool return_cstr) {
1.99 paf 846: if(Value *value=aself.get_element(method_name))
847: if(Junction *junction=value->get_junction())
848: if(const Method *method=junction->method)
849: return execute_method(aself, *method, return_cstr);
1.176 parser 850:
851: return 0;
852: }
853:
1.178 parser 854: const String *Request::execute_nonvirtual_method(VStateless_class& aclass,
1.176 parser 855: const String& method_name,
856: bool return_cstr) {
1.178 parser 857: if(const Method *method=aclass.get_method(method_name))
1.179 parser 858: return execute_method(aclass, *method, return_cstr);
1.99 paf 859:
1.85 paf 860: return 0;
1.70 paf 861: }