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