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

Dependents:   Squirrel

Committer:
jhnwkmn
Date:
Tue Dec 16 11:39:42 2014 +0000
Revision:
3:7268a3ceaffc
Parent:
1:8a2835ae5c5d
Accepts \r as line terminator as well.

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 1:8a2835ae5c5d 660 #if defined(__MBED__)
jhnwkmn 1:8a2835ae5c5d 661 extern "C" void mbed_execute_idle(HSQUIRRELVM);
jhnwkmn 1:8a2835ae5c5d 662 #endif
jhnwkmn 1:8a2835ae5c5d 663
jhnwkmn 0:97a4f8cc534c 664 bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
jhnwkmn 0:97a4f8cc534c 665 {
jhnwkmn 0:97a4f8cc534c 666 if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
jhnwkmn 0:97a4f8cc534c 667 _nnativecalls++;
jhnwkmn 0:97a4f8cc534c 668 AutoDec ad(&_nnativecalls);
jhnwkmn 0:97a4f8cc534c 669 SQInteger traps = 0;
jhnwkmn 0:97a4f8cc534c 670 CallInfo *prevci = ci;
jhnwkmn 0:97a4f8cc534c 671
jhnwkmn 0:97a4f8cc534c 672 switch(et) {
jhnwkmn 0:97a4f8cc534c 673 case ET_CALL: {
jhnwkmn 0:97a4f8cc534c 674 temp_reg = closure;
jhnwkmn 0:97a4f8cc534c 675 if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) {
jhnwkmn 0:97a4f8cc534c 676 //call the handler if there are no calls in the stack, if not relies on the previous node
jhnwkmn 0:97a4f8cc534c 677 if(ci == NULL) CallErrorHandler(_lasterror);
jhnwkmn 0:97a4f8cc534c 678 return false;
jhnwkmn 0:97a4f8cc534c 679 }
jhnwkmn 0:97a4f8cc534c 680 if(ci == prevci) {
jhnwkmn 0:97a4f8cc534c 681 outres = STK(_top-nargs);
jhnwkmn 0:97a4f8cc534c 682 return true;
jhnwkmn 0:97a4f8cc534c 683 }
jhnwkmn 0:97a4f8cc534c 684 ci->_root = SQTrue;
jhnwkmn 0:97a4f8cc534c 685 }
jhnwkmn 0:97a4f8cc534c 686 break;
jhnwkmn 0:97a4f8cc534c 687 case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;
jhnwkmn 0:97a4f8cc534c 688 case ET_RESUME_VM:
jhnwkmn 0:97a4f8cc534c 689 case ET_RESUME_THROW_VM:
jhnwkmn 0:97a4f8cc534c 690 traps = _suspended_traps;
jhnwkmn 0:97a4f8cc534c 691 ci->_root = _suspended_root;
jhnwkmn 0:97a4f8cc534c 692 _suspended = SQFalse;
jhnwkmn 0:97a4f8cc534c 693 if(et == ET_RESUME_THROW_VM) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 694 break;
jhnwkmn 0:97a4f8cc534c 695 }
jhnwkmn 0:97a4f8cc534c 696
jhnwkmn 0:97a4f8cc534c 697 exception_restore:
jhnwkmn 0:97a4f8cc534c 698 //
jhnwkmn 0:97a4f8cc534c 699 {
jhnwkmn 0:97a4f8cc534c 700 for(;;)
jhnwkmn 0:97a4f8cc534c 701 {
jhnwkmn 1:8a2835ae5c5d 702 #if defined(__MBED__)
jhnwkmn 1:8a2835ae5c5d 703 mbed_execute_idle(this);
jhnwkmn 1:8a2835ae5c5d 704 #endif
jhnwkmn 0:97a4f8cc534c 705 const SQInstruction &_i_ = *ci->_ip++;
jhnwkmn 0:97a4f8cc534c 706 //dumpstack(_stackbase);
jhnwkmn 0:97a4f8cc534c 707 //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 708 switch(_i_.op)
jhnwkmn 0:97a4f8cc534c 709 {
jhnwkmn 0:97a4f8cc534c 710 case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
jhnwkmn 0:97a4f8cc534c 711 case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
jhnwkmn 0:97a4f8cc534c 712 case _OP_LOADINT:
jhnwkmn 0:97a4f8cc534c 713 #ifndef _SQ64
jhnwkmn 0:97a4f8cc534c 714 TARGET = (SQInteger)arg1; continue;
jhnwkmn 0:97a4f8cc534c 715 #else
jhnwkmn 0:97a4f8cc534c 716 TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;
jhnwkmn 0:97a4f8cc534c 717 #endif
jhnwkmn 0:97a4f8cc534c 718 case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
jhnwkmn 0:97a4f8cc534c 719 case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
jhnwkmn 0:97a4f8cc534c 720 case _OP_TAILCALL:{
jhnwkmn 0:97a4f8cc534c 721 SQObjectPtr &t = STK(arg1);
jhnwkmn 0:97a4f8cc534c 722 if (type(t) == OT_CLOSURE
jhnwkmn 0:97a4f8cc534c 723 && (!_closure(t)->_function->_bgenerator)){
jhnwkmn 0:97a4f8cc534c 724 SQObjectPtr clo = t;
jhnwkmn 0:97a4f8cc534c 725 if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
jhnwkmn 0:97a4f8cc534c 726 for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
jhnwkmn 0:97a4f8cc534c 727 _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
jhnwkmn 0:97a4f8cc534c 728 continue;
jhnwkmn 0:97a4f8cc534c 729 }
jhnwkmn 0:97a4f8cc534c 730 }
jhnwkmn 0:97a4f8cc534c 731 case _OP_CALL: {
jhnwkmn 0:97a4f8cc534c 732 SQObjectPtr clo = STK(arg1);
jhnwkmn 0:97a4f8cc534c 733 switch (type(clo)) {
jhnwkmn 0:97a4f8cc534c 734 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 735 _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
jhnwkmn 0:97a4f8cc534c 736 continue;
jhnwkmn 0:97a4f8cc534c 737 case OT_NATIVECLOSURE: {
jhnwkmn 0:97a4f8cc534c 738 bool suspend;
jhnwkmn 0:97a4f8cc534c 739 _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
jhnwkmn 0:97a4f8cc534c 740 if(suspend){
jhnwkmn 0:97a4f8cc534c 741 _suspended = SQTrue;
jhnwkmn 0:97a4f8cc534c 742 _suspended_target = sarg0;
jhnwkmn 0:97a4f8cc534c 743 _suspended_root = ci->_root;
jhnwkmn 0:97a4f8cc534c 744 _suspended_traps = traps;
jhnwkmn 0:97a4f8cc534c 745 outres = clo;
jhnwkmn 0:97a4f8cc534c 746 return true;
jhnwkmn 0:97a4f8cc534c 747 }
jhnwkmn 0:97a4f8cc534c 748 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 749 STK(arg0) = clo;
jhnwkmn 0:97a4f8cc534c 750 }
jhnwkmn 0:97a4f8cc534c 751 }
jhnwkmn 0:97a4f8cc534c 752 continue;
jhnwkmn 0:97a4f8cc534c 753 case OT_CLASS:{
jhnwkmn 0:97a4f8cc534c 754 SQObjectPtr inst;
jhnwkmn 0:97a4f8cc534c 755 _GUARD(CreateClassInstance(_class(clo),inst,clo));
jhnwkmn 0:97a4f8cc534c 756 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 757 STK(arg0) = inst;
jhnwkmn 0:97a4f8cc534c 758 }
jhnwkmn 0:97a4f8cc534c 759 SQInteger stkbase;
jhnwkmn 0:97a4f8cc534c 760 switch(type(clo)) {
jhnwkmn 0:97a4f8cc534c 761 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 762 stkbase = _stackbase+arg2;
jhnwkmn 0:97a4f8cc534c 763 _stack._vals[stkbase] = inst;
jhnwkmn 0:97a4f8cc534c 764 _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
jhnwkmn 0:97a4f8cc534c 765 break;
jhnwkmn 0:97a4f8cc534c 766 case OT_NATIVECLOSURE:
jhnwkmn 0:97a4f8cc534c 767 bool suspend;
jhnwkmn 0:97a4f8cc534c 768 stkbase = _stackbase+arg2;
jhnwkmn 0:97a4f8cc534c 769 _stack._vals[stkbase] = inst;
jhnwkmn 0:97a4f8cc534c 770 _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
jhnwkmn 0:97a4f8cc534c 771 break;
jhnwkmn 0:97a4f8cc534c 772 default: break; //shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 773 }
jhnwkmn 0:97a4f8cc534c 774 }
jhnwkmn 0:97a4f8cc534c 775 break;
jhnwkmn 0:97a4f8cc534c 776 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 777 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 778 case OT_INSTANCE:{
jhnwkmn 0:97a4f8cc534c 779 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 780 if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
jhnwkmn 0:97a4f8cc534c 781 Push(clo);
jhnwkmn 0:97a4f8cc534c 782 for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
jhnwkmn 0:97a4f8cc534c 783 if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();
jhnwkmn 0:97a4f8cc534c 784 if(sarg0 != -1) {
jhnwkmn 0:97a4f8cc534c 785 STK(arg0) = clo;
jhnwkmn 0:97a4f8cc534c 786 }
jhnwkmn 0:97a4f8cc534c 787 break;
jhnwkmn 0:97a4f8cc534c 788 }
jhnwkmn 0:97a4f8cc534c 789
jhnwkmn 0:97a4f8cc534c 790 //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
jhnwkmn 0:97a4f8cc534c 791 //SQ_THROW();
jhnwkmn 0:97a4f8cc534c 792 }
jhnwkmn 0:97a4f8cc534c 793 default:
jhnwkmn 0:97a4f8cc534c 794 Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
jhnwkmn 0:97a4f8cc534c 795 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 796 }
jhnwkmn 0:97a4f8cc534c 797 }
jhnwkmn 0:97a4f8cc534c 798 continue;
jhnwkmn 0:97a4f8cc534c 799 case _OP_PREPCALL:
jhnwkmn 0:97a4f8cc534c 800 case _OP_PREPCALLK: {
jhnwkmn 0:97a4f8cc534c 801 SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
jhnwkmn 0:97a4f8cc534c 802 SQObjectPtr &o = STK(arg2);
jhnwkmn 0:97a4f8cc534c 803 if (!Get(o, key, temp_reg,false,arg2)) {
jhnwkmn 0:97a4f8cc534c 804 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 805 }
jhnwkmn 0:97a4f8cc534c 806 STK(arg3) = o;
jhnwkmn 0:97a4f8cc534c 807 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 808 }
jhnwkmn 0:97a4f8cc534c 809 continue;
jhnwkmn 0:97a4f8cc534c 810 case _OP_GETK:
jhnwkmn 0:97a4f8cc534c 811 if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 812 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 813 continue;
jhnwkmn 0:97a4f8cc534c 814 case _OP_MOVE: TARGET = STK(arg1); continue;
jhnwkmn 0:97a4f8cc534c 815 case _OP_NEWSLOT:
jhnwkmn 0:97a4f8cc534c 816 _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
jhnwkmn 0:97a4f8cc534c 817 if(arg0 != 0xFF) TARGET = STK(arg3);
jhnwkmn 0:97a4f8cc534c 818 continue;
jhnwkmn 0:97a4f8cc534c 819 case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
jhnwkmn 0:97a4f8cc534c 820 case _OP_SET:
jhnwkmn 0:97a4f8cc534c 821 if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 822 if (arg0 != 0xFF) TARGET = STK(arg3);
jhnwkmn 0:97a4f8cc534c 823 continue;
jhnwkmn 0:97a4f8cc534c 824 case _OP_GET:
jhnwkmn 0:97a4f8cc534c 825 if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 826 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
jhnwkmn 0:97a4f8cc534c 827 continue;
jhnwkmn 0:97a4f8cc534c 828 case _OP_EQ:{
jhnwkmn 0:97a4f8cc534c 829 bool res;
jhnwkmn 0:97a4f8cc534c 830 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 831 TARGET = res?true:false;
jhnwkmn 0:97a4f8cc534c 832 }continue;
jhnwkmn 0:97a4f8cc534c 833 case _OP_NE:{
jhnwkmn 0:97a4f8cc534c 834 bool res;
jhnwkmn 0:97a4f8cc534c 835 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 836 TARGET = (!res)?true:false;
jhnwkmn 0:97a4f8cc534c 837 } continue;
jhnwkmn 0:97a4f8cc534c 838 case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 839 case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 840 case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 841 case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
jhnwkmn 0:97a4f8cc534c 842 case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 843 case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
jhnwkmn 0:97a4f8cc534c 844 case _OP_RETURN:
jhnwkmn 0:97a4f8cc534c 845 if((ci)->_generator) {
jhnwkmn 0:97a4f8cc534c 846 (ci)->_generator->Kill();
jhnwkmn 0:97a4f8cc534c 847 }
jhnwkmn 0:97a4f8cc534c 848 if(Return(arg0, arg1, temp_reg)){
jhnwkmn 0:97a4f8cc534c 849 assert(traps==0);
jhnwkmn 0:97a4f8cc534c 850 //outres = temp_reg;
jhnwkmn 0:97a4f8cc534c 851 _Swap(outres,temp_reg);
jhnwkmn 0:97a4f8cc534c 852 return true;
jhnwkmn 0:97a4f8cc534c 853 }
jhnwkmn 0:97a4f8cc534c 854 continue;
jhnwkmn 0:97a4f8cc534c 855 case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
jhnwkmn 0:97a4f8cc534c 856 case _OP_LOADROOT: TARGET = _roottable; continue;
jhnwkmn 0:97a4f8cc534c 857 case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
jhnwkmn 0:97a4f8cc534c 858 case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
jhnwkmn 0:97a4f8cc534c 859 case _OP_JMP: ci->_ip += (sarg1); continue;
jhnwkmn 0:97a4f8cc534c 860 //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
jhnwkmn 0:97a4f8cc534c 861 case _OP_JCMP:
jhnwkmn 0:97a4f8cc534c 862 _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
jhnwkmn 0:97a4f8cc534c 863 if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
jhnwkmn 0:97a4f8cc534c 864 continue;
jhnwkmn 0:97a4f8cc534c 865 case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
jhnwkmn 0:97a4f8cc534c 866 case _OP_GETOUTER: {
jhnwkmn 0:97a4f8cc534c 867 SQClosure *cur_cls = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 868 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
jhnwkmn 0:97a4f8cc534c 869 TARGET = *(otr->_valptr);
jhnwkmn 0:97a4f8cc534c 870 }
jhnwkmn 0:97a4f8cc534c 871 continue;
jhnwkmn 0:97a4f8cc534c 872 case _OP_SETOUTER: {
jhnwkmn 0:97a4f8cc534c 873 SQClosure *cur_cls = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 874 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
jhnwkmn 0:97a4f8cc534c 875 *(otr->_valptr) = STK(arg2);
jhnwkmn 0:97a4f8cc534c 876 if(arg0 != 0xFF) {
jhnwkmn 0:97a4f8cc534c 877 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 878 }
jhnwkmn 0:97a4f8cc534c 879 }
jhnwkmn 0:97a4f8cc534c 880 continue;
jhnwkmn 0:97a4f8cc534c 881 case _OP_NEWOBJ:
jhnwkmn 0:97a4f8cc534c 882 switch(arg3) {
jhnwkmn 0:97a4f8cc534c 883 case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
jhnwkmn 0:97a4f8cc534c 884 case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
jhnwkmn 0:97a4f8cc534c 885 case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
jhnwkmn 0:97a4f8cc534c 886 default: assert(0); continue;
jhnwkmn 0:97a4f8cc534c 887 }
jhnwkmn 0:97a4f8cc534c 888 case _OP_APPENDARRAY:
jhnwkmn 0:97a4f8cc534c 889 {
jhnwkmn 0:97a4f8cc534c 890 SQObject val;
jhnwkmn 0:97a4f8cc534c 891 val._unVal.raw = 0;
jhnwkmn 0:97a4f8cc534c 892 switch(arg2) {
jhnwkmn 0:97a4f8cc534c 893 case AAT_STACK:
jhnwkmn 0:97a4f8cc534c 894 val = STK(arg1); break;
jhnwkmn 0:97a4f8cc534c 895 case AAT_LITERAL:
jhnwkmn 0:97a4f8cc534c 896 val = ci->_literals[arg1]; break;
jhnwkmn 0:97a4f8cc534c 897 case AAT_INT:
jhnwkmn 0:97a4f8cc534c 898 val._type = OT_INTEGER;
jhnwkmn 0:97a4f8cc534c 899 #ifndef _SQ64
jhnwkmn 0:97a4f8cc534c 900 val._unVal.nInteger = (SQInteger)arg1;
jhnwkmn 0:97a4f8cc534c 901 #else
jhnwkmn 0:97a4f8cc534c 902 val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1);
jhnwkmn 0:97a4f8cc534c 903 #endif
jhnwkmn 0:97a4f8cc534c 904 break;
jhnwkmn 0:97a4f8cc534c 905 case AAT_FLOAT:
jhnwkmn 0:97a4f8cc534c 906 val._type = OT_FLOAT;
jhnwkmn 0:97a4f8cc534c 907 val._unVal.fFloat = *((SQFloat *)&arg1);
jhnwkmn 0:97a4f8cc534c 908 break;
jhnwkmn 0:97a4f8cc534c 909 case AAT_BOOL:
jhnwkmn 0:97a4f8cc534c 910 val._type = OT_BOOL;
jhnwkmn 0:97a4f8cc534c 911 val._unVal.nInteger = arg1;
jhnwkmn 0:97a4f8cc534c 912 break;
jhnwkmn 0:97a4f8cc534c 913 default: assert(0); break;
jhnwkmn 0:97a4f8cc534c 914
jhnwkmn 0:97a4f8cc534c 915 }
jhnwkmn 0:97a4f8cc534c 916 _array(STK(arg0))->Append(val); continue;
jhnwkmn 0:97a4f8cc534c 917 }
jhnwkmn 0:97a4f8cc534c 918 case _OP_COMPARITH: {
jhnwkmn 0:97a4f8cc534c 919 SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
jhnwkmn 0:97a4f8cc534c 920 _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
jhnwkmn 0:97a4f8cc534c 921 }
jhnwkmn 0:97a4f8cc534c 922 continue;
jhnwkmn 0:97a4f8cc534c 923 case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
jhnwkmn 0:97a4f8cc534c 924 case _OP_INCL: {
jhnwkmn 0:97a4f8cc534c 925 SQObjectPtr &a = STK(arg1);
jhnwkmn 0:97a4f8cc534c 926 if(type(a) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 927 a._unVal.nInteger = _integer(a) + sarg3;
jhnwkmn 0:97a4f8cc534c 928 }
jhnwkmn 0:97a4f8cc534c 929 else {
jhnwkmn 0:97a4f8cc534c 930 SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));
jhnwkmn 0:97a4f8cc534c 931 _ARITH_(+,a,a,o);
jhnwkmn 0:97a4f8cc534c 932 }
jhnwkmn 0:97a4f8cc534c 933 } continue;
jhnwkmn 0:97a4f8cc534c 934 case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
jhnwkmn 0:97a4f8cc534c 935 case _OP_PINCL: {
jhnwkmn 0:97a4f8cc534c 936 SQObjectPtr &a = STK(arg1);
jhnwkmn 0:97a4f8cc534c 937 if(type(a) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 938 TARGET = a;
jhnwkmn 0:97a4f8cc534c 939 a._unVal.nInteger = _integer(a) + sarg3;
jhnwkmn 0:97a4f8cc534c 940 }
jhnwkmn 0:97a4f8cc534c 941 else {
jhnwkmn 0:97a4f8cc534c 942 SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));
jhnwkmn 0:97a4f8cc534c 943 }
jhnwkmn 0:97a4f8cc534c 944
jhnwkmn 0:97a4f8cc534c 945 } continue;
jhnwkmn 0:97a4f8cc534c 946 case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue;
jhnwkmn 0:97a4f8cc534c 947 case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue;
jhnwkmn 0:97a4f8cc534c 948 case _OP_INSTANCEOF:
jhnwkmn 0:97a4f8cc534c 949 if(type(STK(arg1)) != OT_CLASS)
jhnwkmn 0:97a4f8cc534c 950 {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 951 TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
jhnwkmn 0:97a4f8cc534c 952 continue;
jhnwkmn 0:97a4f8cc534c 953 case _OP_AND:
jhnwkmn 0:97a4f8cc534c 954 if(IsFalse(STK(arg2))) {
jhnwkmn 0:97a4f8cc534c 955 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 956 ci->_ip += (sarg1);
jhnwkmn 0:97a4f8cc534c 957 }
jhnwkmn 0:97a4f8cc534c 958 continue;
jhnwkmn 0:97a4f8cc534c 959 case _OP_OR:
jhnwkmn 0:97a4f8cc534c 960 if(!IsFalse(STK(arg2))) {
jhnwkmn 0:97a4f8cc534c 961 TARGET = STK(arg2);
jhnwkmn 0:97a4f8cc534c 962 ci->_ip += (sarg1);
jhnwkmn 0:97a4f8cc534c 963 }
jhnwkmn 0:97a4f8cc534c 964 continue;
jhnwkmn 0:97a4f8cc534c 965 case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
jhnwkmn 0:97a4f8cc534c 966 case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
jhnwkmn 0:97a4f8cc534c 967 case _OP_BWNOT:
jhnwkmn 0:97a4f8cc534c 968 if(type(STK(arg1)) == OT_INTEGER) {
jhnwkmn 0:97a4f8cc534c 969 SQInteger t = _integer(STK(arg1));
jhnwkmn 0:97a4f8cc534c 970 TARGET = SQInteger(~t);
jhnwkmn 0:97a4f8cc534c 971 continue;
jhnwkmn 0:97a4f8cc534c 972 }
jhnwkmn 0:97a4f8cc534c 973 Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
jhnwkmn 0:97a4f8cc534c 974 SQ_THROW();
jhnwkmn 0:97a4f8cc534c 975 case _OP_CLOSURE: {
jhnwkmn 0:97a4f8cc534c 976 SQClosure *c = ci->_closure._unVal.pClosure;
jhnwkmn 0:97a4f8cc534c 977 SQFunctionProto *fp = c->_function;
jhnwkmn 0:97a4f8cc534c 978 if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
jhnwkmn 0:97a4f8cc534c 979 continue;
jhnwkmn 0:97a4f8cc534c 980 }
jhnwkmn 0:97a4f8cc534c 981 case _OP_YIELD:{
jhnwkmn 0:97a4f8cc534c 982 if(ci->_generator) {
jhnwkmn 0:97a4f8cc534c 983 if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
jhnwkmn 0:97a4f8cc534c 984 _GUARD(ci->_generator->Yield(this,arg2));
jhnwkmn 0:97a4f8cc534c 985 traps -= ci->_etraps;
jhnwkmn 0:97a4f8cc534c 986 if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg;
jhnwkmn 0:97a4f8cc534c 987 }
jhnwkmn 0:97a4f8cc534c 988 else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}
jhnwkmn 0:97a4f8cc534c 989 if(Return(arg0, arg1, temp_reg)){
jhnwkmn 0:97a4f8cc534c 990 assert(traps == 0);
jhnwkmn 0:97a4f8cc534c 991 outres = temp_reg;
jhnwkmn 0:97a4f8cc534c 992 return true;
jhnwkmn 0:97a4f8cc534c 993 }
jhnwkmn 0:97a4f8cc534c 994
jhnwkmn 0:97a4f8cc534c 995 }
jhnwkmn 0:97a4f8cc534c 996 continue;
jhnwkmn 0:97a4f8cc534c 997 case _OP_RESUME:
jhnwkmn 0:97a4f8cc534c 998 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 999 _GUARD(_generator(STK(arg1))->Resume(this, TARGET));
jhnwkmn 0:97a4f8cc534c 1000 traps += ci->_etraps;
jhnwkmn 0:97a4f8cc534c 1001 continue;
jhnwkmn 0:97a4f8cc534c 1002 case _OP_FOREACH:{ int tojump;
jhnwkmn 0:97a4f8cc534c 1003 _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
jhnwkmn 0:97a4f8cc534c 1004 ci->_ip += tojump; }
jhnwkmn 0:97a4f8cc534c 1005 continue;
jhnwkmn 0:97a4f8cc534c 1006 case _OP_POSTFOREACH:
jhnwkmn 0:97a4f8cc534c 1007 assert(type(STK(arg0)) == OT_GENERATOR);
jhnwkmn 0:97a4f8cc534c 1008 if(_generator(STK(arg0))->_state == SQGenerator::eDead)
jhnwkmn 0:97a4f8cc534c 1009 ci->_ip += (sarg1 - 1);
jhnwkmn 0:97a4f8cc534c 1010 continue;
jhnwkmn 0:97a4f8cc534c 1011 case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
jhnwkmn 0:97a4f8cc534c 1012 case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
jhnwkmn 0:97a4f8cc534c 1013 case _OP_PUSHTRAP:{
jhnwkmn 0:97a4f8cc534c 1014 SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
jhnwkmn 0:97a4f8cc534c 1015 _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
jhnwkmn 0:97a4f8cc534c 1016 ci->_etraps++;
jhnwkmn 0:97a4f8cc534c 1017 }
jhnwkmn 0:97a4f8cc534c 1018 continue;
jhnwkmn 0:97a4f8cc534c 1019 case _OP_POPTRAP: {
jhnwkmn 0:97a4f8cc534c 1020 for(SQInteger i = 0; i < arg0; i++) {
jhnwkmn 0:97a4f8cc534c 1021 _etraps.pop_back(); traps--;
jhnwkmn 0:97a4f8cc534c 1022 ci->_etraps--;
jhnwkmn 0:97a4f8cc534c 1023 }
jhnwkmn 0:97a4f8cc534c 1024 }
jhnwkmn 0:97a4f8cc534c 1025 continue;
jhnwkmn 0:97a4f8cc534c 1026 case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;
jhnwkmn 0:97a4f8cc534c 1027 case _OP_NEWSLOTA:
jhnwkmn 0:97a4f8cc534c 1028 _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 1029 continue;
jhnwkmn 0:97a4f8cc534c 1030 case _OP_GETBASE:{
jhnwkmn 0:97a4f8cc534c 1031 SQClosure *clo = _closure(ci->_closure);
jhnwkmn 0:97a4f8cc534c 1032 if(clo->_base) {
jhnwkmn 0:97a4f8cc534c 1033 TARGET = clo->_base;
jhnwkmn 0:97a4f8cc534c 1034 }
jhnwkmn 0:97a4f8cc534c 1035 else {
jhnwkmn 0:97a4f8cc534c 1036 TARGET.Null();
jhnwkmn 0:97a4f8cc534c 1037 }
jhnwkmn 0:97a4f8cc534c 1038 continue;
jhnwkmn 0:97a4f8cc534c 1039 }
jhnwkmn 0:97a4f8cc534c 1040 case _OP_CLOSE:
jhnwkmn 0:97a4f8cc534c 1041 if(_openouters) CloseOuters(&(STK(arg1)));
jhnwkmn 0:97a4f8cc534c 1042 continue;
jhnwkmn 0:97a4f8cc534c 1043 }
jhnwkmn 0:97a4f8cc534c 1044
jhnwkmn 0:97a4f8cc534c 1045 }
jhnwkmn 0:97a4f8cc534c 1046 }
jhnwkmn 0:97a4f8cc534c 1047 exception_trap:
jhnwkmn 0:97a4f8cc534c 1048 {
jhnwkmn 0:97a4f8cc534c 1049 SQObjectPtr currerror = _lasterror;
jhnwkmn 0:97a4f8cc534c 1050 // dumpstack(_stackbase);
jhnwkmn 0:97a4f8cc534c 1051 // SQInteger n = 0;
jhnwkmn 0:97a4f8cc534c 1052 SQInteger last_top = _top;
jhnwkmn 0:97a4f8cc534c 1053
jhnwkmn 0:97a4f8cc534c 1054 if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
jhnwkmn 0:97a4f8cc534c 1055
jhnwkmn 0:97a4f8cc534c 1056 while( ci ) {
jhnwkmn 0:97a4f8cc534c 1057 if(ci->_etraps > 0) {
jhnwkmn 0:97a4f8cc534c 1058 SQExceptionTrap &et = _etraps.top();
jhnwkmn 0:97a4f8cc534c 1059 ci->_ip = et._ip;
jhnwkmn 0:97a4f8cc534c 1060 _top = et._stacksize;
jhnwkmn 0:97a4f8cc534c 1061 _stackbase = et._stackbase;
jhnwkmn 0:97a4f8cc534c 1062 _stack._vals[_stackbase + et._extarget] = currerror;
jhnwkmn 0:97a4f8cc534c 1063 _etraps.pop_back(); traps--; ci->_etraps--;
jhnwkmn 0:97a4f8cc534c 1064 while(last_top >= _top) _stack._vals[last_top--].Null();
jhnwkmn 0:97a4f8cc534c 1065 goto exception_restore;
jhnwkmn 0:97a4f8cc534c 1066 }
jhnwkmn 0:97a4f8cc534c 1067 else if (_debughook) {
jhnwkmn 0:97a4f8cc534c 1068 //notify debugger of a "return"
jhnwkmn 0:97a4f8cc534c 1069 //even if it really an exception unwinding the stack
jhnwkmn 0:97a4f8cc534c 1070 for(SQInteger i = 0; i < ci->_ncalls; i++) {
jhnwkmn 0:97a4f8cc534c 1071 CallDebugHook(_SC('r'));
jhnwkmn 0:97a4f8cc534c 1072 }
jhnwkmn 0:97a4f8cc534c 1073 }
jhnwkmn 0:97a4f8cc534c 1074 if(ci->_generator) ci->_generator->Kill();
jhnwkmn 0:97a4f8cc534c 1075 bool mustbreak = ci && ci->_root;
jhnwkmn 0:97a4f8cc534c 1076 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1077 if(mustbreak) break;
jhnwkmn 0:97a4f8cc534c 1078 }
jhnwkmn 0:97a4f8cc534c 1079
jhnwkmn 0:97a4f8cc534c 1080 _lasterror = currerror;
jhnwkmn 0:97a4f8cc534c 1081 return false;
jhnwkmn 0:97a4f8cc534c 1082 }
jhnwkmn 0:97a4f8cc534c 1083 assert(0);
jhnwkmn 0:97a4f8cc534c 1084 }
jhnwkmn 0:97a4f8cc534c 1085
jhnwkmn 0:97a4f8cc534c 1086 bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
jhnwkmn 0:97a4f8cc534c 1087 {
jhnwkmn 0:97a4f8cc534c 1088 inst = theclass->CreateInstance();
jhnwkmn 0:97a4f8cc534c 1089 if(!theclass->GetConstructor(constructor)) {
jhnwkmn 0:97a4f8cc534c 1090 constructor.Null();
jhnwkmn 0:97a4f8cc534c 1091 }
jhnwkmn 0:97a4f8cc534c 1092 return true;
jhnwkmn 0:97a4f8cc534c 1093 }
jhnwkmn 0:97a4f8cc534c 1094
jhnwkmn 0:97a4f8cc534c 1095 void SQVM::CallErrorHandler(SQObjectPtr &error)
jhnwkmn 0:97a4f8cc534c 1096 {
jhnwkmn 0:97a4f8cc534c 1097 if(type(_errorhandler) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1098 SQObjectPtr out;
jhnwkmn 0:97a4f8cc534c 1099 Push(_roottable); Push(error);
jhnwkmn 0:97a4f8cc534c 1100 Call(_errorhandler, 2, _top-2, out,SQFalse);
jhnwkmn 0:97a4f8cc534c 1101 Pop(2);
jhnwkmn 0:97a4f8cc534c 1102 }
jhnwkmn 0:97a4f8cc534c 1103 }
jhnwkmn 0:97a4f8cc534c 1104
jhnwkmn 0:97a4f8cc534c 1105
jhnwkmn 0:97a4f8cc534c 1106 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
jhnwkmn 0:97a4f8cc534c 1107 {
jhnwkmn 0:97a4f8cc534c 1108 _debughook = false;
jhnwkmn 0:97a4f8cc534c 1109 SQFunctionProto *func=_closure(ci->_closure)->_function;
jhnwkmn 0:97a4f8cc534c 1110 if(_debughook_native) {
jhnwkmn 0:97a4f8cc534c 1111 const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
jhnwkmn 0:97a4f8cc534c 1112 const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
jhnwkmn 0:97a4f8cc534c 1113 SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
jhnwkmn 0:97a4f8cc534c 1114 _debughook_native(this,type,src,line,fname);
jhnwkmn 0:97a4f8cc534c 1115 }
jhnwkmn 0:97a4f8cc534c 1116 else {
jhnwkmn 0:97a4f8cc534c 1117 SQObjectPtr temp_reg;
jhnwkmn 0:97a4f8cc534c 1118 SQInteger nparams=5;
jhnwkmn 0:97a4f8cc534c 1119 Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
jhnwkmn 0:97a4f8cc534c 1120 Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);
jhnwkmn 0:97a4f8cc534c 1121 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1122 }
jhnwkmn 0:97a4f8cc534c 1123 _debughook = true;
jhnwkmn 0:97a4f8cc534c 1124 }
jhnwkmn 0:97a4f8cc534c 1125
jhnwkmn 0:97a4f8cc534c 1126 bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
jhnwkmn 0:97a4f8cc534c 1127 {
jhnwkmn 0:97a4f8cc534c 1128 SQInteger nparamscheck = nclosure->_nparamscheck;
jhnwkmn 0:97a4f8cc534c 1129 SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
jhnwkmn 0:97a4f8cc534c 1130
jhnwkmn 0:97a4f8cc534c 1131 if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
jhnwkmn 0:97a4f8cc534c 1132 Raise_Error(_SC("Native stack overflow"));
jhnwkmn 0:97a4f8cc534c 1133 return false;
jhnwkmn 0:97a4f8cc534c 1134 }
jhnwkmn 0:97a4f8cc534c 1135
jhnwkmn 0:97a4f8cc534c 1136 if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
jhnwkmn 0:97a4f8cc534c 1137 ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
jhnwkmn 0:97a4f8cc534c 1138 {
jhnwkmn 0:97a4f8cc534c 1139 Raise_Error(_SC("wrong number of parameters"));
jhnwkmn 0:97a4f8cc534c 1140 return false;
jhnwkmn 0:97a4f8cc534c 1141 }
jhnwkmn 0:97a4f8cc534c 1142
jhnwkmn 0:97a4f8cc534c 1143 SQInteger tcs;
jhnwkmn 0:97a4f8cc534c 1144 SQIntVec &tc = nclosure->_typecheck;
jhnwkmn 0:97a4f8cc534c 1145 if((tcs = tc.size())) {
jhnwkmn 0:97a4f8cc534c 1146 for(SQInteger i = 0; i < nargs && i < tcs; i++) {
jhnwkmn 0:97a4f8cc534c 1147 if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
jhnwkmn 0:97a4f8cc534c 1148 Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
jhnwkmn 0:97a4f8cc534c 1149 return false;
jhnwkmn 0:97a4f8cc534c 1150 }
jhnwkmn 0:97a4f8cc534c 1151 }
jhnwkmn 0:97a4f8cc534c 1152 }
jhnwkmn 0:97a4f8cc534c 1153
jhnwkmn 0:97a4f8cc534c 1154 if(!EnterFrame(newbase, newtop, false)) return false;
jhnwkmn 0:97a4f8cc534c 1155 ci->_closure = nclosure;
jhnwkmn 0:97a4f8cc534c 1156
jhnwkmn 0:97a4f8cc534c 1157 SQInteger outers = nclosure->_noutervalues;
jhnwkmn 0:97a4f8cc534c 1158 for (SQInteger i = 0; i < outers; i++) {
jhnwkmn 0:97a4f8cc534c 1159 _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
jhnwkmn 0:97a4f8cc534c 1160 }
jhnwkmn 0:97a4f8cc534c 1161 if(nclosure->_env) {
jhnwkmn 0:97a4f8cc534c 1162 _stack._vals[newbase] = nclosure->_env->_obj;
jhnwkmn 0:97a4f8cc534c 1163 }
jhnwkmn 0:97a4f8cc534c 1164
jhnwkmn 0:97a4f8cc534c 1165 _nnativecalls++;
jhnwkmn 0:97a4f8cc534c 1166 SQInteger ret = (nclosure->_function)(this);
jhnwkmn 0:97a4f8cc534c 1167 _nnativecalls--;
jhnwkmn 0:97a4f8cc534c 1168
jhnwkmn 0:97a4f8cc534c 1169 suspend = false;
jhnwkmn 0:97a4f8cc534c 1170 if (ret == SQ_SUSPEND_FLAG) {
jhnwkmn 0:97a4f8cc534c 1171 suspend = true;
jhnwkmn 0:97a4f8cc534c 1172 }
jhnwkmn 0:97a4f8cc534c 1173 else if (ret < 0) {
jhnwkmn 0:97a4f8cc534c 1174 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1175 Raise_Error(_lasterror);
jhnwkmn 0:97a4f8cc534c 1176 return false;
jhnwkmn 0:97a4f8cc534c 1177 }
jhnwkmn 0:97a4f8cc534c 1178 if(ret) {
jhnwkmn 0:97a4f8cc534c 1179 retval = _stack._vals[_top-1];
jhnwkmn 0:97a4f8cc534c 1180 }
jhnwkmn 0:97a4f8cc534c 1181 else {
jhnwkmn 0:97a4f8cc534c 1182 retval.Null();
jhnwkmn 0:97a4f8cc534c 1183 }
jhnwkmn 0:97a4f8cc534c 1184 //retval = ret ? _stack._vals[_top-1] : _null_;
jhnwkmn 0:97a4f8cc534c 1185 LeaveFrame();
jhnwkmn 0:97a4f8cc534c 1186 return true;
jhnwkmn 0:97a4f8cc534c 1187 }
jhnwkmn 0:97a4f8cc534c 1188
jhnwkmn 0:97a4f8cc534c 1189 #define FALLBACK_OK 0
jhnwkmn 0:97a4f8cc534c 1190 #define FALLBACK_NO_MATCH 1
jhnwkmn 0:97a4f8cc534c 1191 #define FALLBACK_ERROR 2
jhnwkmn 0:97a4f8cc534c 1192
jhnwkmn 0:97a4f8cc534c 1193 bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx)
jhnwkmn 0:97a4f8cc534c 1194 {
jhnwkmn 0:97a4f8cc534c 1195 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1196 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1197 if(_table(self)->Get(key,dest))return true;
jhnwkmn 0:97a4f8cc534c 1198 break;
jhnwkmn 0:97a4f8cc534c 1199 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1200 if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; }
jhnwkmn 0:97a4f8cc534c 1201 break;
jhnwkmn 0:97a4f8cc534c 1202 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1203 if(_instance(self)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1204 break;
jhnwkmn 0:97a4f8cc534c 1205 case OT_CLASS:
jhnwkmn 0:97a4f8cc534c 1206 if(_class(self)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1207 break;
jhnwkmn 0:97a4f8cc534c 1208 case OT_STRING:
jhnwkmn 0:97a4f8cc534c 1209 if(sq_isnumeric(key)){
jhnwkmn 0:97a4f8cc534c 1210 SQInteger n = tointeger(key);
jhnwkmn 0:97a4f8cc534c 1211 if(abs((int)n) < _string(self)->_len) {
jhnwkmn 0:97a4f8cc534c 1212 if(n < 0) n = _string(self)->_len - n;
jhnwkmn 0:97a4f8cc534c 1213 dest = SQInteger(_stringval(self)[n]);
jhnwkmn 0:97a4f8cc534c 1214 return true;
jhnwkmn 0:97a4f8cc534c 1215 }
jhnwkmn 0:97a4f8cc534c 1216 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1217 return false;
jhnwkmn 0:97a4f8cc534c 1218 }
jhnwkmn 0:97a4f8cc534c 1219 break;
jhnwkmn 0:97a4f8cc534c 1220 default:break; //shut up compiler
jhnwkmn 0:97a4f8cc534c 1221 }
jhnwkmn 0:97a4f8cc534c 1222 if(!raw) {
jhnwkmn 0:97a4f8cc534c 1223 switch(FallBackGet(self,key,dest)) {
jhnwkmn 0:97a4f8cc534c 1224 case FALLBACK_OK: return true; //okie
jhnwkmn 0:97a4f8cc534c 1225 case FALLBACK_NO_MATCH: break; //keep falling back
jhnwkmn 0:97a4f8cc534c 1226 case FALLBACK_ERROR: return false; // the metamethod failed
jhnwkmn 0:97a4f8cc534c 1227 }
jhnwkmn 0:97a4f8cc534c 1228 if(InvokeDefaultDelegate(self,key,dest)) {
jhnwkmn 0:97a4f8cc534c 1229 return true;
jhnwkmn 0:97a4f8cc534c 1230 }
jhnwkmn 0:97a4f8cc534c 1231 }
jhnwkmn 0:97a4f8cc534c 1232 //#ifdef ROOT_FALLBACK
jhnwkmn 0:97a4f8cc534c 1233 if(selfidx == 0) {
jhnwkmn 0:97a4f8cc534c 1234 if(_table(_roottable)->Get(key,dest)) return true;
jhnwkmn 0:97a4f8cc534c 1235 }
jhnwkmn 0:97a4f8cc534c 1236 //#endif
jhnwkmn 0:97a4f8cc534c 1237 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1238 return false;
jhnwkmn 0:97a4f8cc534c 1239 }
jhnwkmn 0:97a4f8cc534c 1240
jhnwkmn 0:97a4f8cc534c 1241 bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 1242 {
jhnwkmn 0:97a4f8cc534c 1243 SQTable *ddel = NULL;
jhnwkmn 0:97a4f8cc534c 1244 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1245 case OT_CLASS: ddel = _class_ddel; break;
jhnwkmn 0:97a4f8cc534c 1246 case OT_TABLE: ddel = _table_ddel; break;
jhnwkmn 0:97a4f8cc534c 1247 case OT_ARRAY: ddel = _array_ddel; break;
jhnwkmn 0:97a4f8cc534c 1248 case OT_STRING: ddel = _string_ddel; break;
jhnwkmn 0:97a4f8cc534c 1249 case OT_INSTANCE: ddel = _instance_ddel; break;
jhnwkmn 0:97a4f8cc534c 1250 case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
jhnwkmn 0:97a4f8cc534c 1251 case OT_GENERATOR: ddel = _generator_ddel; break;
jhnwkmn 0:97a4f8cc534c 1252 case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;
jhnwkmn 0:97a4f8cc534c 1253 case OT_THREAD: ddel = _thread_ddel; break;
jhnwkmn 0:97a4f8cc534c 1254 case OT_WEAKREF: ddel = _weakref_ddel; break;
jhnwkmn 0:97a4f8cc534c 1255 default: return false;
jhnwkmn 0:97a4f8cc534c 1256 }
jhnwkmn 0:97a4f8cc534c 1257 return ddel->Get(key,dest);
jhnwkmn 0:97a4f8cc534c 1258 }
jhnwkmn 0:97a4f8cc534c 1259
jhnwkmn 0:97a4f8cc534c 1260
jhnwkmn 0:97a4f8cc534c 1261 SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
jhnwkmn 0:97a4f8cc534c 1262 {
jhnwkmn 0:97a4f8cc534c 1263 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1264 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1265 case OT_USERDATA:
jhnwkmn 0:97a4f8cc534c 1266 //delegation
jhnwkmn 0:97a4f8cc534c 1267 if(_delegable(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1268 if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1269 }
jhnwkmn 0:97a4f8cc534c 1270 else {
jhnwkmn 0:97a4f8cc534c 1271 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1272 }
jhnwkmn 0:97a4f8cc534c 1273 //go through
jhnwkmn 0:97a4f8cc534c 1274 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1275 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1276 if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
jhnwkmn 0:97a4f8cc534c 1277 Push(self);Push(key);
jhnwkmn 0:97a4f8cc534c 1278 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1279 AutoDec ad(&_nmetamethodscall);
jhnwkmn 0:97a4f8cc534c 1280 if(Call(closure, 2, _top - 2, dest, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1281 Pop(2);
jhnwkmn 0:97a4f8cc534c 1282 return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1283 }
jhnwkmn 0:97a4f8cc534c 1284 else {
jhnwkmn 0:97a4f8cc534c 1285 Pop(2);
jhnwkmn 0:97a4f8cc534c 1286 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
jhnwkmn 0:97a4f8cc534c 1287 return FALLBACK_ERROR;
jhnwkmn 0:97a4f8cc534c 1288 }
jhnwkmn 0:97a4f8cc534c 1289 }
jhnwkmn 0:97a4f8cc534c 1290 }
jhnwkmn 0:97a4f8cc534c 1291 }
jhnwkmn 0:97a4f8cc534c 1292 break;
jhnwkmn 0:97a4f8cc534c 1293 default: break;//shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 1294 }
jhnwkmn 0:97a4f8cc534c 1295 // no metamethod or no fallback type
jhnwkmn 0:97a4f8cc534c 1296 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1297 }
jhnwkmn 0:97a4f8cc534c 1298
jhnwkmn 0:97a4f8cc534c 1299 bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)
jhnwkmn 0:97a4f8cc534c 1300 {
jhnwkmn 0:97a4f8cc534c 1301 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1302 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1303 if(_table(self)->Set(key,val)) return true;
jhnwkmn 0:97a4f8cc534c 1304 break;
jhnwkmn 0:97a4f8cc534c 1305 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1306 if(_instance(self)->Set(key,val)) return true;
jhnwkmn 0:97a4f8cc534c 1307 break;
jhnwkmn 0:97a4f8cc534c 1308 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1309 if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
jhnwkmn 0:97a4f8cc534c 1310 if(!_array(self)->Set(tointeger(key),val)) {
jhnwkmn 0:97a4f8cc534c 1311 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1312 return false;
jhnwkmn 0:97a4f8cc534c 1313 }
jhnwkmn 0:97a4f8cc534c 1314 return true;
jhnwkmn 0:97a4f8cc534c 1315 default:
jhnwkmn 0:97a4f8cc534c 1316 Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1317 return false;
jhnwkmn 0:97a4f8cc534c 1318 }
jhnwkmn 0:97a4f8cc534c 1319
jhnwkmn 0:97a4f8cc534c 1320 switch(FallBackSet(self,key,val)) {
jhnwkmn 0:97a4f8cc534c 1321 case FALLBACK_OK: return true; //okie
jhnwkmn 0:97a4f8cc534c 1322 case FALLBACK_NO_MATCH: break; //keep falling back
jhnwkmn 0:97a4f8cc534c 1323 case FALLBACK_ERROR: return false; // the metamethod failed
jhnwkmn 0:97a4f8cc534c 1324 }
jhnwkmn 0:97a4f8cc534c 1325 if(selfidx == 0) {
jhnwkmn 0:97a4f8cc534c 1326 if(_table(_roottable)->Set(key,val))
jhnwkmn 0:97a4f8cc534c 1327 return true;
jhnwkmn 0:97a4f8cc534c 1328 }
jhnwkmn 0:97a4f8cc534c 1329 Raise_IdxError(key);
jhnwkmn 0:97a4f8cc534c 1330 return false;
jhnwkmn 0:97a4f8cc534c 1331 }
jhnwkmn 0:97a4f8cc534c 1332
jhnwkmn 0:97a4f8cc534c 1333 SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
jhnwkmn 0:97a4f8cc534c 1334 {
jhnwkmn 0:97a4f8cc534c 1335 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1336 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1337 if(_table(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1338 if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1339 }
jhnwkmn 0:97a4f8cc534c 1340 //keps on going
jhnwkmn 0:97a4f8cc534c 1341 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1342 case OT_USERDATA:{
jhnwkmn 0:97a4f8cc534c 1343 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1344 SQObjectPtr t;
jhnwkmn 0:97a4f8cc534c 1345 if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
jhnwkmn 0:97a4f8cc534c 1346 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1347 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1348 AutoDec ad(&_nmetamethodscall);
jhnwkmn 0:97a4f8cc534c 1349 if(Call(closure, 3, _top - 3, t, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1350 Pop(3);
jhnwkmn 0:97a4f8cc534c 1351 return FALLBACK_OK;
jhnwkmn 0:97a4f8cc534c 1352 }
jhnwkmn 0:97a4f8cc534c 1353 else {
jhnwkmn 0:97a4f8cc534c 1354 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
jhnwkmn 0:97a4f8cc534c 1355 //error
jhnwkmn 0:97a4f8cc534c 1356 Pop(3);
jhnwkmn 0:97a4f8cc534c 1357 return FALLBACK_ERROR;
jhnwkmn 0:97a4f8cc534c 1358 }
jhnwkmn 0:97a4f8cc534c 1359 }
jhnwkmn 0:97a4f8cc534c 1360 }
jhnwkmn 0:97a4f8cc534c 1361 }
jhnwkmn 0:97a4f8cc534c 1362 break;
jhnwkmn 0:97a4f8cc534c 1363 default: break;//shutup GCC 4.x
jhnwkmn 0:97a4f8cc534c 1364 }
jhnwkmn 0:97a4f8cc534c 1365 // no metamethod or no fallback type
jhnwkmn 0:97a4f8cc534c 1366 return FALLBACK_NO_MATCH;
jhnwkmn 0:97a4f8cc534c 1367 }
jhnwkmn 0:97a4f8cc534c 1368
jhnwkmn 0:97a4f8cc534c 1369 bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
jhnwkmn 0:97a4f8cc534c 1370 {
jhnwkmn 0:97a4f8cc534c 1371 SQObjectPtr temp_reg;
jhnwkmn 0:97a4f8cc534c 1372 SQObjectPtr newobj;
jhnwkmn 0:97a4f8cc534c 1373 switch(type(self)){
jhnwkmn 0:97a4f8cc534c 1374 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1375 newobj = _table(self)->Clone();
jhnwkmn 0:97a4f8cc534c 1376 goto cloned_mt;
jhnwkmn 0:97a4f8cc534c 1377 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1378 newobj = _instance(self)->Clone(_ss(this));
jhnwkmn 0:97a4f8cc534c 1379 cloned_mt:
jhnwkmn 0:97a4f8cc534c 1380 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1381 if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
jhnwkmn 0:97a4f8cc534c 1382 Push(newobj);
jhnwkmn 0:97a4f8cc534c 1383 Push(self);
jhnwkmn 0:97a4f8cc534c 1384 if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
jhnwkmn 0:97a4f8cc534c 1385 return false;
jhnwkmn 0:97a4f8cc534c 1386 }
jhnwkmn 0:97a4f8cc534c 1387 }
jhnwkmn 0:97a4f8cc534c 1388 target = newobj;
jhnwkmn 0:97a4f8cc534c 1389 return true;
jhnwkmn 0:97a4f8cc534c 1390 case OT_ARRAY:
jhnwkmn 0:97a4f8cc534c 1391 target = _array(self)->Clone();
jhnwkmn 0:97a4f8cc534c 1392 return true;
jhnwkmn 0:97a4f8cc534c 1393 default:
jhnwkmn 0:97a4f8cc534c 1394 Raise_Error(_SC("cloning a %s"), GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1395 return false;
jhnwkmn 0:97a4f8cc534c 1396 }
jhnwkmn 0:97a4f8cc534c 1397 }
jhnwkmn 0:97a4f8cc534c 1398
jhnwkmn 0:97a4f8cc534c 1399 bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw)
jhnwkmn 0:97a4f8cc534c 1400 {
jhnwkmn 0:97a4f8cc534c 1401 if(type(self) != OT_CLASS) {
jhnwkmn 0:97a4f8cc534c 1402 Raise_Error(_SC("object must be a class"));
jhnwkmn 0:97a4f8cc534c 1403 return false;
jhnwkmn 0:97a4f8cc534c 1404 }
jhnwkmn 0:97a4f8cc534c 1405 SQClass *c = _class(self);
jhnwkmn 0:97a4f8cc534c 1406 if(!raw) {
jhnwkmn 0:97a4f8cc534c 1407 SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
jhnwkmn 0:97a4f8cc534c 1408 if(type(mm) != OT_NULL ) {
jhnwkmn 0:97a4f8cc534c 1409 Push(self); Push(key); Push(val);
jhnwkmn 0:97a4f8cc534c 1410 Push(attrs);
jhnwkmn 0:97a4f8cc534c 1411 Push(bstatic);
jhnwkmn 0:97a4f8cc534c 1412 return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);
jhnwkmn 0:97a4f8cc534c 1413 }
jhnwkmn 0:97a4f8cc534c 1414 }
jhnwkmn 0:97a4f8cc534c 1415 if(!NewSlot(self, key, val,bstatic))
jhnwkmn 0:97a4f8cc534c 1416 return false;
jhnwkmn 0:97a4f8cc534c 1417 if(type(attrs) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1418 c->SetAttributes(key,attrs);
jhnwkmn 0:97a4f8cc534c 1419 }
jhnwkmn 0:97a4f8cc534c 1420 return true;
jhnwkmn 0:97a4f8cc534c 1421 }
jhnwkmn 0:97a4f8cc534c 1422
jhnwkmn 0:97a4f8cc534c 1423 bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
jhnwkmn 0:97a4f8cc534c 1424 {
jhnwkmn 0:97a4f8cc534c 1425 if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
jhnwkmn 0:97a4f8cc534c 1426 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1427 case OT_TABLE: {
jhnwkmn 0:97a4f8cc534c 1428 bool rawcall = true;
jhnwkmn 0:97a4f8cc534c 1429 if(_table(self)->_delegate) {
jhnwkmn 0:97a4f8cc534c 1430 SQObjectPtr res;
jhnwkmn 0:97a4f8cc534c 1431 if(!_table(self)->Get(key,res)) {
jhnwkmn 0:97a4f8cc534c 1432 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1433 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1434 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1435 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
jhnwkmn 0:97a4f8cc534c 1436 return false;
jhnwkmn 0:97a4f8cc534c 1437 }
jhnwkmn 0:97a4f8cc534c 1438 rawcall = false;
jhnwkmn 0:97a4f8cc534c 1439 }
jhnwkmn 0:97a4f8cc534c 1440 else {
jhnwkmn 0:97a4f8cc534c 1441 rawcall = true;
jhnwkmn 0:97a4f8cc534c 1442 }
jhnwkmn 0:97a4f8cc534c 1443 }
jhnwkmn 0:97a4f8cc534c 1444 }
jhnwkmn 0:97a4f8cc534c 1445 if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
jhnwkmn 0:97a4f8cc534c 1446
jhnwkmn 0:97a4f8cc534c 1447 break;}
jhnwkmn 0:97a4f8cc534c 1448 case OT_INSTANCE: {
jhnwkmn 0:97a4f8cc534c 1449 SQObjectPtr res;
jhnwkmn 0:97a4f8cc534c 1450 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1451 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1452 Push(self);Push(key);Push(val);
jhnwkmn 0:97a4f8cc534c 1453 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
jhnwkmn 0:97a4f8cc534c 1454 return false;
jhnwkmn 0:97a4f8cc534c 1455 }
jhnwkmn 0:97a4f8cc534c 1456 break;
jhnwkmn 0:97a4f8cc534c 1457 }
jhnwkmn 0:97a4f8cc534c 1458 Raise_Error(_SC("class instances do not support the new slot operator"));
jhnwkmn 0:97a4f8cc534c 1459 return false;
jhnwkmn 0:97a4f8cc534c 1460 break;}
jhnwkmn 0:97a4f8cc534c 1461 case OT_CLASS:
jhnwkmn 0:97a4f8cc534c 1462 if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
jhnwkmn 0:97a4f8cc534c 1463 if(_class(self)->_locked) {
jhnwkmn 0:97a4f8cc534c 1464 Raise_Error(_SC("trying to modify a class that has already been instantiated"));
jhnwkmn 0:97a4f8cc534c 1465 return false;
jhnwkmn 0:97a4f8cc534c 1466 }
jhnwkmn 0:97a4f8cc534c 1467 else {
jhnwkmn 0:97a4f8cc534c 1468 SQObjectPtr oval = PrintObjVal(key);
jhnwkmn 0:97a4f8cc534c 1469 Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
jhnwkmn 0:97a4f8cc534c 1470 return false;
jhnwkmn 0:97a4f8cc534c 1471 }
jhnwkmn 0:97a4f8cc534c 1472 }
jhnwkmn 0:97a4f8cc534c 1473 break;
jhnwkmn 0:97a4f8cc534c 1474 default:
jhnwkmn 0:97a4f8cc534c 1475 Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
jhnwkmn 0:97a4f8cc534c 1476 return false;
jhnwkmn 0:97a4f8cc534c 1477 break;
jhnwkmn 0:97a4f8cc534c 1478 }
jhnwkmn 0:97a4f8cc534c 1479 return true;
jhnwkmn 0:97a4f8cc534c 1480 }
jhnwkmn 0:97a4f8cc534c 1481
jhnwkmn 0:97a4f8cc534c 1482
jhnwkmn 0:97a4f8cc534c 1483
jhnwkmn 0:97a4f8cc534c 1484 bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)
jhnwkmn 0:97a4f8cc534c 1485 {
jhnwkmn 0:97a4f8cc534c 1486 switch(type(self)) {
jhnwkmn 0:97a4f8cc534c 1487 case OT_TABLE:
jhnwkmn 0:97a4f8cc534c 1488 case OT_INSTANCE:
jhnwkmn 0:97a4f8cc534c 1489 case OT_USERDATA: {
jhnwkmn 0:97a4f8cc534c 1490 SQObjectPtr t;
jhnwkmn 0:97a4f8cc534c 1491 //bool handled = false;
jhnwkmn 0:97a4f8cc534c 1492 SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1493 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
jhnwkmn 0:97a4f8cc534c 1494 Push(self);Push(key);
jhnwkmn 0:97a4f8cc534c 1495 return CallMetaMethod(closure,MT_DELSLOT,2,res);
jhnwkmn 0:97a4f8cc534c 1496 }
jhnwkmn 0:97a4f8cc534c 1497 else {
jhnwkmn 0:97a4f8cc534c 1498 if(type(self) == OT_TABLE) {
jhnwkmn 0:97a4f8cc534c 1499 if(_table(self)->Get(key,t)) {
jhnwkmn 0:97a4f8cc534c 1500 _table(self)->Remove(key);
jhnwkmn 0:97a4f8cc534c 1501 }
jhnwkmn 0:97a4f8cc534c 1502 else {
jhnwkmn 0:97a4f8cc534c 1503 Raise_IdxError((SQObject &)key);
jhnwkmn 0:97a4f8cc534c 1504 return false;
jhnwkmn 0:97a4f8cc534c 1505 }
jhnwkmn 0:97a4f8cc534c 1506 }
jhnwkmn 0:97a4f8cc534c 1507 else {
jhnwkmn 0:97a4f8cc534c 1508 Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1509 return false;
jhnwkmn 0:97a4f8cc534c 1510 }
jhnwkmn 0:97a4f8cc534c 1511 }
jhnwkmn 0:97a4f8cc534c 1512 res = t;
jhnwkmn 0:97a4f8cc534c 1513 }
jhnwkmn 0:97a4f8cc534c 1514 break;
jhnwkmn 0:97a4f8cc534c 1515 default:
jhnwkmn 0:97a4f8cc534c 1516 Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
jhnwkmn 0:97a4f8cc534c 1517 return false;
jhnwkmn 0:97a4f8cc534c 1518 }
jhnwkmn 0:97a4f8cc534c 1519 return true;
jhnwkmn 0:97a4f8cc534c 1520 }
jhnwkmn 0:97a4f8cc534c 1521
jhnwkmn 0:97a4f8cc534c 1522 bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
jhnwkmn 0:97a4f8cc534c 1523 {
jhnwkmn 0:97a4f8cc534c 1524 #ifdef _DEBUG
jhnwkmn 0:97a4f8cc534c 1525 SQInteger prevstackbase = _stackbase;
jhnwkmn 0:97a4f8cc534c 1526 #endif
jhnwkmn 0:97a4f8cc534c 1527 switch(type(closure)) {
jhnwkmn 0:97a4f8cc534c 1528 case OT_CLOSURE:
jhnwkmn 0:97a4f8cc534c 1529 return Execute(closure, nparams, stackbase, outres, raiseerror);
jhnwkmn 0:97a4f8cc534c 1530 break;
jhnwkmn 0:97a4f8cc534c 1531 case OT_NATIVECLOSURE:{
jhnwkmn 0:97a4f8cc534c 1532 bool suspend;
jhnwkmn 0:97a4f8cc534c 1533 return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
jhnwkmn 0:97a4f8cc534c 1534
jhnwkmn 0:97a4f8cc534c 1535 }
jhnwkmn 0:97a4f8cc534c 1536 break;
jhnwkmn 0:97a4f8cc534c 1537 case OT_CLASS: {
jhnwkmn 0:97a4f8cc534c 1538 SQObjectPtr constr;
jhnwkmn 0:97a4f8cc534c 1539 SQObjectPtr temp;
jhnwkmn 0:97a4f8cc534c 1540 CreateClassInstance(_class(closure),outres,constr);
jhnwkmn 0:97a4f8cc534c 1541 if(type(constr) != OT_NULL) {
jhnwkmn 0:97a4f8cc534c 1542 _stack[stackbase] = outres;
jhnwkmn 0:97a4f8cc534c 1543 return Call(constr,nparams,stackbase,temp,raiseerror);
jhnwkmn 0:97a4f8cc534c 1544 }
jhnwkmn 0:97a4f8cc534c 1545 return true;
jhnwkmn 0:97a4f8cc534c 1546 }
jhnwkmn 0:97a4f8cc534c 1547 break;
jhnwkmn 0:97a4f8cc534c 1548 default:
jhnwkmn 0:97a4f8cc534c 1549 return false;
jhnwkmn 0:97a4f8cc534c 1550 }
jhnwkmn 0:97a4f8cc534c 1551 #ifdef _DEBUG
jhnwkmn 0:97a4f8cc534c 1552 if(!_suspended) {
jhnwkmn 0:97a4f8cc534c 1553 assert(_stackbase == prevstackbase);
jhnwkmn 0:97a4f8cc534c 1554 }
jhnwkmn 0:97a4f8cc534c 1555 #endif
jhnwkmn 0:97a4f8cc534c 1556 return true;
jhnwkmn 0:97a4f8cc534c 1557 }
jhnwkmn 0:97a4f8cc534c 1558
jhnwkmn 0:97a4f8cc534c 1559 bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
jhnwkmn 0:97a4f8cc534c 1560 {
jhnwkmn 0:97a4f8cc534c 1561 //SQObjectPtr closure;
jhnwkmn 0:97a4f8cc534c 1562
jhnwkmn 0:97a4f8cc534c 1563 _nmetamethodscall++;
jhnwkmn 0:97a4f8cc534c 1564 if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
jhnwkmn 0:97a4f8cc534c 1565 _nmetamethodscall--;
jhnwkmn 0:97a4f8cc534c 1566 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1567 return true;
jhnwkmn 0:97a4f8cc534c 1568 }
jhnwkmn 0:97a4f8cc534c 1569 _nmetamethodscall--;
jhnwkmn 0:97a4f8cc534c 1570 //}
jhnwkmn 0:97a4f8cc534c 1571 Pop(nparams);
jhnwkmn 0:97a4f8cc534c 1572 return false;
jhnwkmn 0:97a4f8cc534c 1573 }
jhnwkmn 0:97a4f8cc534c 1574
jhnwkmn 0:97a4f8cc534c 1575 void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
jhnwkmn 0:97a4f8cc534c 1576 {
jhnwkmn 0:97a4f8cc534c 1577 SQOuter **pp = &_openouters;
jhnwkmn 0:97a4f8cc534c 1578 SQOuter *p;
jhnwkmn 0:97a4f8cc534c 1579 SQOuter *otr;
jhnwkmn 0:97a4f8cc534c 1580
jhnwkmn 0:97a4f8cc534c 1581 while ((p = *pp) != NULL && p->_valptr >= stackindex) {
jhnwkmn 0:97a4f8cc534c 1582 if (p->_valptr == stackindex) {
jhnwkmn 0:97a4f8cc534c 1583 target = SQObjectPtr(p);
jhnwkmn 0:97a4f8cc534c 1584 return;
jhnwkmn 0:97a4f8cc534c 1585 }
jhnwkmn 0:97a4f8cc534c 1586 pp = &p->_next;
jhnwkmn 0:97a4f8cc534c 1587 }
jhnwkmn 0:97a4f8cc534c 1588 otr = SQOuter::Create(_ss(this), stackindex);
jhnwkmn 0:97a4f8cc534c 1589 otr->_next = *pp;
jhnwkmn 0:97a4f8cc534c 1590 otr->_idx = (stackindex - _stack._vals);
jhnwkmn 0:97a4f8cc534c 1591 __ObjAddRef(otr);
jhnwkmn 0:97a4f8cc534c 1592 *pp = otr;
jhnwkmn 0:97a4f8cc534c 1593 target = SQObjectPtr(otr);
jhnwkmn 0:97a4f8cc534c 1594 }
jhnwkmn 0:97a4f8cc534c 1595
jhnwkmn 0:97a4f8cc534c 1596 bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)
jhnwkmn 0:97a4f8cc534c 1597 {
jhnwkmn 0:97a4f8cc534c 1598 if( !tailcall ) {
jhnwkmn 0:97a4f8cc534c 1599 if( _callsstacksize == _alloccallsstacksize ) {
jhnwkmn 0:97a4f8cc534c 1600 GrowCallStack();
jhnwkmn 0:97a4f8cc534c 1601 }
jhnwkmn 0:97a4f8cc534c 1602 ci = &_callsstack[_callsstacksize++];
jhnwkmn 0:97a4f8cc534c 1603 ci->_prevstkbase = (SQInt32)(newbase - _stackbase);
jhnwkmn 0:97a4f8cc534c 1604 ci->_prevtop = (SQInt32)(_top - _stackbase);
jhnwkmn 0:97a4f8cc534c 1605 ci->_etraps = 0;
jhnwkmn 0:97a4f8cc534c 1606 ci->_ncalls = 1;
jhnwkmn 0:97a4f8cc534c 1607 ci->_generator = NULL;
jhnwkmn 0:97a4f8cc534c 1608 ci->_root = SQFalse;
jhnwkmn 0:97a4f8cc534c 1609 }
jhnwkmn 0:97a4f8cc534c 1610 else {
jhnwkmn 0:97a4f8cc534c 1611 ci->_ncalls++;
jhnwkmn 0:97a4f8cc534c 1612 }
jhnwkmn 0:97a4f8cc534c 1613
jhnwkmn 0:97a4f8cc534c 1614 _stackbase = newbase;
jhnwkmn 0:97a4f8cc534c 1615 _top = newtop;
jhnwkmn 0:97a4f8cc534c 1616 if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {
jhnwkmn 0:97a4f8cc534c 1617 if(_nmetamethodscall) {
jhnwkmn 0:97a4f8cc534c 1618 Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod"));
jhnwkmn 0:97a4f8cc534c 1619 return false;
jhnwkmn 0:97a4f8cc534c 1620 }
jhnwkmn 0:97a4f8cc534c 1621 _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2));
jhnwkmn 0:97a4f8cc534c 1622 RelocateOuters();
jhnwkmn 0:97a4f8cc534c 1623 }
jhnwkmn 0:97a4f8cc534c 1624 return true;
jhnwkmn 0:97a4f8cc534c 1625 }
jhnwkmn 0:97a4f8cc534c 1626
jhnwkmn 0:97a4f8cc534c 1627 void SQVM::LeaveFrame() {
jhnwkmn 0:97a4f8cc534c 1628 SQInteger last_top = _top;
jhnwkmn 0:97a4f8cc534c 1629 SQInteger last_stackbase = _stackbase;
jhnwkmn 0:97a4f8cc534c 1630 SQInteger css = --_callsstacksize;
jhnwkmn 0:97a4f8cc534c 1631
jhnwkmn 0:97a4f8cc534c 1632 /* First clean out the call stack frame */
jhnwkmn 0:97a4f8cc534c 1633 ci->_closure.Null();
jhnwkmn 0:97a4f8cc534c 1634 _stackbase -= ci->_prevstkbase;
jhnwkmn 0:97a4f8cc534c 1635 _top = _stackbase + ci->_prevtop;
jhnwkmn 0:97a4f8cc534c 1636 ci = (css) ? &_callsstack[css-1] : NULL;
jhnwkmn 0:97a4f8cc534c 1637
jhnwkmn 0:97a4f8cc534c 1638 if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
jhnwkmn 0:97a4f8cc534c 1639 while (last_top >= _top) {
jhnwkmn 0:97a4f8cc534c 1640 _stack._vals[last_top--].Null();
jhnwkmn 0:97a4f8cc534c 1641 }
jhnwkmn 0:97a4f8cc534c 1642 }
jhnwkmn 0:97a4f8cc534c 1643
jhnwkmn 0:97a4f8cc534c 1644 void SQVM::RelocateOuters()
jhnwkmn 0:97a4f8cc534c 1645 {
jhnwkmn 0:97a4f8cc534c 1646 SQOuter *p = _openouters;
jhnwkmn 0:97a4f8cc534c 1647 while (p) {
jhnwkmn 0:97a4f8cc534c 1648 p->_valptr = _stack._vals + p->_idx;
jhnwkmn 0:97a4f8cc534c 1649 p = p->_next;
jhnwkmn 0:97a4f8cc534c 1650 }
jhnwkmn 0:97a4f8cc534c 1651 }
jhnwkmn 0:97a4f8cc534c 1652
jhnwkmn 0:97a4f8cc534c 1653 void SQVM::CloseOuters(SQObjectPtr *stackindex) {
jhnwkmn 0:97a4f8cc534c 1654 SQOuter *p;
jhnwkmn 0:97a4f8cc534c 1655 while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
jhnwkmn 0:97a4f8cc534c 1656 p->_value = *(p->_valptr);
jhnwkmn 0:97a4f8cc534c 1657 p->_valptr = &p->_value;
jhnwkmn 0:97a4f8cc534c 1658 _openouters = p->_next;
jhnwkmn 0:97a4f8cc534c 1659 __ObjRelease(p);
jhnwkmn 0:97a4f8cc534c 1660 }
jhnwkmn 0:97a4f8cc534c 1661 }
jhnwkmn 0:97a4f8cc534c 1662
jhnwkmn 0:97a4f8cc534c 1663 void SQVM::Remove(SQInteger n) {
jhnwkmn 0:97a4f8cc534c 1664 n = (n >= 0)?n + _stackbase - 1:_top + n;
jhnwkmn 0:97a4f8cc534c 1665 for(SQInteger i = n; i < _top; i++){
jhnwkmn 0:97a4f8cc534c 1666 _stack[i] = _stack[i+1];
jhnwkmn 0:97a4f8cc534c 1667 }
jhnwkmn 0:97a4f8cc534c 1668 _stack[_top].Null();
jhnwkmn 0:97a4f8cc534c 1669 _top--;
jhnwkmn 0:97a4f8cc534c 1670 }
jhnwkmn 0:97a4f8cc534c 1671
jhnwkmn 0:97a4f8cc534c 1672 void SQVM::Pop() {
jhnwkmn 0:97a4f8cc534c 1673 _stack[--_top].Null();
jhnwkmn 0:97a4f8cc534c 1674 }
jhnwkmn 0:97a4f8cc534c 1675
jhnwkmn 0:97a4f8cc534c 1676 void SQVM::Pop(SQInteger n) {
jhnwkmn 0:97a4f8cc534c 1677 for(SQInteger i = 0; i < n; i++){
jhnwkmn 0:97a4f8cc534c 1678 _stack[--_top].Null();
jhnwkmn 0:97a4f8cc534c 1679 }
jhnwkmn 0:97a4f8cc534c 1680 }
jhnwkmn 0:97a4f8cc534c 1681
jhnwkmn 0:97a4f8cc534c 1682 void SQVM::PushNull() { _stack[_top++].Null(); }
jhnwkmn 0:97a4f8cc534c 1683 void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }
jhnwkmn 0:97a4f8cc534c 1684 SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }
jhnwkmn 0:97a4f8cc534c 1685 SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }
jhnwkmn 0:97a4f8cc534c 1686 SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; }
jhnwkmn 0:97a4f8cc534c 1687 SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }
jhnwkmn 0:97a4f8cc534c 1688
jhnwkmn 0:97a4f8cc534c 1689 #ifdef _DEBUG_DUMP
jhnwkmn 0:97a4f8cc534c 1690 void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
jhnwkmn 0:97a4f8cc534c 1691 {
jhnwkmn 0:97a4f8cc534c 1692 SQInteger size=dumpall?_stack.size():_top;
jhnwkmn 0:97a4f8cc534c 1693 SQInteger n=0;
jhnwkmn 0:97a4f8cc534c 1694 scprintf(_SC("\n>>>>stack dump<<<<\n"));
jhnwkmn 0:97a4f8cc534c 1695 CallInfo &ci=_callsstack[_callsstacksize-1];
jhnwkmn 0:97a4f8cc534c 1696 scprintf(_SC("IP: %p\n"),ci._ip);
jhnwkmn 0:97a4f8cc534c 1697 scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
jhnwkmn 0:97a4f8cc534c 1698 scprintf(_SC("prev top: %d\n"),ci._prevtop);
jhnwkmn 0:97a4f8cc534c 1699 for(SQInteger i=0;i<size;i++){
jhnwkmn 0:97a4f8cc534c 1700 SQObjectPtr &obj=_stack[i];
jhnwkmn 0:97a4f8cc534c 1701 if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
jhnwkmn 0:97a4f8cc534c 1702 scprintf(_SC("[%d]:"),n);
jhnwkmn 0:97a4f8cc534c 1703 switch(type(obj)){
jhnwkmn 0:97a4f8cc534c 1704 case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
jhnwkmn 0:97a4f8cc534c 1705 case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break;
jhnwkmn 0:97a4f8cc534c 1706 case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
jhnwkmn 0:97a4f8cc534c 1707 case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
jhnwkmn 0:97a4f8cc534c 1708 case OT_NULL: scprintf(_SC("NULL")); break;
jhnwkmn 0:97a4f8cc534c 1709 case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
jhnwkmn 0:97a4f8cc534c 1710 case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break;
jhnwkmn 0:97a4f8cc534c 1711 case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
jhnwkmn 0:97a4f8cc534c 1712 case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;
jhnwkmn 0:97a4f8cc534c 1713 case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
jhnwkmn 0:97a4f8cc534c 1714 case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break;
jhnwkmn 0:97a4f8cc534c 1715 case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;
jhnwkmn 0:97a4f8cc534c 1716 case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
jhnwkmn 0:97a4f8cc534c 1717 case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;
jhnwkmn 0:97a4f8cc534c 1718 case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break;
jhnwkmn 0:97a4f8cc534c 1719 case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
jhnwkmn 0:97a4f8cc534c 1720 default:
jhnwkmn 0:97a4f8cc534c 1721 assert(0);
jhnwkmn 0:97a4f8cc534c 1722 break;
jhnwkmn 0:97a4f8cc534c 1723 };
jhnwkmn 0:97a4f8cc534c 1724 scprintf(_SC("\n"));
jhnwkmn 0:97a4f8cc534c 1725 ++n;
jhnwkmn 0:97a4f8cc534c 1726 }
jhnwkmn 0:97a4f8cc534c 1727 }
jhnwkmn 0:97a4f8cc534c 1728
jhnwkmn 0:97a4f8cc534c 1729
jhnwkmn 0:97a4f8cc534c 1730
jhnwkmn 0:97a4f8cc534c 1731 #endif