4 #include "sqpcheader.h"     8 #include "sqfuncproto.h"    10 #include "sqclosure.h"    13 #include "squserdata.h"    17 #define TOP() (_stack._vals[_top-1])    19 #define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); }    20 void SQVM::ClearStack(SQInteger last_top)
    22     SQObjectType tOldType;
    23     SQObjectValue unOldVal;
    24     while (last_top >= _top) {
    25         SQObjectPtr &o = _stack._vals[last_top--];
    29         o._unVal.pUserPointer = 
NULL;
    30         __Release(tOldType,unOldVal);
    34 bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,
const SQObjectPtr &o1,
const SQObjectPtr &o2)
    37     SQInteger 
i1 = _integer(o1), i2 = _integer(o2);
    38     if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER))
    41             case BW_AND:    res = i1 & i2; 
break;
    42             case BW_OR:     res = i1 | i2; 
break;
    43             case BW_XOR:    res = i1 ^ i2; 
break;
    44             case BW_SHIFTL: res = i1 << i2; 
break;
    45             case BW_SHIFTR: res = i1 >> i2; 
break;
    46             case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); 
break;
    47             default: { Raise_Error(_SC(
"internal vm error bitwise op failed")); 
return false; }
    50     else { Raise_Error(_SC(
"bitwise op between '%s' and '%s'"),
GetTypeName(o1),
GetTypeName(o2)); 
return false;}
    55 bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,
const SQObjectPtr &o1,
const SQObjectPtr &o2)
    57     if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
    58             if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {
    59                 SQInteger res, 
i1 = _integer(o1), i2 = _integer(o2);
    61                 case '+': res = i1 + i2; 
break;
    62                 case '-': res = i1 - i2; 
break;
    63                 case '/': 
if(i2 == 0) { Raise_Error(_SC(
"division by zero")); 
return false; }
    66                 case '*': res = i1 * i2; 
break;
    67                 case '%': 
if(i2 == 0) { Raise_Error(_SC(
"modulo by zero")); 
return false; }
    70                 default: res = 0xDEADBEEF;
    74                 SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
    76                 case '+': res = f1 + f2; 
break;
    77                 case '-': res = f1 - f2; 
break;
    78                 case '/': res = f1 / f2; 
break;
    79                 case '*': res = f1 * f2; 
break;
    80                 case '%': res = SQFloat(fmod((
double)f1,(
double)f2)); 
break;
    86             if(op == 
'+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){
    87                     if(!StringCat(o1, o2, trg)) 
return false;
    89             else if(!ArithMetaMethod(op,o1,o2,trg)) {
    96 SQVM::SQVM(SQSharedState *ss)
   100     _suspended_target=-1;
   101     _suspended_root = SQFalse;
   109     INIT_CHAIN();ADD_TO_CHAIN(&_ss(
this)->_gc_chain,
this);
   112 void SQVM::Finalize()
   119     _callstackdata.resize(0);
   120     SQInteger size=_stack.size();
   121     for(SQInteger i=0;i<size;i++)
   129     REMOVE_FROM_CHAIN(&_ss(
this)->_gc_chain,
this);
   132 bool SQVM::ArithMetaMethod(SQInteger op,
const SQObjectPtr &o1,
const SQObjectPtr &o2,SQObjectPtr &dest)
   136         case _SC(
'+'): mm=MT_ADD; 
break;
   137         case _SC(
'-'): mm=MT_SUB; 
break;
   138         case _SC(
'/'): mm=MT_DIV; 
break;
   139         case _SC(
'*'): mm=MT_MUL; 
break;
   140         case _SC(
'%'): mm=MT_MODULO; 
break;
   141         default: mm = MT_ADD; assert(0); 
break; 
   143     if(is_delegable(o1) && _delegable(o1)->_delegate) {
   145         return CallMetaMethod(_delegable(o1),mm,2,dest);
   150 bool SQVM::NEG_OP(SQObjectPtr &trg,
const SQObjectPtr &o)
   163         if(_delegable(o)->_delegate) {
   165             if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) {
   172     Raise_Error(_SC(
"attempt to negate a %s"), 
GetTypeName(o));
   176 #define _RET_SUCCEED(exp) { result = (exp); return true; }   177 bool SQVM::ObjCmp(
const SQObjectPtr &o1,
const SQObjectPtr &o2,SQInteger &result)
   179     if(type(o1)==type(o2)){
   192             if(_delegable(o1)->_delegate) {
   194                 if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) 
break;
   198             _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
   200         if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); 
return false; }
   205         if(sq_isnumeric(o1) && sq_isnumeric(o2)){
   206             if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) {
   208                 else if( _integer(o1)<_float(o2) ) { 
_RET_SUCCEED(-1); }
   213                 else if( _float(o1)<_integer(o2) ) { 
_RET_SUCCEED(-1); }
   219         else { Raise_CompareError(o1,o2); 
return false; }
   226 bool SQVM::CMP_OP(CmpOP op, 
const SQObjectPtr &o1,
const SQObjectPtr &o2,SQObjectPtr &res)
   229     if(ObjCmp(o1,o2,r)) {
   242 void SQVM::ToString(
const SQObjectPtr &o,SQObjectPtr &res)
   249         scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC(
"%g"),_float(o));
   254         scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC(
"%I64d"),_integer(o));
   257         scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC(
"%ld"),_integer(o));
   259         scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC(
"%d"),_integer(o));
   263         scsprintf(_sp(rsl(6)),_integer(o)?_SC(
"true"):_SC(
"false"));
   268         if(_delegable(o)->_delegate) {
   270             if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) {
   271                 if(type(res) == OT_STRING)
   277         scsprintf(_sp(rsl(
sizeof(
void*)+20)),_SC(
"(%s : 0x%p)"),
GetTypeName(o),(
void*)_rawval(o));
   279     res = SQString::Create(_ss(
this),_spval);
   283 bool SQVM::StringCat(
const SQObjectPtr &str,
const SQObjectPtr &obj,SQObjectPtr &dest)
   288     SQInteger l = _string(a)->_len , ol = _string(b)->_len;
   289     SQChar *s = _sp(rsl(l + ol + 1));
   290     memcpy(s, _stringval(a), rsl(l));
   291     memcpy(s + l, _stringval(b), rsl(ol));
   292     dest = SQString::Create(_ss(
this), _spval, l + ol);
   296 void SQVM::TypeOf(
const SQObjectPtr &obj1,SQObjectPtr &dest)
   298     if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
   300         if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest))
   303     dest = SQString::Create(_ss(
this),
GetTypeName(obj1));
   306 bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
   308     _stack.resize(stacksize);
   309     _alloccallsstacksize = 4;
   310     _callstackdata.resize(_alloccallsstacksize);
   312     _callsstack = &_callstackdata[0];
   316         _roottable = SQTable::Create(_ss(
this), 0);
   318         _roottable = friendvm->_roottable;
   319         _errorhandler = friendvm->_errorhandler;
   320         _debughook = friendvm->_debughook;
   329 bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,
bool tailcall)
   331     SQFunctionProto *func = _funcproto(closure->_function);
   333     const SQInteger paramssize = func->_nparameters;
   334     const SQInteger newtop = stackbase + func->_stacksize;
   335     SQInteger nargs = args;
   336     if (paramssize != nargs) {
   337         SQInteger ndef = func->_ndefaultparams;
   339         if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
   340             for(SQInteger n = ndef - diff; n < ndef; n++) {
   341                 _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
   344         else if(func->_varparams)
   346             if (nargs < paramssize) {
   347                 Raise_Error(_SC(
"wrong number of parameters"));
   350             for(SQInteger n = 0; n < nargs - paramssize; n++) {
   351                 _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]);
   352                 _stack._vals[stackbase+paramssize+n] = 
_null_;
   356             Raise_Error(_SC(
"wrong number of parameters"));
   361     if(type(closure->_env) == OT_WEAKREF) {
   362         _stack._vals[stackbase] = _weakref(closure->_env)->_obj;
   367         lc._generator = 
NULL;
   369         lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );
   370         lc._target = (SQInt32) target;
   371         lc._prevtop = (SQInt32) (_top - _stackbase);
   374         PUSH_CALLINFO(
this, lc);
   379     ci->_vargs.size = (SQInt32)(nargs - paramssize);
   380     ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));
   381     ci->_closure = closure;
   382     ci->_literals = func->_literals;
   383     ci->_ip = func->_instructions;
   385     if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) {
   386         _stack.resize(_stack.size() + (func->_stacksize<<1));
   390     _stackbase = stackbase;
   391     if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
   392         CallDebugHook(_SC(
'c'));
   396 bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
   398     if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
   399         for(SQInteger i=0;i<ci->_ncalls;i++)
   400             CallDebugHook(_SC(
'r'));
   402     SQBool broot = ci->_root;
   403     SQInteger last_top = _top;
   404     SQInteger target = ci->_target;
   405     SQInteger oldstackbase = _stackbase;
   406     _stackbase -= ci->_prevstkbase;
   407     _top = _stackbase + ci->_prevtop;
   408     if(ci->_vargs.size) PopVarArgs(ci->_vargs);
   411         if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1];
   416             if (_arg0 != MAX_FUNC_STACKSIZE)
   417                 STK(target) = _stack._vals[oldstackbase+_arg1];
   424     assert(oldstackbase >= _stackbase);
   425     return broot?
true:
false;
   428 #define _RET_ON_FAIL(exp) { if(!exp) return false; }   430 bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
   437 bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
   446 bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &
self, SQObjectPtr &key, SQObjectPtr &incr, 
bool postfix)
   448     SQObjectPtr tmp, tself = 
self, tkey = key;
   449     if (!Get(tself, tkey, tmp, 
false, 
true)) { Raise_IdxError(tkey); 
return false; }
   451     Set(tself, tkey, target,
true);
   452     if (postfix) target = tmp;
   456 #define arg0 (_i_._arg0)   457 #define arg1 (_i_._arg1)   458 #define sarg1 (*((SQInt32 *)&_i_._arg1))   459 #define arg2 (_i_._arg2)   460 #define arg3 (_i_._arg3)   461 #define sarg3 ((SQInteger)*((signed char *)&_i_._arg3))   463 SQRESULT SQVM::Suspend()
   466         return sq_throwerror(
this, _SC(
"cannot suspend an already suspended vm"));
   467     if (_nnativecalls!=2)
   468         return sq_throwerror(
this, _SC(
"cannot suspend through native calls/metamethods"));
   469     return SQ_SUSPEND_FLAG;
   472 void SQVM::PopVarArgs(VarArgs &vargs)
   474     for(SQInteger n = 0; n< vargs.size; n++)
   475         _vargsstack.pop_back();
   478 #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }   479 bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
   480 &o3,SQObjectPtr &o4,SQInteger arg_2,
int exitpos,
int &jump)
   485         if((nrefidx = _table(o1)->Next(
false,o4, o2, o3)) == -1) 
_FINISH(exitpos);
   486         o4 = (SQInteger)nrefidx; 
_FINISH(1);
   488         if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) 
_FINISH(exitpos);
   489         o4 = (SQInteger) nrefidx; 
_FINISH(1);
   491         if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)
_FINISH(exitpos);
   492         o4 = (SQInteger)nrefidx; 
_FINISH(1);
   494         if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)
_FINISH(exitpos);
   495         o4 = (SQInteger)nrefidx; 
_FINISH(1);
   498         if(_delegable(o1)->_delegate) {
   502             if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){
   504                 if(type(itr) == OT_NULL) 
_FINISH(exitpos);
   505                 if(!Get(o1, itr, o3, 
false,
false)) {
   506                     Raise_Error(_SC(
"_nexti returned an invalid idx"));
   511             Raise_Error(_SC(
"_nexti failed"));
   516         if(_generator(o1)->_state == SQGenerator::eDead) 
_FINISH(exitpos);
   517         if(_generator(o1)->_state == SQGenerator::eSuspended) {
   519             if(type(o4) == OT_INTEGER) {
   520                 idx = _integer(o4) + 1;
   524             _generator(o1)->Resume(
this, arg_2+1);
   528         Raise_Error(_SC(
"cannot iterate %s"), 
GetTypeName(o1));
   533 bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)
   535     if(type(o1) != OT_TABLE) { Raise_Error(_SC(
"delegating a '%s'"), 
GetTypeName(o1)); 
return false; }
   538         if(!_table(o1)->SetDelegate(_table(o2))){
   539             Raise_Error(_SC(
"delegate cycle detected"));
   544         _table(o1)->SetDelegate(
NULL);
   547         Raise_Error(_SC(
"using '%s' as delegate"), 
GetTypeName(o2));
   554 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))   556 #define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }   558 #define SQ_THROW() { goto exception_trap; }   560 bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
   563     SQClosure *closure = SQClosure::Create(_ss(
this), func);
   564     if((nouters = func->_noutervalues)) {
   565         closure->_outervalues.reserve(nouters);
   566         for(SQInteger i = 0; i<nouters; i++) {
   567             SQOuterVar &v = func->_outervalues[i];
   570                 closure->_outervalues.push_back(
_null_);
   571                 if(!Get(_stack._vals[_stackbase], v._src, closure->_outervalues.top(), 
false,
true))
   572                 {Raise_IdxError(v._src); 
return false; }
   575                 closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]);
   578                 closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]);
   583     SQInteger ndefparams;
   584     if((ndefparams = func->_ndefaultparams)) {
   585         closure->_defaultparams.reserve(ndefparams);
   586         for(SQInteger i = 0; i < ndefparams; i++) {
   587             SQInteger spos = func->_defaultparams[i];
   588             closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]);
   597 bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *callinfo)
   599     if(callinfo->_vargs.size == 0) {
   600         Raise_Error(_SC(
"the function doesn't have var args"));
   603     if(!sq_isnumeric(index)){
   604         Raise_Error(_SC(
"indexing 'vargv' with %s"),
GetTypeName(index));
   607     SQInteger idx = tointeger(index);
   608     if(idx < 0 || idx >= callinfo->_vargs.size){ Raise_Error(_SC(
"vargv index out of range")); 
return false; }
   609     target = _vargsstack[callinfo->_vargs.base+idx];
   613 bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes)
   615     SQClass *base = 
NULL;
   617     if(baseclass != -1) {
   618         if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC(
"trying to inherit from a %s"),
GetTypeName(_stack._vals[_stackbase+baseclass])); 
return false; }
   619         base = _class(_stack._vals[_stackbase + baseclass]);
   621     if(attributes != MAX_FUNC_STACKSIZE) {
   622         attrs = _stack._vals[_stackbase+attributes];
   624     target = SQClass::Create(_ss(
this),base);
   625     if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
   628         Push(target); Push(attrs);
   629         Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, 
false);
   632     _class(target)->_attributes = attrs;
   638 bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,
bool &res)
   640     if(type(o1) == type(o2)) {
   641         res = ((_rawval(o1) == _rawval(o2)?
true:
false));
   644         if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
   646             if(!ObjCmp(o1, o2,cmpres)) 
return false;
   656 bool SQVM::IsFalse(SQObjectPtr &o)
   659     if(( (type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )
   660         || (_integer(o) == 0) ) { 
   666 bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)
   669         case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):
_null_;
   671         case OT_CLASS: target = _class(o)->_base?_class(o)->_base:
_null_;
   674             Raise_Error(_SC(
"the %s type doesn't have a parent slot"), 
GetTypeName(o));
   680 bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
   682     if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC(
"Native stack overflow")); 
return false; }
   684     AutoDec ad(&_nnativecalls);
   688     SQInteger ct_stackbase;
   693             SQInteger last_top = _top;
   695             if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, 
false)) {
   697                 if(ci == 
NULL) CallErrorHandler(_lasterror);
   700             if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
   703                 SQGenerator *gen = SQGenerator::Create(_ss(
this), _closure(temp_reg));
   705                 Return(1, ci->_target, temp_reg);
   713         case ET_RESUME_GENERATOR: _generator(closure)->Resume(
this, target); ci->_root = SQTrue; traps += ci->_etraps; 
break;
   715         case ET_RESUME_THROW_VM:
   716             traps = _suspended_traps;
   717             ci->_root = _suspended_root;
   718             ci->_vargs = _suspend_varargs;
   719             _suspended = SQFalse;
   720             if(et  == ET_RESUME_THROW_VM) { 
SQ_THROW(); }
   729             const SQInstruction &_i_ = *ci->_ip++;
   735                 if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
   736                     CallDebugHook(_SC(
'l'),
arg1);
   738             case _OP_LOAD: TARGET = ci->_literals[
arg1]; 
continue;
   739             case _OP_LOADINT: TARGET = (SQInteger)
arg1; 
continue;
   740             case _OP_LOADFLOAT: TARGET = *((SQFloat *)&
arg1); 
continue;
   741             case _OP_DLOAD: TARGET = ci->_literals[
arg1]; STK(
arg2) = ci->_literals[
arg3];
continue;
   743                 temp_reg = STK(
arg1);
   744                 if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){
   746                     if(ci->_vargs.size) PopVarArgs(ci->_vargs);
   747                     for (SQInteger i = 0; i < 
arg3; i++) STK(i) = STK(
arg2 + i);
   748                     ct_target = ci->_target;
   749                     ct_stackbase = _stackbase;
   755                     temp_reg = STK(
arg1);
   756                     ct_stackbase = _stackbase+
arg2;
   759                     SQObjectPtr clo = temp_reg;
   760                     SQInteger last_top = _top;
   763                         _GUARD(StartCall(_closure(clo), ct_target, 
arg3, ct_stackbase, ct_tailcall));
   764                         if (_funcproto(_closure(clo)->_function)->_bgenerator) {
   765                             SQGenerator *gen = SQGenerator::Create(_ss(
this), _closure(clo));
   767                             Return(1, ct_target, clo);
   768                             STK(ct_target) = gen;
   774                     case OT_NATIVECLOSURE: {
   776                         _GUARD(CallNative(_nativeclosure(clo), 
arg3, ct_stackbase, clo,suspend));
   779                             _suspended_target = ct_target;
   780                             _suspended_root = ci->_root;
   781                             _suspended_traps = traps;
   782                             _suspend_varargs = ci->_vargs;
   786                         if(ct_target != -1) { 
   787                             STK(ct_target) = clo;
   793                         _GUARD(CreateClassInstance(_class(clo),inst,temp_reg));
   794                         STK(ct_target) = inst;
   796                         if(type(temp_reg) != OT_NULL) {
   797                             _stack._vals[ct_stackbase] = inst;
   807                         for (SQInteger i = 0; i < 
arg3; i++) Push(STK(arg2 + i));
   808                         if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){
   809                             STK(ct_target) = clo;
   812                         Raise_Error(_SC(
"attempt to call '%s'"), 
GetTypeName(clo));
   816                         Raise_Error(_SC(
"attempt to call '%s'"), 
GetTypeName(clo));
   824                     SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[
arg1]:STK(
arg1);
   825                     SQObjectPtr &o = STK(
arg2);
   826                     if (!Get(o, key, temp_reg,
false,
true)) {
   827                         if(type(o) == OT_CLASS) { 
   828                             if(_class_ddel->Get(key,temp_reg)) {
   837                     STK(
arg3) = type(o) == OT_CLASS?STK(0):o;
   842                 if (!Get(STK(
arg2), ci->_literals[
arg1], temp_reg, 
false,
true)) { Raise_IdxError(ci->_literals[
arg1]); 
SQ_THROW();}
   845             case _OP_MOVE: TARGET = STK(
arg1); 
continue;
   850             case _OP_DELETE: 
_GUARD(DeleteSlot(STK(
arg1), STK(
arg2), TARGET)); 
continue;
   856                 if (!Get(STK(
arg1), STK(
arg2), temp_reg, 
false,
true)) { Raise_IdxError(STK(
arg2)); 
SQ_THROW(); }
   869             case _OP_ARITH: 
_GUARD(ARITH_OP( 
arg3 , temp_reg, STK(
arg2), STK(
arg1))); TARGET = temp_reg; 
continue;
   873                     ci->_generator->Kill();
   881             case _OP_LOADNULLS:{ 
for(SQInt32 n=0; n < 
arg1; n++) STK(
arg0+n) = 
_null_; }
continue;
   882             case _OP_LOADROOTTABLE: TARGET = _roottable; 
continue;
   885             case _OP_JMP: ci->_ip += (
sarg1); 
continue;
   886             case _OP_JNZ: 
if(!IsFalse(STK(
arg0))) ci->_ip+=(
sarg1); 
continue;
   887             case _OP_JZ: 
if(IsFalse(STK(
arg0))) ci->_ip+=(
sarg1); 
continue;
   888             case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[
arg1]; 
continue;
   889             case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); 
continue;
   893             case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(
this), 
arg1); 
continue;
   894             case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(
this), 0); _array(TARGET)->Reserve(
arg1); 
continue;
   896             case _OP_GETPARENT: 
_GUARD(GETPARENT_OP(STK(
arg1),TARGET)); 
continue;
   897             case _OP_COMPARITH: 
_GUARD(DerefInc(
arg3, TARGET, STK((((SQUnsignedInteger)
arg1&0xFFFF0000)>>16)), STK(
arg2), STK(
arg1&0x0000FFFF), 
false)); 
continue;
   899             case _OP_INC: {SQObjectPtr o(
sarg3); 
_GUARD(DerefInc(
'+',TARGET, STK(
arg1), STK(
arg2), o, 
false));} 
continue;
   900             case _OP_INCL: {SQObjectPtr o(
sarg3); 
_GUARD(LOCAL_INC(
'+',TARGET, STK(
arg1), o));} 
continue;
   901             case _OP_PINC: {SQObjectPtr o(
sarg3); 
_GUARD(DerefInc(
'+',TARGET, STK(
arg1), STK(
arg2), o, 
true));} 
continue;
   902             case _OP_PINCL: {SQObjectPtr o(
sarg3); 
_GUARD(PLOCAL_INC(
'+',TARGET, STK(
arg1), o));} 
continue;
   906                 if(type(STK(
arg1)) != OT_CLASS || type(STK(
arg2)) != OT_INSTANCE)
   911                 if(IsFalse(STK(
arg2))) {
   917                 if(!IsFalse(STK(
arg2))) {
   922             case _OP_NEG: 
_GUARD(NEG_OP(TARGET,STK(
arg1))); 
continue;
   925                 if(type(STK(
arg1)) == OT_INTEGER) {
   926                     SQInteger t = _integer(STK(
arg1));
   927                     TARGET = SQInteger(~t);
   930                 Raise_Error(_SC(
"attempt to perform a bitwise op on a %s"), 
GetTypeName(STK(
arg1)));
   933                 SQClosure *c = ci->_closure._unVal.pClosure;
   934                 SQFunctionProto *fp = c->_function._unVal.pFunctionProto;
   935                 if(!CLOSURE_OP(TARGET,fp->_functions[
arg1]._unVal.pFunctionProto)) { 
SQ_THROW(); }
   940                     if(
sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(
arg1);
   941                     _GUARD(ci->_generator->Yield(
this));
   942                     traps -= ci->_etraps;
   943                     if(
sarg1 != MAX_FUNC_STACKSIZE) STK(
arg1) = temp_reg;
   945                 else { Raise_Error(_SC(
"trying to yield a '%s',only genenerator can be yielded"), 
GetTypeName(ci->_generator)); 
SQ_THROW();}
   955                 if(type(STK(
arg1)) != OT_GENERATOR){ Raise_Error(_SC(
"trying to resume a '%s',only genenerator can be resumed"), 
GetTypeName(STK(
arg1))); 
SQ_THROW();}
   957                 traps += ci->_etraps;
   959             case _OP_FOREACH:{ 
int tojump;
   963             case _OP_POSTFOREACH:
   964                 assert(type(STK(
arg0)) == OT_GENERATOR);
   965                 if(_generator(STK(
arg0))->_state == SQGenerator::eDead)
   966                     ci->_ip += (
sarg1 - 1);
   968             case _OP_DELEGATE: 
_GUARD(DELEGATE_OP(TARGET,STK(
arg1),STK(
arg2))); 
continue;
   970                 if(!Clone(STK(
arg1), TARGET))
   973             case _OP_TYPEOF: TypeOf(STK(
arg1), TARGET); 
continue;
   975                 SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions;
   976                 _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+
arg1], 
arg0)); traps++;
   981                 for(SQInteger i = 0; i < 
arg0; i++) {
   982                     _etraps.pop_back(); traps--;
   987             case _OP_THROW: Raise_Error(TARGET); 
SQ_THROW(); 
continue;
   990                 bool bstatic = (
arg0&NEW_SLOT_STATIC_FLAG)?
true:
false;
   991                 if(type(STK(
arg1)) == OT_CLASS) {
   992                     if(type(_class(STK(
arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) {
   993                         Push(STK(
arg1)); Push(STK(
arg2)); Push(STK(arg3));
   997                         if(Call(_class(STK(
arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {
  1004                 if((
arg0&NEW_SLOT_ATTRIBUTES_FLAG)) {
  1005                     _class(STK(
arg1))->SetAttributes(STK(
arg2),STK(
arg2-1));
  1014         SQObjectPtr currerror = _lasterror;
  1017         SQInteger last_top = _top;
  1019             if(_ss(
this)->_notifyallexceptions) CallErrorHandler(currerror);
  1023                     if(ci->_etraps > 0) {
  1025                         SQExceptionTrap &etrap = _etraps.top();
  1026                         ci->_ip = etrap._ip;
  1027                         _top = etrap._stacksize;
  1028                         _stackbase = etrap._stackbase;
  1029                         _stack._vals[_stackbase+etrap._extarget] = currerror;
  1030                         _etraps.pop_back(); traps--; ci->_etraps--;
  1032                         goto exception_restore;
  1035                     if(type(ci->_closure) != OT_CLOSURE && n)
  1037                     if(ci->_generator) ci->_generator->Kill();
  1038                     PopVarArgs(ci->_vargs);
  1041                 } 
while(_callsstacksize);
  1045                 if(raiseerror && !_ss(
this)->_notifyallexceptions)
  1046                     CallErrorHandler(currerror);
  1050                 SQBool exitafterthisone = ci->_root;
  1051                 if(ci->_generator) ci->_generator->Kill();
  1052                 _stackbase -= ci->_prevstkbase;
  1053                 _top = _stackbase + ci->_prevtop;
  1054                 PopVarArgs(ci->_vargs);
  1056                 if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) 
break;
  1057             } 
while(_callsstacksize);
  1061         _lasterror = currerror;
  1069 bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
  1071     inst = theclass->CreateInstance();
  1072     if(!theclass->Get(_ss(
this)->_constructoridx,constructor)) {
  1078 void SQVM::CallErrorHandler(SQObjectPtr &error)
  1080     if(type(_errorhandler) != OT_NULL) {
  1082         Push(_roottable); Push(error);
  1083         Call(_errorhandler, 2, _top-2, out,SQFalse);
  1088 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
  1091     SQObjectPtr tmp_reg;
  1092     SQInteger nparams=5;
  1093     SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);
  1094     Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
  1095     Call(_debughook,nparams,_top-nparams,tmp_reg,SQFalse);
  1099 bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,
bool &suspend)
  1101     if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC(
"Native stack overflow")); 
return false; }
  1102     SQInteger nparamscheck = nclosure->_nparamscheck;
  1103     if(((nparamscheck > 0) && (nparamscheck != nargs))
  1104         || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {
  1105         Raise_Error(_SC(
"wrong number of parameters"));
  1110     if((tcs = nclosure->_typecheck.size())) {
  1111         for(SQInteger i = 0; i < nargs && i < tcs; i++)
  1112             if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) {
  1113                 Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i]));
  1118     if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) {
  1119         _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));
  1121     SQInteger oldtop = _top;
  1122     SQInteger oldstackbase = _stackbase;
  1123     _top = stackbase + nargs;
  1125     lci._closure = nclosure;
  1126     lci._generator = 
NULL;
  1128     lci._prevstkbase = (SQInt32) (stackbase - _stackbase);
  1130     lci._prevtop = (SQInt32) (oldtop - oldstackbase);
  1131     PUSH_CALLINFO(
this, lci);
  1132     _stackbase = stackbase;
  1134     SQInteger outers = nclosure->_outervalues.size();
  1135     for (SQInteger i = 0; i < outers; i++) {
  1136         Push(nclosure->_outervalues[i]);
  1139     if(type(nclosure->_env) == OT_WEAKREF) {
  1140         _stack[stackbase] = _weakref(nclosure->_env)->_obj;
  1144     SQInteger ret = (nclosure->_function)(
this);
  1147     if( ret == SQ_SUSPEND_FLAG) suspend = 
true;
  1149         _stackbase = oldstackbase;
  1152         Raise_Error(_lasterror);
  1156     if (ret != 0){ retval = 
TOP(); 
TOP().Null(); }
  1157     else { retval = 
_null_; }
  1158     _stackbase = oldstackbase;
  1164 bool SQVM::Get(
const SQObjectPtr &
self,
const SQObjectPtr &key,SQObjectPtr &dest,
bool raw, 
bool fetchroot)
  1168         if(_table(
self)->Get(key,dest))
return true;
  1171         if(sq_isnumeric(key)){
  1172             return _array(
self)->Get(tointeger(key),dest);
  1176         if(_instance(
self)->Get(key,dest)) 
return true;
  1180     if(FallBackGet(
self,key,dest,raw)) 
return true;
  1183         if(_rawval(STK(0)) == _rawval(
self) &&
  1184             type(STK(0)) == type(
self)) {
  1185                 return _table(_roottable)->Get(key,dest);
  1191 bool SQVM::FallBackGet(
const SQObjectPtr &
self,
const SQObjectPtr &key,SQObjectPtr &dest,
bool raw)
  1195         return _class(
self)->Get(key,dest);
  1200         if(_delegable(
self)->_delegate) {
  1201             if(Get(SQObjectPtr(_delegable(
self)->_delegate),key,dest,raw,
false))
  1203             if(raw)
return false;
  1204             Push(
self);Push(key);
  1205             if(CallMetaMethod(_delegable(
self),MT_GET,2,dest))
  1208         if(type(
self) == OT_TABLE) {
  1209             if(raw) 
return false;
  1210             return _table_ddel->Get(key,dest);
  1215         if(raw)
return false;
  1216         return _array_ddel->Get(key,dest);
  1218         if(sq_isnumeric(key)){
  1219             SQInteger n=tointeger(key);
  1220             if(abs((
int)n)<_string(
self)->_len){
  1221                 if(n<0)n=_string(
self)->_len-n;
  1222                 dest=SQInteger(_stringval(
self)[n]);
  1228             if(raw)
return false;
  1229             return _string_ddel->Get(key,dest);
  1233         if(raw)
return false;
  1234         Push(
self);Push(key);
  1235         if(!CallMetaMethod(_delegable(
self),MT_GET,2,dest)) {
  1236             return _instance_ddel->Get(key,dest);
  1239     case OT_INTEGER:
case OT_FLOAT:
case OT_BOOL:
  1240         if(raw)
return false;
  1241         return _number_ddel->Get(key,dest);
  1243         if(raw)
return false;
  1244         return _generator_ddel->Get(key,dest);
  1245     case OT_CLOSURE: 
case OT_NATIVECLOSURE:
  1246         if(raw)
return false;
  1247         return _closure_ddel->Get(key,dest);
  1249         if(raw)
return false;
  1250         return  _thread_ddel->Get(key,dest);
  1252         if(raw)
return false;
  1253         return  _weakref_ddel->Get(key,dest);
  1254     default:
return false;
  1259 bool SQVM::Set(
const SQObjectPtr &
self,
const SQObjectPtr &key,
const SQObjectPtr &val,
bool fetchroot)
  1263         if(_table(
self)->Set(key,val))
  1265         if(_table(
self)->_delegate) {
  1266             if(Set(_table(
self)->_delegate,key,val,
false)) {
  1272         if(_delegable(
self)->_delegate) {
  1274             Push(
self);Push(key);Push(val);
  1275             if(CallMetaMethod(_delegable(
self),MT_SET,3,t)) 
return true;
  1279         if(_instance(
self)->Set(key,val))
  1282         Push(
self);Push(key);Push(val);
  1283         if(CallMetaMethod(_delegable(
self),MT_SET,3,t)) 
return true;
  1287         if(!sq_isnumeric(key)) {Raise_Error(_SC(
"indexing %s with %s"),
GetTypeName(
self),
GetTypeName(key)); 
return false; }
  1288         return _array(
self)->Set(tointeger(key),val);
  1290         Raise_Error(_SC(
"trying to set '%s'"),
GetTypeName(
self));
  1294         if(_rawval(STK(0)) == _rawval(
self) &&
  1295             type(STK(0)) == type(
self)) {
  1296                 return _table(_roottable)->Set(key,val);
  1302 bool SQVM::Clone(
const SQObjectPtr &
self,SQObjectPtr &target)
  1305     SQObjectPtr tmp_reg;
  1309         newobj = _table(
self)->Clone();
  1312         newobj = _instance(
self)->Clone(_ss(
this));
  1314         if(_delegable(newobj)->_delegate){
  1317             CallMetaMethod(_delegable(newobj),MT_CLONED,2,tmp_reg);
  1322         target = _array(
self)->Clone();
  1324     default: 
return false;
  1328 bool SQVM::NewSlot(
const SQObjectPtr &
self,
const SQObjectPtr &key,
const SQObjectPtr &val,
bool bstatic)
  1330     if(type(key) == OT_NULL) { Raise_Error(_SC(
"null cannot be used as index")); 
return false; }
  1331     switch(type(
self)) {
  1333         bool rawcall = 
true;
  1334         if(_table(
self)->_delegate) {
  1336             if(!_table(
self)->Get(key,res)) {
  1337                 Push(
self);Push(key);Push(val);
  1338                 rawcall = !CallMetaMethod(_table(
self),MT_NEWSLOT,3,res);
  1341         if(rawcall) _table(
self)->NewSlot(key,val); 
  1346         Push(
self);Push(key);Push(val);
  1347         if(!CallMetaMethod(_instance(
self),MT_NEWSLOT,3,res)) {
  1348             Raise_Error(_SC(
"class instances do not support the new slot operator"));
  1353         if(!_class(
self)->NewSlot(_ss(
this),key,val,bstatic)) {
  1354             if(_class(
self)->_locked) {
  1355                 Raise_Error(_SC(
"trying to modify a class that has already been instantiated"));
  1359                 SQObjectPtr oval = PrintObjVal(key);
  1360                 Raise_Error(_SC(
"the property '%s' already exists"),_stringval(oval));
  1373 bool SQVM::DeleteSlot(
const SQObjectPtr &
self,
const SQObjectPtr &key,SQObjectPtr &res)
  1375     switch(type(
self)) {
  1380         bool handled = 
false;
  1381         if(_delegable(
self)->_delegate) {
  1382             Push(
self);Push(key);
  1383             handled = CallMetaMethod(_delegable(
self),MT_DELSLOT,2,t);
  1387             if(type(
self) == OT_TABLE) {
  1388                 if(_table(
self)->Get(key,t)) {
  1389                     _table(
self)->Remove(key);
  1392                     Raise_IdxError((SQObject &)key);
  1397                 Raise_Error(_SC(
"cannot delete a slot from %s"),
GetTypeName(
self));
  1405         Raise_Error(_SC(
"attempt to delete a slot from a %s"),
GetTypeName(
self));
  1411 bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
  1414 SQInteger prevstackbase = _stackbase;
  1416     switch(type(closure)) {
  1418         return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror);
  1420     case OT_NATIVECLOSURE:{
  1422         return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
  1429         CreateClassInstance(_class(closure),outres,constr);
  1430         if(type(constr) != OT_NULL) {
  1431             _stack[stackbase] = outres;
  1432             return Call(constr,nparams,stackbase,temp,raiseerror);
  1442         assert(_stackbase == prevstackbase);
  1448 bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
  1450     SQObjectPtr closure;
  1451     if(del->GetMetaMethod(
this, mm, closure)) {
  1452         if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
  1461 void SQVM::Remove(SQInteger n) {
  1462     n = (n >= 0)?n + _stackbase - 1:_top + n;
  1463     for(SQInteger i = n; i < _top; i++){
  1464         _stack[i] = _stack[i+1];
  1474 void SQVM::Pop(SQInteger n) {
  1475     for(SQInteger i = 0; i < n; i++){
  1480 void SQVM::Push(
const SQObjectPtr &o) { _stack[_top++] = o; }
  1481 SQObjectPtr &SQVM::Top() { 
return _stack[_top-1]; }
  1482 SQObjectPtr &SQVM::PopGet() { 
return _stack[--_top]; }
  1483 SQObjectPtr &SQVM::GetUp(SQInteger n) { 
return _stack[_top+n]; }
  1484 SQObjectPtr &SQVM::GetAt(SQInteger n) { 
return _stack[n]; }
  1487 void SQVM::dumpstack(SQInteger stackbase,
bool dumpall)
  1489     SQInteger size=dumpall?_stack.size():_top;
  1491     scprintf(_SC(
"\n>>>>stack dump<<<<\n"));
  1492     CallInfo &ci=_callsstack[_callsstacksize-1];
  1493     scprintf(_SC(
"IP: %p\n"),ci._ip);
  1494     scprintf(_SC(
"prev stack base: %d\n"),ci._prevstkbase);
  1495     scprintf(_SC(
"prev top: %d\n"),ci._prevtop);
  1496     for(SQInteger i=0;i<size;i++){
  1497         SQObjectPtr &obj=_stack[i];
  1498         if(stackbase==i)scprintf(_SC(
">"));
else scprintf(_SC(
" "));
  1499         scprintf(_SC(
"[%d]:"),n);
  1501         case OT_FLOAT:          scprintf(_SC(
"FLOAT %.3f"),_float(obj));
break;
  1502         case OT_INTEGER:        scprintf(_SC(
"INTEGER %d"),_integer(obj));
break;
  1503         case OT_BOOL:           scprintf(_SC(
"BOOL %s"),_integer(obj)?
"true":
"false");
break;
  1504         case OT_STRING:         scprintf(_SC(
"STRING %s"),_stringval(obj));
break;
  1505         case OT_NULL:           scprintf(_SC(
"NULL"));  
break;
  1506         case OT_TABLE:          scprintf(_SC(
"TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);
break;
  1507         case OT_ARRAY:          scprintf(_SC(
"ARRAY %p"),_array(obj));
break;
  1508         case OT_CLOSURE:        scprintf(_SC(
"CLOSURE [%p]"),_closure(obj));
break;
  1509         case OT_NATIVECLOSURE:  scprintf(_SC(
"NATIVECLOSURE"));
break;
  1510         case OT_USERDATA:       scprintf(_SC(
"USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);
break;
  1511         case OT_GENERATOR:      scprintf(_SC(
"GENERATOR %p"),_generator(obj));
break;
  1512         case OT_THREAD:         scprintf(_SC(
"THREAD [%p]"),_thread(obj));
break;
  1513         case OT_USERPOINTER:    scprintf(_SC(
"USERPOINTER %p"),_userpointer(obj));
break;
  1514         case OT_CLASS:          scprintf(_SC(
"CLASS %p"),_class(obj));
break;
  1515         case OT_INSTANCE:       scprintf(_SC(
"INSTANCE %p"),_instance(obj));
break;
  1516         case OT_WEAKREF:        scprintf(_SC(
"WEAKERF %p"),_weakref(obj));
break;
  1521         scprintf(_SC(
"\n"));
 int Execute(const wxString &command)
#define _RET_SUCCEED(exp)
SQObjectPtr _false_(false)
SQRESULT sq_throwerror(HSQUIRRELVM v, const SQChar *err)
SQInstructionDesc g_InstrDesc[]
#define _FINISH(howmuchtojump)
void sq_base_register(HSQUIRRELVM v)
const SQChar * GetTypeName(const SQObjectPtr &obj1)
#define CLEARSTACK(_last_top)
#define _RET_ON_FAIL(exp)