this shouldn't be in svn
[supertux.git] / src / squirrel / squirrel / sqvm.cpp
index 3137b0a..b13ae24 100644 (file)
@@ -82,6 +82,7 @@ SQVM::SQVM(SQSharedState *ss)
        _lasterror = _null_;\r
        _errorhandler = _null_;\r
        _debughook = _null_;\r
+       ci = NULL;\r
        INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
 }\r
 \r
@@ -112,6 +113,7 @@ bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr
                case _SC('/'): mm=MT_DIV; break;\r
                case _SC('*'): mm=MT_MUL; break;\r
                case _SC('%'): mm=MT_MODULO; break;\r
+               default: mm = MT_ADD; assert(0); break; //shutup compiler\r
        }\r
        if(is_delegable(o1) && _delegable(o1)->_delegate) {\r
                Push(o1);Push(o2);\r
@@ -140,8 +142,7 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
                                return true;\r
                        }\r
                }\r
-               return true;\r
-\r
+       default:break; //shutup compiler\r
        }\r
        Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));\r
        return false;\r
@@ -166,9 +167,11 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
                        Push(o1);Push(o2);\r
                        if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);\r
                        break;\r
+               default: break; //shutup compiler\r
                }\r
                if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
-               _RET_SUCCEED(_integer(res));\r
+                       _RET_SUCCEED(_integer(res));\r
+               \r
        }\r
        else{\r
                if(sq_isnumeric(o1) && sq_isnumeric(o2)){\r
@@ -235,49 +238,22 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
                        }\r
                }\r
        default:\r
-               scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),_rawval(o));\r
+               scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));\r
        }\r
        res = SQString::Create(_ss(this),_spval);\r
-       return;\r
 }\r
 \r
 \r
 bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)\r
 {\r
-       switch(type(obj))\r
-       {\r
-       case OT_STRING:\r
-               switch(type(str)){\r
-               case OT_STRING: {\r
-                       SQInteger l=_string(str)->_len,ol=_string(obj)->_len;\r
-                       SQChar *s=_sp(rsl(l+ol+1));\r
-                       memcpy(s,_stringval(str),rsl(l));memcpy(s+l,_stringval(obj),rsl(ol));s[l+ol]=_SC('\0');\r
-                       break;\r
-               }\r
-               case OT_FLOAT:\r
-                       scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%g%s"),_float(str),_stringval(obj));\r
-                       break;\r
-               case OT_INTEGER:\r
-                       scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%d%s"),_integer(str),_stringval(obj));\r
-                       break;\r
-               default:\r
-                       Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
-                       return false;\r
-               }\r
-               dest=SQString::Create(_ss(this),_spval);\r
-               break;\r
-       case OT_FLOAT:\r
-               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%g"),_stringval(str),_float(obj));\r
-               dest=SQString::Create(_ss(this),_spval);\r
-               break;\r
-       case OT_INTEGER:\r
-               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%d"),_stringval(str),_integer(obj));\r
-               dest=SQString::Create(_ss(this),_spval);\r
-               break;\r
-       default:\r
-               Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
-               return false;\r
-       }\r
+       SQObjectPtr a, b;\r
+       ToString(str, a);\r
+       ToString(obj, b);\r
+       SQInteger l = _string(a)->_len , ol = _string(b)->_len;\r
+       SQChar *s = _sp(rsl(l + ol + 1));\r
+       memcpy(s, _stringval(a), rsl(l)); \r
+       memcpy(s + l, _stringval(b), rsl(ol));\r
+       dest = SQString::Create(_ss(this), _spval, l + ol);\r
        return true;\r
 }\r
 \r
@@ -347,10 +323,8 @@ extern SQInstructionDesc g_InstrDesc[];
 bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteger stackbase,bool tailcall)\r
 {\r
        SQFunctionProto *func = _funcproto(closure->_function);\r
-       //const SQInteger outerssize = func->_outervalues.size();\r
-\r
+       \r
        const SQInteger paramssize = func->_parameters.size();\r
-       const SQInteger oldtop = _top;\r
        const SQInteger newtop = stackbase + func->_stacksize;\r
        \r
        \r
@@ -371,21 +345,27 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteg
                        return false;\r
                }\r
        }\r
-       \r
+\r
+       if(type(closure->_env) == OT_WEAKREF) {\r
+               _stack[stackbase] = _weakref(closure->_env)->_obj;\r
+       }\r
+\r
        if (!tailcall) {\r
-               PUSH_CALLINFO(this, CallInfo());\r
-               ci->_etraps = 0;\r
-               ci->_prevstkbase = stackbase - _stackbase;\r
-               ci->_target = target;\r
-               ci->_prevtop = _top - _stackbase;\r
-               ci->_ncalls = 1;\r
-               ci->_root = SQFalse;\r
+               CallInfo lc;\r
+               lc._etraps = 0;\r
+               lc._prevstkbase = stackbase - _stackbase;\r
+               lc._target = target;\r
+               lc._prevtop = _top - _stackbase;\r
+               lc._ncalls = 1;\r
+               lc._root = SQFalse;\r
+               PUSH_CALLINFO(this, lc);\r
        }\r
        else {\r
                ci->_ncalls++;\r
+               if(ci->_vargs.size) PopVarArgs(ci->_vargs);\r
        }\r
        ci->_vargs.size = (nargs - paramssize);\r
-       ci->_vargs.base = _vargsstack.size()-(nargs - paramssize);\r
+       ci->_vargs.base = _vargsstack.size()-(ci->_vargs.size);\r
        ci->_closure._unVal.pClosure = closure;\r
        ci->_closure._type = OT_CLOSURE;\r
        ci->_iv = &func->_instructions;\r
@@ -406,7 +386,7 @@ bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
        if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
                for(SQInteger i=0;i<ci->_ncalls;i++)\r
                        CallDebugHook(_SC('r'));\r
-                                               \r
+                       \r
        SQBool broot = ci->_root;\r
        SQInteger last_top = _top;\r
        SQInteger target = ci->_target;\r
@@ -420,10 +400,12 @@ bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
                else retval = _null_;\r
        }\r
        else {\r
-               if (_arg0 != MAX_FUNC_STACKSIZE)\r
-                       STK(target) = _stack[oldstackbase+_arg1];\r
-               else\r
-                       STK(target) = _null_;\r
+               if(target != -1) { //-1 is when a class contructor ret value has to be ignored\r
+                       if (_arg0 != MAX_FUNC_STACKSIZE)\r
+                               STK(target) = _stack[oldstackbase+_arg1];\r
+                       else\r
+                               STK(target) = _null_;\r
+               }\r
        }\r
 \r
        while (last_top >= _top) _stack[last_top--].Null();\r
@@ -461,10 +443,10 @@ bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjec
 \r
 #define arg0 (_i_._arg0)\r
 #define arg1 (_i_._arg1)\r
-#define sarg1 (*((SQInteger *)&_i_._arg1))\r
+#define sarg1 (*((SQInt32 *)&_i_._arg1))\r
 #define arg2 (_i_._arg2)\r
 #define arg3 (_i_._arg3)\r
-#define sarg3 (*((char *)&_i_._arg3))\r
+#define sarg3 ((SQInteger)*((signed char *)&_i_._arg3))\r
 \r
 SQRESULT SQVM::Suspend()\r
 {\r
@@ -530,8 +512,9 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
                        _generator(o1)->Resume(this, arg_2+1);\r
                        _FINISH(false);\r
                }\r
+       default: \r
+               Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));\r
        }\r
-       Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));\r
        return false; //cannot be hit(just to avoid warnings)\r
 }\r
 \r
@@ -566,7 +549,7 @@ bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
 {\r
        SQInteger nouters;\r
        SQClosure *closure = SQClosure::Create(_ss(this), func);\r
-       if(nouters = func->_outervalues.size()) {\r
+       if((nouters = func->_outervalues.size())) {\r
                closure->_outervalues.reserve(nouters);\r
                for(SQInteger i = 0; i<nouters; i++) {\r
                        SQOuterVar &v = func->_outervalues[i];\r
@@ -610,7 +593,7 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes
 {\r
        SQClass *base = NULL;\r
        SQObjectPtr attrs;\r
-       if(baseclass != MAX_LITERALS) {\r
+       if(baseclass != -1) {\r
                if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }\r
                base = _class(_stack._vals[_stackbase + baseclass]);\r
        }\r
@@ -618,6 +601,13 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes
                attrs = _stack._vals[_stackbase+attributes];\r
        }\r
        target = SQClass::Create(_ss(this),base);\r
+       if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {\r
+               int nparams = 2;\r
+               SQObjectPtr ret;\r
+               Push(target); Push(attrs);\r
+               Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false);\r
+               Pop(nparams);\r
+       }\r
        _class(target)->_attributes = attrs;\r
        return true;\r
 }\r
@@ -642,7 +632,30 @@ bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)
        return true;\r
 }\r
 \r
-bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, ExecutionType et)\r
+bool SQVM::IsFalse(SQObjectPtr &o)\r
+{\r
+       if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )\r
+               || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)\r
+{\r
+       switch(type(o)) {\r
+               case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_;\r
+                       break;\r
+               case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_;\r
+                       break;\r
+               default:\r
+                       Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o));\r
+                       return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)\r
 {\r
        if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
        _nnativecalls++;\r
@@ -684,6 +697,7 @@ exception_restore:
                                        CallDebugHook(_SC('l'),arg1);\r
                                continue;\r
                        case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue;\r
+                       case _OP_LOADINT: TARGET = (SQInteger)arg1; continue;\r
                        case _OP_DLOAD: TARGET = (*ci->_literals)[arg1]; STK(arg2) = (*ci->_literals)[arg3];continue;\r
                        case _OP_TAILCALL:\r
                                temp_reg = STK(arg1);\r
@@ -726,11 +740,20 @@ common_call:
                                                        outres = temp_reg;\r
                                                        return true;\r
                                                }\r
-                                               STK(ct_target) = temp_reg;\r
+                                               if(ct_target != -1) { //skip return value for contructors\r
+                                                       STK(ct_target) = temp_reg;\r
+                                               }\r
                                                                                   }\r
                                                break;\r
                                        case OT_CLASS:{\r
-                                               _GUARD(CreateClassInstance(_class(temp_reg),arg3,_stackbase+arg2,STK(ct_target)));\r
+                                               SQObjectPtr inst;\r
+                                               _GUARD(CreateClassInstance(_class(temp_reg),inst,temp_reg));\r
+                                               STK(ct_target) = inst;\r
+                                               ct_target = -1; //fakes return value target so that is not overwritten by the contructor\r
+                                               if(type(temp_reg) != OT_NULL) {\r
+                                                       _stack[_stackbase+arg2] = inst;\r
+                                                       goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the contructor)\r
+                                               }\r
                                                }\r
                                                break;\r
                                        case OT_TABLE:\r
@@ -782,7 +805,7 @@ common_prepcall:
                                continue;\r
                        case _OP_MOVE: TARGET = STK(arg1); continue;\r
                        case _OP_NEWSLOT:\r
-                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
+                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));\r
                                if(arg0 != arg3) TARGET = STK(arg3);\r
                                continue;\r
                        case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;\r
@@ -831,17 +854,7 @@ common_prepcall:
                        case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;\r
                        case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;\r
                        case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL);  continue;\r
-                       case _OP_GETPARENT:\r
-                               switch(type(STK(arg1))) {\r
-                               case OT_TABLE: \r
-                       TARGET = _table(STK(arg1))->_delegate?SQObjectPtr(_table(STK(arg1))->_delegate):_null_;\r
-                                       continue;\r
-                               case OT_CLASS: TARGET = _class(STK(arg1))->_base?_class(STK(arg1))->_base:_null_;\r
-                                       continue;\r
-                               }\r
-                               Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(STK(arg1)));\r
-                               SQ_THROW();\r
-                               continue;\r
+                       case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue;\r
                        case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue;\r
                        case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue;\r
                        case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue;\r
@@ -871,7 +884,8 @@ common_prepcall:
                        case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue;\r
                        case _OP_BWNOT:\r
                                if(type(STK(arg1)) == OT_INTEGER) {\r
-                                       TARGET = SQInteger(~_integer(STK(arg1)));\r
+                                       SQInteger t = _integer(STK(arg1));\r
+                                       TARGET = SQInteger(~t);\r
                                        continue;\r
                                }\r
                                Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));\r
@@ -891,7 +905,7 @@ common_prepcall:
                                }\r
                                else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}\r
                                if(Return(arg0, arg1, temp_reg)){\r
-                                       assert(traps==0);\r
+                                       assert(traps == 0);\r
                                        outres = temp_reg;\r
                                        return true;\r
                                }\r
@@ -917,18 +931,31 @@ common_prepcall:
                                _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++;\r
                                ci->_etraps++;\r
                                continue;\r
-                       case _OP_POPTRAP:{\r
-                               for(SQInteger i=0; i<arg0; i++) {\r
+                       case _OP_POPTRAP:\r
+                               for(SQInteger i = 0; i < arg0; i++) {\r
                                        _etraps.pop_back(); traps--;\r
                                        ci->_etraps--;\r
-                               }}\r
+                               }\r
                                continue;\r
                        case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;\r
                        case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;\r
                        case _OP_NEWSLOTA:\r
-                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
-                               _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
-                               if(arg0 != arg3) TARGET = STK(arg3);\r
+                               bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false;\r
+                               if(type(STK(arg1)) == OT_CLASS) {\r
+                                       if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) {\r
+                                               Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3));\r
+                                               Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_);\r
+                                               int nparams = 4;\r
+                                               if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {\r
+                                                       Pop(nparams);\r
+                                                       continue;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic));\r
+                               if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) {\r
+                                       _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
+                               }\r
                                continue;\r
                        }\r
                        \r
@@ -941,6 +968,8 @@ exception_trap:
                SQInteger n = 0;\r
                SQInteger last_top = _top;\r
                if(ci) {\r
+                       if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror);\r
+\r
                        if(traps) {\r
                                do {\r
                                        if(ci->_etraps > 0) {\r
@@ -960,12 +989,15 @@ exception_trap:
                                        PopVarArgs(ci->_vargs);\r
                                        POP_CALLINFO(this);\r
                                        n++;\r
-                               }while(_callsstack.size());\r
+                               } while(_callsstack.size());\r
+                       }\r
+                       else {\r
+                               //call the hook\r
+                               if(raiseerror && !_ss(this)->_notifyallexceptions)\r
+                                       CallErrorHandler(currerror);\r
                        }\r
-                       //call the hook\r
-                       CallErrorHandler(currerror);\r
                        //remove call stack until a C function is found or the cstack is empty\r
-                       if(ci) do{\r
+                       if(ci) do {\r
                                SQBool exitafterthisone = ci->_root;\r
                                if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();\r
                                _stackbase -= ci->_prevstkbase;\r
@@ -973,7 +1005,7 @@ exception_trap:
                                PopVarArgs(ci->_vargs);\r
                                POP_CALLINFO(this);\r
                                if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;\r
-                       }while(_callsstack.size());\r
+                       } while(_callsstack.size());\r
 \r
                        while(last_top >= _top) _stack[last_top--].Null();\r
                }\r
@@ -983,16 +1015,14 @@ exception_trap:
        assert(0);\r
 }\r
 \r
-bool SQVM::CreateClassInstance(SQClass *theclass, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval)\r
+bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)\r
 {\r
-       SQObjectPtr constr;\r
-       SQObjectPtr inst = theclass->CreateInstance();\r
-       _stack[stackbase] = inst;\r
-       if(theclass->Get(_ss(this)->_constructoridx,constr)) {\r
-               if(!Call(constr,nargs,stackbase,constr))\r
-                       return false;\r
+       inst = theclass->CreateInstance();\r
+       if(!theclass->Get(_ss(this)->_constructoridx,constructor)) {\r
+               //if(!Call(constr,nargs,stackbase,constr,false))\r
+               //      return false;\r
+               constructor = _null_;\r
        }\r
-       retval = inst;\r
        return true;\r
 }\r
 \r
@@ -1001,7 +1031,7 @@ void SQVM::CallErrorHandler(SQObjectPtr &error)
        if(type(_errorhandler) != OT_NULL) {\r
                SQObjectPtr out;\r
                Push(_roottable); Push(error);\r
-               Call(_errorhandler, 2, _top-2, out);\r
+               Call(_errorhandler, 2, _top-2, out,SQFalse);\r
                Pop(2);\r
        }\r
 }\r
@@ -1012,7 +1042,7 @@ void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
        SQInteger nparams=5;\r
        SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);\r
        Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);\r
-       Call(_debughook,nparams,_top-nparams,temp_reg);\r
+       Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse);\r
        Pop(nparams);\r
 }\r
 \r
@@ -1027,7 +1057,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackb
                }\r
 \r
        SQInteger tcs;\r
-       if(tcs = nclosure->_typecheck.size()) {\r
+       if((tcs = nclosure->_typecheck.size())) {\r
                for(SQInteger i = 0; i < nargs && i < tcs; i++)\r
                        if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) {\r
                 Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i]));\r
@@ -1053,6 +1083,11 @@ bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackb
        for (SQInteger i = 0; i < outers; i++) {\r
                Push(nclosure->_outervalues[i]);\r
        }\r
+\r
+       if(type(nclosure->_env) == OT_WEAKREF) {\r
+               _stack[stackbase] = _weakref(nclosure->_env)->_obj;\r
+       }\r
+\r
        ci->_prevtop = (oldtop - oldstackbase);\r
        SQInteger ret = (nclosure->_function)(this);\r
        _nnativecalls--;\r
@@ -1088,6 +1123,7 @@ bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,
        case OT_INSTANCE:\r
                if(_instance(self)->Get(key,dest)) return true;\r
                break;\r
+       default:break; //shut up compiler\r
        }\r
        if(FallBackGet(self,key,dest,raw)) return true;\r
 \r
@@ -1129,7 +1165,7 @@ bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPt
        case OT_STRING:\r
                if(sq_isnumeric(key)){\r
                        SQInteger n=tointeger(key);\r
-                       if(abs(n)<_string(self)->_len){\r
+                       if(abs((int)n)<_string(self)->_len){\r
                                if(n<0)n=_string(self)->_len-n;\r
                                dest=SQInteger(_stringval(self)[n]);\r
                                return true;\r
@@ -1214,27 +1250,29 @@ bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr
 bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)\r
 {\r
        SQObjectPtr temp_reg;\r
+       SQObjectPtr newobj;\r
        switch(type(self)){\r
        case OT_TABLE:\r
-               target = _table(self)->Clone();\r
+               newobj = _table(self)->Clone();\r
                goto cloned_mt;\r
        case OT_INSTANCE:\r
-               target = _instance(self)->Clone(_ss(this));\r
+               newobj = _instance(self)->Clone(_ss(this));\r
 cloned_mt:\r
-               if(_delegable(target)->_delegate){\r
-                       Push(target);\r
+               if(_delegable(newobj)->_delegate){\r
+                       Push(newobj);\r
                        Push(self);\r
-                       CallMetaMethod(_delegable(target),MT_CLONED,2,temp_reg);\r
+                       CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg);\r
                }\r
+               target = newobj;\r
                return true;\r
        case OT_ARRAY: \r
-               target=_array(self)->Clone();\r
+               target = _array(self)->Clone();\r
                return true;\r
        default: return false;\r
        }\r
 }\r
 \r
-bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)\r
+bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)\r
 {\r
        if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }\r
        switch(type(self)) {\r
@@ -1251,7 +1289,7 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject
                \r
                break;}\r
        case OT_CLASS: \r
-               if(!_class(self)->NewSlot(key,val)) {\r
+               if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {\r
                        if(_class(self)->_locked) {\r
                                Raise_Error(_SC("trying to modify a class that has already been instantiated"));\r
                                return false;\r
@@ -1309,14 +1347,14 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr
        return true;\r
 }\r
 \r
-bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres)\r
+bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)\r
 {\r
 #ifdef _DEBUG\r
 SQInteger prevstackbase = _stackbase;\r
 #endif\r
        switch(type(closure)) {\r
        case OT_CLOSURE:\r
-               return Execute(closure, _top - nparams, nparams, stackbase,outres);\r
+               return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror);\r
                break;\r
        case OT_NATIVECLOSURE:{\r
                bool suspend;\r
@@ -1324,8 +1362,16 @@ SQInteger prevstackbase = _stackbase;
                \r
                                                  }\r
                break;\r
-       case OT_CLASS:\r
-               return CreateClassInstance(_class(closure),nparams,stackbase,outres);\r
+       case OT_CLASS: {\r
+               SQObjectPtr constr;\r
+               SQObjectPtr temp;\r
+               CreateClassInstance(_class(closure),outres,constr);\r
+               if(type(constr) != OT_NULL) {\r
+                       _stack[stackbase] = outres;\r
+                       return Call(constr,nparams,stackbase,temp,raiseerror);\r
+               }\r
+               return true;\r
+                                  }\r
                break;\r
        default:\r
                return false;\r
@@ -1341,8 +1387,8 @@ SQInteger prevstackbase = _stackbase;
 bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)\r
 {\r
        SQObjectPtr closure;\r
-       if(del->GetMetaMethod(mm, closure)) {\r
-               if(Call(closure, nparams, _top - nparams, outres)) {\r
+       if(del->GetMetaMethod(this, mm, closure)) {\r
+               if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {\r
                        Pop(nparams);\r
                        return true;\r
                }\r
@@ -1360,6 +1406,21 @@ void SQVM::Remove(SQInteger n) {
        _top--;\r
 }\r
 \r
+void SQVM::Pop() {\r
+       _stack[--_top] = _null_;\r
+}\r
+\r
+void SQVM::Pop(SQInteger n) {\r
+       for(SQInteger i = 0; i < n; i++){\r
+               _stack[--_top] = _null_;\r
+       }\r
+}\r
+\r
+void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }\r
+SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }\r
+SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }\r
+SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; }\r
+SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }\r
 \r
 #ifdef _DEBUG_DUMP\r
 void SQVM::dumpstack(SQInteger stackbase,bool dumpall)\r
@@ -1368,7 +1429,7 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
        SQInteger n=0;\r
        scprintf(_SC("\n>>>>stack dump<<<<\n"));\r
        CallInfo &ci=_callsstack.back();\r
-       scprintf(_SC("IP: %d\n"),ci._ip);\r
+       scprintf(_SC("IP: %p\n"),ci._ip);\r
        scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);\r
        scprintf(_SC("prev top: %d\n"),ci._prevtop);\r
        for(SQInteger i=0;i<size;i++){\r
@@ -1401,4 +1462,6 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
        }\r
 }\r
 \r
+\r
+\r
 #endif\r