|
|
1.117 paf 1: /** @file
1.118 paf 2: Parser: executor part of request class.
3:
1.313 paf 4: Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
1.218 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.243 paf 6: */
1.118 paf 7:
1.319 ! misha 8: static const char * const IDENT_EXECUTE_C="$Date: 2007/11/29 08:07:26 $";
1.1 paf 9:
1.152 paf 10: #include "pa_opcode.h"
1.8 paf 11: #include "pa_array.h"
1.11 paf 12: #include "pa_request.h"
1.15 paf 13: #include "pa_vstring.h"
1.22 paf 14: #include "pa_vhash.h"
1.167 parser 15: #include "pa_vvoid.h"
1.145 paf 16: #include "pa_vcode_frame.h"
1.319 ! misha 17: #include "pa_vmethod_frame_local.h"
! 18: #include "pa_vmethod_frame_global.h"
1.38 paf 19: #include "pa_vobject.h"
1.49 paf 20: #include "pa_vdouble.h"
1.54 paf 21: #include "pa_vbool.h"
1.94 paf 22: #include "pa_vtable.h"
1.132 paf 23: #include "pa_vfile.h"
1.144 paf 24: #include "pa_vimage.h"
1.194 parser 25: #include "pa_wwrapper.h"
1.1 paf 26:
1.233 paf 27: //#define DEBUG_EXECUTE
1.157 parser 28:
29: #ifdef DEBUG_EXECUTE
1.1 paf 30: char *opcode_name[]={
1.49 paf 31: // literals
1.109 paf 32: "VALUE", "CURLY_CODE__STORE_PARAM", "EXPR_CODE__STORE_PARAM",
1.209 paf 33: "NESTED_CODE",
1.49 paf 34:
35: // actions
1.187 parser 36: "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE",
1.66 paf 37: "GET_CLASS",
1.182 parser 38: "CONSTRUCT_VALUE", "CONSTRUCT_EXPR", "CURLY_CODE__CONSTRUCT",
1.108 paf 39: "WRITE_VALUE", "WRITE_EXPR_RESULT", "STRING__WRITE",
1.284 paf 40: "GET_ELEMENT_OR_OPERATOR", "GET_ELEMENT", "GET_ELEMENT__WRITE",
1.232 paf 41: "OBJECT_POOL", "STRING_POOL",
1.1 paf 42: "STORE_PARAM",
1.232 paf 43: "PREPARE_TO_CONSTRUCT_OBJECT", "PREPARE_TO_EXPRESSION",
44: "CALL", "CALL__WRITE",
1.49 paf 45:
46: // expression ops: unary
1.148 paf 47: "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS",
1.49 paf 48: // expression ops: binary
1.201 paf 49: "SUB", "ADD", "MUL", "DIV", "MOD", "INTDIV",
1.275 paf 50: "BIN_SL", "BIN_SR",
1.56 paf 51: "BIN_AND", "BIN_OR", "BIN_XOR",
52: "LOG_AND", "LOG_OR", "LOG_XOR",
1.49 paf 53: "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE",
1.103 paf 54: "STR_LT", "STR_GT", "STR_LE", "STR_GE", "STR_EQ", "STR_NE",
55: "IS"
1.1 paf 56: };
57:
1.297 paf 58: void va_debug_printf(SAPI_Info& sapi_info, const char* fmt,va_list args) {
1.127 paf 59: char buf[MAX_STRING];
60: vsnprintf(buf, MAX_STRING, fmt, args);
1.297 paf 61: SAPI::log(sapi_info, "%s", buf);
1.107 paf 62: }
63:
1.297 paf 64: void debug_printf(SAPI_Info& sapi_info, const char* fmt, ...) {
1.107 paf 65: va_list args;
1.297 paf 66: va_start(args, fmt);
67: va_debug_printf(sapi_info, fmt, args);
1.107 paf 68: va_end(args);
1.105 paf 69: }
70:
1.297 paf 71: void debug_dump(SAPI_Info& sapi_info, int level, ArrayOperation& ops) {
72: Array_iterator<Operation> i(ops);
1.190 parser 73: while(i.has_next()) {
1.297 paf 74: OPCODE opcode=i.next().code;
1.1 paf 75:
1.297 paf 76: if(opcode==OP_VALUE || opcode==OP_STRING__WRITE) {
77: Operation::Origin origin=i.next().origin;
78: Value& value=*i.next().value;
79: debug_printf(sapi_info,
1.133 paf 80: "%*s%s"
81: " \"%s\" %s",
1.297 paf 82: level*4, "", opcode_name[opcode],
83: value.get_string()->cstr(), value.type());
1.133 paf 84: continue;
1.15 paf 85: }
1.297 paf 86: debug_printf(sapi_info, "%*s%s", level*4, "", opcode_name[opcode]);
1.1 paf 87:
1.297 paf 88: switch(opcode) {
1.184 parser 89: case OP_CURLY_CODE__STORE_PARAM:
90: case OP_EXPR_CODE__STORE_PARAM:
91: case OP_CURLY_CODE__CONSTRUCT:
1.209 paf 92: case OP_NESTED_CODE:
1.226 paf 93: case OP_OBJECT_POOL:
94: case OP_STRING_POOL:
1.237 paf 95: case OP_CALL:
1.297 paf 96: case OP_CALL__WRITE:
97: if(ArrayOperation* local_ops=i.next().ops)
98: debug_dump(sapi_info, level+1, *local_ops);
1.1 paf 99: }
100: }
101: }
1.157 parser 102: #endif
1.1 paf 103:
1.297 paf 104: // Request
105:
106: void Request::execute(ArrayOperation& ops) {
107: register Stack<StackItem>& stack=this->stack; // helps a lot on MSVC: 'esi'
1.159 parser 108:
1.304 paf 109: const String* debug_name=0; Operation::Origin debug_origin={0, 0, 0};
1.297 paf 110: try{
1.157 parser 111: #ifdef DEBUG_EXECUTE
1.297 paf 112: debug_printf(sapi_info, "source----------------------------\n");
113: debug_dump(sapi_info, 0, ops);
114: debug_printf(sapi_info, "execution-------------------------\n");
1.157 parser 115: #endif
1.297 paf 116: for(Array_iterator<Operation> i(ops); i.has_next(); ) {
1.315 paf 117: if(get_skip())
118: return;
1.297 paf 119: if(get_interrupted()) {
120: set_interrupted(false);
1.293 paf 121: throw Exception("parser.interrupted",
122: 0,
123: "execution stopped");
1.297 paf 124: }
125: OPCODE opcode=i.next().code;
1.293 paf 126:
1.157 parser 127: #ifdef DEBUG_EXECUTE
1.297 paf 128: debug_printf(sapi_info, "%d:%s", stack.top_index()+1, opcode_name[opcode]);
1.157 parser 129: #endif
1.11 paf 130:
1.297 paf 131: switch(opcode) {
1.51 paf 132: // param in next instruction
1.52 paf 133: case OP_VALUE:
1.32 paf 134: {
1.297 paf 135: debug_origin=i.next().origin;
136: Value& value=*i.next().value;
1.157 parser 137: #ifdef DEBUG_EXECUTE
1.297 paf 138: debug_printf(sapi_info, " \"%s\" %s", value.get_string()->cstr(), value.type());
1.157 parser 139: #endif
1.297 paf 140: stack.push(value);
1.32 paf 141: break;
142: }
1.66 paf 143: case OP_GET_CLASS:
1.38 paf 144: {
1.130 paf 145: // maybe they do ^class:method[] call, remember the fact
1.215 paf 146: wcontext->set_somebody_entered_some_class();
1.98 paf 147:
1.297 paf 148: const String& name=stack.pop().string();
149: Value* value=classes().get(name);
1.120 paf 150: if(!value)
1.316 misha 151: throw Exception(PARSER_RUNTIME,
1.66 paf 152: &name,
1.143 paf 153: "class is undefined");
1.66 paf 154:
1.297 paf 155: stack.push(*value);
1.38 paf 156: break;
157: }
1.32 paf 158:
1.51 paf 159: // OP_WITH
1.187 parser 160: case OP_WITH_ROOT:
161: {
1.297 paf 162: stack.push(*method_frame);
1.187 parser 163: break;
164: }
1.37 paf 165: case OP_WITH_SELF:
166: {
1.297 paf 167: stack.push(get_self());
1.37 paf 168: break;
169: }
1.15 paf 170: case OP_WITH_READ:
171: {
1.297 paf 172: stack.push(*rcontext);
1.20 paf 173: break;
174: }
1.37 paf 175: case OP_WITH_WRITE:
1.20 paf 176: {
1.287 paf 177: if(wcontext==method_frame)
1.316 misha 178: throw Exception(PARSER_RUNTIME,
1.287 paf 179: 0,
180: "$.name outside of $name[...]");
181:
1.297 paf 182: stack.push(*wcontext);
1.20 paf 183: break;
184: }
1.37 paf 185:
1.51 paf 186: // OTHER ACTIONS BUT WITHs
1.80 paf 187: case OP_CONSTRUCT_VALUE:
1.20 paf 188: {
1.297 paf 189: Value& value=stack.pop().value();
190: const String& name=stack.pop().string(); debug_name=&name;
191: Value& ncontext=stack.pop().value();
1.309 paf 192: put_element(ncontext, name, value);
1.308 paf 193:
1.213 paf 194: break;
195: }
1.80 paf 196: case OP_CONSTRUCT_EXPR:
197: {
1.219 paf 198: // see OP_PREPARE_TO_EXPRESSION
199: wcontext->set_in_expression(false);
200:
1.308 paf 201: Value& expr=stack.pop().value();
1.297 paf 202: const String& name=stack.pop().string(); debug_name=&name;
203: Value& ncontext=stack.pop().value();
1.308 paf 204: Value& value=expr.as_expr_result();
1.309 paf 205: put_element(ncontext, name, value);
1.80 paf 206: break;
207: }
1.182 parser 208: case OP_CURLY_CODE__CONSTRUCT:
209: {
1.297 paf 210: ArrayOperation& local_ops=*i.next().ops;
1.182 parser 211: #ifdef DEBUG_EXECUTE
1.297 paf 212: debug_printf(sapi_info, " (%d)\n", local_ops.count());
213: debug_dump(sapi_info, 1, local_ops);
1.182 parser 214: #endif
1.312 paf 215: Value& value=*new VJunction(
1.297 paf 216: get_self(), 0,
1.257 paf 217: method_frame,
1.240 paf 218: rcontext,
219: wcontext,
1.312 paf 220: &local_ops);
1.238 paf 221:
1.297 paf 222: const String& name=stack.pop().string(); debug_name=&name;
223: Value& ncontext=stack.pop().value();
1.312 paf 224: if(const VJunction* vjunction=ncontext.put_element(ncontext, name, &value, false))
225: if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT)
1.316 misha 226: throw Exception(PARSER_RUNTIME,
1.308 paf 227: 0,
228: "property value can not be code, use [] or () brackets");
229:
1.182 parser 230: break;
231: }
1.209 paf 232: case OP_NESTED_CODE:
233: {
1.297 paf 234: ArrayOperation& local_ops=*i.next().ops;
1.209 paf 235: #ifdef DEBUG_EXECUTE
1.297 paf 236: debug_printf(sapi_info, " (%d)\n", local_ops.count());
237: debug_dump(sapi_info, 1, local_ops);
1.209 paf 238: #endif
1.297 paf 239: stack.push(local_ops);
1.209 paf 240: break;
241: }
1.108 paf 242: case OP_WRITE_VALUE:
1.13 paf 243: {
1.297 paf 244: Value& value=stack.pop().value();
245: write_assign_lang(value);
1.86 paf 246: break;
247: }
1.108 paf 248: case OP_WRITE_EXPR_RESULT:
249: {
1.297 paf 250: Value& value=stack.pop().value();
251: write_no_lang(value.as_expr_result());
1.230 paf 252:
253: // must be after write(result) and
1.219 paf 254: // see OP_PREPARE_TO_EXPRESSION
255: wcontext->set_in_expression(false);
1.108 paf 256: break;
257: }
1.86 paf 258: case OP_STRING__WRITE:
259: {
1.297 paf 260: i.next(); // ignore origin
261: Value* value=i.next().value;
1.157 parser 262: #ifdef DEBUG_EXECUTE
1.297 paf 263: debug_printf(sapi_info, " \"%s\"", value->get_string()->cstr());
1.157 parser 264: #endif
1.297 paf 265: write_no_lang(*value->get_string());
1.13 paf 266: break;
1.14 paf 267: }
1.13 paf 268:
1.215 paf 269: case OP_GET_ELEMENT_OR_OPERATOR:
270: {
1.297 paf 271: const String& name=stack.pop().string(); debug_name=&name;
272: Value& ncontext=stack.pop().value();
273: Value& value=get_element(ncontext, name, true);
274: stack.push(value);
1.215 paf 275: break;
276: }
1.15 paf 277: case OP_GET_ELEMENT:
1.11 paf 278: {
1.297 paf 279: const String& name=stack.pop().string(); debug_name=&name;
280: Value& ncontext=stack.pop().value();
281: Value& value=get_element(ncontext, name, false);
282: stack.push(value);
1.17 paf 283: break;
284: }
285:
1.18 paf 286: case OP_GET_ELEMENT__WRITE:
1.17 paf 287: {
1.297 paf 288: const String& name=stack.pop().string(); debug_name=&name;
289: Value& ncontext=stack.pop().value();
290: Value& value=get_element(ncontext, name, false);
291: write_assign_lang(value);
1.17 paf 292: break;
293: }
294:
1.32 paf 295:
1.226 paf 296: case OP_OBJECT_POOL:
1.17 paf 297: {
1.297 paf 298: ArrayOperation& local_ops=*i.next().ops;
1.226 paf 299:
1.257 paf 300: WContext *saved_wcontext=wcontext;
1.297 paf 301: String::Language saved_lang=flang;
302: flang=String::L_PASS_APPENDED;
303: WWrapper local(0/*empty*/, wcontext);
1.226 paf 304: wcontext=&local;
305:
1.297 paf 306: execute(local_ops);
1.226 paf 307:
1.297 paf 308: stack.push(wcontext->result().as_value());
1.257 paf 309: flang=saved_lang;
310: wcontext=saved_wcontext;
1.13 paf 311: break;
1.15 paf 312: }
1.13 paf 313:
1.226 paf 314: case OP_STRING_POOL:
1.49 paf 315: {
1.297 paf 316: ArrayOperation& local_ops=*i.next().ops;
1.226 paf 317:
1.257 paf 318: WContext *saved_wcontext=wcontext;
1.297 paf 319: WWrapper local(0 /*empty*/, wcontext);
1.226 paf 320: wcontext=&local;
321:
1.297 paf 322: execute(local_ops);
1.226 paf 323:
1.297 paf 324: Value* value;
1.49 paf 325: // from "$a $b" part of expression taking only string value,
326: // ignoring any other content of wcontext
1.297 paf 327: if(const String* string=wcontext->get_string())
328: value=new VString(*string);
1.80 paf 329: else
1.297 paf 330: value=new VVoid;
331: stack.push(*value);
332:
1.257 paf 333: wcontext=saved_wcontext;
1.49 paf 334: break;
335: }
336:
1.51 paf 337: // CALL
1.237 paf 338: case OP_STORE_PARAM:
1.28 paf 339: {
1.297 paf 340: Value& value=stack.pop().value();
1.299 paf 341: VMethodFrame& frame=stack.top_value().method_frame();
1.297 paf 342: // this op is executed from CALL local_ops only, so may skip the check "method_frame_to_fill==0"
343: frame.store_param(value);
1.28 paf 344: break;
345: }
1.237 paf 346: case OP_CURLY_CODE__STORE_PARAM:
347: case OP_EXPR_CODE__STORE_PARAM:
1.28 paf 348: {
1.237 paf 349: // code
1.297 paf 350: ArrayOperation& local_ops=*i.next().ops;
1.299 paf 351: VMethodFrame& frame=stack.top_value().method_frame();
1.237 paf 352: #ifdef DEBUG_EXECUTE
1.297 paf 353: debug_printf(sapi_info, " (%d)\n", local_ops.count());
354: debug_dump(sapi_info, 1, local_ops);
1.237 paf 355: #endif
356: // when they evaluate expression parameter,
357: // the object expression result
358: // does not need to be written into calling frame
359: // it must go into any expressions using that parameter
360: // hence, we zero junction.wcontext here, and later
361: // in .process we would test that field
362: // in decision "which wwrapper to use"
1.312 paf 363: Value& value=*new VJunction(
1.297 paf 364: get_self(), 0,
1.257 paf 365: method_frame,
1.237 paf 366: rcontext,
1.297 paf 367: opcode==OP_EXPR_CODE__STORE_PARAM?0:wcontext,
1.312 paf 368: &local_ops);
1.237 paf 369: // store param
370: // this op is executed from CALL local_ops only, so can not check method_frame_to_fill==0
1.297 paf 371: frame.store_param(value);
1.29 paf 372: break;
373: }
374:
1.186 parser 375: case OP_PREPARE_TO_CONSTRUCT_OBJECT:
376: {
1.200 paf 377: wcontext->set_constructing(true);
1.186 parser 378: break;
379: }
1.219 paf 380:
381: case OP_PREPARE_TO_EXPRESSION:
382: {
383: wcontext->set_in_expression(true);
384: break;
385: }
386:
1.186 parser 387: case OP_CALL:
1.232 paf 388: case OP_CALL__WRITE:
1.29 paf 389: {
1.297 paf 390: //is_debug_junction=true;
391: ArrayOperation* local_ops=i.next().ops;
1.157 parser 392: #ifdef DEBUG_EXECUTE
1.297 paf 393: debug_printf(sapi_info, " (%d)\n", local_ops?local_ops->count():0);
394: if(local_ops)
395: debug_dump(sapi_info, 1, *local_ops);
1.237 paf 396:
1.297 paf 397: debug_printf(sapi_info, "->\n");
1.157 parser 398: #endif
1.297 paf 399: Value& value=stack.pop().value();
1.237 paf 400:
1.297 paf 401: Junction* junction=value.get_junction();
402: if(!junction) {
403: if(value.is("void"))
1.316 misha 404: throw Exception(PARSER_RUNTIME,
1.297 paf 405: 0,
406: "undefined method");
407: else
1.316 misha 408: throw Exception(PARSER_RUNTIME,
1.297 paf 409: 0,
410: "is '%s', not a method or junction, can not call it",
411: value.type());
412: }
1.282 paf 413: /* no check needed, code compiled the way that that's impossible
1.276 paf 414: // check:
415: // that this is method-junction, not a code-junction
1.278 paf 416: // [disabling these contstructions:]
417: // $junction{code}
418: // ^junction[]
1.276 paf 419: if(!junction->method)
1.316 misha 420: throw Exception(PARSER_RUNTIME,
1.297 paf 421: "is '%s', it is code junction, can not call it",
422: value.type());
1.282 paf 423: */
1.237 paf 424:
1.319 ! misha 425: if(junction->method->all_vars_local){
! 426: VMethodFrameLocal frame(*junction, method_frame);
! 427: if(local_ops){ // store param code goes here
! 428: stack.push(frame); // argument for *STORE_PARAM ops
! 429: execute(*local_ops);
! 430: stack.pop().value();
! 431: }
! 432: WContext* result_wcontext=op_call(frame);
! 433: if(opcode==OP_CALL__WRITE) {
! 434: write_assign_lang(result_wcontext->result());
! 435: } else { // OP_CALL
! 436: stack.push(result_wcontext->result().as_value());
! 437: }
! 438: } else {
! 439: VMethodFrameGlobal frame(*junction, method_frame);
! 440: if(local_ops){ // store param code goes here
! 441: stack.push(frame); // argument for *STORE_PARAM ops
! 442: execute(*local_ops);
! 443: stack.pop().value();
! 444: }
! 445: WContext* result_wcontext=op_call(frame);
! 446: if(opcode==OP_CALL__WRITE) {
! 447: write_assign_lang(result_wcontext->result());
! 448: } else { // OP_CALL
! 449: stack.push(result_wcontext->result().as_value());
! 450: }
1.237 paf 451: }
1.220 paf 452:
1.157 parser 453: #ifdef DEBUG_EXECUTE
1.297 paf 454: debug_printf(sapi_info, "<-returned");
1.157 parser 455: #endif
1.297 paf 456: //is_debug_junction=false;
1.49 paf 457: break;
458: }
459:
1.55 paf 460: // expression ops: unary
461: case OP_NEG:
462: {
1.297 paf 463: Value& a=stack.pop().value();
464: Value& value=*new VDouble(-a.as_double());
465: stack.push(value);
1.55 paf 466: break;
467: }
468: case OP_INV:
469: {
1.297 paf 470: Value& a=stack.pop().value();
471: Value& value=*new VDouble(~a.as_int());
472: stack.push(value);
1.55 paf 473: break;
474: }
475: case OP_NOT:
476: {
1.297 paf 477: Value& a=stack.pop().value();
478: Value& value=*new VBool(!a.as_bool());
479: stack.push(value);
1.55 paf 480: break;
481: }
1.62 paf 482: case OP_DEF:
483: {
1.297 paf 484: Value& a=stack.pop().value();
485: Value& value=*new VBool(a.is_defined());
486: stack.push(value);
1.62 paf 487: break;
488: }
489: case OP_IN:
490: {
1.297 paf 491: Value& a=stack.pop().value();
492: const String& path=a.as_string();
493: Value& value=*new VBool(request_info.uri && *request_info.uri && path.this_starts(request_info.uri));
494: stack.push(value);
1.62 paf 495: break;
496: }
497: case OP_FEXISTS:
498: {
1.297 paf 499: Value& a=stack.pop().value();
1.314 paf 500: Value& value=*new VBool(file_exist(absolute(a.as_string())));
1.297 paf 501: stack.push(value);
1.148 paf 502: break;
503: }
504: case OP_DEXISTS:
505: {
1.297 paf 506: Value& a=stack.pop().value();
1.314 paf 507: Value& value=*new VBool(dir_exists(absolute(a.as_string())));
1.297 paf 508: stack.push(value);
1.62 paf 509: break;
510: }
1.55 paf 511:
512: // expression ops: binary
513: case OP_SUB:
1.53 paf 514: {
1.297 paf 515: Value& b=stack.pop().value(); Value& a=stack.pop().value();
516: Value& value=*new VDouble(a.as_double() - b.as_double());
517: stack.push(value);
1.53 paf 518: break;
519: }
1.55 paf 520: case OP_ADD:
1.53 paf 521: {
1.297 paf 522: Value& b=stack.pop().value(); Value& a=stack.pop().value();
523: Value& value=*new VDouble(a.as_double() + b.as_double());
524: stack.push(value);
1.53 paf 525: break;
526: }
1.49 paf 527: case OP_MUL:
528: {
1.297 paf 529: Value& b=stack.pop().value(); Value& a=stack.pop().value();
530: Value& value=*new VDouble(a.as_double() * b.as_double());
531: stack.push(value);
1.53 paf 532: break;
533: }
534: case OP_DIV:
535: {
1.297 paf 536: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 537:
1.297 paf 538: double a_double=a.as_double();
539: double b_double=b.as_double();
1.170 parser 540:
1.171 parser 541: if(b_double == 0) {
1.297 paf 542: //const String* problem_source=b.as_string();
1.223 paf 543: throw Exception("number.zerodivision",
1.297 paf 544: 0, //problem_source,
1.170 parser 545: "Division by zero");
1.171 parser 546: }
1.170 parser 547:
1.297 paf 548: Value& value=*new VDouble(a_double / b_double);
549: stack.push(value);
1.54 paf 550: break;
551: }
1.55 paf 552: case OP_MOD:
553: {
1.297 paf 554: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 555:
1.297 paf 556: double a_double=a.as_double();
557: double b_double=b.as_double();
1.170 parser 558:
1.173 parser 559: if(b_double == 0) {
1.297 paf 560: //const String* problem_source=b.as_string();
1.223 paf 561: throw Exception("number.zerodivision",
1.297 paf 562: 0, //problem_source,
1.170 parser 563: "Modulus by zero");
1.171 parser 564: }
1.170 parser 565:
1.297 paf 566: Value& value=*new VDouble(fmod(a_double, b_double));
567: stack.push(value);
1.201 paf 568: break;
569: }
570: case OP_INTDIV:
571: {
1.297 paf 572: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.201 paf 573:
1.297 paf 574: int a_int=a.as_int();
575: int b_int=b.as_int();
1.201 paf 576:
577: if(b_int == 0) {
1.297 paf 578: //const String* problem_source=b.as_string();
1.223 paf 579: throw Exception("number.zerodivision",
1.297 paf 580: 0, //problem_source,
1.201 paf 581: "Division by zero");
582: }
583:
1.297 paf 584: Value& value=*new VInt(a_int / b_int);
585: stack.push(value);
1.55 paf 586: break;
587: }
1.274 paf 588: case OP_BIN_SL:
589: {
1.297 paf 590: Value& b=stack.pop().value(); Value& a=stack.pop().value();
591: Value& value=*new VInt(
592: a.as_int() <<
593: b.as_int());
594: stack.push(value);
1.274 paf 595: break;
596: }
597: case OP_BIN_SR:
598: {
1.297 paf 599: Value& b=stack.pop().value(); Value& a=stack.pop().value();
600: Value& value=*new VInt(
601: a.as_int() >>
602: b.as_int());
603: stack.push(value);
1.274 paf 604: break;
605: }
1.55 paf 606: case OP_BIN_AND:
1.54 paf 607: {
1.297 paf 608: Value& b=stack.pop().value(); Value& a=stack.pop().value();
609: Value& value=*new VInt(
610: a.as_int() &
611: b.as_int());
612: stack.push(value);
1.54 paf 613: break;
614: }
1.55 paf 615: case OP_BIN_OR:
1.54 paf 616: {
1.297 paf 617: Value& b=stack.pop().value(); Value& a=stack.pop().value();
618: Value& value=*new VInt(
619: a.as_int() |
620: b.as_int());
621: stack.push(value);
1.55 paf 622: break;
623: }
1.56 paf 624: case OP_BIN_XOR:
625: {
1.297 paf 626: Value& b=stack.pop().value(); Value& a=stack.pop().value();
627: Value& value=*new VInt(
628: a.as_int() ^
629: b.as_int());
630: stack.push(value);
1.56 paf 631: break;
632: }
1.55 paf 633: case OP_LOG_AND:
634: {
1.297 paf 635: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 636: bool result;
1.297 paf 637: if(a.as_bool()) {
638: execute(local_ops);
639: Value& b=stack.pop().value();
640: result=b.as_bool();
1.209 paf 641: } else
1.263 paf 642: result=false;
1.297 paf 643: Value& value=*new VBool(result);
644: stack.push(value);
1.55 paf 645: break;
646: }
647: case OP_LOG_OR:
648: {
1.297 paf 649: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 650: bool result;
1.297 paf 651: if(a.as_bool())
1.263 paf 652: result=true;
1.209 paf 653: else {
1.297 paf 654: execute(local_ops);
655: Value& b=stack.pop().value();
656: result=b.as_bool();
1.209 paf 657: }
1.297 paf 658: Value& value=*new VBool(result);
659: stack.push(value);
1.56 paf 660: break;
661: }
662: case OP_LOG_XOR:
663: {
1.297 paf 664: Value& b=stack.pop().value(); Value& a=stack.pop().value();
665: Value& value=*new VBool(a.as_bool() ^ b.as_bool());
666: stack.push(value);
1.55 paf 667: break;
668: }
669: case OP_NUM_LT:
670: {
1.297 paf 671: volatile double b_double=stack.pop().value().as_double();
672: volatile double a_double=stack.pop().value().as_double();
673: Value& value=*new VBool(a_double<b_double);
674: stack.push(value);
1.55 paf 675: break;
676: }
677: case OP_NUM_GT:
678: {
1.297 paf 679: volatile double b_double=stack.pop().value().as_double();
680: volatile double a_double=stack.pop().value().as_double();
681: Value& value=*new VBool(a_double>b_double);
682: stack.push(value);
1.55 paf 683: break;
684: }
685: case OP_NUM_LE:
686: {
1.297 paf 687: volatile double b_double=stack.pop().value().as_double();
688: volatile double a_double=stack.pop().value().as_double();
689: Value& value=*new VBool(a_double<=b_double);
690: stack.push(value);
1.55 paf 691: break;
692: }
693: case OP_NUM_GE:
694: {
1.297 paf 695: volatile double b_double=stack.pop().value().as_double();
696: volatile double a_double=stack.pop().value().as_double();
697: Value& value=*new VBool(a_double>=b_double);
698: stack.push(value);
1.55 paf 699: break;
700: }
701: case OP_NUM_EQ:
702: {
1.297 paf 703: volatile double b_double=stack.pop().value().as_double();
704: volatile double a_double=stack.pop().value().as_double();
705: Value& value=*new VBool(a_double==b_double);
706: stack.push(value);
1.55 paf 707: break;
708: }
709: case OP_NUM_NE:
710: {
1.297 paf 711: volatile double b_double=stack.pop().value().as_double();
712: volatile double a_double=stack.pop().value().as_double();
713: Value& value=*new VBool(a_double!=b_double);
714: stack.push(value);
1.54 paf 715: break;
716: }
1.58 paf 717: case OP_STR_LT:
718: {
1.297 paf 719: Value& b=stack.pop().value(); Value& a=stack.pop().value();
720: Value& value=*new VBool(a.as_string() < b.as_string());
721: stack.push(value);
1.58 paf 722: break;
723: }
724: case OP_STR_GT:
725: {
1.297 paf 726: Value& b=stack.pop().value(); Value& a=stack.pop().value();
727: Value& value=*new VBool(a.as_string() > b.as_string());
728: stack.push(value);
1.58 paf 729: break;
730: }
1.55 paf 731: case OP_STR_LE:
1.58 paf 732: {
1.297 paf 733: Value& b=stack.pop().value(); Value& a=stack.pop().value();
734: Value& value=*new VBool(a.as_string() <= b.as_string());
735: stack.push(value);
1.58 paf 736: break;
737: }
1.55 paf 738: case OP_STR_GE:
1.54 paf 739: {
1.297 paf 740: Value& b=stack.pop().value(); Value& a=stack.pop().value();
741: Value& value=*new VBool(a.as_string() >= b.as_string());
742: stack.push(value);
1.58 paf 743: break;
744: }
745: case OP_STR_EQ:
746: {
1.297 paf 747: Value& b=stack.pop().value(); Value& a=stack.pop().value();
748: Value& value=*new VBool(a.as_string() == b.as_string());
749: stack.push(value);
1.58 paf 750: break;
751: }
752: case OP_STR_NE:
753: {
1.297 paf 754: Value& b=stack.pop().value(); Value& a=stack.pop().value();
755: Value& value=*new VBool(a.as_string() != b.as_string());
756: stack.push(value);
1.103 paf 757: break;
758: }
759: case OP_IS:
760: {
1.297 paf 761: Value& b=stack.pop().value(); Value& a=stack.pop().value();
762: Value& value=*new VBool(a.is(b.as_string().cstr()));
763: stack.push(value);
1.28 paf 764: break;
765: }
766:
1.11 paf 767: default:
1.223 paf 768: throw Exception(0,
1.67 paf 769: 0,
1.297 paf 770: "invalid opcode %d", opcode);
1.11 paf 771: }
772: }
1.306 paf 773: } catch(const Exception&) {
1.297 paf 774: // record it to stack trace
1.301 paf 775: if(debug_name)
776: exception_trace.push(Trace(debug_name, debug_origin));
1.297 paf 777: rethrow;
778: }
1.1 paf 779: }
1.17 paf 780:
1.319 ! misha 781: WContext* Request::op_call(VMethodFrame& frame){
! 782: frame.fill_unspecified_params();
! 783: VMethodFrame *saved_method_frame=method_frame;
! 784: Value* saved_rcontext=rcontext;
! 785: WContext *saved_wcontext=wcontext;
! 786:
! 787: VStateless_class& called_class=*frame.junction.self.get_class();
! 788: Value* new_self;
! 789: if(wcontext->get_constructing()) {
! 790: wcontext->set_constructing(false);
! 791: new_self=&get_self();
! 792: if(frame.junction.method->call_type!=Method::CT_STATIC) {
! 793: // this is a constructor call
! 794: HashStringValue& new_object_fields=*new HashStringValue();
! 795: if(Value* value=called_class.create_new_value(fpool, new_object_fields)) {
! 796: // some stateless_class creatable derivates
! 797: new_self=value;
! 798: } else
! 799: throw Exception(PARSER_RUNTIME,
! 800: 0, //&frame.name(),
! 801: "is not a constructor, system class '%s' can be constructed only implicitly",
! 802: called_class.name().cstr());
! 803:
! 804: frame.write(*new_self,
! 805: String::L_CLEAN // not used, always an object, not string
! 806: );
! 807: } else
! 808: throw Exception(PARSER_RUNTIME,
! 809: 0, //&frame.name(),
! 810: "method is static and can not be used as constructor");
! 811: } else
! 812: new_self=&frame.junction.self;
! 813:
! 814: frame.set_self(*new_self);
! 815:
! 816: // see OP_PREPARE_TO_EXPRESSION
! 817: frame.set_in_expression(wcontext->get_in_expression());
! 818:
! 819: rcontext=wcontext=&frame;
! 820: {
! 821: const Method& method=*frame.junction.method;
! 822: Method::Call_type call_type=&called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC;
! 823: if(
! 824: method.call_type==Method::CT_ANY ||
! 825: method.call_type==call_type) { // allowed call type?
! 826: method_frame=&frame;
! 827: if(method.native_code) { // native code?
! 828: method.check_actual_numbered_params(
! 829: frame.junction.self,
! 830: /*frame.name(), */frame.numbered_params());
! 831: method.native_code(
! 832: *this,
! 833: *frame.numbered_params()); // execute it
! 834: } else // parser code, execute it
! 835: recoursion_checked_execute(*method.parser_code);
! 836: } else
! 837: throw Exception(PARSER_RUNTIME,
! 838: 0, //&frame.name(),
! 839: "is not allowed to be called %s",
! 840: call_type==Method::CT_STATIC?"statically":"dynamically");
! 841: }
! 842:
! 843: WContext *result_wcontext=wcontext;
! 844: // StringOrValue result=wcontext->result();
! 845:
! 846: wcontext=saved_wcontext;
! 847: rcontext=saved_rcontext;
! 848: method_frame=saved_method_frame;
! 849:
! 850: return result_wcontext;
! 851: }
! 852:
! 853:
1.292 paf 854: /**
855: @todo cache|prepare junctions
856: @bug ^superbase:method would dynamically call ^base:method if there is any
857: */
1.297 paf 858: Value& Request::get_element(Value& ncontext, const String& name, bool can_call_operator) {
859: Value* value=0;
1.249 paf 860: if(can_call_operator) {
1.297 paf 861: if(Method* method=main_class.get_method(name)) // looking operator of that name FIRST
1.312 paf 862: value=new VJunction(main_class, method);
1.249 paf 863: }
864: if(!value) {
865: if(!wcontext->get_constructing() // not constructing
866: && wcontext->get_somebody_entered_some_class() ) // ^class:method
1.297 paf 867: if(VStateless_class *called_class=ncontext.get_class())
1.249 paf 868: if(VStateless_class *read_class=rcontext->get_class())
869: if(read_class->derived_from(*called_class)) // current derived from called
1.297 paf 870: if(Value* base=get_self().base()) { // doing DYNAMIC call
1.290 paf 871: Temp_derived temp_derived(*base, 0); // temporarily prevent go-back-down virtual calls
872: value=base->get_element(name, *base, false); // virtual-up lookup starting from parent
1.289 paf 873: goto value_ready;
1.249 paf 874: }
875: }
1.216 paf 876: if(!value)
1.297 paf 877: value=ncontext.get_element(name, ncontext, false);
1.291 paf 878:
879: if(value && wcontext->get_constructing())
1.297 paf 880: if(Junction* junction=value->get_junction()) {
881: if(junction->self.get_class()!=&ncontext)
1.316 misha 882: throw Exception(PARSER_RUNTIME,
1.291 paf 883: &name,
1.297 paf 884: "constructor must be declared in class '%s'",
885: ncontext.get_class()->name_cstr());
1.291 paf 886: }
1.249 paf 887:
1.289 paf 888: value_ready:
1.284 paf 889: if(value)
1.294 paf 890: value=&process_to_value(*value); // process possible code-junction
1.284 paf 891: else
1.297 paf 892: value=new VVoid;
1.63 paf 893:
1.297 paf 894: return *value;
1.309 paf 895: }
896:
897: void Request::put_element(Value& ncontext, const String& name, Value& value) {
898: // put_element can return property-setting-junction
1.312 paf 899: if(const VJunction* vjunction=ncontext.put_element(ncontext, name, &value, false))
900: if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) {
901: const Junction& junction=vjunction->junction();
1.309 paf 902: // process it
1.312 paf 903: ArrayString* params_names=junction.method->params_names;
1.309 paf 904: int param_count=params_names? params_names->count(): 0;
905: if(param_count!=1)
1.316 misha 906: throw Exception(PARSER_RUNTIME,
1.309 paf 907: 0,
908: "setter method must have ONE parameter (has %d parameters)", param_count);
909:
1.319 ! misha 910: VMethodFrameGlobal frame(junction, method_frame/*caller*/);
1.309 paf 911: frame.store_param(value);
912:
913: frame.set_self(frame.junction.self);
914:
915: VMethodFrame *saved_method_frame=method_frame;
916: Value* saved_rcontext=rcontext;
917: WContext *saved_wcontext=wcontext;
918:
919: rcontext=wcontext=&frame;
920: method_frame=&frame;
921:
1.311 paf 922: // prevent non-string writes for better error reporting [setters are not expected to return anything]
1.309 paf 923: wcontext->write(*method_frame);
924:
925: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
926: // we don't need it StringOrValue result=wcontext->result();
927:
928: method_frame=saved_method_frame;
929: wcontext=saved_wcontext;
930: rcontext=saved_rcontext;
931: }
1.34 paf 932: }
1.70 paf 933:
1.162 parser 934: /** @param intercept_string
1.116 paf 935: - true:
936: they want result=string value,
937: possible object result goes to wcontext
938: - false:
939: they want any result[string|object]
940: nothing goes to wcontext.
1.125 paf 941: used in @c (expression) params evaluation
1.224 paf 942:
943: using the fact it's either string_ or value_ result requested to speed up checkes
1.116 paf 944: */
1.229 paf 945: StringOrValue Request::process(Value& input_value, bool intercept_string) {
1.297 paf 946: Junction* junction=input_value.get_junction();
1.307 paf 947: if(junction) {
948: if(junction->is_getter) { // is it a getter-junction?
949: // process it
950:
951: if(junction->method->params_names)
1.316 misha 952: throw Exception(PARSER_RUNTIME,
1.307 paf 953: 0,
954: "getter method must have no parameters");
955:
1.319 ! misha 956: VMethodFrameGlobal frame(*junction, method_frame/*caller*/);
1.317 misha 957:
1.307 paf 958: frame.set_self(frame.junction.self);
959:
960: VMethodFrame *saved_method_frame=method_frame;
961: Value* saved_rcontext=rcontext;
962: WContext *saved_wcontext=wcontext;
963:
964: rcontext=wcontext=&frame;
965: method_frame=&frame;
966:
967: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
968: StringOrValue result=wcontext->result();
969:
970: method_frame=saved_method_frame;
971: wcontext=saved_wcontext;
972: rcontext=saved_rcontext;
973:
974: return result;
975: }
976:
977: if(junction->code) { // is it a code-junction?
978: // process it
979: StringOrValue result;
1.157 parser 980: #ifdef DEBUG_EXECUTE
1.307 paf 981: debug_printf(sapi_info, "ja->\n");
1.157 parser 982: #endif
1.238 paf 983:
1.307 paf 984: if(!junction->method_frame)
1.316 misha 985: throw Exception(PARSER_RUNTIME,
1.240 paf 986: 0,
987: "junction used outside of context");
988:
1.307 paf 989: VMethodFrame *saved_method_frame=method_frame;
990: Value* saved_rcontext=rcontext;
991: WContext *saved_wcontext=wcontext;
992:
993: method_frame=junction->method_frame;
994: rcontext=junction->rcontext;
995:
996: // for expression method params
997: // wcontext is set 0
998: // using the fact in decision "which wwrapper to use"
999: bool using_code_frame=intercept_string && junction->wcontext;
1000: if(using_code_frame) {
1.318 misha 1001: // almost plain wwrapper about junction wcontext
1002:
1003: VCodeFrame local(*junction->wcontext);
1.307 paf 1004: wcontext=&local;
1005:
1006: // execute it
1007: recoursion_checked_execute(*junction->code);
1008:
1009: // CodeFrame soul:
1.318 misha 1010: result=wcontext->result();
1.307 paf 1011: } else {
1012: // plain wwrapper
1013: WWrapper local(0/*empty*/, wcontext);
1014: wcontext=&local;
1015:
1016: // execute it
1017: recoursion_checked_execute(*junction->code);
1018:
1019: result=wcontext->result();
1020: }
1021:
1022: wcontext=saved_wcontext;
1023: rcontext=saved_rcontext;
1024: method_frame=saved_method_frame;
1.207 paf 1025:
1.157 parser 1026: #ifdef DEBUG_EXECUTE
1.307 paf 1027: debug_printf(sapi_info, "<-ja returned");
1.157 parser 1028: #endif
1.307 paf 1029: return result;
1030: }
1031:
1032: // it is then method-junction, do not explode it
1033: // just return it as we do for usual objects
1034: }
1035:
1036: return input_value;
1.85 paf 1037: }
1038:
1.298 paf 1039: StringOrValue Request::execute_method(VMethodFrame& amethod_frame, const Method& method) {
1.257 paf 1040: VMethodFrame *saved_method_frame=method_frame;
1.297 paf 1041: Value* saved_rcontext=rcontext;
1.257 paf 1042: WContext *saved_wcontext=wcontext;
1.99 paf 1043:
1044: // initialize contexts
1.286 paf 1045: rcontext=wcontext=method_frame=&amethod_frame;
1.99 paf 1046:
1047: // execute!
1048: execute(*method.parser_code);
1049:
1050: // result
1.298 paf 1051: StringOrValue result=wcontext->result();
1.208 paf 1052:
1.257 paf 1053: wcontext=saved_wcontext;
1054: rcontext=saved_rcontext;
1055: method_frame=saved_method_frame;
1.242 paf 1056:
1057: // return
1058: return result;
1.208 paf 1059: }
1060:
1.297 paf 1061: const String* Request::execute_method(Value& aself,
1062: const Method& method, VString* optional_param,
1063: bool do_return_string) {
1.317 misha 1064:
1.257 paf 1065: VMethodFrame *saved_method_frame=method_frame;
1.297 paf 1066: Value* saved_rcontext=rcontext;
1.257 paf 1067: WContext *saved_wcontext=wcontext;
1.208 paf 1068:
1.307 paf 1069: Junction local_junction(aself, &method);
1.319 ! misha 1070: VMethodFrameGlobal local_frame(local_junction, method_frame/*caller*/);
1.242 paf 1071: if(optional_param && local_frame.can_store_param()) {
1.297 paf 1072: local_frame.store_param(*optional_param);
1.242 paf 1073: local_frame.fill_unspecified_params();
1074: }
1.285 paf 1075: local_frame.set_self(aself);
1.257 paf 1076: rcontext=wcontext=method_frame=&local_frame;
1.246 paf 1077:
1078: // prevent non-string writes for better error reporting
1.297 paf 1079: if(do_return_string)
1.246 paf 1080: wcontext->write(local_frame);
1.208 paf 1081:
1082: // execute!
1083: execute(*method.parser_code);
1084:
1085: // result
1.297 paf 1086: const String* result=0;
1087: if(do_return_string)
1088: result=&wcontext->result().as_string();
1.99 paf 1089:
1.257 paf 1090: wcontext=saved_wcontext;
1091: rcontext=saved_rcontext;
1092: method_frame=saved_method_frame;
1.297 paf 1093:
1094: return result;
1.242 paf 1095: }
1096:
1.297 paf 1097: Request::Execute_nonvirtual_method_result
1098: Request::execute_nonvirtual_method(VStateless_class& aclass,
1.317 misha 1099: const String& method_name,
1100: VString* optional_param,
1.297 paf 1101: bool do_return_string) {
1102: Execute_nonvirtual_method_result result;
1103: result.method=aclass.get_method(method_name);
1104: if(result.method)
1.317 misha 1105: result.string=execute_method(aclass, *result.method, optional_param, do_return_string);
1.297 paf 1106: return result;
1.99 paf 1107: }
1108:
1.297 paf 1109: const String* Request::execute_virtual_method(Value& aself,
1110: const String& method_name) {
1111: if(Value* value=aself.get_element(method_name, aself, false))
1112: if(Junction* junction=value->get_junction())
1113: if(const Method *method=junction->method)
1114: return execute_method(aself, *method, 0/*no params*/, true);
1.188 parser 1115:
1.176 parser 1116: return 0;
1117: }