--- parser3/src/main/execute.C 2001/07/26 14:15:45 1.187 +++ parser3/src/main/execute.C 2001/11/14 07:46:42 1.204 @@ -2,10 +2,10 @@ Parser: executor part of request class. Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexander Petrosyan (http://paf.design.ru) - Author: Alexander Petrosyan (http://design.ru/paf) + $Id: execute.C,v 1.204 2001/11/14 07:46:42 paf Exp $ */ -static const char *RCSId="$Id: execute.C,v 1.187 2001/07/26 14:15:45 parser Exp $"; #include "pa_opcode.h" #include "pa_array.h" @@ -21,10 +21,11 @@ static const char *RCSId="$Id: execute.C #include "pa_vtable.h" #include "pa_vfile.h" #include "pa_vimage.h" +#include "pa_wwrapper.h" //#define DEBUG_EXECUTE -const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500; +const uint ANTI_ENDLESS_EXECUTE_RECOURSION=200; #ifdef DEBUG_EXECUTE char *opcode_name[]={ @@ -46,7 +47,7 @@ char *opcode_name[]={ // expression ops: unary "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS", // expression ops: binary - "SUB", "ADD", "MUL", "DIV", "MOD", + "SUB", "ADD", "MUL", "DIV", "MOD", "INTDIV", "BIN_AND", "BIN_OR", "BIN_XOR", "LOG_AND", "LOG_OR", "LOG_XOR", "NUM_LT", "NUM_GT", "NUM_LE", "NUM_GE", "NUM_EQ", "NUM_NE", @@ -68,24 +69,13 @@ void debug_printf(Pool& pool, const char } void debug_dump(Pool& pool, int level, const Array& ops) { -/* { - int size=ops.quick_size(); - //debug_printf(pool, "size=%d\n", size); - for(int i=0; i(ops.quick_get(++i)); + Value *value=static_cast(i.next()); debug_printf(pool, "%*s%s" " \"%s\" %s", @@ -99,7 +89,7 @@ void debug_dump(Pool& pool, int level, c case OP_CURLY_CODE__STORE_PARAM: case OP_EXPR_CODE__STORE_PARAM: case OP_CURLY_CODE__CONSTRUCT: - const Array *local_ops=reinterpret_cast(ops.quick_get(++i)); + const Array *local_ops=reinterpret_cast(i.next()); debug_dump(pool, level+1, *local_ops); } } @@ -111,26 +101,28 @@ void debug_dump(Pool& pool, int level, c #define POP_NAME() static_cast(stack.pop())->as_string() void Request::execute(const Array& ops) { +// _asm int 3; #ifdef DEBUG_EXECUTE debug_printf(pool(), "source----------------------------\n"); debug_dump(pool(), 0, ops); debug_printf(pool(), "execution-------------------------\n"); #endif - int size=ops.quick_size(); - //debug_printf(pool(), "size=%d\n", size); - for(int i=0; i(ops.quick_get(++i)); + value=static_cast(i.next()); #ifdef DEBUG_EXECUTE debug_printf(pool(), " \"%s\" %s", value->get_string()->cstr(), value->type()); #endif @@ -142,7 +134,7 @@ void Request::execute(const Array& ops) { VMethodFrame *frame=static_cast(stack.top_value()); // code - const Array *local_ops=reinterpret_cast(ops.quick_get(++i)); + const Array *local_ops=reinterpret_cast(i.next()); #ifdef DEBUG_EXECUTE debug_printf(pool(), " (%d)\n", local_ops->size()); debug_dump(pool(), 1, *local_ops); @@ -161,7 +153,7 @@ void Request::execute(const Array& ops) op.code==OP_EXPR_CODE__STORE_PARAM?0:wcontext, local_ops); - Value *value=NEW VJunction(j); + value=NEW VJunction(j); // store param frame->store_param(frame->name(), value); @@ -173,9 +165,9 @@ void Request::execute(const Array& ops) wcontext->set_somebody_entered_some_class(); const String& name=POP_NAME(); - Value *value=static_cast(classes().get(name)); + value=static_cast(classes().get(name)); if(!value) - THROW(0,0, + throw Exception(0,0, &name, "class is undefined"); @@ -208,7 +200,7 @@ void Request::execute(const Array& ops) // OTHER ACTIONS BUT WITHs case OP_CONSTRUCT_VALUE: { - Value *value=POP(); + value=POP(); const String& name=POP_NAME(); Value *ncontext=POP(); ncontext->put_element(name, value); @@ -217,7 +209,7 @@ void Request::execute(const Array& ops) } case OP_CONSTRUCT_EXPR: { - Value *value=POP(); + value=POP(); const String& name=POP_NAME(); Value *ncontext=POP(); ncontext->put_element(name, value->as_expr_result()); @@ -226,7 +218,7 @@ void Request::execute(const Array& ops) } case OP_CURLY_CODE__CONSTRUCT: { - const Array *local_ops=reinterpret_cast(ops.quick_get(++i)); + const Array *local_ops=reinterpret_cast(i.next()); #ifdef DEBUG_EXECUTE debug_printf(pool(), " (%d)\n", local_ops->size()); debug_dump(pool(), 1, *local_ops); @@ -238,7 +230,7 @@ void Request::execute(const Array& ops) wcontext, local_ops); - Value *value=NEW VJunction(j); + value=NEW VJunction(j); const String& name=POP_NAME(); Value *ncontext=POP(); ncontext->put_element(name, value); @@ -247,23 +239,23 @@ void Request::execute(const Array& ops) } case OP_WRITE_VALUE: { - Value *value=POP(); + value=POP(); write_assign_lang(*value); // forget the fact they've entered some ^object.method[]. // see OP_GET_ELEMENT - wcontext->clear_somebody_entered_some_object(); + wcontext->set_somebody_entered_some_object(false); break; } case OP_WRITE_EXPR_RESULT: { - Value *value=POP(); + value=POP(); write_expr_result(*value->as_expr_result()); break; } case OP_STRING__WRITE: { - VString *vstring=static_cast(ops.quick_get(++i)); + VString *vstring=static_cast(i.next()); #ifdef DEBUG_EXECUTE debug_printf(pool(), " \"%s\"", vstring->string().cstr()); #endif @@ -274,17 +266,17 @@ void Request::execute(const Array& ops) case OP_GET_ELEMENT: { // maybe they do ^object.method[] call, remember the fact - wcontext->inc_somebody_entered_some_object(); + wcontext->set_somebody_entered_some_object(true); //_asm int 3; - Value *value=get_element(); + value=get_element(); PUSH(value); break; } case OP_GET_ELEMENT__WRITE: { - Value *value=get_element(); + value=get_element(); write_assign_lang(*value); break; } @@ -300,7 +292,7 @@ void Request::execute(const Array& ops) } case OP_REDUCE_EWPOOL: { - Value *value=wcontext->result(); + value=wcontext->result(); flang=static_cast(reinterpret_cast(POP())); wcontext=static_cast(POP()); PUSH(value); @@ -331,14 +323,14 @@ void Request::execute(const Array& ops) // CALL case OP_GET_METHOD_FRAME: { - Value *value=POP(); + value=POP(); // info: // code compiled so that this one's always method-junction, // not a code-junction Junction *junction=value->get_junction(); if(!junction) - THROW(0, 0, + throw Exception(0, 0, &value->name(), "(%s) not a method or junction, can not call it", value->type()); @@ -349,7 +341,7 @@ void Request::execute(const Array& ops) } case OP_STORE_PARAM: { - Value *value=POP(); + value=POP(); VMethodFrame *frame=static_cast(stack.top_value()); frame->store_param(frame->name(), value); break; @@ -357,7 +349,7 @@ void Request::execute(const Array& ops) case OP_PREPARE_TO_CONSTRUCT_OBJECT: { - wcontext->constructing(true); + wcontext->set_constructing(true); break; } case OP_CALL: @@ -373,23 +365,25 @@ void Request::execute(const Array& ops) PUSH(wcontext); VStateless_class *called_class=frame->junction.self.get_class(); - if(wcontext->constructing()) { - wcontext->constructing(false); + if(wcontext->get_constructing()) { + wcontext->set_constructing(false); if(frame->junction.method->call_type!=Method::CT_STATIC) { // this is a constructor call if(Value *value=called_class->create_new_value(pool())) { - // some stateless_object creatable derivates + // some stateless_class creatable derivates self=value; - } else { - // stateful object - self=NEW VObject(pool(), *called_class); - } + } else + throw Exception(0, 0, + &frame->name(), + "is not a constructor, system class '%s' can be constructed only implicitly", + called_class->name().cstr()); + frame->write(*self, String::UL_CLEAN // not used, always an object, not string ); } else - THROW(0, 0, + throw Exception(0, 0, &frame->name(), "method is static and can not be used as constructor"); } else { @@ -399,8 +393,8 @@ void Request::execute(const Array& ops) // is context object or class & is it my class or my parent's class and? VStateless_class *read_class=rcontext->get_class(); if( - !(wcontext->somebody_entered_some_object() && - !wcontext->somebody_entered_some_class()) && + !(wcontext->get_somebody_entered_some_object() && + !wcontext->get_somebody_entered_some_class()) && read_class && read_class->is_or_derived_from(*called_class)) // yes self=rcontext; // dynamic call else // no, not me or relative of mine (=total stranger) @@ -408,7 +402,7 @@ void Request::execute(const Array& ops) } frame->set_self(*self); - root=rcontext=wcontext=frame; + rcontext=wcontext=frame; { // take object or class from any wrappers // and substitute class alias to the class they are called AS @@ -419,33 +413,41 @@ void Request::execute(const Array& ops) called_class==self ? Method::CT_STATIC : Method::CT_DYNAMIC; if( method.call_type==Method::CT_ANY || - method.call_type==call_type) // allowed call type? - if(method.native_code) { // native code? - method.check_actual_numbered_params(pool(), - frame->junction.self, - frame->name(), frame->numbered_params()); - method.native_code( - *this, - frame->name(), frame->numbered_params()); // execute it - } else { // parser code - if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { - anti_endless_execute_recoursion=0; // give @exception a chance - THROW(0, 0, - &frame->name(), - "endless recursion detected"); + method.call_type==call_type) { // allowed call type? + try { + if(method.native_code) { // native code? + // root unchanged, so that ^for ^foreach & co may write to locals + method.check_actual_numbered_params( + frame->junction.self, + frame->name(), frame->numbered_params()); + method.native_code( + *this, + frame->name(), frame->numbered_params()); // execute it + } else { // parser code + root=frame; + if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { + anti_endless_execute_recoursion=0; // give @exception a chance + throw Exception(0, 0, + &frame->name(), + "endless recursion detected"); + } + + execute(*method.parser_code); // execute it + anti_endless_execute_recoursion--; } - - execute(*method.parser_code); // execute it - anti_endless_execute_recoursion--; + } catch(...) { + // record it to stack trace + trace.push((void *)&frame->name()); + /*re*/throw; } - else - THROW(0, 0, + } else + throw Exception(0, 0, &frame->name(), "is not allowed to be called %s", call_type==Method::CT_STATIC?"statically":"dynamically"); } - Value *value=wcontext->result(); + value=wcontext->result(); wcontext=static_cast(POP()); rcontext=POP(); @@ -463,36 +465,37 @@ void Request::execute(const Array& ops) case OP_NEG: { Value *operand=POP(); - Value *value=NEW VDouble(pool(), -operand->as_double()); + value=NEW VDouble(pool(), -operand->as_double()); PUSH(value); break; } case OP_INV: { Value *operand=POP(); - Value *value=NEW VDouble(pool(), ~operand->as_int()); + value=NEW VDouble(pool(), ~operand->as_int()); PUSH(value); break; } case OP_NOT: { Value *operand=POP(); - Value *value=NEW VBool(pool(), !operand->as_bool()); + value=NEW VBool(pool(), !operand->as_bool()); PUSH(value); break; } case OP_DEF: { Value *operand=POP(); - Value *value=NEW VBool(pool(), operand->is_defined()); + value=NEW VBool(pool(), operand->is_defined()); PUSH(value); break; } case OP_IN: { + /// @test String::cmp Value *operand=POP(); const char *path=operand->as_string().cstr(); - Value *value=NEW VBool(pool(), + value=NEW VBool(pool(), info.uri && strncmp(path, info.uri, strlen(path))==0); PUSH(value); break; @@ -500,7 +503,7 @@ void Request::execute(const Array& ops) case OP_FEXISTS: { Value *operand=POP(); - Value *value=NEW VBool(pool(), + value=NEW VBool(pool(), file_readable(absolute(operand->as_string()))); PUSH(value); break; @@ -508,7 +511,7 @@ void Request::execute(const Array& ops) case OP_DEXISTS: { Value *operand=POP(); - Value *value=NEW VBool(pool(), + value=NEW VBool(pool(), dir_readable(absolute(operand->as_string()))); PUSH(value); break; @@ -517,28 +520,28 @@ void Request::execute(const Array& ops) // expression ops: binary case OP_SUB: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), a->as_double() - b->as_double()); + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_double() - b->as_double()); PUSH(value); break; } case OP_ADD: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), a->as_double() + b->as_double()); + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_double() + b->as_double()); PUSH(value); break; } case OP_MUL: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), a->as_double() * b->as_double()); + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_double() * b->as_double()); PUSH(value); break; } case OP_DIV: { - Value *b=POP(); Value *a=POP(); + b=POP(); a=POP(); double a_double=a->as_double(); double b_double=b->as_double(); @@ -549,18 +552,18 @@ void Request::execute(const Array& ops) if(!problem_source->origin().file) problem_source=&b->name(); #endif - THROW(0, 0, + throw Exception(0, 0, problem_source, "Division by zero"); } - Value *value=NEW VDouble(pool(), a_double / b_double); + value=NEW VDouble(pool(), a_double / b_double); PUSH(value); break; } case OP_MOD: { - Value *b=POP(); Value *a=POP(); + b=POP(); a=POP(); double a_double=a->as_double(); double b_double=b->as_double(); @@ -571,19 +574,41 @@ void Request::execute(const Array& ops) if(!problem_source->origin().file) problem_source=&b->name(); #endif - THROW(0, 0, + throw Exception(0, 0, problem_source, "Modulus by zero"); } - Value *value=NEW VDouble(pool(), fmod(a_double, b_double)); + value=NEW VDouble(pool(), fmod(a_double, b_double)); + PUSH(value); + break; + } + case OP_INTDIV: + { + b=POP(); a=POP(); + + int a_int=a->as_int(); + int b_int=b->as_int(); + + if(b_int == 0) { + const String *problem_source=&b->as_string(); +#ifndef NO_STRING_ORIGIN + if(!problem_source->origin().file) + problem_source=&b->name(); +#endif + throw Exception(0, 0, + problem_source, + "Division by zero"); + } + + value=NEW VInt(pool(), a_int / b_int); PUSH(value); break; } case OP_BIN_AND: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_int() & b->as_int()); PUSH(value); @@ -591,8 +616,8 @@ void Request::execute(const Array& ops) } case OP_BIN_OR: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_int() | b->as_int()); PUSH(value); @@ -600,8 +625,8 @@ void Request::execute(const Array& ops) } case OP_BIN_XOR: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), + b=POP(); a=POP(); + value=NEW VDouble(pool(), a->as_int() ^ b->as_int()); PUSH(value); @@ -609,119 +634,120 @@ void Request::execute(const Array& ops) } case OP_LOG_AND: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_bool() && b->as_bool()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_bool() && b->as_bool()); PUSH(value); break; } case OP_LOG_OR: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_bool() || b->as_bool()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_bool() || b->as_bool()); PUSH(value); break; } case OP_LOG_XOR: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_bool() ^ b->as_bool()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_bool() ^ b->as_bool()); PUSH(value); break; } case OP_NUM_LT: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() < b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() < b->as_double()); PUSH(value); break; } case OP_NUM_GT: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() > b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() > b->as_double()); PUSH(value); break; } case OP_NUM_LE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() <= b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() <= b->as_double()); PUSH(value); break; } case OP_NUM_GE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() >= b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() >= b->as_double()); PUSH(value); break; } case OP_NUM_EQ: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() == b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() == b->as_double()); PUSH(value); break; } case OP_NUM_NE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_double() != b->as_double()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_double() != b->as_double()); PUSH(value); break; } case OP_STR_LT: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() < b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() < b->as_string()); PUSH(value); break; } case OP_STR_GT: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() > b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() > b->as_string()); PUSH(value); break; } case OP_STR_LE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() <= b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() <= b->as_string()); PUSH(value); break; } case OP_STR_GE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() >= b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() >= b->as_string()); PUSH(value); break; } case OP_STR_EQ: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() == b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() == b->as_string()); PUSH(value); break; } case OP_STR_NE: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), a->as_string() != b->as_string()); + b=POP(); a=POP(); + value=NEW VBool(pool(), a->as_string() != b->as_string()); PUSH(value); break; } case OP_IS: { - Value *b=POP(); Value *a=POP(); - Value *value=NEW VBool(pool(), b->as_string() == a->type()); + //_asm int 3; + b=POP(); a=POP(); + value=NEW VBool(pool(), b->as_string() == a->type()); PUSH(value); break; } default: - THROW(0,0, + throw Exception(0,0, 0, "invalid opcode %d", op.code); } @@ -736,7 +762,7 @@ Value *Request::get_element() { if(Method* method=OP.get_method(name)) { // maybe operator? // as if that method were in self and we have normal dynamic method here Junction& junction=*NEW Junction(pool(), - *self, self->get_class(), method, 0,0,0,0); + *root, self->get_class(), method, 0,0,0,0); value=NEW VJunction(junction); } if(value) @@ -852,7 +878,7 @@ const String *Request::execute_virtual_m if(Junction *junction=value->get_junction()) if(const Method *method=junction->method) return execute_method(aself, *method, return_cstr); - + return 0; }