|
|
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.213 ! paf 7: $Id: execute.C,v 1.212 2002/01/31 12:49:32 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);
241: break;
242: }
1.182 parser 243: case OP_CURLY_CODE__CONSTRUCT:
244: {
1.190 parser 245: const Array *local_ops=reinterpret_cast<const Array *>(i.next());
1.182 parser 246: #ifdef DEBUG_EXECUTE
247: debug_printf(pool(), " (%d)\n", local_ops->size());
248: debug_dump(pool(), 1, *local_ops);
249: #endif
250: Junction& j=*NEW Junction(pool(),
251: *self, 0, 0,
252: root,
253: rcontext,
254: wcontext,
255: local_ops);
256:
1.197 parser 257: value=NEW VJunction(j);
1.182 parser 258: const String& name=POP_NAME();
259: Value *ncontext=POP();
260: ncontext->put_element(name, value);
261: value->set_name(name);
262: break;
263: }
1.209 paf 264: case OP_NESTED_CODE:
265: {
266: Array *local_ops=static_cast<Array *>(i.next());
267: #ifdef DEBUG_EXECUTE
268: debug_printf(pool(), " (%d)\n", local_ops->size());
269: debug_dump(pool(), 1, *local_ops);
270: #endif
271: PUSH(local_ops);
272: break;
273: }
1.108 paf 274: case OP_WRITE_VALUE:
1.13 paf 275: {
1.197 parser 276: value=POP();
1.92 paf 277: write_assign_lang(*value);
1.150 paf 278:
1.211 paf 279: // forget the fact they've entered some ^object/class.xxx or $object/class.xxx
1.150 paf 280: // see OP_GET_ELEMENT
1.200 paf 281: wcontext->set_somebody_entered_some_object(false);
1.211 paf 282: wcontext->set_somebody_entered_some_class(false);
1.86 paf 283: break;
284: }
1.108 paf 285: case OP_WRITE_EXPR_RESULT:
286: {
1.197 parser 287: value=POP();
1.128 paf 288: write_expr_result(*value->as_expr_result());
1.108 paf 289: break;
290: }
1.86 paf 291: case OP_STRING__WRITE:
292: {
1.190 parser 293: VString *vstring=static_cast<VString *>(i.next());
1.157 parser 294: #ifdef DEBUG_EXECUTE
1.158 parser 295: debug_printf(pool(), " \"%s\"", vstring->string().cstr());
1.157 parser 296: #endif
1.122 paf 297: write_no_lang(vstring->string());
1.13 paf 298: break;
1.14 paf 299: }
1.13 paf 300:
1.15 paf 301: case OP_GET_ELEMENT:
1.11 paf 302: {
1.210 paf 303: //_asm int 3;
1.211 paf 304: // uses entered object/class flags to plug in operators
1.210 paf 305: value=get_element();
306:
1.150 paf 307: // maybe they do ^object.method[] call, remember the fact
1.210 paf 308: // must be below get_element() call, it checks it
1.200 paf 309: wcontext->set_somebody_entered_some_object(true);
1.150 paf 310:
1.24 paf 311: PUSH(value);
1.17 paf 312: break;
313: }
314:
1.18 paf 315: case OP_GET_ELEMENT__WRITE:
1.17 paf 316: {
1.197 parser 317: value=get_element();
1.92 paf 318: write_assign_lang(*value);
1.17 paf 319: break;
320: }
321:
1.32 paf 322:
1.17 paf 323: case OP_CREATE_EWPOOL:
324: {
1.24 paf 325: PUSH(wcontext);
1.137 paf 326: PUSH((void *)flang);
327: flang=String::UL_PASS_APPENDED;
1.186 parser 328: wcontext=NEW WWrapper(pool(), 0 /*empty*/);
1.17 paf 329: break;
330: }
331: case OP_REDUCE_EWPOOL:
332: {
1.208 paf 333: value=&wcontext->result();
1.137 paf 334: flang=static_cast<String::Untaint_lang>(reinterpret_cast<int>(POP()));
1.25 paf 335: wcontext=static_cast<WContext *>(POP());
1.24 paf 336: PUSH(value);
1.13 paf 337: break;
1.15 paf 338: }
1.13 paf 339:
1.49 paf 340: case OP_CREATE_SWPOOL:
341: {
342: PUSH(wcontext);
1.186 parser 343: wcontext=NEW WWrapper(pool(), 0 /*empty*/);
1.49 paf 344: break;
345: }
346: case OP_REDUCE_SWPOOL:
347: {
348: // from "$a $b" part of expression taking only string value,
349: // ignoring any other content of wcontext
1.82 paf 350: const String *string=wcontext->get_string();
1.80 paf 351: Value *value;
352: if(string)
353: value=NEW VString(*string);
354: else
1.167 parser 355: NEW VVoid(pool());
1.50 paf 356: wcontext=static_cast<WContext *>(POP());
1.49 paf 357: PUSH(value);
358: break;
359: }
360:
1.51 paf 361: // CALL
1.28 paf 362: case OP_GET_METHOD_FRAME:
363: {
1.197 parser 364: value=POP();
1.138 paf 365:
1.111 paf 366: // info:
367: // code compiled so that this one's always method-junction,
368: // not a code-junction
1.32 paf 369: Junction *junction=value->get_junction();
1.31 paf 370: if(!junction)
1.196 parser 371: throw Exception(0, 0,
1.42 paf 372: &value->name(),
1.111 paf 373: "(%s) not a method or junction, can not call it",
1.38 paf 374: value->type());
1.70 paf 375:
1.185 parser 376: VMethodFrame *frame=NEW VMethodFrame(pool(), value->name(), *junction);
1.28 paf 377: PUSH(frame);
378: break;
379: }
380: case OP_STORE_PARAM:
381: {
1.197 parser 382: value=POP();
1.73 paf 383: VMethodFrame *frame=static_cast<VMethodFrame *>(stack.top_value());
1.92 paf 384: frame->store_param(frame->name(), value);
1.29 paf 385: break;
386: }
387:
1.186 parser 388: case OP_PREPARE_TO_CONSTRUCT_OBJECT:
389: {
1.200 paf 390: wcontext->set_constructing(true);
1.186 parser 391: break;
392: }
393: case OP_CALL:
1.29 paf 394: {
1.157 parser 395: #ifdef DEBUG_EXECUTE
1.158 parser 396: debug_printf(pool(), "->\n");
1.157 parser 397: #endif
1.34 paf 398: VMethodFrame *frame=static_cast<VMethodFrame *>(POP());
399: frame->fill_unspecified_params();
1.45 paf 400: PUSH(self);
401: PUSH(root);
402: PUSH(rcontext);
403: PUSH(wcontext);
404:
1.100 paf 405: VStateless_class *called_class=frame->junction.self.get_class();
1.200 paf 406: if(wcontext->get_constructing()) {
407: wcontext->set_constructing(false);
1.185 parser 408: if(frame->junction.method->call_type!=Method::CT_STATIC) {
1.138 paf 409: // this is a constructor call
1.185 parser 410:
411: if(Value *value=called_class->create_new_value(pool())) {
1.204 paf 412: // some stateless_class creatable derivates
1.149 paf 413: self=value;
1.204 paf 414: } else
415: throw Exception(0, 0,
416: &frame->name(),
417: "is not a constructor, system class '%s' can be constructed only implicitly",
418: called_class->name().cstr());
419:
1.83 paf 420: frame->write(*self,
1.136 paf 421: String::UL_CLEAN // not used, always an object, not string
1.83 paf 422: );
1.185 parser 423: } else
1.196 parser 424: throw Exception(0, 0,
1.185 parser 425: &frame->name(),
426: "method is static and can not be used as constructor");
427: } else {
428: // this is not constructor call
429:
430: // not ^name.method call, name:method call; and
431: // is context object or class & is it my class or my parent's class and?
432: VStateless_class *read_class=rcontext->get_class();
433: if(
1.200 paf 434: !(wcontext->get_somebody_entered_some_object() &&
435: !wcontext->get_somebody_entered_some_class()) &&
1.185 parser 436: read_class && read_class->is_or_derived_from(*called_class)) // yes
437: self=rcontext; // dynamic call
438: else // no, not me or relative of mine (=total stranger)
439: self=&frame->junction.self; // static call
440: }
1.75 paf 441:
1.45 paf 442: frame->set_self(*self);
1.202 paf 443: rcontext=wcontext=frame;
1.47 paf 444: {
1.48 paf 445: // take object or class from any wrappers
1.102 paf 446: // and substitute class alias to the class they are called AS
447: Temp_alias temp_alias(*self->get_aliased(), *frame->junction.vclass);
1.68 paf 448:
1.99 paf 449: const Method& method=*frame->junction.method;
1.134 paf 450: Method::Call_type call_type=
451: called_class==self ? Method::CT_STATIC : Method::CT_DYNAMIC;
452: if(
453: method.call_type==Method::CT_ANY ||
1.197 parser 454: method.call_type==call_type) { // allowed call type?
455: try {
456: if(method.native_code) { // native code?
1.202 paf 457: // root unchanged, so that ^for ^foreach & co may write to locals
1.197 parser 458: method.check_actual_numbered_params(
459: frame->junction.self,
460: frame->name(), frame->numbered_params());
461: method.native_code(
462: *this,
463: frame->name(), frame->numbered_params()); // execute it
464: } else { // parser code
1.202 paf 465: root=frame;
1.207 paf 466: { // anti_endless_execute_recoursion
467: if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) {
468: anti_endless_execute_recoursion=0; // give @exception a chance
469: throw Exception(0, 0,
470: &frame->name(),
471: "call canceled - endless recursion detected");
472: }
473: execute(*method.parser_code); // execute it
474: anti_endless_execute_recoursion--;
1.197 parser 475: }
1.159 parser 476: }
1.197 parser 477: } catch(...) {
478: // record it to stack trace
479: trace.push((void *)&frame->name());
480: /*re*/throw;
1.159 parser 481: }
1.197 parser 482: } else
1.196 parser 483: throw Exception(0, 0,
1.134 paf 484: &frame->name(),
485: "is not allowed to be called %s",
486: call_type==Method::CT_STATIC?"statically":"dynamically");
487:
1.47 paf 488: }
1.208 paf 489: value=&wcontext->result();
1.45 paf 490:
491: wcontext=static_cast<WContext *>(POP());
492: rcontext=POP();
493: root=POP();
494: self=static_cast<VAliased *>(POP());
1.213 ! paf 495:
! 496: // forget the fact they've entered some ^object/class.xxx
! 497: // see OP_GET_ELEMENT
! 498: wcontext->set_somebody_entered_some_object(false);
! 499: wcontext->set_somebody_entered_some_class(false);
1.62 paf 500:
1.61 paf 501: PUSH(value);
1.157 parser 502: #ifdef DEBUG_EXECUTE
1.158 parser 503: debug_printf(pool(), "<-returned");
1.157 parser 504: #endif
1.49 paf 505: break;
506: }
507:
1.55 paf 508: // expression ops: unary
509: case OP_NEG:
510: {
511: Value *operand=POP();
1.197 parser 512: value=NEW VDouble(pool(), -operand->as_double());
1.55 paf 513: PUSH(value);
514: break;
515: }
516: case OP_INV:
517: {
518: Value *operand=POP();
1.197 parser 519: value=NEW VDouble(pool(), ~operand->as_int());
1.55 paf 520: PUSH(value);
521: break;
522: }
523: case OP_NOT:
524: {
525: Value *operand=POP();
1.197 parser 526: value=NEW VBool(pool(), !operand->as_bool());
1.55 paf 527: PUSH(value);
528: break;
529: }
1.62 paf 530: case OP_DEF:
531: {
532: Value *operand=POP();
1.197 parser 533: value=NEW VBool(pool(), operand->is_defined());
1.62 paf 534: PUSH(value);
535: break;
536: }
537: case OP_IN:
538: {
1.199 paf 539: /// @test String::cmp
1.62 paf 540: Value *operand=POP();
1.110 paf 541: const char *path=operand->as_string().cstr();
1.197 parser 542: value=NEW VBool(pool(),
1.151 paf 543: info.uri && strncmp(path, info.uri, strlen(path))==0);
1.62 paf 544: PUSH(value);
545: break;
546: }
547: case OP_FEXISTS:
548: {
549: Value *operand=POP();
1.197 parser 550: value=NEW VBool(pool(),
1.127 paf 551: file_readable(absolute(operand->as_string())));
1.148 paf 552: PUSH(value);
553: break;
554: }
555: case OP_DEXISTS:
556: {
557: Value *operand=POP();
1.197 parser 558: value=NEW VBool(pool(),
1.148 paf 559: dir_readable(absolute(operand->as_string())));
1.62 paf 560: PUSH(value);
561: break;
562: }
1.55 paf 563:
564: // expression ops: binary
565: case OP_SUB:
1.53 paf 566: {
1.197 parser 567: b=POP(); a=POP();
568: value=NEW VDouble(pool(), a->as_double() - b->as_double());
1.53 paf 569: PUSH(value);
570: break;
571: }
1.55 paf 572: case OP_ADD:
1.53 paf 573: {
1.197 parser 574: b=POP(); a=POP();
575: value=NEW VDouble(pool(), a->as_double() + b->as_double());
1.53 paf 576: PUSH(value);
577: break;
578: }
1.49 paf 579: case OP_MUL:
580: {
1.197 parser 581: b=POP(); a=POP();
582: value=NEW VDouble(pool(), a->as_double() * b->as_double());
1.53 paf 583: PUSH(value);
584: break;
585: }
586: case OP_DIV:
587: {
1.197 parser 588: b=POP(); a=POP();
1.170 parser 589:
590: double a_double=a->as_double();
591: double b_double=b->as_double();
592:
1.171 parser 593: if(b_double == 0) {
594: const String *problem_source=&b->as_string();
595: #ifndef NO_STRING_ORIGIN
596: if(!problem_source->origin().file)
1.172 parser 597: problem_source=&b->name();
1.171 parser 598: #endif
1.196 parser 599: throw Exception(0, 0,
1.171 parser 600: problem_source,
1.170 parser 601: "Division by zero");
1.171 parser 602: }
1.170 parser 603:
1.197 parser 604: value=NEW VDouble(pool(), a_double / b_double);
1.54 paf 605: PUSH(value);
606: break;
607: }
1.55 paf 608: case OP_MOD:
609: {
1.197 parser 610: b=POP(); a=POP();
1.170 parser 611:
1.173 parser 612: double a_double=a->as_double();
613: double b_double=b->as_double();
1.170 parser 614:
1.173 parser 615: if(b_double == 0) {
1.171 parser 616: const String *problem_source=&b->as_string();
617: #ifndef NO_STRING_ORIGIN
618: if(!problem_source->origin().file)
1.172 parser 619: problem_source=&b->name();
1.171 parser 620: #endif
1.196 parser 621: throw Exception(0, 0,
1.171 parser 622: problem_source,
1.170 parser 623: "Modulus by zero");
1.171 parser 624: }
1.170 parser 625:
1.197 parser 626: value=NEW VDouble(pool(), fmod(a_double, b_double));
1.201 paf 627: PUSH(value);
628: break;
629: }
630: case OP_INTDIV:
631: {
632: b=POP(); a=POP();
633:
634: int a_int=a->as_int();
635: int b_int=b->as_int();
636:
637: if(b_int == 0) {
638: const String *problem_source=&b->as_string();
639: #ifndef NO_STRING_ORIGIN
640: if(!problem_source->origin().file)
641: problem_source=&b->name();
642: #endif
643: throw Exception(0, 0,
644: problem_source,
645: "Division by zero");
646: }
647:
648: value=NEW VInt(pool(), a_int / b_int);
1.55 paf 649: PUSH(value);
650: break;
651: }
652: case OP_BIN_AND:
1.54 paf 653: {
1.197 parser 654: b=POP(); a=POP();
655: value=NEW VDouble(pool(),
1.155 parser 656: a->as_int() &
657: b->as_int());
1.54 paf 658: PUSH(value);
659: break;
660: }
1.55 paf 661: case OP_BIN_OR:
1.54 paf 662: {
1.197 parser 663: b=POP(); a=POP();
664: value=NEW VDouble(pool(),
1.155 parser 665: a->as_int() |
666: b->as_int());
1.55 paf 667: PUSH(value);
668: break;
669: }
1.56 paf 670: case OP_BIN_XOR:
671: {
1.197 parser 672: b=POP(); a=POP();
673: value=NEW VDouble(pool(),
1.155 parser 674: a->as_int() ^
675: b->as_int());
1.56 paf 676: PUSH(value);
677: break;
678: }
1.55 paf 679: case OP_LOG_AND:
680: {
1.209 paf 681: b_code=POP_CODE(); a=POP();
682: bool result;
683: if(a->as_bool()) {
684: execute(*b_code);
685: b=POP();
686: result=b->as_bool();
687: } else
688: result=false;
689: value=NEW VBool(pool(), result);
1.55 paf 690: PUSH(value);
691: break;
692: }
693: case OP_LOG_OR:
694: {
1.209 paf 695: b_code=POP_CODE(); a=POP();
696: bool result;
697: if(a->as_bool())
698: result=true;
699: else {
700: execute(*b_code);
701: b=POP();
702: result=b->as_bool();
703: }
704: value=NEW VBool(pool(), result);
1.56 paf 705: PUSH(value);
706: break;
707: }
708: case OP_LOG_XOR:
709: {
1.197 parser 710: b=POP(); a=POP();
711: value=NEW VBool(pool(), a->as_bool() ^ b->as_bool());
1.55 paf 712: PUSH(value);
713: break;
714: }
715: case OP_NUM_LT:
716: {
1.197 parser 717: b=POP(); a=POP();
718: value=NEW VBool(pool(), a->as_double() < b->as_double());
1.55 paf 719: PUSH(value);
720: break;
721: }
722: case OP_NUM_GT:
723: {
1.197 parser 724: b=POP(); a=POP();
725: value=NEW VBool(pool(), a->as_double() > b->as_double());
1.55 paf 726: PUSH(value);
727: break;
728: }
729: case OP_NUM_LE:
730: {
1.197 parser 731: b=POP(); a=POP();
732: value=NEW VBool(pool(), a->as_double() <= b->as_double());
1.55 paf 733: PUSH(value);
734: break;
735: }
736: case OP_NUM_GE:
737: {
1.197 parser 738: b=POP(); a=POP();
739: value=NEW VBool(pool(), a->as_double() >= b->as_double());
1.55 paf 740: PUSH(value);
741: break;
742: }
743: case OP_NUM_EQ:
744: {
1.197 parser 745: b=POP(); a=POP();
746: value=NEW VBool(pool(), a->as_double() == b->as_double());
1.55 paf 747: PUSH(value);
748: break;
749: }
750: case OP_NUM_NE:
751: {
1.197 parser 752: b=POP(); a=POP();
753: value=NEW VBool(pool(), a->as_double() != b->as_double());
1.54 paf 754: PUSH(value);
755: break;
756: }
1.58 paf 757: case OP_STR_LT:
758: {
1.197 parser 759: b=POP(); a=POP();
760: value=NEW VBool(pool(), a->as_string() < b->as_string());
1.58 paf 761: PUSH(value);
762: break;
763: }
764: case OP_STR_GT:
765: {
1.197 parser 766: b=POP(); a=POP();
767: value=NEW VBool(pool(), a->as_string() > b->as_string());
1.58 paf 768: PUSH(value);
769: break;
770: }
1.55 paf 771: case OP_STR_LE:
1.58 paf 772: {
1.197 parser 773: b=POP(); a=POP();
774: value=NEW VBool(pool(), a->as_string() <= b->as_string());
1.58 paf 775: PUSH(value);
776: break;
777: }
1.55 paf 778: case OP_STR_GE:
1.54 paf 779: {
1.197 parser 780: b=POP(); a=POP();
781: value=NEW VBool(pool(), a->as_string() >= b->as_string());
1.58 paf 782: PUSH(value);
783: break;
784: }
785: case OP_STR_EQ:
786: {
1.197 parser 787: b=POP(); a=POP();
788: value=NEW VBool(pool(), a->as_string() == b->as_string());
1.58 paf 789: PUSH(value);
790: break;
791: }
792: case OP_STR_NE:
793: {
1.197 parser 794: b=POP(); a=POP();
795: value=NEW VBool(pool(), a->as_string() != b->as_string());
1.103 paf 796: PUSH(value);
797: break;
798: }
799: case OP_IS:
800: {
1.191 parser 801: //_asm int 3;
1.197 parser 802: b=POP(); a=POP();
803: value=NEW VBool(pool(), b->as_string() == a->type());
1.49 paf 804: PUSH(value);
1.28 paf 805: break;
806: }
807:
1.11 paf 808: default:
1.196 parser 809: throw Exception(0,0,
1.67 paf 810: 0,
1.139 paf 811: "invalid opcode %d", op.code);
1.11 paf 812: }
813: }
1.1 paf 814: }
1.17 paf 815:
816: Value *Request::get_element() {
1.82 paf 817: const String& name=POP_NAME();
1.24 paf 818: Value *ncontext=POP();
1.181 parser 819: Value *value=ncontext->get_element(name);
1.210 paf 820: // operators can not be in form...
821: if(!value &&
822: !wcontext->get_somebody_entered_some_class () && // $class:xxx
823: !wcontext->get_somebody_entered_some_object()) // $object.xxx
824: // they can only be in form ^xxx or $xxx
1.181 parser 825: if(Method* method=OP.get_method(name)) { // maybe operator?
826: // as if that method were in self and we have normal dynamic method here
827: Junction& junction=*NEW Junction(pool(),
1.202 paf 828: *root, self->get_class(), method, 0,0,0,0);
1.181 parser 829: value=NEW VJunction(junction);
830: }
1.76 paf 831: if(value)
1.92 paf 832: value=&process(*value, &name); // process possible code-junction
1.76 paf 833: else {
1.167 parser 834: value=NEW VVoid(pool());
1.76 paf 835: value->set_name(name);
836: }
1.63 paf 837:
1.17 paf 838: return value;
1.34 paf 839: }
1.70 paf 840:
1.162 parser 841: /** @param intercept_string
1.116 paf 842: - true:
843: they want result=string value,
844: possible object result goes to wcontext
845: - false:
846: they want any result[string|object]
847: nothing goes to wcontext.
1.125 paf 848: used in @c (expression) params evaluation
1.116 paf 849: */
1.92 paf 850: Value& Request::process(Value& value, const String *name, bool intercept_string) {
1.91 paf 851: Value *result;
1.70 paf 852: Junction *junction=value.get_junction();
853: if(junction && junction->code) { // is it a code-junction?
1.92 paf 854: // process it
1.157 parser 855: #ifdef DEBUG_EXECUTE
1.158 parser 856: debug_printf(pool(), "ja->\n");
1.157 parser 857: #endif
1.70 paf 858: PUSH(self);
859: PUSH(root);
860: PUSH(rcontext);
1.129 paf 861: PUSH(wcontext);
1.70 paf 862:
1.71 paf 863: WContext *frame;
1.109 paf 864: // for expression method params
865: // wcontext is set 0
866: // using the fact in decision "which wwrapper to use"
867: bool using_code_frame=intercept_string && junction->wcontext;
868: if(using_code_frame) {
1.71 paf 869: // almost plain wwrapper about junction wcontext,
870: // BUT intercepts string writes
871: frame=NEW VCodeFrame(pool(), *junction->wcontext);
872: } else {
873: // plain wwrapper
1.186 parser 874: frame=NEW WWrapper(pool(), 0/*empty*/);
1.71 paf 875: }
876:
1.183 parser 877: //frame->set_name(value.name());
1.71 paf 878: wcontext=frame;
1.70 paf 879: self=&junction->self;
880: root=junction->root;
881: rcontext=junction->rcontext;
1.207 paf 882:
883: { // anti_endless_execute_recoursion
884: if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) {
885: anti_endless_execute_recoursion=0; // give @exception a chance
886: throw Exception(0, 0,
887: name,
888: "junction evaluation canceled - endless recursion detected");
889: }
890: execute(*junction->code);
891: anti_endless_execute_recoursion--;
892: }
893:
1.109 paf 894: if(using_code_frame) {
1.71 paf 895: // CodeFrame soul:
896: // string writes were intercepted
897: // returning them as the result of getting code-junction
898: result=NEW VString(*frame->get_string());
899: } else
1.208 paf 900: result=&frame->result();
1.70 paf 901:
902: wcontext=static_cast<WContext *>(POP());
903: rcontext=POP();
904: root=POP();
905: self=static_cast<VAliased *>(POP());
906:
1.157 parser 907: #ifdef DEBUG_EXECUTE
1.158 parser 908: debug_printf(pool(), "<-ja returned");
1.157 parser 909: #endif
1.70 paf 910: } else
1.91 paf 911: result=&value;
912:
913: if(name)
914: result->set_name(*name);
915: return *result;
1.85 paf 916: }
917:
1.208 paf 918: const String *Request::execute_method(Value& aself, const Method& method,
919: bool return_cstr) {
1.99 paf 920: PUSH(self);
921: PUSH(root);
922: PUSH(rcontext);
923: PUSH(wcontext);
924:
925: // initialize contexts
926: root=rcontext=self=&aself;
1.186 parser 927: wcontext=NEW WWrapper(pool(), &aself);
1.99 paf 928:
929: // execute!
930: execute(*method.parser_code);
931:
932: // result
1.208 paf 933: const String *result=return_cstr ? &wcontext->as_string() : 0;
934:
935: wcontext=static_cast<WContext *>(POP());
936: rcontext=POP();
937: root=POP();
938: self=static_cast<VAliased *>(POP());
939:
940: // return
941: return result;
942: }
943:
944: const String& Request::execute_method(VMethodFrame& amethodFrame, const Method& method) {
945: PUSH(self);
946: PUSH(root);
947: PUSH(rcontext);
948: PUSH(wcontext);
949:
950: // initialize contexts
951: root=rcontext=self=&amethodFrame;
952: wcontext=&amethodFrame;
953:
954: // execute!
955: execute(*method.parser_code);
956:
957: // result
958: const String& result=wcontext->as_string();
1.99 paf 959:
960: wcontext=static_cast<WContext *>(POP());
961: rcontext=POP();
962: root=POP();
963: self=static_cast<VAliased *>(POP());
964:
965: // return
966: return result;
967: }
968:
1.176 parser 969: const String *Request::execute_virtual_method(Value& aself,
1.208 paf 970: const String& method_name) {
1.99 paf 971: if(Value *value=aself.get_element(method_name))
972: if(Junction *junction=value->get_junction())
973: if(const Method *method=junction->method)
1.208 paf 974: return execute_method(aself, *method, true /*return_cstr*/);
1.188 parser 975:
1.176 parser 976: return 0;
977: }
978:
1.178 parser 979: const String *Request::execute_nonvirtual_method(VStateless_class& aclass,
1.208 paf 980: const String& method_name,
1.176 parser 981: bool return_cstr) {
1.178 parser 982: if(const Method *method=aclass.get_method(method_name))
1.179 parser 983: return execute_method(aclass, *method, return_cstr);
1.99 paf 984:
1.85 paf 985: return 0;
1.70 paf 986: }