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