The Squirrel interpreter. See http://www.squirrel-lang.org/

Dependents:   Squirrel

Committer:
jhnwkmn
Date:
Tue Dec 16 10:20:34 2014 +0000
Revision:
0:97a4f8cc534c
Child:
1:8a2835ae5c5d
Initial import of Squirrel.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jhnwkmn 0:97a4f8cc534c 1 /*
jhnwkmn 0:97a4f8cc534c 2 see copyright notice in squirrel.h
jhnwkmn 0:97a4f8cc534c 3 */
jhnwkmn 0:97a4f8cc534c 4 #include "sqpcheader.h"
jhnwkmn 0:97a4f8cc534c 5 #include <math.h>
jhnwkmn 0:97a4f8cc534c 6 #include <stdlib.h>
jhnwkmn 0:97a4f8cc534c 7 #include "sqopcodes.h"
jhnwkmn 0:97a4f8cc534c 8 #include "sqvm.h"
jhnwkmn 0:97a4f8cc534c 9 #include "sqfuncproto.h"
jhnwkmn 0:97a4f8cc534c 10 #include "sqclosure.h"
jhnwkmn 0:97a4f8cc534c 11 #include "sqstring.h"
jhnwkmn 0:97a4f8cc534c 12 #include "sqtable.h"
jhnwkmn 0:97a4f8cc534c 13 #include "squserdata.h"
jhnwkmn 0:97a4f8cc534c 14 #include "sqarray.h"
jhnwkmn 0:97a4f8cc534c 15 #include "sqclass.h"
jhnwkmn 0:97a4f8cc534c 16
jhnwkmn 0:97a4f8cc534c 17 #define TOP() (_stack._vals[_top-1])
jhnwkmn 0:97a4f8cc534c 18
jhnwkmn 0:97a4f8cc534c 19 bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
jhnwkmn 0:97a4f8cc534c 20 {
jhnwkmn 0:97a4f8cc534c 21 SQInteger res;
jhnwkmn 0:97a4f8cc534c 22 if((type(o1)|type(o2)) == OT_INTEGER)
jhnwkmn 0:97a4f8cc534c 23 {
jhnwkmn 0:97a4f8cc534c 24 SQInteger i1 = _integer(o1), i2 = _integer(o2);
jhnwkmn 0:97a4f8cc534c 25 switch(op) {
jhnwkmn 0:97a4f8cc534c 26 case BW_AND: res = i1 & i2; break;
jhnwkmn 0:97a4f8cc534c 27 case BW_OR: res = i1 | i2; break;
jhnwkmn 0:97a4f8cc534c 28 case BW_XOR: res = i1 ^ i2; break;
jhnwkmn 0:97a4f8cc534c 29 case BW_SHIFTL: res = i1 << i2; break;
jhnwkmn 0:97a4f8cc534c 30 case BW_SHIFTR: res = i1 >> i2; break;
jhnwkmn 0:97a4f8cc534c 31 case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break;
jhnwkmn 0:97a4f8cc534c 32 default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }
jhnwkmn 0:97a4f8cc534c 33 }
jhnwkmn 0:97a4f8cc534c 34 }
jhnwkmn 0:97a4f8cc534c 35 else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}
jhnwkmn 0:97a4f8cc534c 36 trg = res;
jhnwkmn 0:97a4f8cc534c 37 return true;
jhnwkmn 0:97a4f8cc534c 38 }
jhnwkmn 0:97a4f8cc534c 39
jhnwkmn 0:97a4f8cc534c 40 #define _ARITH_(op,trg,o1,o2) \
jhnwkmn 0:97a4f8cc534c 41 { \
jhnwkmn 0:97a4f8cc534c 42 SQInteger tmask = type(o1)|type(o2); \
jhnwkmn 0:97a4f8cc534c 43 switch(tmask) { \
jhnwkmn 0:97a4f8cc534c 44 case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
jhnwkmn 0:97a4f8cc534c 45 case (OT_FLOAT|OT_INTEGER): \
jhnwkmn 0:97a4f8cc534c 46 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
jhnwkmn 0:97a4f8cc534c 47 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
jhnwkmn 0:97a4f8cc534c 48 } \
jhnwkmn 0:97a4f8cc534c 49 }
jhnwkmn 0:97a4f8cc534c 50
jhnwkmn 0:97a4f8cc534c 51 #define _ARITH_NOZERO(op,trg,o1,o2,err) \
jhnwkmn 0:97a4f8cc534c 52 { \
jhnwkmn 0:97a4f8cc534c 53 SQInteger tmask = type(o1)|type(o2); \
jhnwkmn 0:97a4f8cc534c 54 switch(tmask) { \
jhnwkmn 0:97a4f8cc534c 55 case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\
jhnwkmn 0:97a4f8cc534c 56 case (OT_FLOAT|OT_INTEGER): \
jhnwkmn 0:97a4f8cc534c 57 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
jhnwkmn 0:97a4f8cc534c 58 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
jhnwkmn 0:97a4f8cc534c 59 } \
jhnwkmn 0:97a4f8cc534c 60 }
jhnwkmn 0:97a4f8cc534c 61
jhnwkmn 0:97a4f8cc534c 62 bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
jhnwkmn 0:97a4f8cc534c 63 {
jhnwkmn 0:97a4f8cc534c 64 SQInteger tmask = type(o1)|type(o2);
jhnwkmn 0:97a4f8cc534c 65 switch(tmask) {
jhnwkmn 0:97a4f8cc534c 66 case OT_INTEGER:{
jhnwkmn 0:97a4f8cc534c 67 SQInteger res, i1 = _integer(o1), i2 = _integer(o2);
jhnwkmn 0:97a4f8cc534c 68 switch(op) {
jhnwkmn 0:97a4f8cc534c 69 case '+': res = i1 + i2; break;
jhnwkmn 0:97a4f8cc534c 70 case '-': res = i1 - i2; break;
jhnwkmn 0:97a4f8cc534c 71 case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
jhnwkmn 0:97a4f8cc534c 72 res = i1 / i2;
jhnwkmn 0:97a4f8cc534c 73 break;
jhnwkmn 0:97a4f8cc534c 74 case '*': res = i1 * i2; break;
jhnwkmn 0:97a4f8cc534c 75 case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
jhnwkmn 0:97a4f8cc534c 76 res = i1 % i2;
jhnwkmn 0:97a4f8cc534c 77 break;
jhnwkmn 0:97a4f8cc534c 78 default: res = 0xDEADBEEF;
jhnwkmn 0:97a4f8cc534c 79 }
jhnwkmn 0:97a4f8cc534c 80 trg = res; }
jhnwkmn 0:97a4f8cc534c 81 break;
jhnwkmn 0:97a4f8cc534c 82 case (OT_FLOAT|OT_INTEGER):
jhnwkmn 0:97a4f8cc534c 83 case (OT_FLOAT):{
jhnwkmn 0:97a4f8cc534c 84 SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
jhnwkmn 0:97a4f8cc534c 85 switch(op) {
jhnwkmn 0:97a4f8cc534c 86 case '+': res = f1 + f2; break;
jhnwkmn 0:97a4f8cc534c 87 case '-': res = f1 - f2; break;
jhnwkmn 0:97a4f8cc534c 88 case '/': res = f1 / f2; break;
jhnwkmn 0:97a4f8cc534c 89 case '*': res = f1 * f2; break;
jhnwkmn 0:97a4f8cc534c 90 case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;
jhnwkmn 0:97a4f8cc534c 91 default: res = 0x0f;
jhnwkmn 0:97a4f8cc534c 92 }
jhnwkmn 0:97a4f8cc534c 93 trg = res; }
jhnwkmn 0:97a4f8cc534c 94 break;
jhnwkmn 0:97a4f8cc534c 95 default:
jhnwkmn 0:97a4f8cc534c 96 if(op == '+' && (tmask & _RT_STRING)){
jhnwkmn 0:97a4f8cc534c 97 if(!StringCat(o1, o2, trg)) return false;
jhnwkmn 0:97a4f8cc534c 98 }
jhnwkmn 0:97a4f8cc534c 99 else if(!ArithMetaMethod(op,o1,o2,trg)) {
jhnwkmn 0:97a4f8cc534c 100 return false;
jhnwkmn 0:97a4f8cc534c 101 }
jhnwkmn 0:97a4f8cc534c 102 }
jhnwkmn 0:97a4f8cc534c 103 return true;
jhnwkmn 0:97a4f8cc534c 104 }
jhnwkmn 0:97a4f8cc534c 105
jhnwkmn 0:97a4f8cc534c 106 SQVM::SQVM(SQSharedState *ss)
jhnwkmn 0:97a4f8cc534c 107 {
jhnwkmn 0:97a4f8cc534c 108 _sharedstate=ss;
jhnwkmn 0:97a4f8cc534c 109 _suspended = SQFalse;
jhnwkmn 0:97a4f8cc534c 110 _suspended_target = -1;
jhnwkmn 0:97a4f8cc534c 111 _suspended_root = SQFalse;
jhnwkmn 0:97a4f8cc534c 112 _suspended_traps = -1;
jhnwkmn 0:97a4f8cc534c 113 _foreignptr = NULL;
jhnwkmn 0:97a4f8cc534c 114 _nnativecalls = 0;
jhnwkmn 0:97a4f8cc534c 115 _nmetamethodscall = 0;
jhnwkmn 0:97a4f8cc534c 116 _lasterror.Null();
jhnwkmn 0:97a4f8cc534c 117 _errorhandler.Null();
jhnwkmn 0:97a4f8cc534c 118 _debughook = false;
jhnwkmn 0:97a4f8cc534c 119 _debughook_native = NULL;
jhnwkmn 0:97a4f8cc534c 120 _debughook_closure.Null();
jhnwkmn 0:97a4f8cc534c 121 _openouters = NULL;
jhnwkmn 0:97a4f8cc534c 122 ci = NULL;
jhnwkmn 0:97a4f8cc534c 123 INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
jhnwkmn 0:97a4f8cc534c 124 }
jhnwkmn 0:97a4f8cc534c 125
jhnwkmn 0:97a4f8cc534c 126 void SQVM::Finalize()
jhnwkmn 0:97a4f8cc534c 127 {
jhnwkmn 0:97a4f8cc534c 128 if(_openouters) CloseOuters(&_stack._vals[0]);
jhnwkmn 0:97a4f8cc534c 129 _roottable.Null();
jhnwkmn 0:97a4f8cc534c 130 _lasterror.Null();
jhnwkmn 0:97a4f8cc534c 131 _errorhandler.Null();
jhnwkmn 0:97a4f8cc534c 132 _debughook = false;
jhnwkmn 0:97a4f8cc534c 133 _debughook_native = NULL;
jhnwkmn 0:97a4f8cc534c 134 _debughook_closure.Null();
jhnwkmn 0:97a4f8cc534c 135 temp_reg.Null();
jhnwkmn 0:97a4f8cc534c 136 _callstackdata.resize(0);
jhnwkmn 0:97a4f8cc534c 137 SQInteger size=_stack.size();
jhnwkmn 0:97a4f8cc534c 138 for(SQInteger i=0;i<size;i++)
jhnwkmn 0:97a4f8cc534c 139 _stack[i].Null();
jhnwkmn 0:97a4f8cc534c 140 }
jhnwkmn 0:97a4f8cc534c 141
jhnwkmn 0:97a4f8cc534c 142 SQVM::~SQVM()
jhnwkmn 0:97a4f8cc534c 143 {
jhnwkmn 0:97a4f8cc534c 144 Finalize();
jhnwkmn 0:97a4f8cc534c 145 REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
jhnwkmn 0:97a4f8cc534c 146 }
jhnwkmn 0:97a4f8cc534c 147
jhnwkmn 0:97a4f8cc534c 148 bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 149 {
jhnwkmn 0:97a4f8cc534c 150 SQMetaMethod mm;
jhnwkmn 0:97a4f8cc534c 151 switch(op){
jhnwkmn 0:97a4f8cc534c 152 case _SC('+'): mm=MT_ADD; break;
jhnwkmn 0:97a4f8cc534c 153 case _SC('-'): mm=MT_SUB; break;
jhnwkmn 0:97a4f8cc534c 154 case _SC('/'): mm=MT_DIV; break;
jhnwkmn 0:97a4f8cc534c 155 case _SC('*'): mm=MT_MUL; break;
jhnwkmn 0:97a4f8cc534c 156 case _SC('%'): mm=MT_MODULO; break;
jhnwkmn 0:97a4f8cc534c 157 default: mm = MT_ADD; assert(0); break; //shutup compiler
jhnwkmn 0:97a4f8cc534c 158 }
jhnwkmn 0:97a4f8cc534c 159 if(is_delegable(o1) && _delegable(o1)->_delegate) {
jhnwkmn 0:97a4f8cc534c 160
jhnwkmn 0:97a4f8cc534c 161 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 162 if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {
jhnwkmn 0:97a4f8cc534c 163 Push(o1);Push(o2);
jhnwkmn 0:97a4f8cc534c 164 return CallMetaMethod(closure,mm,2,dest);
jhnwkmn 0:97a4f8cc534c 165 }
jhnwkmn 0:97a4f8cc534c 166 }
jhnwkmn 0:97a4f8cc534c 167 Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2));
jhnwkmn 0:97a4f8cc534c 168 return false;
jhnwkmn 0:97a4f8cc534c 169 }
jhnwkmn 0:97a4f8cc534c 170
jhnwkmn 0:97a4f8cc534c 171 bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
jhnwkmn 0:97a4f8cc534c 172 {
jhnwkmn 0:97a4f8cc534c 173
jhnwkmn 0:97a4f8cc534c 174 switch(type(o)) {
jhnwkmn 0:97a4f8cc534c 175 case OT_INTEGER:
jhnwkmn 0:97a4f8cc534c 176 trg = -_integer(o);
jhnwkmn 0:97a4f8cc534c 177 return true;
jhnwkmn 0:97a4f8cc534c 178 case OT_FLOAT:
jhnwkmn 0:97a4f8cc534c 179 trg = -_float(o);
jhnwkmn 0:97a4f8cc534c 180 return true;
jhnwkmn 0:97a4f8cc534c 181 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 182 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 183 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 184 if(_delegable(o)->_delegate) {
jhnwkmn 0:97a4f8cc534c 185 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 186 if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {
jhnwkmn 0:97a4f8cc534c 187 Push(o);
jhnwkmn 0:97a4f8cc534c 188 if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;
jhnwkmn 0:97a4f8cc534c 189 _Swap(trg,temp_reg);
jhnwkmn 0:97a4f8cc534c 190 return true;
jhnwkmn 0:97a4f8cc534c 191
jhnwkmn 0:97a4f8cc534c 192 }
jhnwkmn 0:97a4f8cc534c 193 }
jhnwkmn 0:97a4f8cc534c 194 default:break; //shutup compiler
jhnwkmn 0:97a4f8cc534c 195 }
jhnwkmn 0:97a4f8cc534c 196 Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
jhnwkmn 0:97a4f8cc534c 197 return false;
jhnwkmn 0:97a4f8cc534c 198 }
jhnwkmn 0:97a4f8cc534c 199
jhnwkmn 0:97a4f8cc534c 200 #define _RET_SUCCEED(exp) { result = (exp); return true; }
jhnwkmn 0:97a4f8cc534c 201 bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
jhnwkmn 0:97a4f8cc534c 202 {
jhnwkmn 0:97a4f8cc534c 203 SQObjectType t1 = type(o1), t2 = type(o2);
jhnwkmn 0:97a4f8cc534c 204 if(t1 == t2) {
jhnwkmn 0:97a4f8cc534c 205 if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0);
jhnwkmn 0:97a4f8cc534c 206 SQObjectPtr res;
jhnwkmn 0:97a4f8cc534c 207 switch(t1){
jhnwkmn 0:97a4f8cc534c 208 case OT_STRING:
jhnwkmn 0:97a4f8cc534c 209 _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));
jhnwkmn 0:97a4f8cc534c 210 case OT_INTEGER:
jhnwkmn 0:97a4f8cc534c 211 _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1);
jhnwkmn 0:97a4f8cc534c 212 case OT_FLOAT:
jhnwkmn 0:97a4f8cc534c 213 _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
jhnwkmn 0:97a4f8cc534c 214 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 215 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 216 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 217 if(_delegable(o1)->_delegate) {
jhnwkmn 0:97a4f8cc534c 218 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 219 if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {
jhnwkmn 0:97a4f8cc534c 220 Push(o1);Push(o2);
jhnwkmn 0:97a4f8cc534c 221 if(CallMetaMethod(closure,MT_CMP,2,res)) {
jhnwkmn 0:97a4f8cc534c 222 if(type(res) != OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 223 Raise_Error(_SC("_cmp must return an integer"));
jhnwkmn 0:97a4f8cc534c 224 return false;
jhnwkmn 0:97a4f8cc534c 225 }
jhnwkmn 0:97a4f8cc534c 226 _RET_SUCCEED(_integer(res))
jhnwkmn 0:97a4f8cc534c 227 }
jhnwkmn 0:97a4f8cc534c 228 return false;
jhnwkmn 0:97a4f8cc534c 229 }
jhnwkmn 0:97a4f8cc534c 230 }
jhnwkmn 0:97a4f8cc534c 231 //continues through (no break needed)
jhnwkmn 0:97a4f8cc534c 232 default:
jhnwkmn 0:97a4f8cc534c 233 _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
jhnwkmn 0:97a4f8cc534c 234 }
jhnwkmn 0:97a4f8cc534c 235 assert(0);
jhnwkmn 0:97a4f8cc534c 236 //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
jhnwkmn 0:97a4f8cc534c 237 // _RET_SUCCEED(_integer(res));
jhnwkmn 0:97a4f8cc534c 238
jhnwkmn 0:97a4f8cc534c 239 }
jhnwkmn 0:97a4f8cc534c 240 else{
jhnwkmn 0:97a4f8cc534c 241 if(sq_isnumeric(o1) && sq_isnumeric(o2)){
jhnwkmn 0:97a4f8cc534c 242 if((t1==OT_INTEGER) && (t2==OT_FLOAT)) {
jhnwkmn 0:97a4f8cc534c 243 if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
jhnwkmn 0:97a4f8cc534c 244 else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
jhnwkmn 0:97a4f8cc534c 245 _RET_SUCCEED(1);
jhnwkmn 0:97a4f8cc534c 246 }
jhnwkmn 0:97a4f8cc534c 247 else{
jhnwkmn 0:97a4f8cc534c 248 if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }
jhnwkmn 0:97a4f8cc534c 249 else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }
jhnwkmn 0:97a4f8cc534c 250 _RET_SUCCEED(1);
jhnwkmn 0:97a4f8cc534c 251 }
jhnwkmn 0:97a4f8cc534c 252 }
jhnwkmn 0:97a4f8cc534c 253 else if(t1==OT_NULL) {_RET_SUCCEED(-1);}
jhnwkmn 0:97a4f8cc534c 254 else if(t2==OT_NULL) {_RET_SUCCEED(1);}
jhnwkmn 0:97a4f8cc534c 255 else { Raise_CompareError(o1,o2); return false; }
jhnwkmn 0:97a4f8cc534c 256
jhnwkmn 0:97a4f8cc534c 257 }
jhnwkmn 0:97a4f8cc534c 258 assert(0);
jhnwkmn 0:97a4f8cc534c 259 _RET_SUCCEED(0); //cannot happen
jhnwkmn 0:97a4f8cc534c 260 }
jhnwkmn 0:97a4f8cc534c 261
jhnwkmn 0:97a4f8cc534c 262 bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)
jhnwkmn 0:97a4f8cc534c 263 {
jhnwkmn 0:97a4f8cc534c 264 SQInteger r;
jhnwkmn 0:97a4f8cc534c 265 if(ObjCmp(o1,o2,r)) {
jhnwkmn 0:97a4f8cc534c 266 switch(op) {
jhnwkmn 0:97a4f8cc534c 267 case CMP_G: res = (r > 0); return true;
jhnwkmn 0:97a4f8cc534c 268 case CMP_GE: res = (r >= 0); return true;
jhnwkmn 0:97a4f8cc534c 269 case CMP_L: res = (r < 0); return true;
jhnwkmn 0:97a4f8cc534c 270 case CMP_LE: res = (r <= 0); return true;
jhnwkmn 0:97a4f8cc534c 271 case CMP_3W: res = r; return true;
jhnwkmn 0:97a4f8cc534c 272 }
jhnwkmn 0:97a4f8cc534c 273 assert(0);
jhnwkmn 0:97a4f8cc534c 274 }
jhnwkmn 0:97a4f8cc534c 275 return false;
jhnwkmn 0:97a4f8cc534c 276 }
jhnwkmn 0:97a4f8cc534c 277
jhnwkmn 0:97a4f8cc534c 278 bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
jhnwkmn 0:97a4f8cc534c 279 {
jhnwkmn 0:97a4f8cc534c 280 switch(type(o)) {
jhnwkmn 0:97a4f8cc534c 281 case OT_STRING:
jhnwkmn 0:97a4f8cc534c 282 res = o;
jhnwkmn 0:97a4f8cc534c 283 return true;
jhnwkmn 0:97a4f8cc534c 284 case OT_FLOAT:
jhnwkmn 0:97a4f8cc534c 285 scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o));
jhnwkmn 0:97a4f8cc534c 286 break;
jhnwkmn 0:97a4f8cc534c 287 case OT_INTEGER:
jhnwkmn 0:97a4f8cc534c 288 scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o));
jhnwkmn 0:97a4f8cc534c 289 break;
jhnwkmn 0:97a4f8cc534c 290 case OT_BOOL:
jhnwkmn 0:97a4f8cc534c 291 scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false"));
jhnwkmn 0:97a4f8cc534c 292 break;
jhnwkmn 0:97a4f8cc534c 293 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 294 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 295 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 296 if(_delegable(o)->_delegate) {
jhnwkmn 0:97a4f8cc534c 297 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 298 if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {
jhnwkmn 0:97a4f8cc534c 299 Push(o);
jhnwkmn 0:97a4f8cc534c 300 if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;
jhnwkmn 0:97a4f8cc534c 301 if(type(res) == OT_STRING)
jhnwkmn 0:97a4f8cc534c 302 return true;
jhnwkmn 0:97a4f8cc534c 303 }
jhnwkmn 0:97a4f8cc534c 304 else {
jhnwkmn 0:97a4f8cc534c 305 return false;
jhnwkmn 0:97a4f8cc534c 306 }
jhnwkmn 0:97a4f8cc534c 307 }
jhnwkmn 0:97a4f8cc534c 308 }
jhnwkmn 0:97a4f8cc534c 309 default:
jhnwkmn 0:97a4f8cc534c 310 scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
jhnwkmn 0:97a4f8cc534c 311 }
jhnwkmn 0:97a4f8cc534c 312 res = SQString::Create(_ss(this),_spval);
jhnwkmn 0:97a4f8cc534c 313 return true;
jhnwkmn 0:97a4f8cc534c 314 }
jhnwkmn 0:97a4f8cc534c 315
jhnwkmn 0:97a4f8cc534c 316
jhnwkmn 0:97a4f8cc534c 317 bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 318 {
jhnwkmn 0:97a4f8cc534c 319 SQObjectPtr a, b;
jhnwkmn 0:97a4f8cc534c 320 if(!ToString(str, a)) return false;
jhnwkmn 0:97a4f8cc534c 321 if(!ToString(obj, b)) return false;
jhnwkmn 0:97a4f8cc534c 322 SQInteger l = _string(a)->_len , ol = _string(b)->_len;
jhnwkmn 0:97a4f8cc534c 323 SQChar *s = _sp(rsl(l + ol + 1));
jhnwkmn 0:97a4f8cc534c 324 memcpy(s, _stringval(a), rsl(l));
jhnwkmn 0:97a4f8cc534c 325 memcpy(s + l, _stringval(b), rsl(ol));
jhnwkmn 0:97a4f8cc534c 326 dest = SQString::Create(_ss(this), _spval, l + ol);
jhnwkmn 0:97a4f8cc534c 327 return true;
jhnwkmn 0:97a4f8cc534c 328 }
jhnwkmn 0:97a4f8cc534c 329
jhnwkmn 0:97a4f8cc534c 330 bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 331 {
jhnwkmn 0:97a4f8cc534c 332 if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
jhnwkmn 0:97a4f8cc534c 333 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 334 if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {
jhnwkmn 0:97a4f8cc534c 335 Push(obj1);
jhnwkmn 0:97a4f8cc534c 336 return CallMetaMethod(closure,MT_TYPEOF,1,dest);
jhnwkmn 0:97a4f8cc534c 337 }
jhnwkmn 0:97a4f8cc534c 338 }
jhnwkmn 0:97a4f8cc534c 339 dest = SQString::Create(_ss(this),GetTypeName(obj1));
jhnwkmn 0:97a4f8cc534c 340 return true;
jhnwkmn 0:97a4f8cc534c 341 }
jhnwkmn 0:97a4f8cc534c 342
jhnwkmn 0:97a4f8cc534c 343 bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
jhnwkmn 0:97a4f8cc534c 344 {
jhnwkmn 0:97a4f8cc534c 345 _stack.resize(stacksize);
jhnwkmn 0:97a4f8cc534c 346 _alloccallsstacksize = 4;
jhnwkmn 0:97a4f8cc534c 347 _callstackdata.resize(_alloccallsstacksize);
jhnwkmn 0:97a4f8cc534c 348 _callsstacksize = 0;
jhnwkmn 0:97a4f8cc534c 349 _callsstack = &_callstackdata[0];
jhnwkmn 0:97a4f8cc534c 350 _stackbase = 0;
jhnwkmn 0:97a4f8cc534c 351 _top = 0;
jhnwkmn 0:97a4f8cc534c 352 if(!friendvm)
jhnwkmn 0:97a4f8cc534c 353 _roottable = SQTable::Create(_ss(this), 0);
jhnwkmn 0:97a4f8cc534c 354 else {
jhnwkmn 0:97a4f8cc534c 355 _roottable = friendvm->_roottable;
jhnwkmn 0:97a4f8cc534c 356 _errorhandler = friendvm->_errorhandler;
jhnwkmn 0:97a4f8cc534c 357 _debughook = friendvm->_debughook;
jhnwkmn 0:97a4f8cc534c 358 _debughook_native = friendvm->_debughook_native;
jhnwkmn 0:97a4f8cc534c 359 _debughook_closure = friendvm->_debughook_closure;
jhnwkmn 0:97a4f8cc534c 360 }
jhnwkmn 0:97a4f8cc534c 361
jhnwkmn 0:97a4f8cc534c 362 sq_base_register(this);
jhnwkmn 0:97a4f8cc534c 363 return true;
jhnwkmn 0:97a4f8cc534c 364 }
jhnwkmn 0:97a4f8cc534c 365
jhnwkmn 0:97a4f8cc534c 366
jhnwkmn 0:97a4f8cc534c 367 bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
jhnwkmn 0:97a4f8cc534c 368 {
jhnwkmn 0:97a4f8cc534c 369 SQFunctionProto *func = closure->_function;
jhnwkmn 0:97a4f8cc534c 370
jhnwkmn 0:97a4f8cc534c 371 SQInteger paramssize = func->_nparameters;
jhnwkmn 0:97a4f8cc534c 372 const SQInteger newtop = stackbase + func->_stacksize;
jhnwkmn 0:97a4f8cc534c 373 SQInteger nargs = args;
jhnwkmn 0:97a4f8cc534c 374 if(func->_varparams)
jhnwkmn 0:97a4f8cc534c 375 {
jhnwkmn 0:97a4f8cc534c 376 paramssize--;
jhnwkmn 0:97a4f8cc534c 377 if (nargs < paramssize) {
jhnwkmn 0:97a4f8cc534c 378 Raise_Error(_SC("wrong number of parameters"));
jhnwkmn 0:97a4f8cc534c 379 return false;
jhnwkmn 0:97a4f8cc534c 380 }
jhnwkmn 0:97a4f8cc534c 381
jhnwkmn 0:97a4f8cc534c 382 //dumpstack(stackbase);
jhnwkmn 0:97a4f8cc534c 383 SQInteger nvargs = nargs - paramssize;
jhnwkmn 0:97a4f8cc534c 384 SQArray *arr = SQArray::Create(_ss(this),nvargs);
jhnwkmn 0:97a4f8cc534c 385 SQInteger pbase = stackbase+paramssize;
jhnwkmn 0:97a4f8cc534c 386 for(SQInteger n = 0; n < nvargs; n++) {
jhnwkmn 0:97a4f8cc534c 387 arr->_values[n] = _stack._vals[pbase];
jhnwkmn 0:97a4f8cc534c 388 _stack._vals[pbase].Null();
jhnwkmn 0:97a4f8cc534c 389 pbase++;
jhnwkmn 0:97a4f8cc534c 390
jhnwkmn 0:97a4f8cc534c 391 }
jhnwkmn 0:97a4f8cc534c 392 _stack._vals[stackbase+paramssize] = arr;
jhnwkmn 0:97a4f8cc534c 393 //dumpstack(stackbase);
jhnwkmn 0:97a4f8cc534c 394 }
jhnwkmn 0:97a4f8cc534c 395 else if (paramssize != nargs) {
jhnwkmn 0:97a4f8cc534c 396 SQInteger ndef = func->_ndefaultparams;
jhnwkmn 0:97a4f8cc534c 397 SQInteger diff;
jhnwkmn 0:97a4f8cc534c 398 if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
jhnwkmn 0:97a4f8cc534c 399 for(SQInteger n = ndef - diff; n < ndef; n++) {
jhnwkmn 0:97a4f8cc534c 400 _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
jhnwkmn 0:97a4f8cc534c 401 }
jhnwkmn 0:97a4f8cc534c 402 }
jhnwkmn 0:97a4f8cc534c 403 else {
jhnwkmn 0:97a4f8cc534c 404 Raise_Error(_SC("wrong number of parameters"));
jhnwkmn 0:97a4f8cc534c 405 return false;
jhnwkmn 0:97a4f8cc534c 406 }
jhnwkmn 0:97a4f8cc534c 407 }
jhnwkmn 0:97a4f8cc534c 408
jhnwkmn 0:97a4f8cc534c 409 if(closure->_env) {
jhnwkmn 0:97a4f8cc534c 410 _stack._vals[stackbase] = closure->_env->_obj;
jhnwkmn 0:97a4f8cc534c 411 }
jhnwkmn 0:97a4f8cc534c 412
jhnwkmn 0:97a4f8cc534c 413 if(!EnterFrame(stackbase, newtop, tailcall)) return false;
jhnwkmn 0:97a4f8cc534c 414
jhnwkmn 0:97a4f8cc534c 415 ci->_closure = closure;
jhnwkmn 0:97a4f8cc534c 416 ci->_literals = func->_literals;
jhnwkmn 0:97a4f8cc534c 417 ci->_ip = func->_instructions;
jhnwkmn 0:97a4f8cc534c 418 ci->_target = (SQInt32)target;
jhnwkmn 0:97a4f8cc534c 419
jhnwkmn 0:97a4f8cc534c 420 if (_debughook) {
jhnwkmn 0:97a4f8cc534c 421 CallDebugHook(_SC('c'));
jhnwkmn 0:97a4f8cc534c 422 }
jhnwkmn 0:97a4f8cc534c 423
jhnwkmn 0:97a4f8cc534c 424 if (closure->_function->_bgenerator) {
jhnwkmn 0:97a4f8cc534c 425 SQFunctionProto *f = closure->_function;
jhnwkmn 0:97a4f8cc534c 426 SQGenerator *gen = SQGenerator::Create(_ss(this), closure);
jhnwkmn 0:97a4f8cc534c 427 if(!gen->Yield(this,f->_stacksize))
jhnwkmn 0:97a4f8cc534c 428 return false;
jhnwkmn 0:97a4f8cc534c 429 SQObjectPtr temp;
jhnwkmn 0:97a4f8cc534c 430 Return(1, target, temp);
jhnwkmn 0:97a4f8cc534c 431 STK(target) = gen;
jhnwkmn 0:97a4f8cc534c 432 }
jhnwkmn 0:97a4f8cc534c 433
jhnwkmn 0:97a4f8cc534c 434
jhnwkmn 0:97a4f8cc534c 435 return true;
jhnwkmn 0:97a4f8cc534c 436 }
jhnwkmn 0:97a4f8cc534c 437
jhnwkmn 0:97a4f8cc534c 438 bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
jhnwkmn 0:97a4f8cc534c 439 {
jhnwkmn 0:97a4f8cc534c 440 SQBool _isroot = ci->_root;
jhnwkmn 0:97a4f8cc534c 441 SQInteger callerbase = _stackbase - ci->_prevstkbase;
jhnwkmn 0:97a4f8cc534c 442
jhnwkmn 0:97a4f8cc534c 443 if (_debughook) {
jhnwkmn 0:97a4f8cc534c 444 for(SQInteger i=0; i<ci->_ncalls; i++) {
jhnwkmn 0:97a4f8cc534c 445 CallDebugHook(_SC('r'));
jhnwkmn 0:97a4f8cc534c 446 }
jhnwkmn 0:97a4f8cc534c 447 }
jhnwkmn 0:97a4f8cc534c 448
jhnwkmn 0:97a4f8cc534c 449 SQObjectPtr *dest;
jhnwkmn 0:97a4f8cc534c 450 if (_isroot) {
jhnwkmn 0:97a4f8cc534c 451 dest = &(retval);
jhnwkmn 0:97a4f8cc534c 452 } else if (ci->_target == -1) {
jhnwkmn 0:97a4f8cc534c 453 dest = NULL;
jhnwkmn 0:97a4f8cc534c 454 } else {
jhnwkmn 0:97a4f8cc534c 455 dest = &_stack._vals[callerbase + ci->_target];
jhnwkmn 0:97a4f8cc534c 456 }
jhnwkmn 0:97a4f8cc534c 457 if (dest) {
jhnwkmn 0:97a4f8cc534c 458 if(_arg0 != 0xFF) {
jhnwkmn 0:97a4f8cc534c 459 *dest = _stack._vals[_stackbase+_arg1];
jhnwkmn 0:97a4f8cc534c 460 }
jhnwkmn 0:97a4f8cc534c 461 else {
jhnwkmn 0:97a4f8cc534c 462 dest->Null();
jhnwkmn 0:97a4f8cc534c 463 }
jhnwkmn 0:97a4f8cc534c 464 //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_;
jhnwkmn 0:97a4f8cc534c 465 }
jhnwkmn 0:97a4f8cc534c 466 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 467 return _isroot ? true : false;
jhnwkmn 0:97a4f8cc534c 468 }
jhnwkmn 0:97a4f8cc534c 469
jhnwkmn 0:97a4f8cc534c 470 #define _RET_ON_FAIL(exp) { if(!exp) return false; }
jhnwkmn 0:97a4f8cc534c 471
jhnwkmn 0:97a4f8cc534c 472 bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
jhnwkmn 0:97a4f8cc534c 473 {
jhnwkmn 0:97a4f8cc534c 474 SQObjectPtr trg;
jhnwkmn 0:97a4f8cc534c 475 _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));
jhnwkmn 0:97a4f8cc534c 476 target = a;
jhnwkmn 0:97a4f8cc534c 477 a = trg;
jhnwkmn 0:97a4f8cc534c 478 return true;
jhnwkmn 0:97a4f8cc534c 479 }
jhnwkmn 0:97a4f8cc534c 480
jhnwkmn 0:97a4f8cc534c 481 bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx)
jhnwkmn 0:97a4f8cc534c 482 {
jhnwkmn 0:97a4f8cc534c 483 SQObjectPtr tmp, tself = self, tkey = key;
jhnwkmn 0:97a4f8cc534c 484 if (!Get(tself, tkey, tmp, false, selfidx)) { return false; }
jhnwkmn 0:97a4f8cc534c 485 _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
jhnwkmn 0:97a4f8cc534c 486 if (!Set(tself, tkey, target,selfidx)) { return false; }
jhnwkmn 0:97a4f8cc534c 487 if (postfix) target = tmp;
jhnwkmn 0:97a4f8cc534c 488 return true;
jhnwkmn 0:97a4f8cc534c 489 }
jhnwkmn 0:97a4f8cc534c 490
jhnwkmn 0:97a4f8cc534c 491 #define arg0 (_i_._arg0)
jhnwkmn 0:97a4f8cc534c 492 #define sarg0 ((SQInteger)*((signed char *)&_i_._arg0))
jhnwkmn 0:97a4f8cc534c 493 #define arg1 (_i_._arg1)
jhnwkmn 0:97a4f8cc534c 494 #define sarg1 (*((SQInt32 *)&_i_._arg1))
jhnwkmn 0:97a4f8cc534c 495 #define arg2 (_i_._arg2)
jhnwkmn 0:97a4f8cc534c 496 #define arg3 (_i_._arg3)
jhnwkmn 0:97a4f8cc534c 497 #define sarg3 ((SQInteger)*((signed char *)&_i_._arg3))
jhnwkmn 0:97a4f8cc534c 498
jhnwkmn 0:97a4f8cc534c 499 SQRESULT SQVM::Suspend()
jhnwkmn 0:97a4f8cc534c 500 {
jhnwkmn 0:97a4f8cc534c 501 if (_suspended)
jhnwkmn 0:97a4f8cc534c 502 return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));
jhnwkmn 0:97a4f8cc534c 503 if (_nnativecalls!=2)
jhnwkmn 0:97a4f8cc534c 504 return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));
jhnwkmn 0:97a4f8cc534c 505 return SQ_SUSPEND_FLAG;
jhnwkmn 0:97a4f8cc534c 506 }
jhnwkmn 0:97a4f8cc534c 507
jhnwkmn 0:97a4f8cc534c 508
jhnwkmn 0:97a4f8cc534c 509 #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
jhnwkmn 0:97a4f8cc534c 510 bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
jhnwkmn 0:97a4f8cc534c 511 &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)
jhnwkmn 0:97a4f8cc534c 512 {
jhnwkmn 0:97a4f8cc534c 513 SQInteger nrefidx;
jhnwkmn 0:97a4f8cc534c 514 switch(type(o1)) {
jhnwkmn 0:97a4f8cc534c 515 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 516 if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 517 o4 = (SQInteger)nrefidx; _FINISH(1);
jhnwkmn 0:97a4f8cc534c 518 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 519 if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 520 o4 = (SQInteger) nrefidx; _FINISH(1);
jhnwkmn 0:97a4f8cc534c 521 case OT_STRING:
jhnwkmn 0:97a4f8cc534c 522 if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 523 o4 = (SQInteger)nrefidx; _FINISH(1);
jhnwkmn 0:97a4f8cc534c 524 case OT_CLASS:
jhnwkmn 0:97a4f8cc534c 525 if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 526 o4 = (SQInteger)nrefidx; _FINISH(1);
jhnwkmn 0:97a4f8cc534c 527 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 528 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 529 if(_delegable(o1)->_delegate) {
jhnwkmn 0:97a4f8cc534c 530 SQObjectPtr itr;
jhnwkmn 0:97a4f8cc534c 531 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 532 if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {
jhnwkmn 0:97a4f8cc534c 533 Push(o1);
jhnwkmn 0:97a4f8cc534c 534 Push(o4);
jhnwkmn 0:97a4f8cc534c 535 if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {
jhnwkmn 0:97a4f8cc534c 536 o4 = o2 = itr;
jhnwkmn 0:97a4f8cc534c 537 if(type(itr) == OT_NULL) _FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 538 if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) {
jhnwkmn 0:97a4f8cc534c 539 Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed
jhnwkmn 0:97a4f8cc534c 540 return false;
jhnwkmn 0:97a4f8cc534c 541 }
jhnwkmn 0:97a4f8cc534c 542 _FINISH(1);
jhnwkmn 0:97a4f8cc534c 543 }
jhnwkmn 0:97a4f8cc534c 544 else {
jhnwkmn 0:97a4f8cc534c 545 return false;
jhnwkmn 0:97a4f8cc534c 546 }
jhnwkmn 0:97a4f8cc534c 547 }
jhnwkmn 0:97a4f8cc534c 548 Raise_Error(_SC("_nexti failed"));
jhnwkmn 0:97a4f8cc534c 549 return false;
jhnwkmn 0:97a4f8cc534c 550 }
jhnwkmn 0:97a4f8cc534c 551 break;
jhnwkmn 0:97a4f8cc534c 552 case OT_GENERATOR:
jhnwkmn 0:97a4f8cc534c 553 if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
jhnwkmn 0:97a4f8cc534c 554 if(_generator(o1)->_state == SQGenerator::eSuspended) {
jhnwkmn 0:97a4f8cc534c 555 SQInteger idx = 0;
jhnwkmn 0:97a4f8cc534c 556 if(type(o4) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 557 idx = _integer(o4) + 1;
jhnwkmn 0:97a4f8cc534c 558 }
jhnwkmn 0:97a4f8cc534c 559 o2 = idx;
jhnwkmn 0:97a4f8cc534c 560 o4 = idx;
jhnwkmn 0:97a4f8cc534c 561 _generator(o1)->Resume(this, o3);
jhnwkmn 0:97a4f8cc534c 562 _FINISH(0);
jhnwkmn 0:97a4f8cc534c 563 }
jhnwkmn 0:97a4f8cc534c 564 default:
jhnwkmn 0:97a4f8cc534c 565 Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
jhnwkmn 0:97a4f8cc534c 566 }
jhnwkmn 0:97a4f8cc534c 567 return false; //cannot be hit(just to avoid warnings)
jhnwkmn 0:97a4f8cc534c 568 }
jhnwkmn 0:97a4f8cc534c 569
jhnwkmn 0:97a4f8cc534c 570 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
jhnwkmn 0:97a4f8cc534c 571
jhnwkmn 0:97a4f8cc534c 572 #define SQ_THROW() { goto exception_trap; }
jhnwkmn 0:97a4f8cc534c 573
jhnwkmn 0:97a4f8cc534c 574 #define _GUARD(exp) { if(!exp) { SQ_THROW();} }
jhnwkmn 0:97a4f8cc534c 575
jhnwkmn 0:97a4f8cc534c 576 bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
jhnwkmn 0:97a4f8cc534c 577 {
jhnwkmn 0:97a4f8cc534c 578 SQInteger nouters;
jhnwkmn 0:97a4f8cc534c 579 SQClosure *closure = SQClosure::Create(_ss(this), func);
jhnwkmn 0:97a4f8cc534c 580 if((nouters = func->_noutervalues)) {
jhnwkmn 0:97a4f8cc534c 581 for(SQInteger i = 0; i<nouters; i++) {
jhnwkmn 0:97a4f8cc534c 582 SQOuterVar &v = func->_outervalues[i];
jhnwkmn 0:97a4f8cc534c 583 switch(v._type){
jhnwkmn 0:97a4f8cc534c 584 case otLOCAL:
jhnwkmn 0:97a4f8cc534c 585 FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));
jhnwkmn 0:97a4f8cc534c 586 break;
jhnwkmn 0:97a4f8cc534c 587 case otOUTER:
jhnwkmn 0:97a4f8cc534c 588 closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];
jhnwkmn 0:97a4f8cc534c 589 break;
jhnwkmn 0:97a4f8cc534c 590 }
jhnwkmn 0:97a4f8cc534c 591 }
jhnwkmn 0:97a4f8cc534c 592 }
jhnwkmn 0:97a4f8cc534c 593 SQInteger ndefparams;
jhnwkmn 0:97a4f8cc534c 594 if((ndefparams = func->_ndefaultparams)) {
jhnwkmn 0:97a4f8cc534c 595 for(SQInteger i = 0; i < ndefparams; i++) {
jhnwkmn 0:97a4f8cc534c 596 SQInteger spos = func->_defaultparams[i];
jhnwkmn 0:97a4f8cc534c 597 closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
jhnwkmn 0:97a4f8cc534c 598 }
jhnwkmn 0:97a4f8cc534c 599 }
jhnwkmn 0:97a4f8cc534c 600 target = closure;
jhnwkmn 0:97a4f8cc534c 601 return true;
jhnwkmn 0:97a4f8cc534c 602
jhnwkmn 0:97a4f8cc534c 603 }
jhnwkmn 0:97a4f8cc534c 604
jhnwkmn 0:97a4f8cc534c 605
jhnwkmn 0:97a4f8cc534c 606 bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes)
jhnwkmn 0:97a4f8cc534c 607 {
jhnwkmn 0:97a4f8cc534c 608 SQClass *base = NULL;
jhnwkmn 0:97a4f8cc534c 609 SQObjectPtr attrs;
jhnwkmn 0:97a4f8cc534c 610 if(baseclass != -1) {
jhnwkmn 0:97a4f8cc534c 611 if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
jhnwkmn 0:97a4f8cc534c 612 base = _class(_stack._vals[_stackbase + baseclass]);
jhnwkmn 0:97a4f8cc534c 613 }
jhnwkmn 0:97a4f8cc534c 614 if(attributes != MAX_FUNC_STACKSIZE) {
jhnwkmn 0:97a4f8cc534c 615 attrs = _stack._vals[_stackbase+attributes];
jhnwkmn 0:97a4f8cc534c 616 }
jhnwkmn 0:97a4f8cc534c 617 target = SQClass::Create(_ss(this),base);
jhnwkmn 0:97a4f8cc534c 618 if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 619 int nparams = 2;
jhnwkmn 0:97a4f8cc534c 620 SQObjectPtr ret;
jhnwkmn 0:97a4f8cc534c 621 Push(target); Push(attrs);
jhnwkmn 0:97a4f8cc534c 622 Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false);
jhnwkmn 0:97a4f8cc534c 623 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 624 }
jhnwkmn 0:97a4f8cc534c 625 _class(target)->_attributes = attrs;
jhnwkmn 0:97a4f8cc534c 626 return true;
jhnwkmn 0:97a4f8cc534c 627 }
jhnwkmn 0:97a4f8cc534c 628
jhnwkmn 0:97a4f8cc534c 629 bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)
jhnwkmn 0:97a4f8cc534c 630 {
jhnwkmn 0:97a4f8cc534c 631 if(type(o1) == type(o2)) {
jhnwkmn 0:97a4f8cc534c 632 res = (_rawval(o1) == _rawval(o2));
jhnwkmn 0:97a4f8cc534c 633 }
jhnwkmn 0:97a4f8cc534c 634 else {
jhnwkmn 0:97a4f8cc534c 635 if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
jhnwkmn 0:97a4f8cc534c 636 res = (tofloat(o1) == tofloat(o2));
jhnwkmn 0:97a4f8cc534c 637 }
jhnwkmn 0:97a4f8cc534c 638 else {
jhnwkmn 0:97a4f8cc534c 639 res = false;
jhnwkmn 0:97a4f8cc534c 640 }
jhnwkmn 0:97a4f8cc534c 641 }
jhnwkmn 0:97a4f8cc534c 642 return true;
jhnwkmn 0:97a4f8cc534c 643 }
jhnwkmn 0:97a4f8cc534c 644
jhnwkmn 0:97a4f8cc534c 645 bool SQVM::IsFalse(SQObjectPtr &o)
jhnwkmn 0:97a4f8cc534c 646 {
jhnwkmn 0:97a4f8cc534c 647 if(((type(o) & SQOBJECT_CANBEFALSE)
jhnwkmn 0:97a4f8cc534c 648 && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ))
jhnwkmn 0:97a4f8cc534c 649 #if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64))
jhnwkmn 0:97a4f8cc534c 650 || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL
jhnwkmn 0:97a4f8cc534c 651 #else
jhnwkmn 0:97a4f8cc534c 652 || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL
jhnwkmn 0:97a4f8cc534c 653 #endif
jhnwkmn 0:97a4f8cc534c 654 {
jhnwkmn 0:97a4f8cc534c 655 return true;
jhnwkmn 0:97a4f8cc534c 656 }
jhnwkmn 0:97a4f8cc534c 657 return false;
jhnwkmn 0:97a4f8cc534c 658 }
jhnwkmn 0:97a4f8cc534c 659
jhnwkmn 0:97a4f8cc534c 660 bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
jhnwkmn 0:97a4f8cc534c 661 {
jhnwkmn 0:97a4f8cc534c 662 if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
jhnwkmn 0:97a4f8cc534c 663 _nnativecalls++;
jhnwkmn 0:97a4f8cc534c 664 AutoDec ad(&_nnativecalls);
jhnwkmn 0:97a4f8cc534c 665 SQInteger traps = 0;
jhnwkmn 0:97a4f8cc534c 666 CallInfo *prevci = ci;
jhnwkmn 0:97a4f8cc534c 667
jhnwkmn 0:97a4f8cc534c 668 switch(et) {
jhnwkmn 0:97a4f8cc534c 669 case ET_CALL: {
jhnwkmn 0:97a4f8cc534c 670 temp_reg = closure;
jhnwkmn 0:97a4f8cc534c 671 if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) {
jhnwkmn 0:97a4f8cc534c 672 //call the handler if there are no calls in the stack, if not relies on the previous node
jhnwkmn 0:97a4f8cc534c 673 if(ci == NULL) CallErrorHandler(_lasterror);
jhnwkmn 0:97a4f8cc534c 674 return false;
jhnwkmn 0:97a4f8cc534c 675 }
jhnwkmn 0:97a4f8cc534c 676 if(ci == prevci) {
jhnwkmn 0:97a4f8cc534c 677 outres = STK(_top-nargs);
jhnwkmn 0:97a4f8cc534c 678 return true;
jhnwkmn 0:97a4f8cc534c 679 }
jhnwkmn 0:97a4f8cc534c 680 ci->_root = SQTrue;
jhnwkmn 0:97a4f8cc534c 681 }
jhnwkmn 0:97a4f8cc534c 682 break;
jhnwkmn 0:97a4f8cc534c 683 case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;
jhnwkmn 0:97a4f8cc534c 684 case ET_RESUME_VM:
jhnwkmn 0:97a4f8cc534c 685 case ET_RESUME_THROW_VM:
jhnwkmn 0:97a4f8cc534c 686 traps = _suspended_traps;
jhnwkmn 0:97a4f8cc534c 687 ci->_root = _suspended_root;
jhnwkmn 0:97a4f8cc534c 688 _suspended = SQFalse;
jhnwkmn 0:97a4f8cc534c 689 if(et == ET_RESUME_THROW_VM) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 690 break;
jhnwkmn 0:97a4f8cc534c 691 }
jhnwkmn 0:97a4f8cc534c 692
jhnwkmn 0:97a4f8cc534c 693 exception_restore:
jhnwkmn 0:97a4f8cc534c 694 //
jhnwkmn 0:97a4f8cc534c 695 {
jhnwkmn 0:97a4f8cc534c 696 for(;;)
jhnwkmn 0:97a4f8cc534c 697 {
jhnwkmn 0:97a4f8cc534c 698 const SQInstruction &_i_ = *ci->_ip++;
jhnwkmn 0:97a4f8cc534c 699 //dumpstack(_stackbase);
jhnwkmn 0:97a4f8cc534c 700 //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
jhnwkmn 0:97a4f8cc534c 701 switch(_i_.op)
jhnwkmn 0:97a4f8cc534c 702 {
jhnwkmn 0:97a4f8cc534c 703 case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
jhnwkmn 0:97a4f8cc534c 704 case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
jhnwkmn 0:97a4f8cc534c 705 case _OP_LOADINT:
jhnwkmn 0:97a4f8cc534c 706 #ifndef _SQ64
jhnwkmn 0:97a4f8cc534c 707 TARGET = (SQInteger)arg1; continue;
jhnwkmn 0:97a4f8cc534c 708 #else
jhnwkmn 0:97a4f8cc534c 709 TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;
jhnwkmn 0:97a4f8cc534c 710 #endif
jhnwkmn 0:97a4f8cc534c 711 case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
jhnwkmn 0:97a4f8cc534c 712 case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
jhnwkmn 0:97a4f8cc534c 713 case _OP_TAILCALL:{
jhnwkmn 0:97a4f8cc534c 714 SQObjectPtr &t = STK(arg1);
jhnwkmn 0:97a4f8cc534c 715 if (type(t) == OT_CLOSURE
jhnwkmn 0:97a4f8cc534c 716 && (!_closure(t)->_function->_bgenerator)){
jhnwkmn 0:97a4f8cc534c 717 SQObjectPtr clo = t;
jhnwkmn 0:97a4f8cc534c 718 if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
jhnwkmn 0:97a4f8cc534c 719 for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
jhnwkmn 0:97a4f8cc534c 720 _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
jhnwkmn 0:97a4f8cc534c 721 continue;
jhnwkmn 0:97a4f8cc534c 722 }
jhnwkmn 0:97a4f8cc534c 723 }
jhnwkmn 0:97a4f8cc534c 724 case _OP_CALL: {
jhnwkmn 0:97a4f8cc534c 725 SQObjectPtr clo = STK(arg1);
jhnwkmn 0:97a4f8cc534c 726 switch (type(clo)) {
jhnwkmn 0:97a4f8cc534c 727 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 728 _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
jhnwkmn 0:97a4f8cc534c 729 continue;
jhnwkmn 0:97a4f8cc534c 730 case OT_NATIVECLOSURE: {
jhnwkmn 0:97a4f8cc534c 731 bool suspend;
jhnwkmn 0:97a4f8cc534c 732 _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
jhnwkmn 0:97a4f8cc534c 733 if(suspend){
jhnwkmn 0:97a4f8cc534c 734 _suspended = SQTrue;
jhnwkmn 0:97a4f8cc534c 735 _suspended_target = sarg0;
jhnwkmn 0:97a4f8cc534c 736 _suspended_root = ci->_root;
jhnwkmn 0:97a4f8cc534c 737 _suspended_traps = traps;
jhnwkmn 0:97a4f8cc534c 738 outres = clo;
jhnwkmn 0:97a4f8cc534c 739 return true;
jhnwkmn 0:97a4f8cc534c 740 }
jhnwkmn 0:97a4f8cc534c 741 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 742 STK(arg0) = clo;
jhnwkmn 0:97a4f8cc534c 743 }
jhnwkmn 0:97a4f8cc534c 744 }
jhnwkmn 0:97a4f8cc534c 745 continue;
jhnwkmn 0:97a4f8cc534c 746 case OT_CLASS:{
jhnwkmn 0:97a4f8cc534c 747 SQObjectPtr inst;
jhnwkmn 0:97a4f8cc534c 748 _GUARD(CreateClassInstance(_class(clo),inst,clo));
jhnwkmn 0:97a4f8cc534c 749 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 750 STK(arg0) = inst;
jhnwkmn 0:97a4f8cc534c 751 }
jhnwkmn 0:97a4f8cc534c 752 SQInteger stkbase;
jhnwkmn 0:97a4f8cc534c 753 switch(type(clo)) {
jhnwkmn 0:97a4f8cc534c 754 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 755 stkbase = _stackbase+arg2;
jhnwkmn 0:97a4f8cc534c 756 _stack._vals[stkbase] = inst;
jhnwkmn 0:97a4f8cc534c 757 _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
jhnwkmn 0:97a4f8cc534c 758 break;
jhnwkmn 0:97a4f8cc534c 759 case OT_NATIVECLOSURE:
jhnwkmn 0:97a4f8cc534c 760 bool suspend;
jhnwkmn 0:97a4f8cc534c 761 stkbase = _stackbase+arg2;
jhnwkmn 0:97a4f8cc534c 762 _stack._vals[stkbase] = inst;
jhnwkmn 0:97a4f8cc534c 763 _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
jhnwkmn 0:97a4f8cc534c 764 break;
jhnwkmn 0:97a4f8cc534c 765 default: break; //shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 766 }
jhnwkmn 0:97a4f8cc534c 767 }
jhnwkmn 0:97a4f8cc534c 768 break;
jhnwkmn 0:97a4f8cc534c 769 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 770 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 771 case OT_INSTANCE:{
jhnwkmn 0:97a4f8cc534c 772 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 773 if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
jhnwkmn 0:97a4f8cc534c 774 Push(clo);
jhnwkmn 0:97a4f8cc534c 775 for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
jhnwkmn 0:97a4f8cc534c 776 if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();
jhnwkmn 0:97a4f8cc534c 777 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 778 STK(arg0) = clo;
jhnwkmn 0:97a4f8cc534c 779 }
jhnwkmn 0:97a4f8cc534c 780 break;
jhnwkmn 0:97a4f8cc534c 781 }
jhnwkmn 0:97a4f8cc534c 782
jhnwkmn 0:97a4f8cc534c 783 //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
jhnwkmn 0:97a4f8cc534c 784 //SQ_THROW();
jhnwkmn 0:97a4f8cc534c 785 }
jhnwkmn 0:97a4f8cc534c 786 default:
jhnwkmn 0:97a4f8cc534c 787 Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
jhnwkmn 0:97a4f8cc534c 788 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 789 }
jhnwkmn 0:97a4f8cc534c 790 }
jhnwkmn 0:97a4f8cc534c 791 continue;
jhnwkmn 0:97a4f8cc534c 792 case _OP_PREPCALL:
jhnwkmn 0:97a4f8cc534c 793 case _OP_PREPCALLK: {
jhnwkmn 0:97a4f8cc534c 794 SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
jhnwkmn 0:97a4f8cc534c 795 SQObjectPtr &o = STK(arg2);
jhnwkmn 0:97a4f8cc534c 796 if (!Get(o, key, temp_reg,false,arg2)) {
jhnwkmn 0:97a4f8cc534c 797 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 798 }
jhnwkmn 0:97a4f8cc534c 799 STK(arg3) = o;
jhnwkmn 0:97a4f8cc534c 800 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 801 }
jhnwkmn 0:97a4f8cc534c 802 continue;
jhnwkmn 0:97a4f8cc534c 803 case _OP_GETK:
jhnwkmn 0:97a4f8cc534c 804 if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 805 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 806 continue;
jhnwkmn 0:97a4f8cc534c 807 case _OP_MOVE: TARGET = STK(arg1); continue;
jhnwkmn 0:97a4f8cc534c 808 case _OP_NEWSLOT:
jhnwkmn 0:97a4f8cc534c 809 _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
jhnwkmn 0:97a4f8cc534c 810 if(arg0 != 0xFF) TARGET = STK(arg3);
jhnwkmn 0:97a4f8cc534c 811 continue;
jhnwkmn 0:97a4f8cc534c 812 case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
jhnwkmn 0:97a4f8cc534c 813 case _OP_SET:
jhnwkmn 0:97a4f8cc534c 814 if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 815 if (arg0 != 0xFF) TARGET = STK(arg3);
jhnwkmn 0:97a4f8cc534c 816 continue;
jhnwkmn 0:97a4f8cc534c 817 case _OP_GET:
jhnwkmn 0:97a4f8cc534c 818 if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 819 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 820 continue;
jhnwkmn 0:97a4f8cc534c 821 case _OP_EQ:{
jhnwkmn 0:97a4f8cc534c 822 bool res;
jhnwkmn 0:97a4f8cc534c 823 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 824 TARGET = res?true:false;
jhnwkmn 0:97a4f8cc534c 825 }continue;
jhnwkmn 0:97a4f8cc534c 826 case _OP_NE:{
jhnwkmn 0:97a4f8cc534c 827 bool res;
jhnwkmn 0:97a4f8cc534c 828 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 829 TARGET = (!res)?true:false;
jhnwkmn 0:97a4f8cc534c 830 } continue;
jhnwkmn 0:97a4f8cc534c 831 case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 832 case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 833 case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 834 case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
jhnwkmn 0:97a4f8cc534c 835 case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 836 case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
jhnwkmn 0:97a4f8cc534c 837 case _OP_RETURN:
jhnwkmn 0:97a4f8cc534c 838 if((ci)->_generator) {
jhnwkmn 0:97a4f8cc534c 839 (ci)->_generator->Kill();
jhnwkmn 0:97a4f8cc534c 840 }
jhnwkmn 0:97a4f8cc534c 841 if(Return(arg0, arg1, temp_reg)){
jhnwkmn 0:97a4f8cc534c 842 assert(traps==0);
jhnwkmn 0:97a4f8cc534c 843 //outres = temp_reg;
jhnwkmn 0:97a4f8cc534c 844 _Swap(outres,temp_reg);
jhnwkmn 0:97a4f8cc534c 845 return true;
jhnwkmn 0:97a4f8cc534c 846 }
jhnwkmn 0:97a4f8cc534c 847 continue;
jhnwkmn 0:97a4f8cc534c 848 case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
jhnwkmn 0:97a4f8cc534c 849 case _OP_LOADROOT: TARGET = _roottable; continue;
jhnwkmn 0:97a4f8cc534c 850 case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
jhnwkmn 0:97a4f8cc534c 851 case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
jhnwkmn 0:97a4f8cc534c 852 case _OP_JMP: ci->_ip += (sarg1); continue;
jhnwkmn 0:97a4f8cc534c 853 //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
jhnwkmn 0:97a4f8cc534c 854 case _OP_JCMP:
jhnwkmn 0:97a4f8cc534c 855 _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
jhnwkmn 0:97a4f8cc534c 856 if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
jhnwkmn 0:97a4f8cc534c 857 continue;
jhnwkmn 0:97a4f8cc534c 858 case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
jhnwkmn 0:97a4f8cc534c 859 case _OP_GETOUTER: {
jhnwkmn 0:97a4f8cc534c 860 SQClosure *cur_cls = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 861 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
jhnwkmn 0:97a4f8cc534c 862 TARGET = *(otr->_valptr);
jhnwkmn 0:97a4f8cc534c 863 }
jhnwkmn 0:97a4f8cc534c 864 continue;
jhnwkmn 0:97a4f8cc534c 865 case _OP_SETOUTER: {
jhnwkmn 0:97a4f8cc534c 866 SQClosure *cur_cls = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 867 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
jhnwkmn 0:97a4f8cc534c 868 *(otr->_valptr) = STK(arg2);
jhnwkmn 0:97a4f8cc534c 869 if(arg0 != 0xFF) {
jhnwkmn 0:97a4f8cc534c 870 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 871 }
jhnwkmn 0:97a4f8cc534c 872 }
jhnwkmn 0:97a4f8cc534c 873 continue;
jhnwkmn 0:97a4f8cc534c 874 case _OP_NEWOBJ:
jhnwkmn 0:97a4f8cc534c 875 switch(arg3) {
jhnwkmn 0:97a4f8cc534c 876 case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
jhnwkmn 0:97a4f8cc534c 877 case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
jhnwkmn 0:97a4f8cc534c 878 case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
jhnwkmn 0:97a4f8cc534c 879 default: assert(0); continue;
jhnwkmn 0:97a4f8cc534c 880 }
jhnwkmn 0:97a4f8cc534c 881 case _OP_APPENDARRAY:
jhnwkmn 0:97a4f8cc534c 882 {
jhnwkmn 0:97a4f8cc534c 883 SQObject val;
jhnwkmn 0:97a4f8cc534c 884 val._unVal.raw = 0;
jhnwkmn 0:97a4f8cc534c 885 switch(arg2) {
jhnwkmn 0:97a4f8cc534c 886 case AAT_STACK:
jhnwkmn 0:97a4f8cc534c 887 val = STK(arg1); break;
jhnwkmn 0:97a4f8cc534c 888 case AAT_LITERAL:
jhnwkmn 0:97a4f8cc534c 889 val = ci->_literals[arg1]; break;
jhnwkmn 0:97a4f8cc534c 890 case AAT_INT:
jhnwkmn 0:97a4f8cc534c 891 val._type = OT_INTEGER;
jhnwkmn 0:97a4f8cc534c 892 #ifndef _SQ64
jhnwkmn 0:97a4f8cc534c 893 val._unVal.nInteger = (SQInteger)arg1;
jhnwkmn 0:97a4f8cc534c 894 #else
jhnwkmn 0:97a4f8cc534c 895 val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1);
jhnwkmn 0:97a4f8cc534c 896 #endif
jhnwkmn 0:97a4f8cc534c 897 break;
jhnwkmn 0:97a4f8cc534c 898 case AAT_FLOAT:
jhnwkmn 0:97a4f8cc534c 899 val._type = OT_FLOAT;
jhnwkmn 0:97a4f8cc534c 900 val._unVal.fFloat = *((SQFloat *)&arg1);
jhnwkmn 0:97a4f8cc534c 901 break;
jhnwkmn 0:97a4f8cc534c 902 case AAT_BOOL:
jhnwkmn 0:97a4f8cc534c 903 val._type = OT_BOOL;
jhnwkmn 0:97a4f8cc534c 904 val._unVal.nInteger = arg1;
jhnwkmn 0:97a4f8cc534c 905 break;
jhnwkmn 0:97a4f8cc534c 906 default: assert(0); break;
jhnwkmn 0:97a4f8cc534c 907
jhnwkmn 0:97a4f8cc534c 908 }
jhnwkmn 0:97a4f8cc534c 909 _array(STK(arg0))->Append(val); continue;
jhnwkmn 0:97a4f8cc534c 910 }
jhnwkmn 0:97a4f8cc534c 911 case _OP_COMPARITH: {
jhnwkmn 0:97a4f8cc534c 912 SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
jhnwkmn 0:97a4f8cc534c 913 _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
jhnwkmn 0:97a4f8cc534c 914 }
jhnwkmn 0:97a4f8cc534c 915 continue;
jhnwkmn 0:97a4f8cc534c 916 case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
jhnwkmn 0:97a4f8cc534c 917 case _OP_INCL: {
jhnwkmn 0:97a4f8cc534c 918 SQObjectPtr &a = STK(arg1);
jhnwkmn 0:97a4f8cc534c 919 if(type(a) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 920 a._unVal.nInteger = _integer(a) + sarg3;
jhnwkmn 0:97a4f8cc534c 921 }
jhnwkmn 0:97a4f8cc534c 922 else {
jhnwkmn 0:97a4f8cc534c 923 SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));
jhnwkmn 0:97a4f8cc534c 924 _ARITH_(+,a,a,o);
jhnwkmn 0:97a4f8cc534c 925 }
jhnwkmn 0:97a4f8cc534c 926 } continue;
jhnwkmn 0:97a4f8cc534c 927 case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
jhnwkmn 0:97a4f8cc534c 928 case _OP_PINCL: {
jhnwkmn 0:97a4f8cc534c 929 SQObjectPtr &a = STK(arg1);
jhnwkmn 0:97a4f8cc534c 930 if(type(a) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 931 TARGET = a;
jhnwkmn 0:97a4f8cc534c 932 a._unVal.nInteger = _integer(a) + sarg3;
jhnwkmn 0:97a4f8cc534c 933 }
jhnwkmn 0:97a4f8cc534c 934 else {
jhnwkmn 0:97a4f8cc534c 935 SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));
jhnwkmn 0:97a4f8cc534c 936 }
jhnwkmn 0:97a4f8cc534c 937
jhnwkmn 0:97a4f8cc534c 938 } continue;
jhnwkmn 0:97a4f8cc534c 939 case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue;
jhnwkmn 0:97a4f8cc534c 940 case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue;
jhnwkmn 0:97a4f8cc534c 941 case _OP_INSTANCEOF:
jhnwkmn 0:97a4f8cc534c 942 if(type(STK(arg1)) != OT_CLASS)
jhnwkmn 0:97a4f8cc534c 943 {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 944 TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
jhnwkmn 0:97a4f8cc534c 945 continue;
jhnwkmn 0:97a4f8cc534c 946 case _OP_AND:
jhnwkmn 0:97a4f8cc534c 947 if(IsFalse(STK(arg2))) {
jhnwkmn 0:97a4f8cc534c 948 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 949 ci->_ip += (sarg1);
jhnwkmn 0:97a4f8cc534c 950 }
jhnwkmn 0:97a4f8cc534c 951 continue;
jhnwkmn 0:97a4f8cc534c 952 case _OP_OR:
jhnwkmn 0:97a4f8cc534c 953 if(!IsFalse(STK(arg2))) {
jhnwkmn 0:97a4f8cc534c 954 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 955 ci->_ip += (sarg1);
jhnwkmn 0:97a4f8cc534c 956 }
jhnwkmn 0:97a4f8cc534c 957 continue;
jhnwkmn 0:97a4f8cc534c 958 case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
jhnwkmn 0:97a4f8cc534c 959 case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 960 case _OP_BWNOT:
jhnwkmn 0:97a4f8cc534c 961 if(type(STK(arg1)) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 962 SQInteger t = _integer(STK(arg1));
jhnwkmn 0:97a4f8cc534c 963 TARGET = SQInteger(~t);
jhnwkmn 0:97a4f8cc534c 964 continue;
jhnwkmn 0:97a4f8cc534c 965 }
jhnwkmn 0:97a4f8cc534c 966 Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
jhnwkmn 0:97a4f8cc534c 967 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 968 case _OP_CLOSURE: {
jhnwkmn 0:97a4f8cc534c 969 SQClosure *c = ci->_closure._unVal.pClosure;
jhnwkmn 0:97a4f8cc534c 970 SQFunctionProto *fp = c->_function;
jhnwkmn 0:97a4f8cc534c 971 if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 972 continue;
jhnwkmn 0:97a4f8cc534c 973 }
jhnwkmn 0:97a4f8cc534c 974 case _OP_YIELD:{
jhnwkmn 0:97a4f8cc534c 975 if(ci->_generator) {
jhnwkmn 0:97a4f8cc534c 976 if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
jhnwkmn 0:97a4f8cc534c 977 _GUARD(ci->_generator->Yield(this,arg2));
jhnwkmn 0:97a4f8cc534c 978 traps -= ci->_etraps;
jhnwkmn 0:97a4f8cc534c 979 if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg;
jhnwkmn 0:97a4f8cc534c 980 }
jhnwkmn 0:97a4f8cc534c 981 else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 982 if(Return(arg0, arg1, temp_reg)){
jhnwkmn 0:97a4f8cc534c 983 assert(traps == 0);
jhnwkmn 0:97a4f8cc534c 984 outres = temp_reg;
jhnwkmn 0:97a4f8cc534c 985 return true;
jhnwkmn 0:97a4f8cc534c 986 }
jhnwkmn 0:97a4f8cc534c 987
jhnwkmn 0:97a4f8cc534c 988 }
jhnwkmn 0:97a4f8cc534c 989 continue;
jhnwkmn 0:97a4f8cc534c 990 case _OP_RESUME:
jhnwkmn 0:97a4f8cc534c 991 if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 992 _GUARD(_generator(STK(arg1))->Resume(this, TARGET));
jhnwkmn 0:97a4f8cc534c 993 traps += ci->_etraps;
jhnwkmn 0:97a4f8cc534c 994 continue;
jhnwkmn 0:97a4f8cc534c 995 case _OP_FOREACH:{ int tojump;
jhnwkmn 0:97a4f8cc534c 996 _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
jhnwkmn 0:97a4f8cc534c 997 ci->_ip += tojump; }
jhnwkmn 0:97a4f8cc534c 998 continue;
jhnwkmn 0:97a4f8cc534c 999 case _OP_POSTFOREACH:
jhnwkmn 0:97a4f8cc534c 1000 assert(type(STK(arg0)) == OT_GENERATOR);
jhnwkmn 0:97a4f8cc534c 1001 if(_generator(STK(arg0))->_state == SQGenerator::eDead)
jhnwkmn 0:97a4f8cc534c 1002 ci->_ip += (sarg1 - 1);
jhnwkmn 0:97a4f8cc534c 1003 continue;
jhnwkmn 0:97a4f8cc534c 1004 case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
jhnwkmn 0:97a4f8cc534c 1005 case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
jhnwkmn 0:97a4f8cc534c 1006 case _OP_PUSHTRAP:{
jhnwkmn 0:97a4f8cc534c 1007 SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
jhnwkmn 0:97a4f8cc534c 1008 _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
jhnwkmn 0:97a4f8cc534c 1009 ci->_etraps++;
jhnwkmn 0:97a4f8cc534c 1010 }
jhnwkmn 0:97a4f8cc534c 1011 continue;
jhnwkmn 0:97a4f8cc534c 1012 case _OP_POPTRAP: {
jhnwkmn 0:97a4f8cc534c 1013 for(SQInteger i = 0; i < arg0; i++) {
jhnwkmn 0:97a4f8cc534c 1014 _etraps.pop_back(); traps--;
jhnwkmn 0:97a4f8cc534c 1015 ci->_etraps--;
jhnwkmn 0:97a4f8cc534c 1016 }
jhnwkmn 0:97a4f8cc534c 1017 }
jhnwkmn 0:97a4f8cc534c 1018 continue;
jhnwkmn 0:97a4f8cc534c 1019 case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;
jhnwkmn 0:97a4f8cc534c 1020 case _OP_NEWSLOTA:
jhnwkmn 0:97a4f8cc534c 1021 _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
jhnwkmn 0:97a4f8cc534c 1022 continue;
jhnwkmn 0:97a4f8cc534c 1023 case _OP_GETBASE:{
jhnwkmn 0:97a4f8cc534c 1024 SQClosure *clo = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 1025 if(clo->_base) {
jhnwkmn 0:97a4f8cc534c 1026 TARGET = clo->_base;
jhnwkmn 0:97a4f8cc534c 1027 }
jhnwkmn 0:97a4f8cc534c 1028 else {
jhnwkmn 0:97a4f8cc534c 1029 TARGET.Null();
jhnwkmn 0:97a4f8cc534c 1030 }
jhnwkmn 0:97a4f8cc534c 1031 continue;
jhnwkmn 0:97a4f8cc534c 1032 }
jhnwkmn 0:97a4f8cc534c 1033 case _OP_CLOSE:
jhnwkmn 0:97a4f8cc534c 1034 if(_openouters) CloseOuters(&(STK(arg1)));
jhnwkmn 0:97a4f8cc534c 1035 continue;
jhnwkmn 0:97a4f8cc534c 1036 }
jhnwkmn 0:97a4f8cc534c 1037
jhnwkmn 0:97a4f8cc534c 1038 }
jhnwkmn 0:97a4f8cc534c 1039 }
jhnwkmn 0:97a4f8cc534c 1040 exception_trap:
jhnwkmn 0:97a4f8cc534c 1041 {
jhnwkmn 0:97a4f8cc534c 1042 SQObjectPtr currerror = _lasterror;
jhnwkmn 0:97a4f8cc534c 1043 // dumpstack(_stackbase);
jhnwkmn 0:97a4f8cc534c 1044 // SQInteger n = 0;
jhnwkmn 0:97a4f8cc534c 1045 SQInteger last_top = _top;
jhnwkmn 0:97a4f8cc534c 1046
jhnwkmn 0:97a4f8cc534c 1047 if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
jhnwkmn 0:97a4f8cc534c 1048
jhnwkmn 0:97a4f8cc534c 1049 while( ci ) {
jhnwkmn 0:97a4f8cc534c 1050 if(ci->_etraps > 0) {
jhnwkmn 0:97a4f8cc534c 1051 SQExceptionTrap &et = _etraps.top();
jhnwkmn 0:97a4f8cc534c 1052 ci->_ip = et._ip;
jhnwkmn 0:97a4f8cc534c 1053 _top = et._stacksize;
jhnwkmn 0:97a4f8cc534c 1054 _stackbase = et._stackbase;
jhnwkmn 0:97a4f8cc534c 1055 _stack._vals[_stackbase + et._extarget] = currerror;
jhnwkmn 0:97a4f8cc534c 1056 _etraps.pop_back(); traps--; ci->_etraps--;
jhnwkmn 0:97a4f8cc534c 1057 while(last_top >= _top) _stack._vals[last_top--].Null();
jhnwkmn 0:97a4f8cc534c 1058 goto exception_restore;
jhnwkmn 0:97a4f8cc534c 1059 }
jhnwkmn 0:97a4f8cc534c 1060 else if (_debughook) {
jhnwkmn 0:97a4f8cc534c 1061 //notify debugger of a "return"
jhnwkmn 0:97a4f8cc534c 1062 //even if it really an exception unwinding the stack
jhnwkmn 0:97a4f8cc534c 1063 for(SQInteger i = 0; i < ci->_ncalls; i++) {
jhnwkmn 0:97a4f8cc534c 1064 CallDebugHook(_SC('r'));
jhnwkmn 0:97a4f8cc534c 1065 }
jhnwkmn 0:97a4f8cc534c 1066 }
jhnwkmn 0:97a4f8cc534c 1067 if(ci->_generator) ci->_generator->Kill();
jhnwkmn 0:97a4f8cc534c 1068 bool mustbreak = ci && ci->_root;
jhnwkmn 0:97a4f8cc534c 1069 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1070 if(mustbreak) break;
jhnwkmn 0:97a4f8cc534c 1071 }
jhnwkmn 0:97a4f8cc534c 1072
jhnwkmn 0:97a4f8cc534c 1073 _lasterror = currerror;
jhnwkmn 0:97a4f8cc534c 1074 return false;
jhnwkmn 0:97a4f8cc534c 1075 }
jhnwkmn 0:97a4f8cc534c 1076 assert(0);
jhnwkmn 0:97a4f8cc534c 1077 }
jhnwkmn 0:97a4f8cc534c 1078
jhnwkmn 0:97a4f8cc534c 1079 bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
jhnwkmn 0:97a4f8cc534c 1080 {
jhnwkmn 0:97a4f8cc534c 1081 inst = theclass->CreateInstance();
jhnwkmn 0:97a4f8cc534c 1082 if(!theclass->GetConstructor(constructor)) {
jhnwkmn 0:97a4f8cc534c 1083 constructor.Null();
jhnwkmn 0:97a4f8cc534c 1084 }
jhnwkmn 0:97a4f8cc534c 1085 return true;
jhnwkmn 0:97a4f8cc534c 1086 }
jhnwkmn 0:97a4f8cc534c 1087
jhnwkmn 0:97a4f8cc534c 1088 void SQVM::CallErrorHandler(SQObjectPtr &error)
jhnwkmn 0:97a4f8cc534c 1089 {
jhnwkmn 0:97a4f8cc534c 1090 if(type(_errorhandler) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1091 SQObjectPtr out;
jhnwkmn 0:97a4f8cc534c 1092 Push(_roottable); Push(error);
jhnwkmn 0:97a4f8cc534c 1093 Call(_errorhandler, 2, _top-2, out,SQFalse);
jhnwkmn 0:97a4f8cc534c 1094 Pop(2);
jhnwkmn 0:97a4f8cc534c 1095 }
jhnwkmn 0:97a4f8cc534c 1096 }
jhnwkmn 0:97a4f8cc534c 1097
jhnwkmn 0:97a4f8cc534c 1098
jhnwkmn 0:97a4f8cc534c 1099 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
jhnwkmn 0:97a4f8cc534c 1100 {
jhnwkmn 0:97a4f8cc534c 1101 _debughook = false;
jhnwkmn 0:97a4f8cc534c 1102 SQFunctionProto *func=_closure(ci->_closure)->_function;
jhnwkmn 0:97a4f8cc534c 1103 if(_debughook_native) {
jhnwkmn 0:97a4f8cc534c 1104 const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
jhnwkmn 0:97a4f8cc534c 1105 const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
jhnwkmn 0:97a4f8cc534c 1106 SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
jhnwkmn 0:97a4f8cc534c 1107 _debughook_native(this,type,src,line,fname);
jhnwkmn 0:97a4f8cc534c 1108 }
jhnwkmn 0:97a4f8cc534c 1109 else {
jhnwkmn 0:97a4f8cc534c 1110 SQObjectPtr temp_reg;
jhnwkmn 0:97a4f8cc534c 1111 SQInteger nparams=5;
jhnwkmn 0:97a4f8cc534c 1112 Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
jhnwkmn 0:97a4f8cc534c 1113 Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);
jhnwkmn 0:97a4f8cc534c 1114 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1115 }
jhnwkmn 0:97a4f8cc534c 1116 _debughook = true;
jhnwkmn 0:97a4f8cc534c 1117 }
jhnwkmn 0:97a4f8cc534c 1118
jhnwkmn 0:97a4f8cc534c 1119 bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
jhnwkmn 0:97a4f8cc534c 1120 {
jhnwkmn 0:97a4f8cc534c 1121 SQInteger nparamscheck = nclosure->_nparamscheck;
jhnwkmn 0:97a4f8cc534c 1122 SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
jhnwkmn 0:97a4f8cc534c 1123
jhnwkmn 0:97a4f8cc534c 1124 if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
jhnwkmn 0:97a4f8cc534c 1125 Raise_Error(_SC("Native stack overflow"));
jhnwkmn 0:97a4f8cc534c 1126 return false;
jhnwkmn 0:97a4f8cc534c 1127 }
jhnwkmn 0:97a4f8cc534c 1128
jhnwkmn 0:97a4f8cc534c 1129 if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
jhnwkmn 0:97a4f8cc534c 1130 ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
jhnwkmn 0:97a4f8cc534c 1131 {
jhnwkmn 0:97a4f8cc534c 1132 Raise_Error(_SC("wrong number of parameters"));
jhnwkmn 0:97a4f8cc534c 1133 return false;
jhnwkmn 0:97a4f8cc534c 1134 }
jhnwkmn 0:97a4f8cc534c 1135
jhnwkmn 0:97a4f8cc534c 1136 SQInteger tcs;
jhnwkmn 0:97a4f8cc534c 1137 SQIntVec &tc = nclosure->_typecheck;
jhnwkmn 0:97a4f8cc534c 1138 if((tcs = tc.size())) {
jhnwkmn 0:97a4f8cc534c 1139 for(SQInteger i = 0; i < nargs && i < tcs; i++) {
jhnwkmn 0:97a4f8cc534c 1140 if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
jhnwkmn 0:97a4f8cc534c 1141 Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
jhnwkmn 0:97a4f8cc534c 1142 return false;
jhnwkmn 0:97a4f8cc534c 1143 }
jhnwkmn 0:97a4f8cc534c 1144 }
jhnwkmn 0:97a4f8cc534c 1145 }
jhnwkmn 0:97a4f8cc534c 1146
jhnwkmn 0:97a4f8cc534c 1147 if(!EnterFrame(newbase, newtop, false)) return false;
jhnwkmn 0:97a4f8cc534c 1148 ci->_closure = nclosure;
jhnwkmn 0:97a4f8cc534c 1149
jhnwkmn 0:97a4f8cc534c 1150 SQInteger outers = nclosure->_noutervalues;
jhnwkmn 0:97a4f8cc534c 1151 for (SQInteger i = 0; i < outers; i++) {
jhnwkmn 0:97a4f8cc534c 1152 _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
jhnwkmn 0:97a4f8cc534c 1153 }
jhnwkmn 0:97a4f8cc534c 1154 if(nclosure->_env) {
jhnwkmn 0:97a4f8cc534c 1155 _stack._vals[newbase] = nclosure->_env->_obj;
jhnwkmn 0:97a4f8cc534c 1156 }
jhnwkmn 0:97a4f8cc534c 1157
jhnwkmn 0:97a4f8cc534c 1158 _nnativecalls++;
jhnwkmn 0:97a4f8cc534c 1159 SQInteger ret = (nclosure->_function)(this);
jhnwkmn 0:97a4f8cc534c 1160 _nnativecalls--;
jhnwkmn 0:97a4f8cc534c 1161
jhnwkmn 0:97a4f8cc534c 1162 suspend = false;
jhnwkmn 0:97a4f8cc534c 1163 if (ret == SQ_SUSPEND_FLAG) {
jhnwkmn 0:97a4f8cc534c 1164 suspend = true;
jhnwkmn 0:97a4f8cc534c 1165 }
jhnwkmn 0:97a4f8cc534c 1166 else if (ret < 0) {
jhnwkmn 0:97a4f8cc534c 1167 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1168 Raise_Error(_lasterror);
jhnwkmn 0:97a4f8cc534c 1169 return false;
jhnwkmn 0:97a4f8cc534c 1170 }
jhnwkmn 0:97a4f8cc534c 1171 if(ret) {
jhnwkmn 0:97a4f8cc534c 1172 retval = _stack._vals[_top-1];
jhnwkmn 0:97a4f8cc534c 1173 }
jhnwkmn 0:97a4f8cc534c 1174 else {
jhnwkmn 0:97a4f8cc534c 1175 retval.Null();
jhnwkmn 0:97a4f8cc534c 1176 }
jhnwkmn 0:97a4f8cc534c 1177 //retval = ret ? _stack._vals[_top-1] : _null_;
jhnwkmn 0:97a4f8cc534c 1178 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1179 return true;
jhnwkmn 0:97a4f8cc534c 1180 }
jhnwkmn 0:97a4f8cc534c 1181
jhnwkmn 0:97a4f8cc534c 1182 #define FALLBACK_OK 0
jhnwkmn 0:97a4f8cc534c 1183 #define FALLBACK_NO_MATCH 1
jhnwkmn 0:97a4f8cc534c 1184 #define FALLBACK_ERROR 2
jhnwkmn 0:97a4f8cc534c 1185
jhnwkmn 0:97a4f8cc534c 1186 bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx)
jhnwkmn 0:97a4f8cc534c 1187 {
jhnwkmn 0:97a4f8cc534c 1188 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1189 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1190 if(_table(self)->Get(key,dest))return true;
jhnwkmn 0:97a4f8cc534c 1191 break;
jhnwkmn 0:97a4f8cc534c 1192 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1193 if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; }
jhnwkmn 0:97a4f8cc534c 1194 break;
jhnwkmn 0:97a4f8cc534c 1195 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1196 if(_instance(self)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1197 break;
jhnwkmn 0:97a4f8cc534c 1198 case OT_CLASS:
jhnwkmn 0:97a4f8cc534c 1199 if(_class(self)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1200 break;
jhnwkmn 0:97a4f8cc534c 1201 case OT_STRING:
jhnwkmn 0:97a4f8cc534c 1202 if(sq_isnumeric(key)){
jhnwkmn 0:97a4f8cc534c 1203 SQInteger n = tointeger(key);
jhnwkmn 0:97a4f8cc534c 1204 if(abs((int)n) < _string(self)->_len) {
jhnwkmn 0:97a4f8cc534c 1205 if(n < 0) n = _string(self)->_len - n;
jhnwkmn 0:97a4f8cc534c 1206 dest = SQInteger(_stringval(self)[n]);
jhnwkmn 0:97a4f8cc534c 1207 return true;
jhnwkmn 0:97a4f8cc534c 1208 }
jhnwkmn 0:97a4f8cc534c 1209 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1210 return false;
jhnwkmn 0:97a4f8cc534c 1211 }
jhnwkmn 0:97a4f8cc534c 1212 break;
jhnwkmn 0:97a4f8cc534c 1213 default:break; //shut up compiler
jhnwkmn 0:97a4f8cc534c 1214 }
jhnwkmn 0:97a4f8cc534c 1215 if(!raw) {
jhnwkmn 0:97a4f8cc534c 1216 switch(FallBackGet(self,key,dest)) {
jhnwkmn 0:97a4f8cc534c 1217 case FALLBACK_OK: return true; //okie
jhnwkmn 0:97a4f8cc534c 1218 case FALLBACK_NO_MATCH: break; //keep falling back
jhnwkmn 0:97a4f8cc534c 1219 case FALLBACK_ERROR: return false; // the metamethod failed
jhnwkmn 0:97a4f8cc534c 1220 }
jhnwkmn 0:97a4f8cc534c 1221 if(InvokeDefaultDelegate(self,key,dest)) {
jhnwkmn 0:97a4f8cc534c 1222 return true;
jhnwkmn 0:97a4f8cc534c 1223 }
jhnwkmn 0:97a4f8cc534c 1224 }
jhnwkmn 0:97a4f8cc534c 1225 //#ifdef ROOT_FALLBACK
jhnwkmn 0:97a4f8cc534c 1226 if(selfidx == 0) {
jhnwkmn 0:97a4f8cc534c 1227 if(_table(_roottable)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1228 }
jhnwkmn 0:97a4f8cc534c 1229 //#endif
jhnwkmn 0:97a4f8cc534c 1230 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1231 return false;
jhnwkmn 0:97a4f8cc534c 1232 }
jhnwkmn 0:97a4f8cc534c 1233
jhnwkmn 0:97a4f8cc534c 1234 bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 1235 {
jhnwkmn 0:97a4f8cc534c 1236 SQTable *ddel = NULL;
jhnwkmn 0:97a4f8cc534c 1237 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1238 case OT_CLASS: ddel = _class_ddel; break;
jhnwkmn 0:97a4f8cc534c 1239 case OT_TABLE: ddel = _table_ddel; break;
jhnwkmn 0:97a4f8cc534c 1240 case OT_ARRAY: ddel = _array_ddel; break;
jhnwkmn 0:97a4f8cc534c 1241 case OT_STRING: ddel = _string_ddel; break;
jhnwkmn 0:97a4f8cc534c 1242 case OT_INSTANCE: ddel = _instance_ddel; break;
jhnwkmn 0:97a4f8cc534c 1243 case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
jhnwkmn 0:97a4f8cc534c 1244 case OT_GENERATOR: ddel = _generator_ddel; break;
jhnwkmn 0:97a4f8cc534c 1245 case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;
jhnwkmn 0:97a4f8cc534c 1246 case OT_THREAD: ddel = _thread_ddel; break;
jhnwkmn 0:97a4f8cc534c 1247 case OT_WEAKREF: ddel = _weakref_ddel; break;
jhnwkmn 0:97a4f8cc534c 1248 default: return false;
jhnwkmn 0:97a4f8cc534c 1249 }
jhnwkmn 0:97a4f8cc534c 1250 return ddel->Get(key,dest);
jhnwkmn 0:97a4f8cc534c 1251 }
jhnwkmn 0:97a4f8cc534c 1252
jhnwkmn 0:97a4f8cc534c 1253
jhnwkmn 0:97a4f8cc534c 1254 SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 1255 {
jhnwkmn 0:97a4f8cc534c 1256 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1257 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1258 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 1259 //delegation
jhnwkmn 0:97a4f8cc534c 1260 if(_delegable(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1261 if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1262 }
jhnwkmn 0:97a4f8cc534c 1263 else {
jhnwkmn 0:97a4f8cc534c 1264 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1265 }
jhnwkmn 0:97a4f8cc534c 1266 //go through
jhnwkmn 0:97a4f8cc534c 1267 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1268 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1269 if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
jhnwkmn 0:97a4f8cc534c 1270 Push(self);Push(key);
jhnwkmn 0:97a4f8cc534c 1271 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1272 AutoDec ad(&_nmetamethodscall);
jhnwkmn 0:97a4f8cc534c 1273 if(Call(closure, 2, _top - 2, dest, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1274 Pop(2);
jhnwkmn 0:97a4f8cc534c 1275 return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1276 }
jhnwkmn 0:97a4f8cc534c 1277 else {
jhnwkmn 0:97a4f8cc534c 1278 Pop(2);
jhnwkmn 0:97a4f8cc534c 1279 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
jhnwkmn 0:97a4f8cc534c 1280 return FALLBACK_ERROR;
jhnwkmn 0:97a4f8cc534c 1281 }
jhnwkmn 0:97a4f8cc534c 1282 }
jhnwkmn 0:97a4f8cc534c 1283 }
jhnwkmn 0:97a4f8cc534c 1284 }
jhnwkmn 0:97a4f8cc534c 1285 break;
jhnwkmn 0:97a4f8cc534c 1286 default: break;//shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 1287 }
jhnwkmn 0:97a4f8cc534c 1288 // no metamethod or no fallback type
jhnwkmn 0:97a4f8cc534c 1289 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1290 }
jhnwkmn 0:97a4f8cc534c 1291
jhnwkmn 0:97a4f8cc534c 1292 bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)
jhnwkmn 0:97a4f8cc534c 1293 {
jhnwkmn 0:97a4f8cc534c 1294 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1295 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1296 if(_table(self)->Set(key,val)) return true;
jhnwkmn 0:97a4f8cc534c 1297 break;
jhnwkmn 0:97a4f8cc534c 1298 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1299 if(_instance(self)->Set(key,val)) return true;
jhnwkmn 0:97a4f8cc534c 1300 break;
jhnwkmn 0:97a4f8cc534c 1301 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1302 if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
jhnwkmn 0:97a4f8cc534c 1303 if(!_array(self)->Set(tointeger(key),val)) {
jhnwkmn 0:97a4f8cc534c 1304 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1305 return false;
jhnwkmn 0:97a4f8cc534c 1306 }
jhnwkmn 0:97a4f8cc534c 1307 return true;
jhnwkmn 0:97a4f8cc534c 1308 default:
jhnwkmn 0:97a4f8cc534c 1309 Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1310 return false;
jhnwkmn 0:97a4f8cc534c 1311 }
jhnwkmn 0:97a4f8cc534c 1312
jhnwkmn 0:97a4f8cc534c 1313 switch(FallBackSet(self,key,val)) {
jhnwkmn 0:97a4f8cc534c 1314 case FALLBACK_OK: return true; //okie
jhnwkmn 0:97a4f8cc534c 1315 case FALLBACK_NO_MATCH: break; //keep falling back
jhnwkmn 0:97a4f8cc534c 1316 case FALLBACK_ERROR: return false; // the metamethod failed
jhnwkmn 0:97a4f8cc534c 1317 }
jhnwkmn 0:97a4f8cc534c 1318 if(selfidx == 0) {
jhnwkmn 0:97a4f8cc534c 1319 if(_table(_roottable)->Set(key,val))
jhnwkmn 0:97a4f8cc534c 1320 return true;
jhnwkmn 0:97a4f8cc534c 1321 }
jhnwkmn 0:97a4f8cc534c 1322 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1323 return false;
jhnwkmn 0:97a4f8cc534c 1324 }
jhnwkmn 0:97a4f8cc534c 1325
jhnwkmn 0:97a4f8cc534c 1326 SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
jhnwkmn 0:97a4f8cc534c 1327 {
jhnwkmn 0:97a4f8cc534c 1328 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1329 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1330 if(_table(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1331 if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1332 }
jhnwkmn 0:97a4f8cc534c 1333 //keps on going
jhnwkmn 0:97a4f8cc534c 1334 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1335 case OT_USERDATA:{
jhnwkmn 0:97a4f8cc534c 1336 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1337 SQObjectPtr t;
jhnwkmn 0:97a4f8cc534c 1338 if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
jhnwkmn 0:97a4f8cc534c 1339 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1340 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1341 AutoDec ad(&_nmetamethodscall);
jhnwkmn 0:97a4f8cc534c 1342 if(Call(closure, 3, _top - 3, t, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1343 Pop(3);
jhnwkmn 0:97a4f8cc534c 1344 return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1345 }
jhnwkmn 0:97a4f8cc534c 1346 else {
jhnwkmn 0:97a4f8cc534c 1347 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
jhnwkmn 0:97a4f8cc534c 1348 //error
jhnwkmn 0:97a4f8cc534c 1349 Pop(3);
jhnwkmn 0:97a4f8cc534c 1350 return FALLBACK_ERROR;
jhnwkmn 0:97a4f8cc534c 1351 }
jhnwkmn 0:97a4f8cc534c 1352 }
jhnwkmn 0:97a4f8cc534c 1353 }
jhnwkmn 0:97a4f8cc534c 1354 }
jhnwkmn 0:97a4f8cc534c 1355 break;
jhnwkmn 0:97a4f8cc534c 1356 default: break;//shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 1357 }
jhnwkmn 0:97a4f8cc534c 1358 // no metamethod or no fallback type
jhnwkmn 0:97a4f8cc534c 1359 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1360 }
jhnwkmn 0:97a4f8cc534c 1361
jhnwkmn 0:97a4f8cc534c 1362 bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
jhnwkmn 0:97a4f8cc534c 1363 {
jhnwkmn 0:97a4f8cc534c 1364 SQObjectPtr temp_reg;
jhnwkmn 0:97a4f8cc534c 1365 SQObjectPtr newobj;
jhnwkmn 0:97a4f8cc534c 1366 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1367 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1368 newobj = _table(self)->Clone();
jhnwkmn 0:97a4f8cc534c 1369 goto cloned_mt;
jhnwkmn 0:97a4f8cc534c 1370 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1371 newobj = _instance(self)->Clone(_ss(this));
jhnwkmn 0:97a4f8cc534c 1372 cloned_mt:
jhnwkmn 0:97a4f8cc534c 1373 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1374 if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
jhnwkmn 0:97a4f8cc534c 1375 Push(newobj);
jhnwkmn 0:97a4f8cc534c 1376 Push(self);
jhnwkmn 0:97a4f8cc534c 1377 if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
jhnwkmn 0:97a4f8cc534c 1378 return false;
jhnwkmn 0:97a4f8cc534c 1379 }
jhnwkmn 0:97a4f8cc534c 1380 }
jhnwkmn 0:97a4f8cc534c 1381 target = newobj;
jhnwkmn 0:97a4f8cc534c 1382 return true;
jhnwkmn 0:97a4f8cc534c 1383 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1384 target = _array(self)->Clone();
jhnwkmn 0:97a4f8cc534c 1385 return true;
jhnwkmn 0:97a4f8cc534c 1386 default:
jhnwkmn 0:97a4f8cc534c 1387 Raise_Error(_SC("cloning a %s"), GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1388 return false;
jhnwkmn 0:97a4f8cc534c 1389 }
jhnwkmn 0:97a4f8cc534c 1390 }
jhnwkmn 0:97a4f8cc534c 1391
jhnwkmn 0:97a4f8cc534c 1392 bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw)
jhnwkmn 0:97a4f8cc534c 1393 {
jhnwkmn 0:97a4f8cc534c 1394 if(type(self) != OT_CLASS) {
jhnwkmn 0:97a4f8cc534c 1395 Raise_Error(_SC("object must be a class"));
jhnwkmn 0:97a4f8cc534c 1396 return false;
jhnwkmn 0:97a4f8cc534c 1397 }
jhnwkmn 0:97a4f8cc534c 1398 SQClass *c = _class(self);
jhnwkmn 0:97a4f8cc534c 1399 if(!raw) {
jhnwkmn 0:97a4f8cc534c 1400 SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
jhnwkmn 0:97a4f8cc534c 1401 if(type(mm) != OT_NULL ) {
jhnwkmn 0:97a4f8cc534c 1402 Push(self); Push(key); Push(val);
jhnwkmn 0:97a4f8cc534c 1403 Push(attrs);
jhnwkmn 0:97a4f8cc534c 1404 Push(bstatic);
jhnwkmn 0:97a4f8cc534c 1405 return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);
jhnwkmn 0:97a4f8cc534c 1406 }
jhnwkmn 0:97a4f8cc534c 1407 }
jhnwkmn 0:97a4f8cc534c 1408 if(!NewSlot(self, key, val,bstatic))
jhnwkmn 0:97a4f8cc534c 1409 return false;
jhnwkmn 0:97a4f8cc534c 1410 if(type(attrs) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1411 c->SetAttributes(key,attrs);
jhnwkmn 0:97a4f8cc534c 1412 }
jhnwkmn 0:97a4f8cc534c 1413 return true;
jhnwkmn 0:97a4f8cc534c 1414 }
jhnwkmn 0:97a4f8cc534c 1415
jhnwkmn 0:97a4f8cc534c 1416 bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
jhnwkmn 0:97a4f8cc534c 1417 {
jhnwkmn 0:97a4f8cc534c 1418 if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
jhnwkmn 0:97a4f8cc534c 1419 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1420 case OT_TABLE: {
jhnwkmn 0:97a4f8cc534c 1421 bool rawcall = true;
jhnwkmn 0:97a4f8cc534c 1422 if(_table(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1423 SQObjectPtr res;
jhnwkmn 0:97a4f8cc534c 1424 if(!_table(self)->Get(key,res)) {
jhnwkmn 0:97a4f8cc534c 1425 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1426 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1427 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1428 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
jhnwkmn 0:97a4f8cc534c 1429 return false;
jhnwkmn 0:97a4f8cc534c 1430 }
jhnwkmn 0:97a4f8cc534c 1431 rawcall = false;
jhnwkmn 0:97a4f8cc534c 1432 }
jhnwkmn 0:97a4f8cc534c 1433 else {
jhnwkmn 0:97a4f8cc534c 1434 rawcall = true;
jhnwkmn 0:97a4f8cc534c 1435 }
jhnwkmn 0:97a4f8cc534c 1436 }
jhnwkmn 0:97a4f8cc534c 1437 }
jhnwkmn 0:97a4f8cc534c 1438 if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
jhnwkmn 0:97a4f8cc534c 1439
jhnwkmn 0:97a4f8cc534c 1440 break;}
jhnwkmn 0:97a4f8cc534c 1441 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1442 SQObjectPtr res;
jhnwkmn 0:97a4f8cc534c 1443 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1444 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1445 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1446 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
jhnwkmn 0:97a4f8cc534c 1447 return false;
jhnwkmn 0:97a4f8cc534c 1448 }
jhnwkmn 0:97a4f8cc534c 1449 break;
jhnwkmn 0:97a4f8cc534c 1450 }
jhnwkmn 0:97a4f8cc534c 1451 Raise_Error(_SC("class instances do not support the new slot operator"));
jhnwkmn 0:97a4f8cc534c 1452 return false;
jhnwkmn 0:97a4f8cc534c 1453 break;}
jhnwkmn 0:97a4f8cc534c 1454 case OT_CLASS:
jhnwkmn 0:97a4f8cc534c 1455 if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
jhnwkmn 0:97a4f8cc534c 1456 if(_class(self)->_locked) {
jhnwkmn 0:97a4f8cc534c 1457 Raise_Error(_SC("trying to modify a class that has already been instantiated"));
jhnwkmn 0:97a4f8cc534c 1458 return false;
jhnwkmn 0:97a4f8cc534c 1459 }
jhnwkmn 0:97a4f8cc534c 1460 else {
jhnwkmn 0:97a4f8cc534c 1461 SQObjectPtr oval = PrintObjVal(key);
jhnwkmn 0:97a4f8cc534c 1462 Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
jhnwkmn 0:97a4f8cc534c 1463 return false;
jhnwkmn 0:97a4f8cc534c 1464 }
jhnwkmn 0:97a4f8cc534c 1465 }
jhnwkmn 0:97a4f8cc534c 1466 break;
jhnwkmn 0:97a4f8cc534c 1467 default:
jhnwkmn 0:97a4f8cc534c 1468 Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
jhnwkmn 0:97a4f8cc534c 1469 return false;
jhnwkmn 0:97a4f8cc534c 1470 break;
jhnwkmn 0:97a4f8cc534c 1471 }
jhnwkmn 0:97a4f8cc534c 1472 return true;
jhnwkmn 0:97a4f8cc534c 1473 }
jhnwkmn 0:97a4f8cc534c 1474
jhnwkmn 0:97a4f8cc534c 1475
jhnwkmn 0:97a4f8cc534c 1476
jhnwkmn 0:97a4f8cc534c 1477 bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)
jhnwkmn 0:97a4f8cc534c 1478 {
jhnwkmn 0:97a4f8cc534c 1479 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1480 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1481 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1482 case OT_USERDATA: {
jhnwkmn 0:97a4f8cc534c 1483 SQObjectPtr t;
jhnwkmn 0:97a4f8cc534c 1484 //bool handled = false;
jhnwkmn 0:97a4f8cc534c 1485 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1486 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1487 Push(self);Push(key);
jhnwkmn 0:97a4f8cc534c 1488 return CallMetaMethod(closure,MT_DELSLOT,2,res);
jhnwkmn 0:97a4f8cc534c 1489 }
jhnwkmn 0:97a4f8cc534c 1490 else {
jhnwkmn 0:97a4f8cc534c 1491 if(type(self) == OT_TABLE) {
jhnwkmn 0:97a4f8cc534c 1492 if(_table(self)->Get(key,t)) {
jhnwkmn 0:97a4f8cc534c 1493 _table(self)->Remove(key);
jhnwkmn 0:97a4f8cc534c 1494 }
jhnwkmn 0:97a4f8cc534c 1495 else {
jhnwkmn 0:97a4f8cc534c 1496 Raise_IdxError((SQObject &)key);
jhnwkmn 0:97a4f8cc534c 1497 return false;
jhnwkmn 0:97a4f8cc534c 1498 }
jhnwkmn 0:97a4f8cc534c 1499 }
jhnwkmn 0:97a4f8cc534c 1500 else {
jhnwkmn 0:97a4f8cc534c 1501 Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1502 return false;
jhnwkmn 0:97a4f8cc534c 1503 }
jhnwkmn 0:97a4f8cc534c 1504 }
jhnwkmn 0:97a4f8cc534c 1505 res = t;
jhnwkmn 0:97a4f8cc534c 1506 }
jhnwkmn 0:97a4f8cc534c 1507 break;
jhnwkmn 0:97a4f8cc534c 1508 default:
jhnwkmn 0:97a4f8cc534c 1509 Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1510 return false;
jhnwkmn 0:97a4f8cc534c 1511 }
jhnwkmn 0:97a4f8cc534c 1512 return true;
jhnwkmn 0:97a4f8cc534c 1513 }
jhnwkmn 0:97a4f8cc534c 1514
jhnwkmn 0:97a4f8cc534c 1515 bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
jhnwkmn 0:97a4f8cc534c 1516 {
jhnwkmn 0:97a4f8cc534c 1517 #ifdef _DEBUG
jhnwkmn 0:97a4f8cc534c 1518 SQInteger prevstackbase = _stackbase;
jhnwkmn 0:97a4f8cc534c 1519 #endif
jhnwkmn 0:97a4f8cc534c 1520 switch(type(closure)) {
jhnwkmn 0:97a4f8cc534c 1521 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 1522 return Execute(closure, nparams, stackbase, outres, raiseerror);
jhnwkmn 0:97a4f8cc534c 1523 break;
jhnwkmn 0:97a4f8cc534c 1524 case OT_NATIVECLOSURE:{
jhnwkmn 0:97a4f8cc534c 1525 bool suspend;
jhnwkmn 0:97a4f8cc534c 1526 return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
jhnwkmn 0:97a4f8cc534c 1527
jhnwkmn 0:97a4f8cc534c 1528 }
jhnwkmn 0:97a4f8cc534c 1529 break;
jhnwkmn 0:97a4f8cc534c 1530 case OT_CLASS: {
jhnwkmn 0:97a4f8cc534c 1531 SQObjectPtr constr;
jhnwkmn 0:97a4f8cc534c 1532 SQObjectPtr temp;
jhnwkmn 0:97a4f8cc534c 1533 CreateClassInstance(_class(closure),outres,constr);
jhnwkmn 0:97a4f8cc534c 1534 if(type(constr) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1535 _stack[stackbase] = outres;
jhnwkmn 0:97a4f8cc534c 1536 return Call(constr,nparams,stackbase,temp,raiseerror);
jhnwkmn 0:97a4f8cc534c 1537 }
jhnwkmn 0:97a4f8cc534c 1538 return true;
jhnwkmn 0:97a4f8cc534c 1539 }
jhnwkmn 0:97a4f8cc534c 1540 break;
jhnwkmn 0:97a4f8cc534c 1541 default:
jhnwkmn 0:97a4f8cc534c 1542 return false;
jhnwkmn 0:97a4f8cc534c 1543 }
jhnwkmn 0:97a4f8cc534c 1544 #ifdef _DEBUG
jhnwkmn 0:97a4f8cc534c 1545 if(!_suspended) {
jhnwkmn 0:97a4f8cc534c 1546 assert(_stackbase == prevstackbase);
jhnwkmn 0:97a4f8cc534c 1547 }
jhnwkmn 0:97a4f8cc534c 1548 #endif
jhnwkmn 0:97a4f8cc534c 1549 return true;
jhnwkmn 0:97a4f8cc534c 1550 }
jhnwkmn 0:97a4f8cc534c 1551
jhnwkmn 0:97a4f8cc534c 1552 bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
jhnwkmn 0:97a4f8cc534c 1553 {
jhnwkmn 0:97a4f8cc534c 1554 //SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1555
jhnwkmn 0:97a4f8cc534c 1556 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1557 if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1558 _nmetamethodscall--;
jhnwkmn 0:97a4f8cc534c 1559 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1560 return true;
jhnwkmn 0:97a4f8cc534c 1561 }
jhnwkmn 0:97a4f8cc534c 1562 _nmetamethodscall--;
jhnwkmn 0:97a4f8cc534c 1563 //}
jhnwkmn 0:97a4f8cc534c 1564 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1565 return false;
jhnwkmn 0:97a4f8cc534c 1566 }
jhnwkmn 0:97a4f8cc534c 1567
jhnwkmn 0:97a4f8cc534c 1568 void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
jhnwkmn 0:97a4f8cc534c 1569 {
jhnwkmn 0:97a4f8cc534c 1570 SQOuter **pp = &_openouters;
jhnwkmn 0:97a4f8cc534c 1571 SQOuter *p;
jhnwkmn 0:97a4f8cc534c 1572 SQOuter *otr;
jhnwkmn 0:97a4f8cc534c 1573
jhnwkmn 0:97a4f8cc534c 1574 while ((p = *pp) != NULL && p->_valptr >= stackindex) {
jhnwkmn 0:97a4f8cc534c 1575 if (p->_valptr == stackindex) {
jhnwkmn 0:97a4f8cc534c 1576 target = SQObjectPtr(p);
jhnwkmn 0:97a4f8cc534c 1577 return;
jhnwkmn 0:97a4f8cc534c 1578 }
jhnwkmn 0:97a4f8cc534c 1579 pp = &p->_next;
jhnwkmn 0:97a4f8cc534c 1580 }
jhnwkmn 0:97a4f8cc534c 1581 otr = SQOuter::Create(_ss(this), stackindex);
jhnwkmn 0:97a4f8cc534c 1582 otr->_next = *pp;
jhnwkmn 0:97a4f8cc534c 1583 otr->_idx = (stackindex - _stack._vals);
jhnwkmn 0:97a4f8cc534c 1584 __ObjAddRef(otr);
jhnwkmn 0:97a4f8cc534c 1585 *pp = otr;
jhnwkmn 0:97a4f8cc534c 1586 target = SQObjectPtr(otr);
jhnwkmn 0:97a4f8cc534c 1587 }
jhnwkmn 0:97a4f8cc534c 1588
jhnwkmn 0:97a4f8cc534c 1589 bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)
jhnwkmn 0:97a4f8cc534c 1590 {
jhnwkmn 0:97a4f8cc534c 1591 if( !tailcall ) {
jhnwkmn 0:97a4f8cc534c 1592 if( _callsstacksize == _alloccallsstacksize ) {
jhnwkmn 0:97a4f8cc534c 1593 GrowCallStack();
jhnwkmn 0:97a4f8cc534c 1594 }
jhnwkmn 0:97a4f8cc534c 1595 ci = &_callsstack[_callsstacksize++];
jhnwkmn 0:97a4f8cc534c 1596 ci->_prevstkbase = (SQInt32)(newbase - _stackbase);
jhnwkmn 0:97a4f8cc534c 1597 ci->_prevtop = (SQInt32)(_top - _stackbase);
jhnwkmn 0:97a4f8cc534c 1598 ci->_etraps = 0;
jhnwkmn 0:97a4f8cc534c 1599 ci->_ncalls = 1;
jhnwkmn 0:97a4f8cc534c 1600 ci->_generator = NULL;
jhnwkmn 0:97a4f8cc534c 1601 ci->_root = SQFalse;
jhnwkmn 0:97a4f8cc534c 1602 }
jhnwkmn 0:97a4f8cc534c 1603 else {
jhnwkmn 0:97a4f8cc534c 1604 ci->_ncalls++;
jhnwkmn 0:97a4f8cc534c 1605 }
jhnwkmn 0:97a4f8cc534c 1606
jhnwkmn 0:97a4f8cc534c 1607 _stackbase = newbase;
jhnwkmn 0:97a4f8cc534c 1608 _top = newtop;
jhnwkmn 0:97a4f8cc534c 1609 if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {
jhnwkmn 0:97a4f8cc534c 1610 if(_nmetamethodscall) {
jhnwkmn 0:97a4f8cc534c 1611 Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod"));
jhnwkmn 0:97a4f8cc534c 1612 return false;
jhnwkmn 0:97a4f8cc534c 1613 }
jhnwkmn 0:97a4f8cc534c 1614 _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2));
jhnwkmn 0:97a4f8cc534c 1615 RelocateOuters();
jhnwkmn 0:97a4f8cc534c 1616 }
jhnwkmn 0:97a4f8cc534c 1617 return true;
jhnwkmn 0:97a4f8cc534c 1618 }
jhnwkmn 0:97a4f8cc534c 1619
jhnwkmn 0:97a4f8cc534c 1620 void SQVM::LeaveFrame() {
jhnwkmn 0:97a4f8cc534c 1621 SQInteger last_top = _top;
jhnwkmn 0:97a4f8cc534c 1622 SQInteger last_stackbase = _stackbase;
jhnwkmn 0:97a4f8cc534c 1623 SQInteger css = --_callsstacksize;
jhnwkmn 0:97a4f8cc534c 1624
jhnwkmn 0:97a4f8cc534c 1625 /* First clean out the call stack frame */
jhnwkmn 0:97a4f8cc534c 1626 ci->_closure.Null();
jhnwkmn 0:97a4f8cc534c 1627 _stackbase -= ci->_prevstkbase;
jhnwkmn 0:97a4f8cc534c 1628 _top = _stackbase + ci->_prevtop;
jhnwkmn 0:97a4f8cc534c 1629 ci = (css) ? &_callsstack[css-1] : NULL;
jhnwkmn 0:97a4f8cc534c 1630
jhnwkmn 0:97a4f8cc534c 1631 if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
jhnwkmn 0:97a4f8cc534c 1632 while (last_top >= _top) {
jhnwkmn 0:97a4f8cc534c 1633 _stack._vals[last_top--].Null();
jhnwkmn 0:97a4f8cc534c 1634 }
jhnwkmn 0:97a4f8cc534c 1635 }
jhnwkmn 0:97a4f8cc534c 1636
jhnwkmn 0:97a4f8cc534c 1637 void SQVM::RelocateOuters()
jhnwkmn 0:97a4f8cc534c 1638 {
jhnwkmn 0:97a4f8cc534c 1639 SQOuter *p = _openouters;
jhnwkmn 0:97a4f8cc534c 1640 while (p) {
jhnwkmn 0:97a4f8cc534c 1641 p->_valptr = _stack._vals + p->_idx;
jhnwkmn 0:97a4f8cc534c 1642 p = p->_next;
jhnwkmn 0:97a4f8cc534c 1643 }
jhnwkmn 0:97a4f8cc534c 1644 }
jhnwkmn 0:97a4f8cc534c 1645
jhnwkmn 0:97a4f8cc534c 1646 void SQVM::CloseOuters(SQObjectPtr *stackindex) {
jhnwkmn 0:97a4f8cc534c 1647 SQOuter *p;
jhnwkmn 0:97a4f8cc534c 1648 while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
jhnwkmn 0:97a4f8cc534c 1649 p->_value = *(p->_valptr);
jhnwkmn 0:97a4f8cc534c 1650 p->_valptr = &p->_value;
jhnwkmn 0:97a4f8cc534c 1651 _openouters = p->_next;
jhnwkmn 0:97a4f8cc534c 1652 __ObjRelease(p);
jhnwkmn 0:97a4f8cc534c 1653 }
jhnwkmn 0:97a4f8cc534c 1654 }
jhnwkmn 0:97a4f8cc534c 1655
jhnwkmn 0:97a4f8cc534c 1656 void SQVM::Remove(SQInteger n) {
jhnwkmn 0:97a4f8cc534c 1657 n = (n >= 0)?n + _stackbase - 1:_top + n;
jhnwkmn 0:97a4f8cc534c 1658 for(SQInteger i = n; i < _top; i++){
jhnwkmn 0:97a4f8cc534c 1659 _stack[i] = _stack[i+1];
jhnwkmn 0:97a4f8cc534c 1660 }
jhnwkmn 0:97a4f8cc534c 1661 _stack[_top].Null();
jhnwkmn 0:97a4f8cc534c 1662 _top--;
jhnwkmn 0:97a4f8cc534c 1663 }
jhnwkmn 0:97a4f8cc534c 1664
jhnwkmn 0:97a4f8cc534c 1665 void SQVM::Pop() {
jhnwkmn 0:97a4f8cc534c 1666 _stack[--_top].Null();
jhnwkmn 0:97a4f8cc534c 1667 }
jhnwkmn 0:97a4f8cc534c 1668
jhnwkmn 0:97a4f8cc534c 1669 void SQVM::Pop(SQInteger n) {
jhnwkmn 0:97a4f8cc534c 1670 for(SQInteger i = 0; i < n; i++){
jhnwkmn 0:97a4f8cc534c 1671 _stack[--_top].Null();
jhnwkmn 0:97a4f8cc534c 1672 }
jhnwkmn 0:97a4f8cc534c 1673 }
jhnwkmn 0:97a4f8cc534c 1674
jhnwkmn 0:97a4f8cc534c 1675 void SQVM::PushNull() { _stack[_top++].Null(); }
jhnwkmn 0:97a4f8cc534c 1676 void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }
jhnwkmn 0:97a4f8cc534c 1677 SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }
jhnwkmn 0:97a4f8cc534c 1678 SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }
jhnwkmn 0:97a4f8cc534c 1679 SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; }
jhnwkmn 0:97a4f8cc534c 1680 SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }
jhnwkmn 0:97a4f8cc534c 1681
jhnwkmn 0:97a4f8cc534c 1682 #ifdef _DEBUG_DUMP
jhnwkmn 0:97a4f8cc534c 1683 void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
jhnwkmn 0:97a4f8cc534c 1684 {
jhnwkmn 0:97a4f8cc534c 1685 SQInteger size=dumpall?_stack.size():_top;
jhnwkmn 0:97a4f8cc534c 1686 SQInteger n=0;
jhnwkmn 0:97a4f8cc534c 1687 scprintf(_SC("\n>>>>stack dump<<<<\n"));
jhnwkmn 0:97a4f8cc534c 1688 CallInfo &ci=_callsstack[_callsstacksize-1];
jhnwkmn 0:97a4f8cc534c 1689 scprintf(_SC("IP: %p\n"),ci._ip);
jhnwkmn 0:97a4f8cc534c 1690 scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
jhnwkmn 0:97a4f8cc534c 1691 scprintf(_SC("prev top: %d\n"),ci._prevtop);
jhnwkmn 0:97a4f8cc534c 1692 for(SQInteger i=0;i<size;i++){
jhnwkmn 0:97a4f8cc534c 1693 SQObjectPtr &obj=_stack[i];
jhnwkmn 0:97a4f8cc534c 1694 if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
jhnwkmn 0:97a4f8cc534c 1695 scprintf(_SC("[%d]:"),n);
jhnwkmn 0:97a4f8cc534c 1696 switch(type(obj)){
jhnwkmn 0:97a4f8cc534c 1697 case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
jhnwkmn 0:97a4f8cc534c 1698 case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break;
jhnwkmn 0:97a4f8cc534c 1699 case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
jhnwkmn 0:97a4f8cc534c 1700 case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
jhnwkmn 0:97a4f8cc534c 1701 case OT_NULL: scprintf(_SC("NULL")); break;
jhnwkmn 0:97a4f8cc534c 1702 case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
jhnwkmn 0:97a4f8cc534c 1703 case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break;
jhnwkmn 0:97a4f8cc534c 1704 case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
jhnwkmn 0:97a4f8cc534c 1705 case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;
jhnwkmn 0:97a4f8cc534c 1706 case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
jhnwkmn 0:97a4f8cc534c 1707 case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break;
jhnwkmn 0:97a4f8cc534c 1708 case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;
jhnwkmn 0:97a4f8cc534c 1709 case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
jhnwkmn 0:97a4f8cc534c 1710 case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;
jhnwkmn 0:97a4f8cc534c 1711 case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break;
jhnwkmn 0:97a4f8cc534c 1712 case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
jhnwkmn 0:97a4f8cc534c 1713 default:
jhnwkmn 0:97a4f8cc534c 1714 assert(0);
jhnwkmn 0:97a4f8cc534c 1715 break;
jhnwkmn 0:97a4f8cc534c 1716 };
jhnwkmn 0:97a4f8cc534c 1717 scprintf(_SC("\n"));
jhnwkmn 0:97a4f8cc534c 1718 ++n;
jhnwkmn 0:97a4f8cc534c 1719 }
jhnwkmn 0:97a4f8cc534c 1720 }
jhnwkmn 0:97a4f8cc534c 1721
jhnwkmn 0:97a4f8cc534c 1722
jhnwkmn 0:97a4f8cc534c 1723
jhnwkmn 0:97a4f8cc534c 1724 #endif