|
|
1.117 paf 1: /** @file
1.118 paf 2: Parser: executor part of request class.
3:
1.324 misha 4: Copyright (c) 2001-2009 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.334 ! misha 8: static const char * const IDENT_EXECUTE_C="$Date: 2009-05-13 07:35:41 $";
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.321 misha 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.157 parser 27:
28: #ifdef DEBUG_EXECUTE
1.1 paf 29: char *opcode_name[]={
1.49 paf 30: // literals
1.109 paf 31: "VALUE", "CURLY_CODE__STORE_PARAM", "EXPR_CODE__STORE_PARAM",
1.209 paf 32: "NESTED_CODE",
1.49 paf 33:
34: // actions
1.187 parser 35: "WITH_ROOT", "WITH_SELF", "WITH_READ", "WITH_WRITE",
1.328 misha 36: #ifdef OPTIMIZE_BYTECODE_GET_CLASS
37: "VALUE__GET_CLASS",
38: #else
1.66 paf 39: "GET_CLASS",
1.328 misha 40: #endif
1.182 parser 41: "CONSTRUCT_VALUE", "CONSTRUCT_EXPR", "CURLY_CODE__CONSTRUCT",
1.108 paf 42: "WRITE_VALUE", "WRITE_EXPR_RESULT", "STRING__WRITE",
1.328 misha 43: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
44: "VALUE__GET_ELEMENT_OR_OPERATOR",
45: #else
46: "GET_ELEMENT_OR_OPERATOR",
47: #endif
48: "GET_ELEMENT",
1.334 ! misha 49: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT_FIELD
! 50: "GET_ELEMENT_FIELD",
! 51: "GET_ELEMENT_FIELD__WRITE",
! 52: #endif
1.328 misha 53: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
54: "VALUE__GET_ELEMENT",
55: #endif
56: "GET_ELEMENT__WRITE",
57: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
58: "VALUE__GET_ELEMENT__WRITE",
59: #endif
1.232 paf 60: "OBJECT_POOL", "STRING_POOL",
61: "PREPARE_TO_CONSTRUCT_OBJECT", "PREPARE_TO_EXPRESSION",
62: "CALL", "CALL__WRITE",
1.49 paf 63:
64: // expression ops: unary
1.148 paf 65: "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS",
1.49 paf 66: // expression ops: binary
1.201 paf 67: "SUB", "ADD", "MUL", "DIV", "MOD", "INTDIV",
1.275 paf 68: "BIN_SL", "BIN_SR",
1.56 paf 69: "BIN_AND", "BIN_OR", "BIN_XOR",
70: "LOG_AND", "LOG_OR", "LOG_XOR",
1.49 paf 71: "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE",
1.103 paf 72: "STR_LT", "STR_GT", "STR_LE", "STR_GE", "STR_EQ", "STR_NE",
73: "IS"
1.1 paf 74: };
75:
1.297 paf 76: void va_debug_printf(SAPI_Info& sapi_info, const char* fmt,va_list args) {
1.127 paf 77: char buf[MAX_STRING];
78: vsnprintf(buf, MAX_STRING, fmt, args);
1.297 paf 79: SAPI::log(sapi_info, "%s", buf);
1.107 paf 80: }
81:
1.297 paf 82: void debug_printf(SAPI_Info& sapi_info, const char* fmt, ...) {
1.334 ! misha 83: va_list args;
! 84: va_start(args, fmt);
! 85: va_debug_printf(sapi_info, fmt, args);
! 86: va_end(args);
1.105 paf 87: }
88:
1.297 paf 89: void debug_dump(SAPI_Info& sapi_info, int level, ArrayOperation& ops) {
90: Array_iterator<Operation> i(ops);
1.190 parser 91: while(i.has_next()) {
1.323 misha 92: OP::OPCODE opcode=i.next().code;
1.1 paf 93:
1.334 ! misha 94: #if defined(OPTIMIZE_BYTECODE_GET_ELEMENT_FIELD) && defined(OPTIMIZE_BYTECODE_USE_TWO_OPERANDS_INSTRUCTIONS)
! 95: if(
! 96: opcode==OP::OP_GET_ELEMENT_FIELD
! 97: || opcode==OP::OP_GET_ELEMENT_FIELD__WRITE
! 98: ){
! 99: i.next(); // skip origin
! 100: Value& value1=*i.next().value;
! 101: i.next(); // skip origin
! 102: Value& value2=*i.next().value;
! 103: debug_printf(sapi_info,
! 104: "%*s%s"
! 105: " \"%s\" \"%s\"",
! 106: level*4, "", opcode_name[opcode],
! 107: value1.get_string()->cstr(), value2.get_string()->cstr());
! 108: continue;
! 109: }
! 110: #endif
1.328 misha 111: if(
112: opcode==OP::OP_VALUE
113: || opcode==OP::OP_STRING__WRITE
114: #ifdef OPTIMIZE_BYTECODE_GET_CLASS
115: || opcode==OP::OP_VALUE__GET_CLASS
116: #endif
117: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
118: || opcode==OP::OP_VALUE__GET_ELEMENT
119: || opcode==OP::OP_VALUE__GET_ELEMENT__WRITE
120: || opcode==OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR
121: #endif
1.334 ! misha 122: #if defined(OPTIMIZE_BYTECODE_GET_ELEMENT_FIELD) && !defined(OPTIMIZE_BYTECODE_USE_TWO_OPERANDS_INSTRUCTIONS)
! 123: || opcode==OP::OP_GET_ELEMENT_FIELD
! 124: || opcode==OP::OP_GET_ELEMENT_FIELD__WRITE
! 125: #endif
1.328 misha 126: ) {
1.297 paf 127: Operation::Origin origin=i.next().origin;
128: Value& value=*i.next().value;
129: debug_printf(sapi_info,
1.133 paf 130: "%*s%s"
131: " \"%s\" %s",
1.297 paf 132: level*4, "", opcode_name[opcode],
133: value.get_string()->cstr(), value.type());
1.133 paf 134: continue;
1.15 paf 135: }
1.297 paf 136: debug_printf(sapi_info, "%*s%s", level*4, "", opcode_name[opcode]);
1.1 paf 137:
1.297 paf 138: switch(opcode) {
1.323 misha 139: case OP::OP_CURLY_CODE__STORE_PARAM:
140: case OP::OP_EXPR_CODE__STORE_PARAM:
141: case OP::OP_CURLY_CODE__CONSTRUCT:
142: case OP::OP_NESTED_CODE:
143: case OP::OP_OBJECT_POOL:
144: case OP::OP_STRING_POOL:
145: case OP::OP_CALL:
146: case OP::OP_CALL__WRITE:
1.297 paf 147: if(ArrayOperation* local_ops=i.next().ops)
148: debug_dump(sapi_info, level+1, *local_ops);
1.1 paf 149: }
150: }
151: }
1.157 parser 152: #endif
1.1 paf 153:
1.297 paf 154: // Request
155:
156: void Request::execute(ArrayOperation& ops) {
157: register Stack<StackItem>& stack=this->stack; // helps a lot on MSVC: 'esi'
1.159 parser 158:
1.304 paf 159: const String* debug_name=0; Operation::Origin debug_origin={0, 0, 0};
1.297 paf 160: try{
1.157 parser 161: #ifdef DEBUG_EXECUTE
1.297 paf 162: debug_printf(sapi_info, "source----------------------------\n");
163: debug_dump(sapi_info, 0, ops);
164: debug_printf(sapi_info, "execution-------------------------\n");
1.157 parser 165: #endif
1.297 paf 166: for(Array_iterator<Operation> i(ops); i.has_next(); ) {
1.322 misha 167: OP::OPCODE opcode=i.next().code;
1.293 paf 168:
1.157 parser 169: #ifdef DEBUG_EXECUTE
1.297 paf 170: debug_printf(sapi_info, "%d:%s", stack.top_index()+1, opcode_name[opcode]);
1.157 parser 171: #endif
1.11 paf 172:
1.297 paf 173: switch(opcode) {
1.51 paf 174: // param in next instruction
1.322 misha 175: case OP::OP_VALUE:
1.32 paf 176: {
1.297 paf 177: debug_origin=i.next().origin;
178: Value& value=*i.next().value;
1.157 parser 179: #ifdef DEBUG_EXECUTE
1.297 paf 180: debug_printf(sapi_info, " \"%s\" %s", value.get_string()->cstr(), value.type());
1.157 parser 181: #endif
1.297 paf 182: stack.push(value);
1.32 paf 183: break;
184: }
1.328 misha 185:
186: #ifdef OPTIMIZE_BYTECODE_GET_CLASS
187: case OP::OP_VALUE__GET_CLASS:
188: {
189: // maybe they do ^class:method[] call, remember the fact
190: wcontext->set_somebody_entered_some_class();
191:
192: debug_origin=i.next().origin;
193: Value& value=*i.next().value;
194: const String& name=*value.get_string();
195:
196: #ifdef DEBUG_EXECUTE
197: debug_printf(sapi_info, " \"%s\" ", name.cstr());
198: #endif
199:
200: Value* class_value=classes().get(name);
201: if(!class_value)
202: throw Exception(PARSER_RUNTIME,
203: &name,
204: "class is undefined");
205:
206: stack.push(*class_value);
207: break;
208: }
209: #else
1.322 misha 210: case OP::OP_GET_CLASS:
1.38 paf 211: {
1.130 paf 212: // maybe they do ^class:method[] call, remember the fact
1.215 paf 213: wcontext->set_somebody_entered_some_class();
1.98 paf 214:
1.297 paf 215: const String& name=stack.pop().string();
216: Value* value=classes().get(name);
1.120 paf 217: if(!value)
1.316 misha 218: throw Exception(PARSER_RUNTIME,
1.66 paf 219: &name,
1.143 paf 220: "class is undefined");
1.66 paf 221:
1.297 paf 222: stack.push(*value);
1.38 paf 223: break;
224: }
1.328 misha 225: #endif
1.51 paf 226: // OP_WITH
1.322 misha 227: case OP::OP_WITH_ROOT:
1.187 parser 228: {
1.297 paf 229: stack.push(*method_frame);
1.187 parser 230: break;
231: }
1.322 misha 232: case OP::OP_WITH_SELF:
1.37 paf 233: {
1.297 paf 234: stack.push(get_self());
1.37 paf 235: break;
236: }
1.322 misha 237: case OP::OP_WITH_READ:
1.15 paf 238: {
1.297 paf 239: stack.push(*rcontext);
1.20 paf 240: break;
241: }
1.322 misha 242: case OP::OP_WITH_WRITE:
1.20 paf 243: {
1.287 paf 244: if(wcontext==method_frame)
1.316 misha 245: throw Exception(PARSER_RUNTIME,
1.287 paf 246: 0,
247: "$.name outside of $name[...]");
248:
1.297 paf 249: stack.push(*wcontext);
1.20 paf 250: break;
251: }
1.37 paf 252:
1.51 paf 253: // OTHER ACTIONS BUT WITHs
1.322 misha 254: case OP::OP_CONSTRUCT_VALUE:
1.20 paf 255: {
1.297 paf 256: Value& value=stack.pop().value();
257: const String& name=stack.pop().string(); debug_name=&name;
258: Value& ncontext=stack.pop().value();
1.329 misha 259: put_element(ncontext, name, &value);
1.308 paf 260:
1.213 paf 261: break;
262: }
1.322 misha 263: case OP::OP_CONSTRUCT_EXPR:
1.80 paf 264: {
1.219 paf 265: // see OP_PREPARE_TO_EXPRESSION
266: wcontext->set_in_expression(false);
267:
1.308 paf 268: Value& expr=stack.pop().value();
1.297 paf 269: const String& name=stack.pop().string(); debug_name=&name;
270: Value& ncontext=stack.pop().value();
1.308 paf 271: Value& value=expr.as_expr_result();
1.329 misha 272: put_element(ncontext, name, &value);
1.80 paf 273: break;
274: }
1.322 misha 275: case OP::OP_CURLY_CODE__CONSTRUCT:
1.182 parser 276: {
1.297 paf 277: ArrayOperation& local_ops=*i.next().ops;
1.182 parser 278: #ifdef DEBUG_EXECUTE
1.297 paf 279: debug_printf(sapi_info, " (%d)\n", local_ops.count());
280: debug_dump(sapi_info, 1, local_ops);
1.326 misha 281: #endif
282: VJunction& value=*new VJunction(
1.297 paf 283: get_self(), 0,
1.257 paf 284: method_frame,
1.240 paf 285: rcontext,
286: wcontext,
1.312 paf 287: &local_ops);
1.238 paf 288:
1.326 misha 289: wcontext->attach_junction(&value);
290:
1.297 paf 291: const String& name=stack.pop().string(); debug_name=&name;
292: Value& ncontext=stack.pop().value();
1.312 paf 293: if(const VJunction* vjunction=ncontext.put_element(ncontext, name, &value, false))
294: if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT)
1.316 misha 295: throw Exception(PARSER_RUNTIME,
1.308 paf 296: 0,
297: "property value can not be code, use [] or () brackets");
298:
1.182 parser 299: break;
300: }
1.322 misha 301: case OP::OP_NESTED_CODE:
1.209 paf 302: {
1.297 paf 303: ArrayOperation& local_ops=*i.next().ops;
1.209 paf 304: #ifdef DEBUG_EXECUTE
1.297 paf 305: debug_printf(sapi_info, " (%d)\n", local_ops.count());
306: debug_dump(sapi_info, 1, local_ops);
1.209 paf 307: #endif
1.297 paf 308: stack.push(local_ops);
1.209 paf 309: break;
310: }
1.322 misha 311: case OP::OP_WRITE_VALUE:
1.13 paf 312: {
1.297 paf 313: Value& value=stack.pop().value();
314: write_assign_lang(value);
1.86 paf 315: break;
316: }
1.322 misha 317: case OP::OP_WRITE_EXPR_RESULT:
1.108 paf 318: {
1.297 paf 319: Value& value=stack.pop().value();
320: write_no_lang(value.as_expr_result());
1.230 paf 321:
322: // must be after write(result) and
1.219 paf 323: // see OP_PREPARE_TO_EXPRESSION
324: wcontext->set_in_expression(false);
1.108 paf 325: break;
326: }
1.322 misha 327: case OP::OP_STRING__WRITE:
1.86 paf 328: {
1.297 paf 329: i.next(); // ignore origin
330: Value* value=i.next().value;
1.157 parser 331: #ifdef DEBUG_EXECUTE
1.297 paf 332: debug_printf(sapi_info, " \"%s\"", value->get_string()->cstr());
1.157 parser 333: #endif
1.297 paf 334: write_no_lang(*value->get_string());
1.13 paf 335: break;
1.14 paf 336: }
1.328 misha 337:
338: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
339: case OP::OP_VALUE__GET_ELEMENT_OR_OPERATOR:
340: {
341: debug_origin=i.next().origin;
342: const String& name=*i.next().value->get_string(); debug_name=&name;
343:
344: #ifdef DEBUG_EXECUTE
345: debug_printf(sapi_info, " \"%s\" ", name.cstr());
346: #endif
1.330 misha 347: if(Method* method=main_class.get_method(name)){ // looking operator of that name FIRST
348: if(!method->junction_template) method->junction_template=new VJunction(main_class, method);
349: stack.push(*method->junction_template);
350: break;
351: }
352: Value& value=get_element(*rcontext, name);
1.328 misha 353: stack.push(value);
354: break;
355: }
356: #else
1.322 misha 357: case OP::OP_GET_ELEMENT_OR_OPERATOR:
1.215 paf 358: {
1.297 paf 359: const String& name=stack.pop().string(); debug_name=&name;
360: Value& ncontext=stack.pop().value();
1.330 misha 361: if(Method* method=main_class.get_method(name)){ // looking operator of that name FIRST
362: if(!method->junction_template) method->junction_template=new VJunction(main_class, method);
363: stack.push(*method->junction_template);
364: break;
365: }
366: Value& value=get_element(ncontext, name);
1.297 paf 367: stack.push(value);
1.215 paf 368: break;
369: }
1.328 misha 370: #endif
371:
1.334 ! misha 372: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT_FIELD
! 373: case OP::OP_GET_ELEMENT_FIELD:
! 374: case OP::OP_GET_ELEMENT_FIELD__WRITE:
! 375: {
! 376: debug_origin=i.next().origin;
! 377: const String& context_name=*i.next().value->get_string(); debug_name=&context_name;
! 378: #ifdef DEBUG_EXECUTE
! 379: debug_printf(sapi_info, " \"%s\" ", context_name.cstr());
! 380: #endif
! 381: Value& object=get_element(*rcontext, context_name);
! 382:
! 383: #ifndef OPTIMIZE_BYTECODE_USE_TWO_OPERANDS_INSTRUCTIONS
! 384: i.next(); // skip OP_VALUE
! 385: #endif
! 386:
! 387: debug_origin=i.next().origin;
! 388: const String& field_name=*i.next().value->get_string(); debug_name=&field_name;
! 389: #ifdef DEBUG_EXECUTE
! 390: debug_printf(sapi_info, " \"%s\" ", field_name.cstr());
! 391: #endif
! 392: Value& value=get_element(object, field_name);
! 393:
! 394: i.next(); // skip last OP_GET_ELEMENT
! 395:
! 396: if(opcode==OP::OP_GET_ELEMENT_FIELD){
! 397: stack.push(value);
! 398: } else {
! 399: write_assign_lang(value);
! 400: }
! 401: break;
! 402: }
! 403: #endif
! 404:
1.322 misha 405: case OP::OP_GET_ELEMENT:
1.11 paf 406: {
1.297 paf 407: const String& name=stack.pop().string(); debug_name=&name;
408: Value& ncontext=stack.pop().value();
1.330 misha 409: Value& value=get_element(ncontext, name);
1.297 paf 410: stack.push(value);
1.17 paf 411: break;
412: }
413:
1.328 misha 414: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
415: case OP::OP_VALUE__GET_ELEMENT:
416: {
417: debug_origin=i.next().origin;
418: const String& name=*i.next().value->get_string(); debug_name=&name;
419:
420: #ifdef DEBUG_EXECUTE
421: debug_printf(sapi_info, " \"%s\" ", name.cstr());
422: #endif
423:
1.330 misha 424: Value& value=get_element(*rcontext, name);
1.328 misha 425: stack.push(value);
426: break;
427: }
428: #endif
429:
430:
1.322 misha 431: case OP::OP_GET_ELEMENT__WRITE:
1.17 paf 432: {
1.297 paf 433: const String& name=stack.pop().string(); debug_name=&name;
434: Value& ncontext=stack.pop().value();
1.330 misha 435: Value& value=get_element(ncontext, name);
1.297 paf 436: write_assign_lang(value);
1.17 paf 437: break;
438: }
439:
1.328 misha 440: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT
441: case OP::OP_VALUE__GET_ELEMENT__WRITE:
442: {
443: debug_origin=i.next().origin;
444: const String& name=*i.next().value->get_string(); debug_name=&name;
445:
446: #ifdef DEBUG_EXECUTE
447: debug_printf(sapi_info, " \"%s\" ", name.cstr());
448: #endif
449:
1.330 misha 450: Value& value=get_element(*rcontext, name);
1.328 misha 451: write_assign_lang(value);
452: break;
453: }
454: #endif
1.32 paf 455:
1.322 misha 456: case OP::OP_OBJECT_POOL:
1.17 paf 457: {
1.297 paf 458: ArrayOperation& local_ops=*i.next().ops;
1.226 paf 459:
1.257 paf 460: WContext *saved_wcontext=wcontext;
1.297 paf 461: String::Language saved_lang=flang;
462: flang=String::L_PASS_APPENDED;
463: WWrapper local(0/*empty*/, wcontext);
1.226 paf 464: wcontext=&local;
465:
1.297 paf 466: execute(local_ops);
1.226 paf 467:
1.297 paf 468: stack.push(wcontext->result().as_value());
1.257 paf 469: flang=saved_lang;
470: wcontext=saved_wcontext;
1.13 paf 471: break;
1.15 paf 472: }
1.13 paf 473:
1.322 misha 474: case OP::OP_STRING_POOL:
1.49 paf 475: {
1.297 paf 476: ArrayOperation& local_ops=*i.next().ops;
1.226 paf 477:
1.257 paf 478: WContext *saved_wcontext=wcontext;
1.297 paf 479: WWrapper local(0 /*empty*/, wcontext);
1.226 paf 480: wcontext=&local;
481:
1.297 paf 482: execute(local_ops);
1.226 paf 483:
1.297 paf 484: Value* value;
1.49 paf 485: // from "$a $b" part of expression taking only string value,
486: // ignoring any other content of wcontext
1.297 paf 487: if(const String* string=wcontext->get_string())
488: value=new VString(*string);
1.80 paf 489: else
1.324 misha 490: value=VVoid::get();
1.297 paf 491: stack.push(*value);
492:
1.257 paf 493: wcontext=saved_wcontext;
1.49 paf 494: break;
495: }
496:
1.51 paf 497: // CALL
1.322 misha 498: case OP::OP_CURLY_CODE__STORE_PARAM:
499: case OP::OP_EXPR_CODE__STORE_PARAM:
1.28 paf 500: {
1.237 paf 501: // code
1.297 paf 502: ArrayOperation& local_ops=*i.next().ops;
1.237 paf 503: #ifdef DEBUG_EXECUTE
1.297 paf 504: debug_printf(sapi_info, " (%d)\n", local_ops.count());
505: debug_dump(sapi_info, 1, local_ops);
1.237 paf 506: #endif
507: // when they evaluate expression parameter,
508: // the object expression result
509: // does not need to be written into calling frame
510: // it must go into any expressions using that parameter
511: // hence, we zero junction.wcontext here, and later
512: // in .process we would test that field
513: // in decision "which wwrapper to use"
1.326 misha 514: VJunction& value=*new VJunction(
1.297 paf 515: get_self(), 0,
1.257 paf 516: method_frame,
1.237 paf 517: rcontext,
1.322 misha 518: opcode==OP::OP_EXPR_CODE__STORE_PARAM?0:wcontext,
1.312 paf 519: &local_ops);
1.326 misha 520: #ifdef USE_DESTRUCTORS
521: value.set_temporal(true);
522: #else
523: if (opcode!=OP::OP_EXPR_CODE__STORE_PARAM)
524: #endif
525: wcontext->attach_junction(&value);
1.237 paf 526: // store param
1.329 misha 527: stack.push(value);
1.29 paf 528: break;
529: }
530:
1.322 misha 531: case OP::OP_PREPARE_TO_CONSTRUCT_OBJECT:
1.186 parser 532: {
1.200 paf 533: wcontext->set_constructing(true);
1.186 parser 534: break;
535: }
1.219 paf 536:
1.322 misha 537: case OP::OP_PREPARE_TO_EXPRESSION:
1.219 paf 538: {
539: wcontext->set_in_expression(true);
540: break;
541: }
542:
1.322 misha 543: case OP::OP_CALL:
1.29 paf 544: {
1.297 paf 545: ArrayOperation* local_ops=i.next().ops;
1.157 parser 546: #ifdef DEBUG_EXECUTE
1.297 paf 547: debug_printf(sapi_info, " (%d)\n", local_ops?local_ops->count():0);
548: if(local_ops)
549: debug_dump(sapi_info, 1, *local_ops);
1.237 paf 550:
1.297 paf 551: debug_printf(sapi_info, "->\n");
1.157 parser 552: #endif
1.297 paf 553: Value& value=stack.pop().value();
1.237 paf 554:
1.297 paf 555: Junction* junction=value.get_junction();
556: if(!junction) {
557: if(value.is("void"))
1.316 misha 558: throw Exception(PARSER_RUNTIME,
1.297 paf 559: 0,
560: "undefined method");
561: else
1.316 misha 562: throw Exception(PARSER_RUNTIME,
1.297 paf 563: 0,
564: "is '%s', not a method or junction, can not call it",
565: value.type());
566: }
1.237 paf 567:
1.321 misha 568: VMethodFrame frame(*junction, method_frame);
1.330 misha 569:
1.321 misha 570: if(local_ops){ // store param code goes here
1.329 misha 571: size_t first = stack.top_index();
1.321 misha 572: execute(*local_ops);
1.329 misha 573: frame.store_params((Value**)stack.ptr(first), stack.top_index()-first);
1.332 misha 574: op_call(frame);
1.329 misha 575: stack.set_top_index(first);
1.330 misha 576: } else {
577: frame.empty_params();
1.332 misha 578: op_call(frame);
1.321 misha 579: }
1.330 misha 580:
1.332 misha 581: stack.push(frame.result().as_value());
582:
583: #ifdef DEBUG_EXECUTE
584: debug_printf(sapi_info, "<-returned");
585: #endif
586: if(get_skip())
587: return;
588: if(get_interrupted()) {
589: set_interrupted(false);
590: throw Exception("parser.interrupted",
591: 0,
592: "execution stopped");
1.237 paf 593: }
1.332 misha 594: break;
595: }
1.220 paf 596:
1.332 misha 597: case OP::OP_CALL__WRITE:
598: {
599: ArrayOperation* local_ops=i.next().ops;
600: #ifdef DEBUG_EXECUTE
601: debug_printf(sapi_info, " (%d)\n", local_ops?local_ops->count():0);
602: if(local_ops)
603: debug_dump(sapi_info, 1, *local_ops);
604:
605: debug_printf(sapi_info, "->\n");
606: #endif
607: Value& value=stack.pop().value();
608:
609: Junction* junction=value.get_junction();
610: if(!junction) {
611: if(value.is("void"))
612: throw Exception(PARSER_RUNTIME,
613: 0,
614: "undefined method");
615: else
616: throw Exception(PARSER_RUNTIME,
617: 0,
618: "is '%s', not a method or junction, can not call it",
619: value.type());
620: }
621:
622: #ifdef OPTIMIZE_CALL
623: const Method& method=*junction->method;
624: if (!wcontext->get_constructing() && method.call_optimization==Method::CO_WITHOUT_FRAME){
625: if(local_ops){ // store param code goes here
626: size_t first = stack.top_index();
627: execute(*local_ops);
628:
629: MethodParams method_params;
630: method_params.store_params((Value**)stack.ptr(first), stack.top_index()-first);
631: method.check_actual_numbered_params(junction->self, &method_params);
632: method.native_code(*this, method_params); // execute it
633:
634: stack.set_top_index(first);
635: } else {
636: MethodParams method_params;
637: method.check_actual_numbered_params(junction->self, &method_params);
638: method.native_code(*this, method_params); // execute it
639: }
640: } else if (!wcontext->get_constructing() && method.call_optimization==Method::CO_WITHOUT_WCONTEXT){
641: VMethodFrame frame(*junction, method_frame);
642: if(local_ops){ // store param code goes here
643: size_t first = stack.top_index();
644: execute(*local_ops);
645:
646: frame.store_params((Value**)stack.ptr(first), stack.top_index()-first);
647: op_call_write(frame);
648:
649: stack.set_top_index(first);
650: } else {
651: frame.empty_params();
652: op_call_write(frame);
653: }
654: } else
655: #endif // OPTIMIZE_CALL
656: {
657: VMethodFrame frame(*junction, method_frame);
658: if(local_ops){ // store param code goes here
659: size_t first = stack.top_index();
660: execute(*local_ops);
661:
662: frame.store_params((Value**)stack.ptr(first), stack.top_index()-first);
663: op_call(frame);
664:
665: stack.set_top_index(first);
666: } else {
667: frame.empty_params();
668: op_call(frame);
669: }
670: write_assign_lang(frame.result());
671: }
1.157 parser 672: #ifdef DEBUG_EXECUTE
1.297 paf 673: debug_printf(sapi_info, "<-returned");
1.157 parser 674: #endif
1.327 misha 675:
676: if(get_skip())
677: return;
678: if(get_interrupted()) {
679: set_interrupted(false);
680: throw Exception("parser.interrupted",
681: 0,
682: "execution stopped");
683: }
1.49 paf 684: break;
685: }
686:
1.55 paf 687: // expression ops: unary
1.322 misha 688: case OP::OP_NEG:
1.55 paf 689: {
1.297 paf 690: Value& a=stack.pop().value();
691: Value& value=*new VDouble(-a.as_double());
692: stack.push(value);
1.55 paf 693: break;
694: }
1.322 misha 695: case OP::OP_INV:
1.55 paf 696: {
1.297 paf 697: Value& a=stack.pop().value();
698: Value& value=*new VDouble(~a.as_int());
699: stack.push(value);
1.55 paf 700: break;
701: }
1.322 misha 702: case OP::OP_NOT:
1.55 paf 703: {
1.297 paf 704: Value& a=stack.pop().value();
1.327 misha 705: Value& value=VBool::get(!a.as_bool());
1.297 paf 706: stack.push(value);
1.55 paf 707: break;
708: }
1.322 misha 709: case OP::OP_DEF:
1.62 paf 710: {
1.297 paf 711: Value& a=stack.pop().value();
1.327 misha 712: Value& value=VBool::get(a.is_defined());
1.297 paf 713: stack.push(value);
1.62 paf 714: break;
715: }
1.322 misha 716: case OP::OP_IN:
1.62 paf 717: {
1.297 paf 718: Value& a=stack.pop().value();
719: const String& path=a.as_string();
1.327 misha 720: Value& value=VBool::get(request_info.uri && *request_info.uri && path.this_starts(request_info.uri));
1.297 paf 721: stack.push(value);
1.62 paf 722: break;
723: }
1.322 misha 724: case OP::OP_FEXISTS:
1.62 paf 725: {
1.297 paf 726: Value& a=stack.pop().value();
1.327 misha 727: Value& value=VBool::get(file_exist(absolute(a.as_string())));
1.297 paf 728: stack.push(value);
1.148 paf 729: break;
730: }
1.322 misha 731: case OP::OP_DEXISTS:
1.148 paf 732: {
1.297 paf 733: Value& a=stack.pop().value();
1.327 misha 734: Value& value=VBool::get(dir_exists(absolute(a.as_string())));
1.297 paf 735: stack.push(value);
1.62 paf 736: break;
737: }
1.55 paf 738:
739: // expression ops: binary
1.322 misha 740: case OP::OP_SUB:
1.53 paf 741: {
1.297 paf 742: Value& b=stack.pop().value(); Value& a=stack.pop().value();
743: Value& value=*new VDouble(a.as_double() - b.as_double());
744: stack.push(value);
1.53 paf 745: break;
746: }
1.322 misha 747: case OP::OP_ADD:
1.53 paf 748: {
1.297 paf 749: Value& b=stack.pop().value(); Value& a=stack.pop().value();
750: Value& value=*new VDouble(a.as_double() + b.as_double());
751: stack.push(value);
1.53 paf 752: break;
753: }
1.322 misha 754: case OP::OP_MUL:
1.49 paf 755: {
1.297 paf 756: Value& b=stack.pop().value(); Value& a=stack.pop().value();
757: Value& value=*new VDouble(a.as_double() * b.as_double());
758: stack.push(value);
1.53 paf 759: break;
760: }
1.322 misha 761: case OP::OP_DIV:
1.53 paf 762: {
1.297 paf 763: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 764:
1.297 paf 765: double a_double=a.as_double();
766: double b_double=b.as_double();
1.170 parser 767:
1.171 parser 768: if(b_double == 0) {
1.297 paf 769: //const String* problem_source=b.as_string();
1.223 paf 770: throw Exception("number.zerodivision",
1.297 paf 771: 0, //problem_source,
1.170 parser 772: "Division by zero");
1.171 parser 773: }
1.170 parser 774:
1.297 paf 775: Value& value=*new VDouble(a_double / b_double);
776: stack.push(value);
1.54 paf 777: break;
778: }
1.322 misha 779: case OP::OP_MOD:
1.55 paf 780: {
1.297 paf 781: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 782:
1.297 paf 783: double a_double=a.as_double();
784: double b_double=b.as_double();
1.170 parser 785:
1.173 parser 786: if(b_double == 0) {
1.297 paf 787: //const String* problem_source=b.as_string();
1.223 paf 788: throw Exception("number.zerodivision",
1.297 paf 789: 0, //problem_source,
1.170 parser 790: "Modulus by zero");
1.171 parser 791: }
1.170 parser 792:
1.297 paf 793: Value& value=*new VDouble(fmod(a_double, b_double));
794: stack.push(value);
1.201 paf 795: break;
796: }
1.322 misha 797: case OP::OP_INTDIV:
1.201 paf 798: {
1.297 paf 799: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.201 paf 800:
1.297 paf 801: int a_int=a.as_int();
802: int b_int=b.as_int();
1.201 paf 803:
804: if(b_int == 0) {
1.297 paf 805: //const String* problem_source=b.as_string();
1.223 paf 806: throw Exception("number.zerodivision",
1.297 paf 807: 0, //problem_source,
1.201 paf 808: "Division by zero");
809: }
810:
1.297 paf 811: Value& value=*new VInt(a_int / b_int);
812: stack.push(value);
1.55 paf 813: break;
814: }
1.322 misha 815: case OP::OP_BIN_SL:
1.274 paf 816: {
1.297 paf 817: Value& b=stack.pop().value(); Value& a=stack.pop().value();
818: Value& value=*new VInt(
819: a.as_int() <<
820: b.as_int());
821: stack.push(value);
1.274 paf 822: break;
823: }
1.322 misha 824: case OP::OP_BIN_SR:
1.274 paf 825: {
1.297 paf 826: Value& b=stack.pop().value(); Value& a=stack.pop().value();
827: Value& value=*new VInt(
828: a.as_int() >>
829: b.as_int());
830: stack.push(value);
1.274 paf 831: break;
832: }
1.322 misha 833: case OP::OP_BIN_AND:
1.54 paf 834: {
1.297 paf 835: Value& b=stack.pop().value(); Value& a=stack.pop().value();
836: Value& value=*new VInt(
837: a.as_int() &
838: b.as_int());
839: stack.push(value);
1.54 paf 840: break;
841: }
1.322 misha 842: case OP::OP_BIN_OR:
1.54 paf 843: {
1.297 paf 844: Value& b=stack.pop().value(); Value& a=stack.pop().value();
845: Value& value=*new VInt(
846: a.as_int() |
847: b.as_int());
848: stack.push(value);
1.55 paf 849: break;
850: }
1.322 misha 851: case OP::OP_BIN_XOR:
1.56 paf 852: {
1.297 paf 853: Value& b=stack.pop().value(); Value& a=stack.pop().value();
854: Value& value=*new VInt(
855: a.as_int() ^
856: b.as_int());
857: stack.push(value);
1.56 paf 858: break;
859: }
1.322 misha 860: case OP::OP_LOG_AND:
1.55 paf 861: {
1.297 paf 862: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 863: bool result;
1.297 paf 864: if(a.as_bool()) {
865: execute(local_ops);
866: Value& b=stack.pop().value();
867: result=b.as_bool();
1.209 paf 868: } else
1.263 paf 869: result=false;
1.327 misha 870: Value& value=VBool::get(result);
1.297 paf 871: stack.push(value);
1.55 paf 872: break;
873: }
1.322 misha 874: case OP::OP_LOG_OR:
1.55 paf 875: {
1.297 paf 876: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 877: bool result;
1.297 paf 878: if(a.as_bool())
1.263 paf 879: result=true;
1.209 paf 880: else {
1.297 paf 881: execute(local_ops);
882: Value& b=stack.pop().value();
883: result=b.as_bool();
1.209 paf 884: }
1.327 misha 885: Value& value=VBool::get(result);
1.297 paf 886: stack.push(value);
1.56 paf 887: break;
888: }
1.322 misha 889: case OP::OP_LOG_XOR:
1.56 paf 890: {
1.297 paf 891: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 892: Value& value=VBool::get(a.as_bool() ^ b.as_bool());
1.297 paf 893: stack.push(value);
1.55 paf 894: break;
895: }
1.322 misha 896: case OP::OP_NUM_LT:
1.55 paf 897: {
1.297 paf 898: volatile double b_double=stack.pop().value().as_double();
899: volatile double a_double=stack.pop().value().as_double();
1.327 misha 900: Value& value=VBool::get(a_double<b_double);
1.297 paf 901: stack.push(value);
1.55 paf 902: break;
903: }
1.322 misha 904: case OP::OP_NUM_GT:
1.55 paf 905: {
1.297 paf 906: volatile double b_double=stack.pop().value().as_double();
907: volatile double a_double=stack.pop().value().as_double();
1.327 misha 908: Value& value=VBool::get(a_double>b_double);
1.297 paf 909: stack.push(value);
1.55 paf 910: break;
911: }
1.322 misha 912: case OP::OP_NUM_LE:
1.55 paf 913: {
1.297 paf 914: volatile double b_double=stack.pop().value().as_double();
915: volatile double a_double=stack.pop().value().as_double();
1.327 misha 916: Value& value=VBool::get(a_double<=b_double);
1.297 paf 917: stack.push(value);
1.55 paf 918: break;
919: }
1.322 misha 920: case OP::OP_NUM_GE:
1.55 paf 921: {
1.297 paf 922: volatile double b_double=stack.pop().value().as_double();
923: volatile double a_double=stack.pop().value().as_double();
1.327 misha 924: Value& value=VBool::get(a_double>=b_double);
1.297 paf 925: stack.push(value);
1.55 paf 926: break;
927: }
1.322 misha 928: case OP::OP_NUM_EQ:
1.55 paf 929: {
1.297 paf 930: volatile double b_double=stack.pop().value().as_double();
931: volatile double a_double=stack.pop().value().as_double();
1.327 misha 932: Value& value=VBool::get(a_double==b_double);
1.297 paf 933: stack.push(value);
1.55 paf 934: break;
935: }
1.322 misha 936: case OP::OP_NUM_NE:
1.55 paf 937: {
1.297 paf 938: volatile double b_double=stack.pop().value().as_double();
939: volatile double a_double=stack.pop().value().as_double();
1.327 misha 940: Value& value=VBool::get(a_double!=b_double);
1.297 paf 941: stack.push(value);
1.54 paf 942: break;
943: }
1.322 misha 944: case OP::OP_STR_LT:
1.58 paf 945: {
1.297 paf 946: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 947: Value& value=VBool::get(a.as_string() < b.as_string());
1.297 paf 948: stack.push(value);
1.58 paf 949: break;
950: }
1.322 misha 951: case OP::OP_STR_GT:
1.58 paf 952: {
1.297 paf 953: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 954: Value& value=VBool::get(a.as_string() > b.as_string());
1.297 paf 955: stack.push(value);
1.58 paf 956: break;
957: }
1.322 misha 958: case OP::OP_STR_LE:
1.58 paf 959: {
1.297 paf 960: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 961: Value& value=VBool::get(a.as_string() <= b.as_string());
1.297 paf 962: stack.push(value);
1.58 paf 963: break;
964: }
1.322 misha 965: case OP::OP_STR_GE:
1.54 paf 966: {
1.297 paf 967: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 968: Value& value=VBool::get(a.as_string() >= b.as_string());
1.297 paf 969: stack.push(value);
1.58 paf 970: break;
971: }
1.322 misha 972: case OP::OP_STR_EQ:
1.58 paf 973: {
1.297 paf 974: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 975: Value& value=VBool::get(a.as_string() == b.as_string());
1.297 paf 976: stack.push(value);
1.58 paf 977: break;
978: }
1.322 misha 979: case OP::OP_STR_NE:
1.58 paf 980: {
1.297 paf 981: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 982: Value& value=VBool::get(a.as_string() != b.as_string());
1.297 paf 983: stack.push(value);
1.103 paf 984: break;
985: }
1.322 misha 986: case OP::OP_IS:
1.103 paf 987: {
1.297 paf 988: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 989: Value& value=VBool::get(a.is(b.as_string().cstr()));
1.297 paf 990: stack.push(value);
1.28 paf 991: break;
992: }
993:
1.11 paf 994: default:
1.223 paf 995: throw Exception(0,
1.67 paf 996: 0,
1.297 paf 997: "invalid opcode %d", opcode);
1.11 paf 998: }
999: }
1.306 paf 1000: } catch(const Exception&) {
1.297 paf 1001: // record it to stack trace
1.301 paf 1002: if(debug_name)
1003: exception_trace.push(Trace(debug_name, debug_origin));
1.297 paf 1004: rethrow;
1005: }
1.1 paf 1006: }
1.17 paf 1007:
1.330 misha 1008: #define SAVE_CONTEXT \
1009: VMethodFrame *saved_method_frame=method_frame; \
1010: Value* saved_rcontext=rcontext; \
1011: WContext *saved_wcontext=wcontext;
1012:
1013: #define RESTORE_CONTEXT \
1014: wcontext=saved_wcontext; \
1015: rcontext=saved_rcontext; \
1016: method_frame=saved_method_frame;
1017:
1.332 misha 1018: void Request::op_call(VMethodFrame& frame){
1019: const Junction &junction=frame.junction;
1020: VStateless_class& called_class=*junction.self.get_class();
1.319 misha 1021: Value* new_self;
1.332 misha 1022:
1.319 misha 1023: if(wcontext->get_constructing()) {
1024: wcontext->set_constructing(false);
1.332 misha 1025: if(junction.method->call_type!=Method::CT_STATIC) {
1.319 misha 1026: // this is a constructor call
1027: HashStringValue& new_object_fields=*new HashStringValue();
1.332 misha 1028: if(new_self=called_class.create_new_value(fpool, new_object_fields)) {
1.319 misha 1029: // some stateless_class creatable derivates
1030: } else
1031: throw Exception(PARSER_RUNTIME,
1032: 0, //&frame.name(),
1033: "is not a constructor, system class '%s' can be constructed only implicitly",
1034: called_class.name().cstr());
1035:
1036: frame.write(*new_self,
1037: String::L_CLEAN // not used, always an object, not string
1038: );
1039: } else
1040: throw Exception(PARSER_RUNTIME,
1041: 0, //&frame.name(),
1042: "method is static and can not be used as constructor");
1.332 misha 1043: } else
1044: new_self=&junction.self;
1.319 misha 1045:
1046: frame.set_self(*new_self);
1047:
1048: // see OP_PREPARE_TO_EXPRESSION
1049: frame.set_in_expression(wcontext->get_in_expression());
1050:
1.332 misha 1051: SAVE_CONTEXT
1052:
1.319 misha 1053: rcontext=wcontext=&frame;
1.332 misha 1054: method_frame=&frame;
1.319 misha 1055:
1.332 misha 1056: const Method& method=*junction.method;
1057: Method::Call_type call_type=&called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC;
1.319 misha 1058:
1.332 misha 1059: if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type?
1060: if(method.native_code) { // native code?
1061: method.check_actual_numbered_params(junction.self, frame.numbered_params());
1062: method.native_code(*this, *frame.numbered_params()); // execute it
1063: } else // parser code, execute it
1064: recoursion_checked_execute(*method.parser_code);
1065: } else
1066: throw Exception(PARSER_RUNTIME,
1067: 0,
1068: "is not allowed to be called %s",
1069: call_type==Method::CT_STATIC?"statically":"dynamically");
1.334 ! misha 1070:
1.330 misha 1071: RESTORE_CONTEXT
1.332 misha 1072: //return &frame;
1073: }
1074:
1075: void Request::op_call_write(VMethodFrame& frame){
1076: const Junction &junction=frame.junction;
1077:
1078: frame.set_self(junction.self);
1079:
1080: VMethodFrame *saved_method_frame=method_frame;
1081: Value* saved_rcontext=rcontext;
1.319 misha 1082:
1.332 misha 1083: rcontext=&frame;
1084: method_frame=&frame;
1085:
1086: const Method& method=*junction.method;
1087: Method::Call_type call_type=junction.self.get_class()==&junction.self ? Method::CT_STATIC : Method::CT_DYNAMIC;
1088:
1.333 misha 1089: if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type?
1090: if(method.native_code) { // native code?
1091: method.check_actual_numbered_params(junction.self, frame.numbered_params());
1092: method.native_code(*this, *frame.numbered_params()); // execute it
1093: } else // parser code, execute it
1094: recoursion_checked_execute(*method.parser_code);
1.332 misha 1095: } else
1096: throw Exception(PARSER_RUNTIME,
1097: 0,
1098: "is not allowed to be called %s",
1099: call_type==Method::CT_STATIC?"statically":"dynamically");
1100:
1101: rcontext=saved_rcontext;
1102: method_frame=saved_method_frame;
1.319 misha 1103: }
1104:
1.292 paf 1105: /**
1106: @bug ^superbase:method would dynamically call ^base:method if there is any
1107: */
1.330 misha 1108: Value& Request::get_element(Value& ncontext, const String& name) {
1109: if(!wcontext->get_constructing() // not constructing
1110: && wcontext->get_somebody_entered_some_class() ) // ^class:method
1.297 paf 1111: if(VStateless_class *called_class=ncontext.get_class())
1.249 paf 1112: if(VStateless_class *read_class=rcontext->get_class())
1113: if(read_class->derived_from(*called_class)) // current derived from called
1.297 paf 1114: if(Value* base=get_self().base()) { // doing DYNAMIC call
1.330 misha 1115: Temp_derived temp_derived(*base, 0); // temporarily prevent go-back-down virtual calls
1116: Value *value=base->get_element(name, *base, true); // virtual-up lookup starting from parent
1117: return *(value ? &process_to_value(*value) : VVoid::get());
1.249 paf 1118: }
1.330 misha 1119:
1120: Value* value=ncontext.get_element(name, ncontext, true);
1.291 paf 1121:
1122: if(value && wcontext->get_constructing())
1.330 misha 1123: if(Junction* junction=value->get_junction())
1.297 paf 1124: if(junction->self.get_class()!=&ncontext)
1.316 misha 1125: throw Exception(PARSER_RUNTIME,
1.291 paf 1126: &name,
1.297 paf 1127: "constructor must be declared in class '%s'",
1128: ncontext.get_class()->name_cstr());
1.63 paf 1129:
1.330 misha 1130: return *(value ? &process_to_value(*value) : VVoid::get());
1.309 paf 1131: }
1132:
1.329 misha 1133: void Request::put_element(Value& ncontext, const String& name, Value* value) {
1.309 paf 1134: // put_element can return property-setting-junction
1.329 misha 1135: if(const VJunction* vjunction=ncontext.put_element(ncontext, name, value, false))
1.312 paf 1136: if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) {
1.309 paf 1137: // process it
1.329 misha 1138: VMethodFrame frame(vjunction->junction(), method_frame/*caller*/);
1139: int param_count=frame.method_params_count();
1140:
1.309 paf 1141: if(param_count!=1)
1.316 misha 1142: throw Exception(PARSER_RUNTIME,
1.309 paf 1143: 0,
1144: "setter method must have ONE parameter (has %d parameters)", param_count);
1145:
1.329 misha 1146: frame.store_params(&value, 1);
1.309 paf 1147: frame.set_self(frame.junction.self);
1148:
1.330 misha 1149: SAVE_CONTEXT
1.309 paf 1150:
1151: rcontext=wcontext=&frame;
1152: method_frame=&frame;
1153:
1.311 paf 1154: // prevent non-string writes for better error reporting [setters are not expected to return anything]
1.309 paf 1155: wcontext->write(*method_frame);
1156:
1157: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1158: // we don't need it StringOrValue result=wcontext->result();
1159:
1.330 misha 1160: RESTORE_CONTEXT
1.309 paf 1161: }
1.34 paf 1162: }
1.70 paf 1163:
1.162 parser 1164: /** @param intercept_string
1.116 paf 1165: - true:
1166: they want result=string value,
1167: possible object result goes to wcontext
1168: - false:
1169: they want any result[string|object]
1170: nothing goes to wcontext.
1.125 paf 1171: used in @c (expression) params evaluation
1.224 paf 1172:
1.334 ! misha 1173: using the fact it's either string_ or value_ result requested to speed up checkes
1.116 paf 1174: */
1.229 paf 1175: StringOrValue Request::process(Value& input_value, bool intercept_string) {
1.297 paf 1176: Junction* junction=input_value.get_junction();
1.307 paf 1177: if(junction) {
1178: if(junction->is_getter) { // is it a getter-junction?
1.329 misha 1179: VMethodFrame frame(*junction, method_frame/*caller*/);
1180: int param_count=frame.method_params_count();
1181:
1.331 misha 1182: if(param_count){
1183: if(junction->auto_name){ // default getter
1184: if(param_count==1){
1185: Value *param=new VString(*junction->auto_name);
1186: frame.store_params(¶m, 1);
1187: } else
1188: throw Exception(PARSER_RUNTIME,
1189: 0,
1190: "default getter method can't have more then 1 parameter (has %d parameters)", param_count);
1191: } else
1.320 misha 1192: throw Exception(PARSER_RUNTIME,
1193: 0,
1.331 misha 1194: "getter method must have no parameters (has %d parameters)", param_count);
1195: } // no need for else frame.empty_params()
1.320 misha 1196:
1.307 paf 1197: frame.set_self(frame.junction.self);
1198:
1.330 misha 1199: SAVE_CONTEXT
1.307 paf 1200:
1201: rcontext=wcontext=&frame;
1202: method_frame=&frame;
1203:
1204: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1205: StringOrValue result=wcontext->result();
1206:
1.330 misha 1207: RESTORE_CONTEXT
1.307 paf 1208:
1209: return result;
1210: }
1211:
1212: if(junction->code) { // is it a code-junction?
1213: // process it
1214: StringOrValue result;
1.157 parser 1215: #ifdef DEBUG_EXECUTE
1.307 paf 1216: debug_printf(sapi_info, "ja->\n");
1.157 parser 1217: #endif
1.238 paf 1218:
1.307 paf 1219: if(!junction->method_frame)
1.316 misha 1220: throw Exception(PARSER_RUNTIME,
1.240 paf 1221: 0,
1222: "junction used outside of context");
1223:
1.330 misha 1224: SAVE_CONTEXT
1.307 paf 1225:
1226: method_frame=junction->method_frame;
1227: rcontext=junction->rcontext;
1228:
1229: // for expression method params
1230: // wcontext is set 0
1231: // using the fact in decision "which wwrapper to use"
1232: bool using_code_frame=intercept_string && junction->wcontext;
1233: if(using_code_frame) {
1.318 misha 1234: // almost plain wwrapper about junction wcontext
1235:
1236: VCodeFrame local(*junction->wcontext);
1.307 paf 1237: wcontext=&local;
1238:
1239: // execute it
1240: recoursion_checked_execute(*junction->code);
1241:
1242: // CodeFrame soul:
1.318 misha 1243: result=wcontext->result();
1.307 paf 1244: } else {
1245: // plain wwrapper
1246: WWrapper local(0/*empty*/, wcontext);
1247: wcontext=&local;
1248:
1249: // execute it
1250: recoursion_checked_execute(*junction->code);
1251:
1252: result=wcontext->result();
1253: }
1254:
1.330 misha 1255: RESTORE_CONTEXT
1.207 paf 1256:
1.157 parser 1257: #ifdef DEBUG_EXECUTE
1.307 paf 1258: debug_printf(sapi_info, "<-ja returned");
1.157 parser 1259: #endif
1.307 paf 1260: return result;
1261: }
1262:
1263: // it is then method-junction, do not explode it
1264: // just return it as we do for usual objects
1265: }
1266:
1267: return input_value;
1.85 paf 1268: }
1269:
1.332 misha 1270: void Request::process_write(Value& input_value) {
1271: Junction* junction=input_value.get_junction();
1272: if(junction) {
1273: if(junction->is_getter) { // is it a getter-junction?
1274: VMethodFrame frame(*junction, method_frame/*caller*/);
1275: int param_count=frame.method_params_count();
1276:
1277: if(param_count){
1278: if(junction->auto_name){ // default getter
1279: if(param_count==1){
1280: Value *param=new VString(*junction->auto_name);
1281: frame.store_params(¶m, 1);
1282: } else
1283: throw Exception(PARSER_RUNTIME,
1284: 0,
1285: "default getter method can't have more then 1 parameter (has %d parameters)", param_count);
1286: } else
1287: throw Exception(PARSER_RUNTIME,
1288: 0,
1289: "getter method must have no parameters (has %d parameters)", param_count);
1290: } // no need for else frame.empty_params()
1291:
1292: frame.set_self(frame.junction.self);
1293:
1294: SAVE_CONTEXT
1295:
1296: rcontext=wcontext=&frame;
1297: method_frame=&frame;
1298:
1299: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1300:
1301: RESTORE_CONTEXT
1302:
1303: write_pass_lang(frame.result());
1304: return;
1305: }
1306:
1307: if(junction->code) { // is it a code-junction?
1308: // process it
1309: #ifdef DEBUG_EXECUTE
1310: debug_printf(sapi_info, "ja->\n");
1311: #endif
1312: if(!junction->method_frame)
1313: throw Exception(PARSER_RUNTIME,
1314: 0,
1315: "junction used outside of context");
1316:
1317: SAVE_CONTEXT
1318:
1319: method_frame=junction->method_frame;
1320: rcontext=junction->rcontext;
1321:
1322: // for expression method params
1323: // wcontext is set 0
1324: // using the fact in decision "which wwrapper to use"
1325: #ifdef OPTIMIZE_CALL
1326: if(wcontext==junction->wcontext){
1327: // no wrappers for wcontext
1328: recoursion_checked_execute(*junction->code);
1329: RESTORE_CONTEXT
1330:
1331: } else
1332: #endif
1333: if(junction->wcontext) {
1334: // almost plain wwrapper about junction wcontext
1335: VCodeFrame local(*junction->wcontext);
1336: wcontext=&local;
1337:
1338: // execute it
1339: recoursion_checked_execute(*junction->code);
1340: RESTORE_CONTEXT
1341: write_pass_lang(local.result());
1342: } else {
1343: // plain wwrapper
1344: WWrapper local(0/*empty*/, wcontext);
1345: wcontext=&local;
1346:
1347: // execute it
1348: recoursion_checked_execute(*junction->code);
1349: RESTORE_CONTEXT
1350: write_pass_lang(local.result());
1351: }
1352: #ifdef DEBUG_EXECUTE
1353: debug_printf(sapi_info, "<-ja returned");
1354: #endif
1355: return;
1356: }
1357:
1358: // it is then method-junction, do not explode it
1359: // just return it as we do for usual objects
1360: }
1361:
1362: write_pass_lang(input_value);
1363: }
1364:
1.298 paf 1365: StringOrValue Request::execute_method(VMethodFrame& amethod_frame, const Method& method) {
1.330 misha 1366: SAVE_CONTEXT
1.99 paf 1367:
1368: // initialize contexts
1.286 paf 1369: rcontext=wcontext=method_frame=&amethod_frame;
1.99 paf 1370:
1371: // execute!
1372: execute(*method.parser_code);
1373:
1374: // result
1.298 paf 1375: StringOrValue result=wcontext->result();
1.208 paf 1376:
1.330 misha 1377: RESTORE_CONTEXT
1.242 paf 1378:
1379: // return
1380: return result;
1.208 paf 1381: }
1382:
1.297 paf 1383: const String* Request::execute_method(Value& aself,
1.329 misha 1384: const Method& method, Value* optional_param,
1385: bool do_return_string) {
1.317 misha 1386:
1.330 misha 1387: SAVE_CONTEXT
1.208 paf 1388:
1.307 paf 1389: Junction local_junction(aself, &method);
1.321 misha 1390: VMethodFrame local_frame(local_junction, method_frame/*caller*/);
1.329 misha 1391: if(optional_param && local_frame.method_params_count()>0) {
1392: local_frame.store_params(&optional_param, 1);
1.330 misha 1393: } else {
1394: local_frame.empty_params();
1.242 paf 1395: }
1.285 paf 1396: local_frame.set_self(aself);
1.257 paf 1397: rcontext=wcontext=method_frame=&local_frame;
1.246 paf 1398:
1399: // prevent non-string writes for better error reporting
1.297 paf 1400: if(do_return_string)
1.246 paf 1401: wcontext->write(local_frame);
1.208 paf 1402:
1403: // execute!
1404: execute(*method.parser_code);
1405:
1406: // result
1.297 paf 1407: const String* result=0;
1408: if(do_return_string)
1409: result=&wcontext->result().as_string();
1.99 paf 1410:
1.330 misha 1411: RESTORE_CONTEXT
1.297 paf 1412:
1413: return result;
1.242 paf 1414: }
1415:
1.297 paf 1416: Request::Execute_nonvirtual_method_result
1417: Request::execute_nonvirtual_method(VStateless_class& aclass,
1.330 misha 1418: const String& method_name,
1419: VString* optional_param,
1420: bool do_return_string) {
1.297 paf 1421: Execute_nonvirtual_method_result result;
1422: result.method=aclass.get_method(method_name);
1423: if(result.method)
1.317 misha 1424: result.string=execute_method(aclass, *result.method, optional_param, do_return_string);
1.297 paf 1425: return result;
1.99 paf 1426: }
1427:
1.297 paf 1428: const String* Request::execute_virtual_method(Value& aself,
1.330 misha 1429: const String& method_name) {
1.297 paf 1430: if(Value* value=aself.get_element(method_name, aself, false))
1431: if(Junction* junction=value->get_junction())
1432: if(const Method *method=junction->method)
1433: return execute_method(aself, *method, 0/*no params*/, true);
1.188 parser 1434:
1.176 parser 1435: return 0;
1436: }