Annotation of parser3/src/main/execute.C, revision 1.337

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

E-mail: