|
|
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.354 ! misha 8: static const char * const IDENT_EXECUTE_C="$Date: 2009-08-01 04:58:38 $";
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();
856: if(!junction || junction->self.get_class()!=class_value)
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.350 misha 866: VMethodFrame frame(*junction, method_frame);
867: METHOD_FRAME_ACTION(op_call(frame, true /* constructing */));
868: if(opcode==OP::OP_CONSTRUCT_OBJECT)
869: stack.push(frame.result().as_value());
870: else
871: write_pass_lang(frame.result());
1.348 misha 872:
873: DEBUG_PRINT_STR("<-returned")
874: break;
875: }
876:
1.55 paf 877: // expression ops: unary
1.322 misha 878: case OP::OP_NEG:
1.55 paf 879: {
1.297 paf 880: Value& a=stack.pop().value();
881: Value& value=*new VDouble(-a.as_double());
882: stack.push(value);
1.55 paf 883: break;
884: }
1.322 misha 885: case OP::OP_INV:
1.55 paf 886: {
1.297 paf 887: Value& a=stack.pop().value();
888: Value& value=*new VDouble(~a.as_int());
889: stack.push(value);
1.55 paf 890: break;
891: }
1.322 misha 892: case OP::OP_NOT:
1.55 paf 893: {
1.297 paf 894: Value& a=stack.pop().value();
1.327 misha 895: Value& value=VBool::get(!a.as_bool());
1.297 paf 896: stack.push(value);
1.55 paf 897: break;
898: }
1.322 misha 899: case OP::OP_DEF:
1.62 paf 900: {
1.297 paf 901: Value& a=stack.pop().value();
1.327 misha 902: Value& value=VBool::get(a.is_defined());
1.297 paf 903: stack.push(value);
1.62 paf 904: break;
905: }
1.322 misha 906: case OP::OP_IN:
1.62 paf 907: {
1.297 paf 908: Value& a=stack.pop().value();
909: const String& path=a.as_string();
1.327 misha 910: Value& value=VBool::get(request_info.uri && *request_info.uri && path.this_starts(request_info.uri));
1.297 paf 911: stack.push(value);
1.62 paf 912: break;
913: }
1.322 misha 914: case OP::OP_FEXISTS:
1.62 paf 915: {
1.297 paf 916: Value& a=stack.pop().value();
1.327 misha 917: Value& value=VBool::get(file_exist(absolute(a.as_string())));
1.297 paf 918: stack.push(value);
1.148 paf 919: break;
920: }
1.322 misha 921: case OP::OP_DEXISTS:
1.148 paf 922: {
1.297 paf 923: Value& a=stack.pop().value();
1.327 misha 924: Value& value=VBool::get(dir_exists(absolute(a.as_string())));
1.297 paf 925: stack.push(value);
1.62 paf 926: break;
927: }
1.55 paf 928:
929: // expression ops: binary
1.322 misha 930: case OP::OP_SUB:
1.53 paf 931: {
1.297 paf 932: Value& b=stack.pop().value(); Value& a=stack.pop().value();
933: Value& value=*new VDouble(a.as_double() - b.as_double());
934: stack.push(value);
1.53 paf 935: break;
936: }
1.322 misha 937: case OP::OP_ADD:
1.53 paf 938: {
1.297 paf 939: Value& b=stack.pop().value(); Value& a=stack.pop().value();
940: Value& value=*new VDouble(a.as_double() + b.as_double());
941: stack.push(value);
1.53 paf 942: break;
943: }
1.322 misha 944: case OP::OP_MUL:
1.49 paf 945: {
1.297 paf 946: Value& b=stack.pop().value(); Value& a=stack.pop().value();
947: Value& value=*new VDouble(a.as_double() * b.as_double());
948: stack.push(value);
1.53 paf 949: break;
950: }
1.322 misha 951: case OP::OP_DIV:
1.53 paf 952: {
1.297 paf 953: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 954:
1.297 paf 955: double a_double=a.as_double();
956: double b_double=b.as_double();
1.170 parser 957:
1.171 parser 958: if(b_double == 0) {
1.297 paf 959: //const String* problem_source=b.as_string();
1.223 paf 960: throw Exception("number.zerodivision",
1.297 paf 961: 0, //problem_source,
1.170 parser 962: "Division by zero");
1.171 parser 963: }
1.170 parser 964:
1.297 paf 965: Value& value=*new VDouble(a_double / b_double);
966: stack.push(value);
1.54 paf 967: break;
968: }
1.322 misha 969: case OP::OP_MOD:
1.55 paf 970: {
1.297 paf 971: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.170 parser 972:
1.297 paf 973: double a_double=a.as_double();
974: double b_double=b.as_double();
1.170 parser 975:
1.173 parser 976: if(b_double == 0) {
1.297 paf 977: //const String* problem_source=b.as_string();
1.223 paf 978: throw Exception("number.zerodivision",
1.297 paf 979: 0, //problem_source,
1.170 parser 980: "Modulus by zero");
1.171 parser 981: }
1.170 parser 982:
1.297 paf 983: Value& value=*new VDouble(fmod(a_double, b_double));
984: stack.push(value);
1.201 paf 985: break;
986: }
1.322 misha 987: case OP::OP_INTDIV:
1.201 paf 988: {
1.297 paf 989: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.201 paf 990:
1.297 paf 991: int a_int=a.as_int();
992: int b_int=b.as_int();
1.201 paf 993:
994: if(b_int == 0) {
1.297 paf 995: //const String* problem_source=b.as_string();
1.223 paf 996: throw Exception("number.zerodivision",
1.297 paf 997: 0, //problem_source,
1.201 paf 998: "Division by zero");
999: }
1000:
1.297 paf 1001: Value& value=*new VInt(a_int / b_int);
1002: stack.push(value);
1.55 paf 1003: break;
1004: }
1.322 misha 1005: case OP::OP_BIN_SL:
1.274 paf 1006: {
1.297 paf 1007: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1008: Value& value=*new VInt(
1009: a.as_int() <<
1010: b.as_int());
1011: stack.push(value);
1.274 paf 1012: break;
1013: }
1.322 misha 1014: case OP::OP_BIN_SR:
1.274 paf 1015: {
1.297 paf 1016: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1017: Value& value=*new VInt(
1018: a.as_int() >>
1019: b.as_int());
1020: stack.push(value);
1.274 paf 1021: break;
1022: }
1.322 misha 1023: case OP::OP_BIN_AND:
1.54 paf 1024: {
1.297 paf 1025: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1026: Value& value=*new VInt(
1027: a.as_int() &
1028: b.as_int());
1029: stack.push(value);
1.54 paf 1030: break;
1031: }
1.322 misha 1032: case OP::OP_BIN_OR:
1.54 paf 1033: {
1.297 paf 1034: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1035: Value& value=*new VInt(
1036: a.as_int() |
1037: b.as_int());
1038: stack.push(value);
1.55 paf 1039: break;
1040: }
1.322 misha 1041: case OP::OP_BIN_XOR:
1.56 paf 1042: {
1.297 paf 1043: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1044: Value& value=*new VInt(
1045: a.as_int() ^
1046: b.as_int());
1047: stack.push(value);
1.56 paf 1048: break;
1049: }
1.322 misha 1050: case OP::OP_LOG_AND:
1.55 paf 1051: {
1.297 paf 1052: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 1053: bool result;
1.297 paf 1054: if(a.as_bool()) {
1055: execute(local_ops);
1056: Value& b=stack.pop().value();
1057: result=b.as_bool();
1.209 paf 1058: } else
1.263 paf 1059: result=false;
1.327 misha 1060: Value& value=VBool::get(result);
1.297 paf 1061: stack.push(value);
1.55 paf 1062: break;
1063: }
1.322 misha 1064: case OP::OP_LOG_OR:
1.55 paf 1065: {
1.297 paf 1066: ArrayOperation& local_ops=stack.pop().ops(); Value& a=stack.pop().value();
1.263 paf 1067: bool result;
1.297 paf 1068: if(a.as_bool())
1.263 paf 1069: result=true;
1.209 paf 1070: else {
1.297 paf 1071: execute(local_ops);
1072: Value& b=stack.pop().value();
1073: result=b.as_bool();
1.209 paf 1074: }
1.327 misha 1075: Value& value=VBool::get(result);
1.297 paf 1076: stack.push(value);
1.56 paf 1077: break;
1078: }
1.322 misha 1079: case OP::OP_LOG_XOR:
1.56 paf 1080: {
1.297 paf 1081: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1082: Value& value=VBool::get(a.as_bool() ^ b.as_bool());
1.297 paf 1083: stack.push(value);
1.55 paf 1084: break;
1085: }
1.322 misha 1086: case OP::OP_NUM_LT:
1.55 paf 1087: {
1.297 paf 1088: volatile double b_double=stack.pop().value().as_double();
1089: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1090: Value& value=VBool::get(a_double<b_double);
1.297 paf 1091: stack.push(value);
1.55 paf 1092: break;
1093: }
1.322 misha 1094: case OP::OP_NUM_GT:
1.55 paf 1095: {
1.297 paf 1096: volatile double b_double=stack.pop().value().as_double();
1097: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1098: Value& value=VBool::get(a_double>b_double);
1.297 paf 1099: stack.push(value);
1.55 paf 1100: break;
1101: }
1.322 misha 1102: case OP::OP_NUM_LE:
1.55 paf 1103: {
1.297 paf 1104: volatile double b_double=stack.pop().value().as_double();
1105: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1106: Value& value=VBool::get(a_double<=b_double);
1.297 paf 1107: stack.push(value);
1.55 paf 1108: break;
1109: }
1.322 misha 1110: case OP::OP_NUM_GE:
1.55 paf 1111: {
1.297 paf 1112: volatile double b_double=stack.pop().value().as_double();
1113: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1114: Value& value=VBool::get(a_double>=b_double);
1.297 paf 1115: stack.push(value);
1.55 paf 1116: break;
1117: }
1.322 misha 1118: case OP::OP_NUM_EQ:
1.55 paf 1119: {
1.297 paf 1120: volatile double b_double=stack.pop().value().as_double();
1121: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1122: Value& value=VBool::get(a_double==b_double);
1.297 paf 1123: stack.push(value);
1.55 paf 1124: break;
1125: }
1.322 misha 1126: case OP::OP_NUM_NE:
1.55 paf 1127: {
1.297 paf 1128: volatile double b_double=stack.pop().value().as_double();
1129: volatile double a_double=stack.pop().value().as_double();
1.327 misha 1130: Value& value=VBool::get(a_double!=b_double);
1.297 paf 1131: stack.push(value);
1.54 paf 1132: break;
1133: }
1.322 misha 1134: case OP::OP_STR_LT:
1.58 paf 1135: {
1.297 paf 1136: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1137: Value& value=VBool::get(a.as_string() < b.as_string());
1.297 paf 1138: stack.push(value);
1.58 paf 1139: break;
1140: }
1.322 misha 1141: case OP::OP_STR_GT:
1.58 paf 1142: {
1.297 paf 1143: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1144: Value& value=VBool::get(a.as_string() > b.as_string());
1.297 paf 1145: stack.push(value);
1.58 paf 1146: break;
1147: }
1.322 misha 1148: case OP::OP_STR_LE:
1.58 paf 1149: {
1.297 paf 1150: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1151: Value& value=VBool::get(a.as_string() <= b.as_string());
1.297 paf 1152: stack.push(value);
1.58 paf 1153: break;
1154: }
1.322 misha 1155: case OP::OP_STR_GE:
1.54 paf 1156: {
1.297 paf 1157: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1158: Value& value=VBool::get(a.as_string() >= b.as_string());
1.297 paf 1159: stack.push(value);
1.58 paf 1160: break;
1161: }
1.322 misha 1162: case OP::OP_STR_EQ:
1.58 paf 1163: {
1.297 paf 1164: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1165: Value& value=VBool::get(a.as_string() == b.as_string());
1.297 paf 1166: stack.push(value);
1.58 paf 1167: break;
1168: }
1.322 misha 1169: case OP::OP_STR_NE:
1.58 paf 1170: {
1.297 paf 1171: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1172: Value& value=VBool::get(a.as_string() != b.as_string());
1.297 paf 1173: stack.push(value);
1.103 paf 1174: break;
1175: }
1.322 misha 1176: case OP::OP_IS:
1.103 paf 1177: {
1.297 paf 1178: Value& b=stack.pop().value(); Value& a=stack.pop().value();
1.327 misha 1179: Value& value=VBool::get(a.is(b.as_string().cstr()));
1.297 paf 1180: stack.push(value);
1.28 paf 1181: break;
1182: }
1183:
1.11 paf 1184: default:
1.223 paf 1185: throw Exception(0,
1.67 paf 1186: 0,
1.297 paf 1187: "invalid opcode %d", opcode);
1.11 paf 1188: }
1189: }
1.306 paf 1190: } catch(const Exception&) {
1.297 paf 1191: // record it to stack trace
1.301 paf 1192: if(debug_name)
1193: exception_trace.push(Trace(debug_name, debug_origin));
1.297 paf 1194: rethrow;
1195: }
1.1 paf 1196: }
1.17 paf 1197:
1.330 misha 1198: #define SAVE_CONTEXT \
1199: VMethodFrame *saved_method_frame=method_frame; \
1200: Value* saved_rcontext=rcontext; \
1201: WContext *saved_wcontext=wcontext;
1202:
1203: #define RESTORE_CONTEXT \
1204: wcontext=saved_wcontext; \
1205: rcontext=saved_rcontext; \
1206: method_frame=saved_method_frame;
1207:
1.350 misha 1208: void Request::op_call(VMethodFrame& frame, bool constructing){
1.332 misha 1209: const Junction &junction=frame.junction;
1210: VStateless_class& called_class=*junction.self.get_class();
1.319 misha 1211: Value* new_self;
1.332 misha 1212:
1.350 misha 1213: if(constructing) {
1.332 misha 1214: if(junction.method->call_type!=Method::CT_STATIC) {
1.319 misha 1215: // this is a constructor call
1.354 ! misha 1216: if(new_self=called_class.create_new_value(fpool)) {
1.319 misha 1217: // some stateless_class creatable derivates
1218: } else
1219: throw Exception(PARSER_RUNTIME,
1220: 0, //&frame.name(),
1221: "is not a constructor, system class '%s' can be constructed only implicitly",
1222: called_class.name().cstr());
1223:
1224: frame.write(*new_self,
1225: String::L_CLEAN // not used, always an object, not string
1226: );
1227: } else
1228: throw Exception(PARSER_RUNTIME,
1229: 0, //&frame.name(),
1230: "method is static and can not be used as constructor");
1.332 misha 1231: } else
1232: new_self=&junction.self;
1.319 misha 1233:
1234: frame.set_self(*new_self);
1235:
1236: // see OP_PREPARE_TO_EXPRESSION
1237: frame.set_in_expression(wcontext->get_in_expression());
1238:
1.332 misha 1239: SAVE_CONTEXT
1240:
1.319 misha 1241: rcontext=wcontext=&frame;
1.332 misha 1242: method_frame=&frame;
1.319 misha 1243:
1.332 misha 1244: const Method& method=*junction.method;
1245: Method::Call_type call_type=&called_class==new_self ? Method::CT_STATIC : Method::CT_DYNAMIC;
1.319 misha 1246:
1.332 misha 1247: if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type?
1248: if(method.native_code) { // native code?
1249: method.check_actual_numbered_params(junction.self, frame.numbered_params());
1250: method.native_code(*this, *frame.numbered_params()); // execute it
1251: } else // parser code, execute it
1252: recoursion_checked_execute(*method.parser_code);
1253: } else
1254: throw Exception(PARSER_RUNTIME,
1255: 0,
1256: "is not allowed to be called %s",
1257: call_type==Method::CT_STATIC?"statically":"dynamically");
1.334 misha 1258:
1.330 misha 1259: RESTORE_CONTEXT
1.332 misha 1260: //return &frame;
1261: }
1262:
1263: void Request::op_call_write(VMethodFrame& frame){
1264: const Junction &junction=frame.junction;
1265:
1266: frame.set_self(junction.self);
1267:
1268: VMethodFrame *saved_method_frame=method_frame;
1269: Value* saved_rcontext=rcontext;
1.319 misha 1270:
1.332 misha 1271: rcontext=&frame;
1272: method_frame=&frame;
1273:
1274: const Method& method=*junction.method;
1275: Method::Call_type call_type=junction.self.get_class()==&junction.self ? Method::CT_STATIC : Method::CT_DYNAMIC;
1276:
1.333 misha 1277: if(method.call_type==Method::CT_ANY || method.call_type==call_type) { // allowed call type?
1278: if(method.native_code) { // native code?
1279: method.check_actual_numbered_params(junction.self, frame.numbered_params());
1280: method.native_code(*this, *frame.numbered_params()); // execute it
1281: } else // parser code, execute it
1282: recoursion_checked_execute(*method.parser_code);
1.332 misha 1283: } else
1284: throw Exception(PARSER_RUNTIME,
1285: 0,
1286: "is not allowed to be called %s",
1287: call_type==Method::CT_STATIC?"statically":"dynamically");
1288:
1289: rcontext=saved_rcontext;
1290: method_frame=saved_method_frame;
1.319 misha 1291: }
1292:
1.330 misha 1293: Value& Request::get_element(Value& ncontext, const String& name) {
1.353 misha 1294: if(wcontext->get_somebody_entered_some_class()) // ^class:method
1295: if(VStateless_class *called_class=ncontext.get_class())
1296: if(VStateless_class *read_class=rcontext->get_class())
1.354 ! misha 1297: if(read_class->derived_from(*called_class)){ // current derived from called
! 1298: Value *value=called_class->get_element(get_self(), name);
! 1299: return *(value ? &process_to_value(*value) : VVoid::get());
! 1300: }
1.330 misha 1301:
1.354 ! misha 1302: Value* value=ncontext.get_element(name);
1.291 paf 1303:
1.330 misha 1304: return *(value ? &process_to_value(*value) : VVoid::get());
1.309 paf 1305: }
1306:
1.329 misha 1307: void Request::put_element(Value& ncontext, const String& name, Value* value) {
1.309 paf 1308: // put_element can return property-setting-junction
1.354 ! misha 1309: if(const VJunction* vjunction=ncontext.put_element(name, value, false))
1.312 paf 1310: if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) {
1.309 paf 1311: // process it
1.329 misha 1312: VMethodFrame frame(vjunction->junction(), method_frame/*caller*/);
1313:
1.352 misha 1314: size_t param_count=frame.method_params_count();
1.309 paf 1315: if(param_count!=1)
1.316 misha 1316: throw Exception(PARSER_RUNTIME,
1.309 paf 1317: 0,
1318: "setter method must have ONE parameter (has %d parameters)", param_count);
1319:
1.329 misha 1320: frame.store_params(&value, 1);
1.309 paf 1321: frame.set_self(frame.junction.self);
1322:
1.330 misha 1323: SAVE_CONTEXT
1.309 paf 1324:
1325: rcontext=wcontext=&frame;
1326: method_frame=&frame;
1327:
1.311 paf 1328: // prevent non-string writes for better error reporting [setters are not expected to return anything]
1.309 paf 1329: wcontext->write(*method_frame);
1330:
1331: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1332: // we don't need it StringOrValue result=wcontext->result();
1333:
1.330 misha 1334: RESTORE_CONTEXT
1.309 paf 1335: }
1.34 paf 1336: }
1.70 paf 1337:
1.162 parser 1338: /** @param intercept_string
1.116 paf 1339: - true:
1340: they want result=string value,
1341: possible object result goes to wcontext
1342: - false:
1343: they want any result[string|object]
1344: nothing goes to wcontext.
1.125 paf 1345: used in @c (expression) params evaluation
1.224 paf 1346:
1.334 misha 1347: using the fact it's either string_ or value_ result requested to speed up checkes
1.116 paf 1348: */
1.229 paf 1349: StringOrValue Request::process(Value& input_value, bool intercept_string) {
1.297 paf 1350: Junction* junction=input_value.get_junction();
1.307 paf 1351: if(junction) {
1352: if(junction->is_getter) { // is it a getter-junction?
1.329 misha 1353: VMethodFrame frame(*junction, method_frame/*caller*/);
1354:
1.352 misha 1355: if(size_t param_count=frame.method_params_count()){
1.331 misha 1356: if(junction->auto_name){ // default getter
1357: if(param_count==1){
1358: Value *param=new VString(*junction->auto_name);
1359: frame.store_params(¶m, 1);
1360: } else
1361: throw Exception(PARSER_RUNTIME,
1362: 0,
1363: "default getter method can't have more then 1 parameter (has %d parameters)", param_count);
1364: } else
1.320 misha 1365: throw Exception(PARSER_RUNTIME,
1366: 0,
1.331 misha 1367: "getter method must have no parameters (has %d parameters)", param_count);
1368: } // no need for else frame.empty_params()
1.320 misha 1369:
1.307 paf 1370: frame.set_self(frame.junction.self);
1371:
1.330 misha 1372: SAVE_CONTEXT
1.307 paf 1373:
1374: rcontext=wcontext=&frame;
1375: method_frame=&frame;
1376:
1377: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1378: StringOrValue result=wcontext->result();
1379:
1.330 misha 1380: RESTORE_CONTEXT
1.307 paf 1381:
1382: return result;
1383: }
1384:
1385: if(junction->code) { // is it a code-junction?
1386: // process it
1387: StringOrValue result;
1.336 misha 1388:
1389: DEBUG_PRINT_STR("ja->\n")
1.238 paf 1390:
1.307 paf 1391: if(!junction->method_frame)
1.316 misha 1392: throw Exception(PARSER_RUNTIME,
1.352 misha 1393: 0,
1394: "junction used outside of context");
1.240 paf 1395:
1.330 misha 1396: SAVE_CONTEXT
1.307 paf 1397:
1398: method_frame=junction->method_frame;
1399: rcontext=junction->rcontext;
1400:
1401: // for expression method params
1402: // wcontext is set 0
1403: // using the fact in decision "which wwrapper to use"
1404: bool using_code_frame=intercept_string && junction->wcontext;
1405: if(using_code_frame) {
1.318 misha 1406: // almost plain wwrapper about junction wcontext
1407:
1408: VCodeFrame local(*junction->wcontext);
1.307 paf 1409: wcontext=&local;
1410:
1411: // execute it
1412: recoursion_checked_execute(*junction->code);
1413:
1414: // CodeFrame soul:
1.318 misha 1415: result=wcontext->result();
1.307 paf 1416: } else {
1417: // plain wwrapper
1.351 misha 1418: WWrapper local(wcontext);
1.307 paf 1419: wcontext=&local;
1420:
1421: // execute it
1422: recoursion_checked_execute(*junction->code);
1423:
1424: result=wcontext->result();
1425: }
1426:
1.330 misha 1427: RESTORE_CONTEXT
1.207 paf 1428:
1.336 misha 1429: DEBUG_PRINT_STR("<-ja returned")
1430:
1.307 paf 1431: return result;
1432: }
1433:
1434: // it is then method-junction, do not explode it
1435: // just return it as we do for usual objects
1436: }
1437:
1438: return input_value;
1.85 paf 1439: }
1440:
1.332 misha 1441: void Request::process_write(Value& input_value) {
1442: Junction* junction=input_value.get_junction();
1443: if(junction) {
1444: if(junction->is_getter) { // is it a getter-junction?
1445: VMethodFrame frame(*junction, method_frame/*caller*/);
1446:
1.352 misha 1447: if(size_t param_count=frame.method_params_count()){
1.332 misha 1448: if(junction->auto_name){ // default getter
1449: if(param_count==1){
1450: Value *param=new VString(*junction->auto_name);
1451: frame.store_params(¶m, 1);
1452: } else
1453: throw Exception(PARSER_RUNTIME,
1454: 0,
1455: "default getter method can't have more then 1 parameter (has %d parameters)", param_count);
1456: } else
1457: throw Exception(PARSER_RUNTIME,
1458: 0,
1459: "getter method must have no parameters (has %d parameters)", param_count);
1460: } // no need for else frame.empty_params()
1461:
1462: frame.set_self(frame.junction.self);
1463:
1464: SAVE_CONTEXT
1465:
1466: rcontext=wcontext=&frame;
1467: method_frame=&frame;
1468:
1469: recoursion_checked_execute(*frame.junction.method->parser_code); // parser code, execute it
1470:
1471: RESTORE_CONTEXT
1472:
1473: write_pass_lang(frame.result());
1474: return;
1475: }
1476:
1477: if(junction->code) { // is it a code-junction?
1478: // process it
1.336 misha 1479:
1480: DEBUG_PRINT_STR("ja->\n")
1481:
1.332 misha 1482: if(!junction->method_frame)
1483: throw Exception(PARSER_RUNTIME,
1484: 0,
1485: "junction used outside of context");
1486:
1487: SAVE_CONTEXT
1488:
1489: method_frame=junction->method_frame;
1490: rcontext=junction->rcontext;
1491:
1492: // for expression method params
1493: // wcontext is set 0
1494: // using the fact in decision "which wwrapper to use"
1495: #ifdef OPTIMIZE_CALL
1496: if(wcontext==junction->wcontext){
1497: // no wrappers for wcontext
1498: recoursion_checked_execute(*junction->code);
1499: RESTORE_CONTEXT
1500:
1501: } else
1502: #endif
1503: if(junction->wcontext) {
1504: // almost plain wwrapper about junction wcontext
1505: VCodeFrame local(*junction->wcontext);
1506: wcontext=&local;
1507:
1508: // execute it
1509: recoursion_checked_execute(*junction->code);
1510: RESTORE_CONTEXT
1511: write_pass_lang(local.result());
1512: } else {
1513: // plain wwrapper
1.351 misha 1514: WWrapper local(wcontext);
1.332 misha 1515: wcontext=&local;
1516:
1517: // execute it
1518: recoursion_checked_execute(*junction->code);
1519: RESTORE_CONTEXT
1520: write_pass_lang(local.result());
1521: }
1.336 misha 1522:
1523: DEBUG_PRINT_STR("<-ja returned")
1524:
1.332 misha 1525: return;
1526: }
1527:
1528: // it is then method-junction, do not explode it
1529: // just return it as we do for usual objects
1530: }
1531:
1532: write_pass_lang(input_value);
1533: }
1534:
1.298 paf 1535: StringOrValue Request::execute_method(VMethodFrame& amethod_frame, const Method& method) {
1.330 misha 1536: SAVE_CONTEXT
1.99 paf 1537:
1538: // initialize contexts
1.286 paf 1539: rcontext=wcontext=method_frame=&amethod_frame;
1.99 paf 1540:
1541: // execute!
1542: execute(*method.parser_code);
1543:
1544: // result
1.298 paf 1545: StringOrValue result=wcontext->result();
1.208 paf 1546:
1.330 misha 1547: RESTORE_CONTEXT
1.242 paf 1548:
1549: // return
1550: return result;
1.208 paf 1551: }
1552:
1.297 paf 1553: const String* Request::execute_method(Value& aself,
1.329 misha 1554: const Method& method, Value* optional_param,
1555: bool do_return_string) {
1.317 misha 1556:
1.330 misha 1557: SAVE_CONTEXT
1.208 paf 1558:
1.307 paf 1559: Junction local_junction(aself, &method);
1.321 misha 1560: VMethodFrame local_frame(local_junction, method_frame/*caller*/);
1.329 misha 1561: if(optional_param && local_frame.method_params_count()>0) {
1562: local_frame.store_params(&optional_param, 1);
1.330 misha 1563: } else {
1564: local_frame.empty_params();
1.242 paf 1565: }
1.285 paf 1566: local_frame.set_self(aself);
1.257 paf 1567: rcontext=wcontext=method_frame=&local_frame;
1.246 paf 1568:
1569: // prevent non-string writes for better error reporting
1.297 paf 1570: if(do_return_string)
1.246 paf 1571: wcontext->write(local_frame);
1.208 paf 1572:
1573: // execute!
1574: execute(*method.parser_code);
1575:
1576: // result
1.297 paf 1577: const String* result=0;
1578: if(do_return_string)
1579: result=&wcontext->result().as_string();
1.99 paf 1580:
1.330 misha 1581: RESTORE_CONTEXT
1.297 paf 1582:
1583: return result;
1.242 paf 1584: }
1585:
1.297 paf 1586: Request::Execute_nonvirtual_method_result
1587: Request::execute_nonvirtual_method(VStateless_class& aclass,
1.330 misha 1588: const String& method_name,
1589: VString* optional_param,
1590: bool do_return_string) {
1.297 paf 1591: Execute_nonvirtual_method_result result;
1592: result.method=aclass.get_method(method_name);
1593: if(result.method)
1.317 misha 1594: result.string=execute_method(aclass, *result.method, optional_param, do_return_string);
1.297 paf 1595: return result;
1.99 paf 1596: }
1597:
1.297 paf 1598: const String* Request::execute_virtual_method(Value& aself,
1.330 misha 1599: const String& method_name) {
1.354 ! misha 1600: if(Value* value=aself.get_element(method_name))
1.297 paf 1601: if(Junction* junction=value->get_junction())
1602: if(const Method *method=junction->method)
1603: return execute_method(aself, *method, 0/*no params*/, true);
1.188 parser 1604:
1.176 parser 1605: return 0;
1606: }