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