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