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