Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sqvm.cpp
00001 /* 00002 see copyright notice in squirrel.h 00003 */ 00004 #include "sqpcheader.h" 00005 #include <math.h> 00006 #include <stdlib.h> 00007 #include "sqopcodes.h" 00008 #include "sqvm.h" 00009 #include "sqfuncproto.h" 00010 #include "sqclosure.h" 00011 #include "sqstring.h" 00012 #include "sqtable.h" 00013 #include "squserdata.h" 00014 #include "sqarray.h" 00015 #include "sqclass.h" 00016 00017 #define TOP() (_stack._vals[_top-1]) 00018 00019 bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) 00020 { 00021 SQInteger res; 00022 if((type(o1)|type(o2)) == OT_INTEGER) 00023 { 00024 SQInteger i1 = _integer(o1), i2 = _integer(o2); 00025 switch(op) { 00026 case BW_AND: res = i1 & i2; break; 00027 case BW_OR: res = i1 | i2; break; 00028 case BW_XOR: res = i1 ^ i2; break; 00029 case BW_SHIFTL: res = i1 << i2; break; 00030 case BW_SHIFTR: res = i1 >> i2; break; 00031 case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; 00032 default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } 00033 } 00034 } 00035 else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} 00036 trg = res; 00037 return true; 00038 } 00039 00040 #define _ARITH_(op,trg,o1,o2) \ 00041 { \ 00042 SQInteger tmask = type(o1)|type(o2); \ 00043 switch(tmask) { \ 00044 case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ 00045 case (OT_FLOAT|OT_INTEGER): \ 00046 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ 00047 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ 00048 } \ 00049 } 00050 00051 #define _ARITH_NOZERO(op,trg,o1,o2,err) \ 00052 { \ 00053 SQInteger tmask = type(o1)|type(o2); \ 00054 switch(tmask) { \ 00055 case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ 00056 case (OT_FLOAT|OT_INTEGER): \ 00057 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ 00058 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ 00059 } \ 00060 } 00061 00062 bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) 00063 { 00064 SQInteger tmask = type(o1)|type(o2); 00065 switch(tmask) { 00066 case OT_INTEGER:{ 00067 SQInteger res, i1 = _integer(o1), i2 = _integer(o2); 00068 switch(op) { 00069 case '+': res = i1 + i2; break; 00070 case '-': res = i1 - i2; break; 00071 case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } 00072 res = i1 / i2; 00073 break; 00074 case '*': res = i1 * i2; break; 00075 case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } 00076 res = i1 % i2; 00077 break; 00078 default: res = 0xDEADBEEF; 00079 } 00080 trg = res; } 00081 break; 00082 case (OT_FLOAT|OT_INTEGER): 00083 case (OT_FLOAT):{ 00084 SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); 00085 switch(op) { 00086 case '+': res = f1 + f2; break; 00087 case '-': res = f1 - f2; break; 00088 case '/': res = f1 / f2; break; 00089 case '*': res = f1 * f2; break; 00090 case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; 00091 default: res = 0x0f; 00092 } 00093 trg = res; } 00094 break; 00095 default: 00096 if(op == '+' && (tmask & _RT_STRING)){ 00097 if(!StringCat(o1, o2, trg)) return false; 00098 } 00099 else if(!ArithMetaMethod(op,o1,o2,trg)) { 00100 return false; 00101 } 00102 } 00103 return true; 00104 } 00105 00106 SQVM::SQVM(SQSharedState *ss) 00107 { 00108 _sharedstate=ss; 00109 _suspended = SQFalse; 00110 _suspended_target = -1; 00111 _suspended_root = SQFalse; 00112 _suspended_traps = -1; 00113 _foreignptr = NULL; 00114 _nnativecalls = 0; 00115 _nmetamethodscall = 0; 00116 _lasterror.Null(); 00117 _errorhandler.Null(); 00118 _debughook = false; 00119 _debughook_native = NULL; 00120 _debughook_closure.Null(); 00121 _openouters = NULL; 00122 ci = NULL; 00123 INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); 00124 } 00125 00126 void SQVM::Finalize() 00127 { 00128 if(_openouters) CloseOuters(&_stack._vals[0]); 00129 _roottable.Null(); 00130 _lasterror.Null(); 00131 _errorhandler.Null(); 00132 _debughook = false; 00133 _debughook_native = NULL; 00134 _debughook_closure.Null(); 00135 temp_reg.Null(); 00136 _callstackdata.resize(0); 00137 SQInteger size=_stack.size(); 00138 for(SQInteger i=0;i<size;i++) 00139 _stack[i].Null(); 00140 } 00141 00142 SQVM::~SQVM() 00143 { 00144 Finalize(); 00145 REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); 00146 } 00147 00148 bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) 00149 { 00150 SQMetaMethod mm; 00151 switch(op){ 00152 case _SC('+'): mm=MT_ADD; break; 00153 case _SC('-'): mm=MT_SUB; break; 00154 case _SC('/'): mm=MT_DIV; break; 00155 case _SC('*'): mm=MT_MUL; break; 00156 case _SC('%'): mm=MT_MODULO; break; 00157 default: mm = MT_ADD; assert(0); break; //shutup compiler 00158 } 00159 if(is_delegable(o1) && _delegable(o1)->_delegate) { 00160 00161 SQObjectPtr closure; 00162 if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { 00163 Push(o1);Push(o2); 00164 return CallMetaMethod(closure,mm,2,dest); 00165 } 00166 } 00167 Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); 00168 return false; 00169 } 00170 00171 bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) 00172 { 00173 00174 switch(type(o)) { 00175 case OT_INTEGER: 00176 trg = -_integer(o); 00177 return true; 00178 case OT_FLOAT: 00179 trg = -_float(o); 00180 return true; 00181 case OT_TABLE: 00182 case OT_USERDATA: 00183 case OT_INSTANCE: 00184 if(_delegable(o)->_delegate) { 00185 SQObjectPtr closure; 00186 if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { 00187 Push(o); 00188 if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; 00189 _Swap(trg,temp_reg); 00190 return true; 00191 00192 } 00193 } 00194 default:break; //shutup compiler 00195 } 00196 Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); 00197 return false; 00198 } 00199 00200 #define _RET_SUCCEED(exp) { result = (exp); return true; } 00201 bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) 00202 { 00203 SQObjectType t1 = type(o1), t2 = type(o2); 00204 if(t1 == t2) { 00205 if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); 00206 SQObjectPtr res; 00207 switch(t1){ 00208 case OT_STRING: 00209 _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); 00210 case OT_INTEGER: 00211 _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); 00212 case OT_FLOAT: 00213 _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); 00214 case OT_TABLE: 00215 case OT_USERDATA: 00216 case OT_INSTANCE: 00217 if(_delegable(o1)->_delegate) { 00218 SQObjectPtr closure; 00219 if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { 00220 Push(o1);Push(o2); 00221 if(CallMetaMethod(closure,MT_CMP,2,res)) { 00222 if(type(res) != OT_INTEGER) { 00223 Raise_Error(_SC("_cmp must return an integer")); 00224 return false; 00225 } 00226 _RET_SUCCEED(_integer(res)) 00227 } 00228 return false; 00229 } 00230 } 00231 //continues through (no break needed) 00232 default: 00233 _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); 00234 } 00235 assert(0); 00236 //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } 00237 // _RET_SUCCEED(_integer(res)); 00238 00239 } 00240 else{ 00241 if(sq_isnumeric(o1) && sq_isnumeric(o2)){ 00242 if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { 00243 if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } 00244 else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } 00245 _RET_SUCCEED(1); 00246 } 00247 else{ 00248 if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } 00249 else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } 00250 _RET_SUCCEED(1); 00251 } 00252 } 00253 else if(t1==OT_NULL) {_RET_SUCCEED(-1);} 00254 else if(t2==OT_NULL) {_RET_SUCCEED(1);} 00255 else { Raise_CompareError(o1,o2); return false; } 00256 00257 } 00258 assert(0); 00259 _RET_SUCCEED(0); //cannot happen 00260 } 00261 00262 bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) 00263 { 00264 SQInteger r; 00265 if(ObjCmp(o1,o2,r)) { 00266 switch(op) { 00267 case CMP_G: res = (r > 0); return true; 00268 case CMP_GE: res = (r >= 0); return true; 00269 case CMP_L: res = (r < 0); return true; 00270 case CMP_LE: res = (r <= 0); return true; 00271 case CMP_3W: res = r; return true; 00272 } 00273 assert(0); 00274 } 00275 return false; 00276 } 00277 00278 bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) 00279 { 00280 switch(type(o)) { 00281 case OT_STRING: 00282 res = o; 00283 return true; 00284 case OT_FLOAT: 00285 scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); 00286 break; 00287 case OT_INTEGER: 00288 scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o)); 00289 break; 00290 case OT_BOOL: 00291 scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); 00292 break; 00293 case OT_TABLE: 00294 case OT_USERDATA: 00295 case OT_INSTANCE: 00296 if(_delegable(o)->_delegate) { 00297 SQObjectPtr closure; 00298 if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { 00299 Push(o); 00300 if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {; 00301 if(type(res) == OT_STRING) 00302 return true; 00303 } 00304 else { 00305 return false; 00306 } 00307 } 00308 } 00309 default: 00310 scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); 00311 } 00312 res = SQString::Create(_ss(this),_spval); 00313 return true; 00314 } 00315 00316 00317 bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) 00318 { 00319 SQObjectPtr a, b; 00320 if(!ToString(str, a)) return false; 00321 if(!ToString(obj, b)) return false; 00322 SQInteger l = _string(a)->_len , ol = _string(b)->_len; 00323 SQChar *s = _sp(rsl(l + ol + 1)); 00324 memcpy(s, _stringval(a), rsl(l)); 00325 memcpy(s + l, _stringval(b), rsl(ol)); 00326 dest = SQString::Create(_ss(this), _spval, l + ol); 00327 return true; 00328 } 00329 00330 bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) 00331 { 00332 if(is_delegable(obj1) && _delegable(obj1)->_delegate) { 00333 SQObjectPtr closure; 00334 if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { 00335 Push(obj1); 00336 return CallMetaMethod(closure,MT_TYPEOF,1,dest); 00337 } 00338 } 00339 dest = SQString::Create(_ss(this),GetTypeName(obj1)); 00340 return true; 00341 } 00342 00343 bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) 00344 { 00345 _stack.resize(stacksize); 00346 _alloccallsstacksize = 4; 00347 _callstackdata.resize(_alloccallsstacksize); 00348 _callsstacksize = 0; 00349 _callsstack = &_callstackdata[0]; 00350 _stackbase = 0; 00351 _top = 0; 00352 if(!friendvm) 00353 _roottable = SQTable::Create(_ss(this), 0); 00354 else { 00355 _roottable = friendvm->_roottable; 00356 _errorhandler = friendvm->_errorhandler; 00357 _debughook = friendvm->_debughook; 00358 _debughook_native = friendvm->_debughook_native; 00359 _debughook_closure = friendvm->_debughook_closure; 00360 } 00361 00362 sq_base_register(this); 00363 return true; 00364 } 00365 00366 00367 bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) 00368 { 00369 SQFunctionProto *func = closure->_function; 00370 00371 SQInteger paramssize = func->_nparameters; 00372 const SQInteger newtop = stackbase + func->_stacksize; 00373 SQInteger nargs = args; 00374 if(func->_varparams) 00375 { 00376 paramssize--; 00377 if (nargs < paramssize) { 00378 Raise_Error(_SC("wrong number of parameters")); 00379 return false; 00380 } 00381 00382 //dumpstack(stackbase); 00383 SQInteger nvargs = nargs - paramssize; 00384 SQArray *arr = SQArray::Create(_ss(this),nvargs); 00385 SQInteger pbase = stackbase+paramssize; 00386 for(SQInteger n = 0; n < nvargs; n++) { 00387 arr->_values[n] = _stack._vals[pbase]; 00388 _stack._vals[pbase].Null(); 00389 pbase++; 00390 00391 } 00392 _stack._vals[stackbase+paramssize] = arr; 00393 //dumpstack(stackbase); 00394 } 00395 else if (paramssize != nargs) { 00396 SQInteger ndef = func->_ndefaultparams; 00397 SQInteger diff; 00398 if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { 00399 for(SQInteger n = ndef - diff; n < ndef; n++) { 00400 _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; 00401 } 00402 } 00403 else { 00404 Raise_Error(_SC("wrong number of parameters")); 00405 return false; 00406 } 00407 } 00408 00409 if(closure->_env) { 00410 _stack._vals[stackbase] = closure->_env->_obj; 00411 } 00412 00413 if(!EnterFrame(stackbase, newtop, tailcall)) return false; 00414 00415 ci->_closure = closure; 00416 ci->_literals = func->_literals; 00417 ci->_ip = func->_instructions; 00418 ci->_target = (SQInt32)target; 00419 00420 if (_debughook) { 00421 CallDebugHook(_SC('c')); 00422 } 00423 00424 if (closure->_function->_bgenerator) { 00425 SQFunctionProto *f = closure->_function; 00426 SQGenerator *gen = SQGenerator::Create(_ss(this), closure); 00427 if(!gen->Yield(this,f->_stacksize)) 00428 return false; 00429 SQObjectPtr temp; 00430 Return(1, target, temp); 00431 STK(target) = gen; 00432 } 00433 00434 00435 return true; 00436 } 00437 00438 bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) 00439 { 00440 SQBool _isroot = ci->_root; 00441 SQInteger callerbase = _stackbase - ci->_prevstkbase; 00442 00443 if (_debughook) { 00444 for(SQInteger i=0; i<ci->_ncalls; i++) { 00445 CallDebugHook(_SC('r')); 00446 } 00447 } 00448 00449 SQObjectPtr *dest; 00450 if (_isroot) { 00451 dest = &(retval); 00452 } else if (ci->_target == -1) { 00453 dest = NULL; 00454 } else { 00455 dest = &_stack._vals[callerbase + ci->_target]; 00456 } 00457 if (dest) { 00458 if(_arg0 != 0xFF) { 00459 *dest = _stack._vals[_stackbase+_arg1]; 00460 } 00461 else { 00462 dest->Null(); 00463 } 00464 //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; 00465 } 00466 LeaveFrame(); 00467 return _isroot ? true : false; 00468 } 00469 00470 #define _RET_ON_FAIL(exp) { if(!exp) return false; } 00471 00472 bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) 00473 { 00474 SQObjectPtr trg; 00475 _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); 00476 target = a; 00477 a = trg; 00478 return true; 00479 } 00480 00481 bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx) 00482 { 00483 SQObjectPtr tmp, tself = self, tkey = key; 00484 if (!Get(tself, tkey, tmp, false, selfidx)) { return false; } 00485 _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) 00486 if (!Set(tself, tkey, target,selfidx)) { return false; } 00487 if (postfix) target = tmp; 00488 return true; 00489 } 00490 00491 #define arg0 (_i_._arg0) 00492 #define sarg0 ((SQInteger)*((signed char *)&_i_._arg0)) 00493 #define arg1 (_i_._arg1) 00494 #define sarg1 (*((SQInt32 *)&_i_._arg1)) 00495 #define arg2 (_i_._arg2) 00496 #define arg3 (_i_._arg3) 00497 #define sarg3 ((SQInteger)*((signed char *)&_i_._arg3)) 00498 00499 SQRESULT SQVM::Suspend() 00500 { 00501 if (_suspended) 00502 return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); 00503 if (_nnativecalls!=2) 00504 return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); 00505 return SQ_SUSPEND_FLAG; 00506 } 00507 00508 00509 #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; } 00510 bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr 00511 &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump) 00512 { 00513 SQInteger nrefidx; 00514 switch(type(o1)) { 00515 case OT_TABLE: 00516 if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos); 00517 o4 = (SQInteger)nrefidx; _FINISH(1); 00518 case OT_ARRAY: 00519 if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos); 00520 o4 = (SQInteger) nrefidx; _FINISH(1); 00521 case OT_STRING: 00522 if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); 00523 o4 = (SQInteger)nrefidx; _FINISH(1); 00524 case OT_CLASS: 00525 if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); 00526 o4 = (SQInteger)nrefidx; _FINISH(1); 00527 case OT_USERDATA: 00528 case OT_INSTANCE: 00529 if(_delegable(o1)->_delegate) { 00530 SQObjectPtr itr; 00531 SQObjectPtr closure; 00532 if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { 00533 Push(o1); 00534 Push(o4); 00535 if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { 00536 o4 = o2 = itr; 00537 if(type(itr) == OT_NULL) _FINISH(exitpos); 00538 if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) { 00539 Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed 00540 return false; 00541 } 00542 _FINISH(1); 00543 } 00544 else { 00545 return false; 00546 } 00547 } 00548 Raise_Error(_SC("_nexti failed")); 00549 return false; 00550 } 00551 break; 00552 case OT_GENERATOR: 00553 if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos); 00554 if(_generator(o1)->_state == SQGenerator::eSuspended) { 00555 SQInteger idx = 0; 00556 if(type(o4) == OT_INTEGER) { 00557 idx = _integer(o4) + 1; 00558 } 00559 o2 = idx; 00560 o4 = idx; 00561 _generator(o1)->Resume(this, o3); 00562 _FINISH(0); 00563 } 00564 default: 00565 Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); 00566 } 00567 return false; //cannot be hit(just to avoid warnings) 00568 } 00569 00570 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) 00571 00572 #define SQ_THROW() { goto exception_trap; } 00573 00574 #define _GUARD(exp) { if(!exp) { SQ_THROW();} } 00575 00576 bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) 00577 { 00578 SQInteger nouters; 00579 SQClosure *closure = SQClosure::Create(_ss(this), func); 00580 if((nouters = func->_noutervalues)) { 00581 for(SQInteger i = 0; i<nouters; i++) { 00582 SQOuterVar &v = func->_outervalues[i]; 00583 switch(v._type){ 00584 case otLOCAL: 00585 FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); 00586 break; 00587 case otOUTER: 00588 closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; 00589 break; 00590 } 00591 } 00592 } 00593 SQInteger ndefparams; 00594 if((ndefparams = func->_ndefaultparams)) { 00595 for(SQInteger i = 0; i < ndefparams; i++) { 00596 SQInteger spos = func->_defaultparams[i]; 00597 closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; 00598 } 00599 } 00600 target = closure; 00601 return true; 00602 00603 } 00604 00605 00606 bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) 00607 { 00608 SQClass *base = NULL; 00609 SQObjectPtr attrs; 00610 if(baseclass != -1) { 00611 if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } 00612 base = _class(_stack._vals[_stackbase + baseclass]); 00613 } 00614 if(attributes != MAX_FUNC_STACKSIZE) { 00615 attrs = _stack._vals[_stackbase+attributes]; 00616 } 00617 target = SQClass::Create(_ss(this),base); 00618 if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { 00619 int nparams = 2; 00620 SQObjectPtr ret; 00621 Push(target); Push(attrs); 00622 Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false); 00623 Pop(nparams); 00624 } 00625 _class(target)->_attributes = attrs; 00626 return true; 00627 } 00628 00629 bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res) 00630 { 00631 if(type(o1) == type(o2)) { 00632 res = (_rawval(o1) == _rawval(o2)); 00633 } 00634 else { 00635 if(sq_isnumeric(o1) && sq_isnumeric(o2)) { 00636 res = (tofloat(o1) == tofloat(o2)); 00637 } 00638 else { 00639 res = false; 00640 } 00641 } 00642 return true; 00643 } 00644 00645 bool SQVM::IsFalse(SQObjectPtr &o) 00646 { 00647 if(((type(o) & SQOBJECT_CANBEFALSE) 00648 && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) 00649 #if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64)) 00650 || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL 00651 #else 00652 || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL 00653 #endif 00654 { 00655 return true; 00656 } 00657 return false; 00658 } 00659 00660 #if defined(__MBED__) 00661 extern "C" void mbed_execute_idle(HSQUIRRELVM); 00662 #endif 00663 00664 bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) 00665 { 00666 if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } 00667 _nnativecalls++; 00668 AutoDec ad(&_nnativecalls); 00669 SQInteger traps = 0; 00670 CallInfo *prevci = ci; 00671 00672 switch(et) { 00673 case ET_CALL: { 00674 temp_reg = closure; 00675 if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { 00676 //call the handler if there are no calls in the stack, if not relies on the previous node 00677 if(ci == NULL) CallErrorHandler(_lasterror); 00678 return false; 00679 } 00680 if(ci == prevci) { 00681 outres = STK(_top-nargs); 00682 return true; 00683 } 00684 ci->_root = SQTrue; 00685 } 00686 break; 00687 case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; 00688 case ET_RESUME_VM: 00689 case ET_RESUME_THROW_VM: 00690 traps = _suspended_traps; 00691 ci->_root = _suspended_root; 00692 _suspended = SQFalse; 00693 if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } 00694 break; 00695 } 00696 00697 exception_restore: 00698 // 00699 { 00700 for(;;) 00701 { 00702 #if defined(__MBED__) 00703 mbed_execute_idle(this); 00704 #endif 00705 const SQInstruction &_i_ = *ci->_ip++; 00706 //dumpstack(_stackbase); 00707 //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); 00708 switch(_i_.op) 00709 { 00710 case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; 00711 case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; 00712 case _OP_LOADINT: 00713 #ifndef _SQ64 00714 TARGET = (SQInteger)arg1; continue; 00715 #else 00716 TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue; 00717 #endif 00718 case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue; 00719 case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; 00720 case _OP_TAILCALL:{ 00721 SQObjectPtr &t = STK(arg1); 00722 if (type(t) == OT_CLOSURE 00723 && (!_closure(t)->_function->_bgenerator)){ 00724 SQObjectPtr clo = t; 00725 if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); 00726 for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); 00727 _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); 00728 continue; 00729 } 00730 } 00731 case _OP_CALL: { 00732 SQObjectPtr clo = STK(arg1); 00733 switch (type(clo)) { 00734 case OT_CLOSURE: 00735 _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); 00736 continue; 00737 case OT_NATIVECLOSURE: { 00738 bool suspend; 00739 _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend)); 00740 if(suspend){ 00741 _suspended = SQTrue; 00742 _suspended_target = sarg0; 00743 _suspended_root = ci->_root; 00744 _suspended_traps = traps; 00745 outres = clo; 00746 return true; 00747 } 00748 if(sarg0 != -1) { 00749 STK(arg0) = clo; 00750 } 00751 } 00752 continue; 00753 case OT_CLASS:{ 00754 SQObjectPtr inst; 00755 _GUARD(CreateClassInstance(_class(clo),inst,clo)); 00756 if(sarg0 != -1) { 00757 STK(arg0) = inst; 00758 } 00759 SQInteger stkbase; 00760 switch(type(clo)) { 00761 case OT_CLOSURE: 00762 stkbase = _stackbase+arg2; 00763 _stack._vals[stkbase] = inst; 00764 _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); 00765 break; 00766 case OT_NATIVECLOSURE: 00767 bool suspend; 00768 stkbase = _stackbase+arg2; 00769 _stack._vals[stkbase] = inst; 00770 _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend)); 00771 break; 00772 default: break; //shutup GCC 4.x 00773 } 00774 } 00775 break; 00776 case OT_TABLE: 00777 case OT_USERDATA: 00778 case OT_INSTANCE:{ 00779 SQObjectPtr closure; 00780 if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { 00781 Push(clo); 00782 for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); 00783 if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); 00784 if(sarg0 != -1) { 00785 STK(arg0) = clo; 00786 } 00787 break; 00788 } 00789 00790 //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); 00791 //SQ_THROW(); 00792 } 00793 default: 00794 Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); 00795 SQ_THROW(); 00796 } 00797 } 00798 continue; 00799 case _OP_PREPCALL: 00800 case _OP_PREPCALLK: { 00801 SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); 00802 SQObjectPtr &o = STK(arg2); 00803 if (!Get(o, key, temp_reg,false,arg2)) { 00804 SQ_THROW(); 00805 } 00806 STK(arg3) = o; 00807 _Swap(TARGET,temp_reg);//TARGET = temp_reg; 00808 } 00809 continue; 00810 case _OP_GETK: 00811 if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();} 00812 _Swap(TARGET,temp_reg);//TARGET = temp_reg; 00813 continue; 00814 case _OP_MOVE: TARGET = STK(arg1); continue; 00815 case _OP_NEWSLOT: 00816 _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); 00817 if(arg0 != 0xFF) TARGET = STK(arg3); 00818 continue; 00819 case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; 00820 case _OP_SET: 00821 if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } 00822 if (arg0 != 0xFF) TARGET = STK(arg3); 00823 continue; 00824 case _OP_GET: 00825 if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); } 00826 _Swap(TARGET,temp_reg);//TARGET = temp_reg; 00827 continue; 00828 case _OP_EQ:{ 00829 bool res; 00830 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } 00831 TARGET = res?true:false; 00832 }continue; 00833 case _OP_NE:{ 00834 bool res; 00835 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } 00836 TARGET = (!res)?true:false; 00837 } continue; 00838 case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; 00839 case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; 00840 case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; 00841 case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; 00842 case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; 00843 case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; 00844 case _OP_RETURN: 00845 if((ci)->_generator) { 00846 (ci)->_generator->Kill(); 00847 } 00848 if(Return(arg0, arg1, temp_reg)){ 00849 assert(traps==0); 00850 //outres = temp_reg; 00851 _Swap(outres,temp_reg); 00852 return true; 00853 } 00854 continue; 00855 case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; 00856 case _OP_LOADROOT: TARGET = _roottable; continue; 00857 case _OP_LOADBOOL: TARGET = arg1?true:false; continue; 00858 case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; 00859 case _OP_JMP: ci->_ip += (sarg1); continue; 00860 //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; 00861 case _OP_JCMP: 00862 _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); 00863 if(IsFalse(temp_reg)) ci->_ip+=(sarg1); 00864 continue; 00865 case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; 00866 case _OP_GETOUTER: { 00867 SQClosure *cur_cls = _closure(ci->_closure); 00868 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); 00869 TARGET = *(otr->_valptr); 00870 } 00871 continue; 00872 case _OP_SETOUTER: { 00873 SQClosure *cur_cls = _closure(ci->_closure); 00874 SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); 00875 *(otr->_valptr) = STK(arg2); 00876 if(arg0 != 0xFF) { 00877 TARGET = STK(arg2); 00878 } 00879 } 00880 continue; 00881 case _OP_NEWOBJ: 00882 switch(arg3) { 00883 case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; 00884 case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; 00885 case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; 00886 default: assert(0); continue; 00887 } 00888 case _OP_APPENDARRAY: 00889 { 00890 SQObject val; 00891 val._unVal.raw = 0; 00892 switch(arg2) { 00893 case AAT_STACK: 00894 val = STK(arg1); break; 00895 case AAT_LITERAL: 00896 val = ci->_literals[arg1]; break; 00897 case AAT_INT: 00898 val._type = OT_INTEGER; 00899 #ifndef _SQ64 00900 val._unVal.nInteger = (SQInteger)arg1; 00901 #else 00902 val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1); 00903 #endif 00904 break; 00905 case AAT_FLOAT: 00906 val._type = OT_FLOAT; 00907 val._unVal.fFloat = *((SQFloat *)&arg1); 00908 break; 00909 case AAT_BOOL: 00910 val._type = OT_BOOL; 00911 val._unVal.nInteger = arg1; 00912 break; 00913 default: assert(0); break; 00914 00915 } 00916 _array(STK(arg0))->Append(val); continue; 00917 } 00918 case _OP_COMPARITH: { 00919 SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); 00920 _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); 00921 } 00922 continue; 00923 case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; 00924 case _OP_INCL: { 00925 SQObjectPtr &a = STK(arg1); 00926 if(type(a) == OT_INTEGER) { 00927 a._unVal.nInteger = _integer(a) + sarg3; 00928 } 00929 else { 00930 SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); 00931 _ARITH_(+,a,a,o); 00932 } 00933 } continue; 00934 case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; 00935 case _OP_PINCL: { 00936 SQObjectPtr &a = STK(arg1); 00937 if(type(a) == OT_INTEGER) { 00938 TARGET = a; 00939 a._unVal.nInteger = _integer(a) + sarg3; 00940 } 00941 else { 00942 SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); 00943 } 00944 00945 } continue; 00946 case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; 00947 case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue; 00948 case _OP_INSTANCEOF: 00949 if(type(STK(arg1)) != OT_CLASS) 00950 {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} 00951 TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; 00952 continue; 00953 case _OP_AND: 00954 if(IsFalse(STK(arg2))) { 00955 TARGET = STK(arg2); 00956 ci->_ip += (sarg1); 00957 } 00958 continue; 00959 case _OP_OR: 00960 if(!IsFalse(STK(arg2))) { 00961 TARGET = STK(arg2); 00962 ci->_ip += (sarg1); 00963 } 00964 continue; 00965 case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; 00966 case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; 00967 case _OP_BWNOT: 00968 if(type(STK(arg1)) == OT_INTEGER) { 00969 SQInteger t = _integer(STK(arg1)); 00970 TARGET = SQInteger(~t); 00971 continue; 00972 } 00973 Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); 00974 SQ_THROW(); 00975 case _OP_CLOSURE: { 00976 SQClosure *c = ci->_closure._unVal.pClosure; 00977 SQFunctionProto *fp = c->_function; 00978 if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } 00979 continue; 00980 } 00981 case _OP_YIELD:{ 00982 if(ci->_generator) { 00983 if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); 00984 _GUARD(ci->_generator->Yield(this,arg2)); 00985 traps -= ci->_etraps; 00986 if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; 00987 } 00988 else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} 00989 if(Return(arg0, arg1, temp_reg)){ 00990 assert(traps == 0); 00991 outres = temp_reg; 00992 return true; 00993 } 00994 00995 } 00996 continue; 00997 case _OP_RESUME: 00998 if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} 00999 _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); 01000 traps += ci->_etraps; 01001 continue; 01002 case _OP_FOREACH:{ int tojump; 01003 _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump)); 01004 ci->_ip += tojump; } 01005 continue; 01006 case _OP_POSTFOREACH: 01007 assert(type(STK(arg0)) == OT_GENERATOR); 01008 if(_generator(STK(arg0))->_state == SQGenerator::eDead) 01009 ci->_ip += (sarg1 - 1); 01010 continue; 01011 case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; 01012 case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; 01013 case _OP_PUSHTRAP:{ 01014 SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; 01015 _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; 01016 ci->_etraps++; 01017 } 01018 continue; 01019 case _OP_POPTRAP: { 01020 for(SQInteger i = 0; i < arg0; i++) { 01021 _etraps.pop_back(); traps--; 01022 ci->_etraps--; 01023 } 01024 } 01025 continue; 01026 case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; 01027 case _OP_NEWSLOTA: 01028 _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)); 01029 continue; 01030 case _OP_GETBASE:{ 01031 SQClosure *clo = _closure(ci->_closure); 01032 if(clo->_base) { 01033 TARGET = clo->_base; 01034 } 01035 else { 01036 TARGET.Null(); 01037 } 01038 continue; 01039 } 01040 case _OP_CLOSE: 01041 if(_openouters) CloseOuters(&(STK(arg1))); 01042 continue; 01043 } 01044 01045 } 01046 } 01047 exception_trap: 01048 { 01049 SQObjectPtr currerror = _lasterror; 01050 // dumpstack(_stackbase); 01051 // SQInteger n = 0; 01052 SQInteger last_top = _top; 01053 01054 if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); 01055 01056 while( ci ) { 01057 if(ci->_etraps > 0) { 01058 SQExceptionTrap &et = _etraps.top(); 01059 ci->_ip = et._ip; 01060 _top = et._stacksize; 01061 _stackbase = et._stackbase; 01062 _stack._vals[_stackbase + et._extarget] = currerror; 01063 _etraps.pop_back(); traps--; ci->_etraps--; 01064 while(last_top >= _top) _stack._vals[last_top--].Null(); 01065 goto exception_restore; 01066 } 01067 else if (_debughook) { 01068 //notify debugger of a "return" 01069 //even if it really an exception unwinding the stack 01070 for(SQInteger i = 0; i < ci->_ncalls; i++) { 01071 CallDebugHook(_SC('r')); 01072 } 01073 } 01074 if(ci->_generator) ci->_generator->Kill(); 01075 bool mustbreak = ci && ci->_root; 01076 LeaveFrame(); 01077 if(mustbreak) break; 01078 } 01079 01080 _lasterror = currerror; 01081 return false; 01082 } 01083 assert(0); 01084 } 01085 01086 bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) 01087 { 01088 inst = theclass->CreateInstance(); 01089 if(!theclass->GetConstructor(constructor)) { 01090 constructor.Null(); 01091 } 01092 return true; 01093 } 01094 01095 void SQVM::CallErrorHandler(SQObjectPtr &error) 01096 { 01097 if(type(_errorhandler) != OT_NULL) { 01098 SQObjectPtr out; 01099 Push(_roottable); Push(error); 01100 Call(_errorhandler, 2, _top-2, out,SQFalse); 01101 Pop(2); 01102 } 01103 } 01104 01105 01106 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) 01107 { 01108 _debughook = false; 01109 SQFunctionProto *func=_closure(ci->_closure)->_function; 01110 if(_debughook_native) { 01111 const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; 01112 const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL; 01113 SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); 01114 _debughook_native(this,type,src,line,fname); 01115 } 01116 else { 01117 SQObjectPtr temp_reg; 01118 SQInteger nparams=5; 01119 Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); 01120 Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); 01121 Pop(nparams); 01122 } 01123 _debughook = true; 01124 } 01125 01126 bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend) 01127 { 01128 SQInteger nparamscheck = nclosure->_nparamscheck; 01129 SQInteger newtop = newbase + nargs + nclosure->_noutervalues; 01130 01131 if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { 01132 Raise_Error(_SC("Native stack overflow")); 01133 return false; 01134 } 01135 01136 if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || 01137 ((nparamscheck < 0) && (nargs < (-nparamscheck))))) 01138 { 01139 Raise_Error(_SC("wrong number of parameters")); 01140 return false; 01141 } 01142 01143 SQInteger tcs; 01144 SQIntVec &tc = nclosure->_typecheck; 01145 if((tcs = tc.size())) { 01146 for(SQInteger i = 0; i < nargs && i < tcs; i++) { 01147 if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) { 01148 Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i])); 01149 return false; 01150 } 01151 } 01152 } 01153 01154 if(!EnterFrame(newbase, newtop, false)) return false; 01155 ci->_closure = nclosure; 01156 01157 SQInteger outers = nclosure->_noutervalues; 01158 for (SQInteger i = 0; i < outers; i++) { 01159 _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; 01160 } 01161 if(nclosure->_env) { 01162 _stack._vals[newbase] = nclosure->_env->_obj; 01163 } 01164 01165 _nnativecalls++; 01166 SQInteger ret = (nclosure->_function)(this); 01167 _nnativecalls--; 01168 01169 suspend = false; 01170 if (ret == SQ_SUSPEND_FLAG) { 01171 suspend = true; 01172 } 01173 else if (ret < 0) { 01174 LeaveFrame(); 01175 Raise_Error(_lasterror); 01176 return false; 01177 } 01178 if(ret) { 01179 retval = _stack._vals[_top-1]; 01180 } 01181 else { 01182 retval.Null(); 01183 } 01184 //retval = ret ? _stack._vals[_top-1] : _null_; 01185 LeaveFrame(); 01186 return true; 01187 } 01188 01189 #define FALLBACK_OK 0 01190 #define FALLBACK_NO_MATCH 1 01191 #define FALLBACK_ERROR 2 01192 01193 bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx) 01194 { 01195 switch(type(self)){ 01196 case OT_TABLE: 01197 if(_table(self)->Get(key,dest))return true; 01198 break; 01199 case OT_ARRAY: 01200 if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; } 01201 break; 01202 case OT_INSTANCE: 01203 if(_instance(self)->Get(key,dest)) return true; 01204 break; 01205 case OT_CLASS: 01206 if(_class(self)->Get(key,dest)) return true; 01207 break; 01208 case OT_STRING: 01209 if(sq_isnumeric(key)){ 01210 SQInteger n = tointeger(key); 01211 if(abs((int)n) < _string(self)->_len) { 01212 if(n < 0) n = _string(self)->_len - n; 01213 dest = SQInteger(_stringval(self)[n]); 01214 return true; 01215 } 01216 Raise_IdxError(key); 01217 return false; 01218 } 01219 break; 01220 default:break; //shut up compiler 01221 } 01222 if(!raw) { 01223 switch(FallBackGet(self,key,dest)) { 01224 case FALLBACK_OK: return true; //okie 01225 case FALLBACK_NO_MATCH: break; //keep falling back 01226 case FALLBACK_ERROR: return false; // the metamethod failed 01227 } 01228 if(InvokeDefaultDelegate(self,key,dest)) { 01229 return true; 01230 } 01231 } 01232 //#ifdef ROOT_FALLBACK 01233 if(selfidx == 0) { 01234 if(_table(_roottable)->Get(key,dest)) return true; 01235 } 01236 //#endif 01237 Raise_IdxError(key); 01238 return false; 01239 } 01240 01241 bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) 01242 { 01243 SQTable *ddel = NULL; 01244 switch(type(self)) { 01245 case OT_CLASS: ddel = _class_ddel; break; 01246 case OT_TABLE: ddel = _table_ddel; break; 01247 case OT_ARRAY: ddel = _array_ddel; break; 01248 case OT_STRING: ddel = _string_ddel; break; 01249 case OT_INSTANCE: ddel = _instance_ddel; break; 01250 case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; 01251 case OT_GENERATOR: ddel = _generator_ddel; break; 01252 case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; 01253 case OT_THREAD: ddel = _thread_ddel; break; 01254 case OT_WEAKREF: ddel = _weakref_ddel; break; 01255 default: return false; 01256 } 01257 return ddel->Get(key,dest); 01258 } 01259 01260 01261 SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) 01262 { 01263 switch(type(self)){ 01264 case OT_TABLE: 01265 case OT_USERDATA: 01266 //delegation 01267 if(_delegable(self)->_delegate) { 01268 if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK; 01269 } 01270 else { 01271 return FALLBACK_NO_MATCH; 01272 } 01273 //go through 01274 case OT_INSTANCE: { 01275 SQObjectPtr closure; 01276 if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { 01277 Push(self);Push(key); 01278 _nmetamethodscall++; 01279 AutoDec ad(&_nmetamethodscall); 01280 if(Call(closure, 2, _top - 2, dest, SQFalse)) { 01281 Pop(2); 01282 return FALLBACK_OK; 01283 } 01284 else { 01285 Pop(2); 01286 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) 01287 return FALLBACK_ERROR; 01288 } 01289 } 01290 } 01291 } 01292 break; 01293 default: break;//shutup GCC 4.x 01294 } 01295 // no metamethod or no fallback type 01296 return FALLBACK_NO_MATCH; 01297 } 01298 01299 bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx) 01300 { 01301 switch(type(self)){ 01302 case OT_TABLE: 01303 if(_table(self)->Set(key,val)) return true; 01304 break; 01305 case OT_INSTANCE: 01306 if(_instance(self)->Set(key,val)) return true; 01307 break; 01308 case OT_ARRAY: 01309 if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } 01310 if(!_array(self)->Set(tointeger(key),val)) { 01311 Raise_IdxError(key); 01312 return false; 01313 } 01314 return true; 01315 default: 01316 Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); 01317 return false; 01318 } 01319 01320 switch(FallBackSet(self,key,val)) { 01321 case FALLBACK_OK: return true; //okie 01322 case FALLBACK_NO_MATCH: break; //keep falling back 01323 case FALLBACK_ERROR: return false; // the metamethod failed 01324 } 01325 if(selfidx == 0) { 01326 if(_table(_roottable)->Set(key,val)) 01327 return true; 01328 } 01329 Raise_IdxError(key); 01330 return false; 01331 } 01332 01333 SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val) 01334 { 01335 switch(type(self)) { 01336 case OT_TABLE: 01337 if(_table(self)->_delegate) { 01338 if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; 01339 } 01340 //keps on going 01341 case OT_INSTANCE: 01342 case OT_USERDATA:{ 01343 SQObjectPtr closure; 01344 SQObjectPtr t; 01345 if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { 01346 Push(self);Push(key);Push(val); 01347 _nmetamethodscall++; 01348 AutoDec ad(&_nmetamethodscall); 01349 if(Call(closure, 3, _top - 3, t, SQFalse)) { 01350 Pop(3); 01351 return FALLBACK_OK; 01352 } 01353 else { 01354 if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) 01355 //error 01356 Pop(3); 01357 return FALLBACK_ERROR; 01358 } 01359 } 01360 } 01361 } 01362 break; 01363 default: break;//shutup GCC 4.x 01364 } 01365 // no metamethod or no fallback type 01366 return FALLBACK_NO_MATCH; 01367 } 01368 01369 bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) 01370 { 01371 SQObjectPtr temp_reg; 01372 SQObjectPtr newobj; 01373 switch(type(self)){ 01374 case OT_TABLE: 01375 newobj = _table(self)->Clone(); 01376 goto cloned_mt; 01377 case OT_INSTANCE: { 01378 newobj = _instance(self)->Clone(_ss(this)); 01379 cloned_mt: 01380 SQObjectPtr closure; 01381 if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { 01382 Push(newobj); 01383 Push(self); 01384 if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) 01385 return false; 01386 } 01387 } 01388 target = newobj; 01389 return true; 01390 case OT_ARRAY: 01391 target = _array(self)->Clone(); 01392 return true; 01393 default: 01394 Raise_Error(_SC("cloning a %s"), GetTypeName(self)); 01395 return false; 01396 } 01397 } 01398 01399 bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw) 01400 { 01401 if(type(self) != OT_CLASS) { 01402 Raise_Error(_SC("object must be a class")); 01403 return false; 01404 } 01405 SQClass *c = _class(self); 01406 if(!raw) { 01407 SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; 01408 if(type(mm) != OT_NULL ) { 01409 Push(self); Push(key); Push(val); 01410 Push(attrs); 01411 Push(bstatic); 01412 return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); 01413 } 01414 } 01415 if(!NewSlot(self, key, val,bstatic)) 01416 return false; 01417 if(type(attrs) != OT_NULL) { 01418 c->SetAttributes(key,attrs); 01419 } 01420 return true; 01421 } 01422 01423 bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) 01424 { 01425 if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } 01426 switch(type(self)) { 01427 case OT_TABLE: { 01428 bool rawcall = true; 01429 if(_table(self)->_delegate) { 01430 SQObjectPtr res; 01431 if(!_table(self)->Get(key,res)) { 01432 SQObjectPtr closure; 01433 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { 01434 Push(self);Push(key);Push(val); 01435 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { 01436 return false; 01437 } 01438 rawcall = false; 01439 } 01440 else { 01441 rawcall = true; 01442 } 01443 } 01444 } 01445 if(rawcall) _table(self)->NewSlot(key,val); //cannot fail 01446 01447 break;} 01448 case OT_INSTANCE: { 01449 SQObjectPtr res; 01450 SQObjectPtr closure; 01451 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { 01452 Push(self);Push(key);Push(val); 01453 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { 01454 return false; 01455 } 01456 break; 01457 } 01458 Raise_Error(_SC("class instances do not support the new slot operator")); 01459 return false; 01460 break;} 01461 case OT_CLASS: 01462 if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { 01463 if(_class(self)->_locked) { 01464 Raise_Error(_SC("trying to modify a class that has already been instantiated")); 01465 return false; 01466 } 01467 else { 01468 SQObjectPtr oval = PrintObjVal(key); 01469 Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); 01470 return false; 01471 } 01472 } 01473 break; 01474 default: 01475 Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); 01476 return false; 01477 break; 01478 } 01479 return true; 01480 } 01481 01482 01483 01484 bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) 01485 { 01486 switch(type(self)) { 01487 case OT_TABLE: 01488 case OT_INSTANCE: 01489 case OT_USERDATA: { 01490 SQObjectPtr t; 01491 //bool handled = false; 01492 SQObjectPtr closure; 01493 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { 01494 Push(self);Push(key); 01495 return CallMetaMethod(closure,MT_DELSLOT,2,res); 01496 } 01497 else { 01498 if(type(self) == OT_TABLE) { 01499 if(_table(self)->Get(key,t)) { 01500 _table(self)->Remove(key); 01501 } 01502 else { 01503 Raise_IdxError((SQObject &)key); 01504 return false; 01505 } 01506 } 01507 else { 01508 Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); 01509 return false; 01510 } 01511 } 01512 res = t; 01513 } 01514 break; 01515 default: 01516 Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); 01517 return false; 01518 } 01519 return true; 01520 } 01521 01522 bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror) 01523 { 01524 #ifdef _DEBUG 01525 SQInteger prevstackbase = _stackbase; 01526 #endif 01527 switch(type(closure)) { 01528 case OT_CLOSURE: 01529 return Execute(closure, nparams, stackbase, outres, raiseerror); 01530 break; 01531 case OT_NATIVECLOSURE:{ 01532 bool suspend; 01533 return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend); 01534 01535 } 01536 break; 01537 case OT_CLASS: { 01538 SQObjectPtr constr; 01539 SQObjectPtr temp; 01540 CreateClassInstance(_class(closure),outres,constr); 01541 if(type(constr) != OT_NULL) { 01542 _stack[stackbase] = outres; 01543 return Call(constr,nparams,stackbase,temp,raiseerror); 01544 } 01545 return true; 01546 } 01547 break; 01548 default: 01549 return false; 01550 } 01551 #ifdef _DEBUG 01552 if(!_suspended) { 01553 assert(_stackbase == prevstackbase); 01554 } 01555 #endif 01556 return true; 01557 } 01558 01559 bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) 01560 { 01561 //SQObjectPtr closure; 01562 01563 _nmetamethodscall++; 01564 if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { 01565 _nmetamethodscall--; 01566 Pop(nparams); 01567 return true; 01568 } 01569 _nmetamethodscall--; 01570 //} 01571 Pop(nparams); 01572 return false; 01573 } 01574 01575 void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex) 01576 { 01577 SQOuter **pp = &_openouters; 01578 SQOuter *p; 01579 SQOuter *otr; 01580 01581 while ((p = *pp) != NULL && p->_valptr >= stackindex) { 01582 if (p->_valptr == stackindex) { 01583 target = SQObjectPtr(p); 01584 return; 01585 } 01586 pp = &p->_next; 01587 } 01588 otr = SQOuter::Create(_ss(this), stackindex); 01589 otr->_next = *pp; 01590 otr->_idx = (stackindex - _stack._vals); 01591 __ObjAddRef(otr); 01592 *pp = otr; 01593 target = SQObjectPtr(otr); 01594 } 01595 01596 bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall) 01597 { 01598 if( !tailcall ) { 01599 if( _callsstacksize == _alloccallsstacksize ) { 01600 GrowCallStack(); 01601 } 01602 ci = &_callsstack[_callsstacksize++]; 01603 ci->_prevstkbase = (SQInt32)(newbase - _stackbase); 01604 ci->_prevtop = (SQInt32)(_top - _stackbase); 01605 ci->_etraps = 0; 01606 ci->_ncalls = 1; 01607 ci->_generator = NULL; 01608 ci->_root = SQFalse; 01609 } 01610 else { 01611 ci->_ncalls++; 01612 } 01613 01614 _stackbase = newbase; 01615 _top = newtop; 01616 if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { 01617 if(_nmetamethodscall) { 01618 Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); 01619 return false; 01620 } 01621 _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2)); 01622 RelocateOuters(); 01623 } 01624 return true; 01625 } 01626 01627 void SQVM::LeaveFrame() { 01628 SQInteger last_top = _top; 01629 SQInteger last_stackbase = _stackbase; 01630 SQInteger css = --_callsstacksize; 01631 01632 /* First clean out the call stack frame */ 01633 ci->_closure.Null(); 01634 _stackbase -= ci->_prevstkbase; 01635 _top = _stackbase + ci->_prevtop; 01636 ci = (css) ? &_callsstack[css-1] : NULL; 01637 01638 if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); 01639 while (last_top >= _top) { 01640 _stack._vals[last_top--].Null(); 01641 } 01642 } 01643 01644 void SQVM::RelocateOuters() 01645 { 01646 SQOuter *p = _openouters; 01647 while (p) { 01648 p->_valptr = _stack._vals + p->_idx; 01649 p = p->_next; 01650 } 01651 } 01652 01653 void SQVM::CloseOuters(SQObjectPtr *stackindex) { 01654 SQOuter *p; 01655 while ((p = _openouters) != NULL && p->_valptr >= stackindex) { 01656 p->_value = *(p->_valptr); 01657 p->_valptr = &p->_value; 01658 _openouters = p->_next; 01659 __ObjRelease(p); 01660 } 01661 } 01662 01663 void SQVM::Remove(SQInteger n) { 01664 n = (n >= 0)?n + _stackbase - 1:_top + n; 01665 for(SQInteger i = n; i < _top; i++){ 01666 _stack[i] = _stack[i+1]; 01667 } 01668 _stack[_top].Null(); 01669 _top--; 01670 } 01671 01672 void SQVM::Pop() { 01673 _stack[--_top].Null(); 01674 } 01675 01676 void SQVM::Pop(SQInteger n) { 01677 for(SQInteger i = 0; i < n; i++){ 01678 _stack[--_top].Null(); 01679 } 01680 } 01681 01682 void SQVM::PushNull() { _stack[_top++].Null(); } 01683 void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } 01684 SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } 01685 SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } 01686 SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; } 01687 SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } 01688 01689 #ifdef _DEBUG_DUMP 01690 void SQVM::dumpstack(SQInteger stackbase,bool dumpall) 01691 { 01692 SQInteger size=dumpall?_stack.size():_top; 01693 SQInteger n=0; 01694 scprintf(_SC("\n>>>>stack dump<<<<\n")); 01695 CallInfo &ci=_callsstack[_callsstacksize-1]; 01696 scprintf(_SC("IP: %p\n"),ci._ip); 01697 scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); 01698 scprintf(_SC("prev top: %d\n"),ci._prevtop); 01699 for(SQInteger i=0;i<size;i++){ 01700 SQObjectPtr &obj=_stack[i]; 01701 if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" ")); 01702 scprintf(_SC("[%d]:"),n); 01703 switch(type(obj)){ 01704 case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; 01705 case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break; 01706 case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; 01707 case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; 01708 case OT_NULL: scprintf(_SC("NULL")); break; 01709 case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; 01710 case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; 01711 case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; 01712 case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; 01713 case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; 01714 case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break; 01715 case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; 01716 case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; 01717 case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; 01718 case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; 01719 case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; 01720 default: 01721 assert(0); 01722 break; 01723 }; 01724 scprintf(_SC("\n")); 01725 ++n; 01726 } 01727 } 01728 01729 01730 01731 #endif
Generated on Tue Jul 12 2022 21:35:49 by
1.7.2