0001
0002
0003
0004 #include <math.h>
0005 #include "pspcheader.h"
0006 #include <stdlib.h>
0007 #include "psopcodes.h"
0008 #include "psvm.h"
0009 #include "psfuncproto.h"
0010 #include "psclosure.h"
0011 #include "psstring.h"
0012 #include "pstable.h"
0013 #include "psuserdata.h"
0014 #include "psarray.h"
0015 #include "psclass.h"
0016
0017 #define TOP() (_stack._vals[_top-1])
0018
0019 bool PSVM::BW_OP(PSUnsignedInteger op,PSObjectPtr &trg,const PSObjectPtr &o1,const PSObjectPtr &o2)
0020 {
0021 PSInteger res;
0022 if((type(o1)|type(o2)) == OT_INTEGER)
0023 {
0024 PSInteger i1 = _integer(o1), i2 = _integer(o2);
0025 switch(op) {
0026 case BW_AND: res = i1 & i2; break;
0027 case BW_OR: res = i1 | i2; break;
0028 case BW_XOR: res = i1 ^ i2; break;
0029 case BW_SHIFTL: res = i1 << i2; break;
0030 case BW_SHIFTR: res = i1 >> i2; break;
0031 case BW_USHIFTR:res = (PSInteger)(*((PSUnsignedInteger*)&i1) >> i2); break;
0032 default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }
0033 }
0034 }
0035 else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}
0036 trg = res;
0037 return true;
0038 }
0039
0040 #define _ARITH_(op,trg,o1,o2) \
0041 { \
0042 PSInteger tmask = type(o1)|type(o2); \
0043 switch(tmask) { \
0044 case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
0045 case (OT_FLOAT|OT_INTEGER): \
0046 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
0047 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
0048 } \
0049 }
0050
0051 #define _ARITH_NOZERO(op,trg,o1,o2,err) \
0052 { \
0053 PSInteger tmask = type(o1)|type(o2); \
0054 switch(tmask) { \
0055 case OT_INTEGER: { PSInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); PS_THROW(); } trg = _integer(o1) op i2; } break;\
0056 case (OT_FLOAT|OT_INTEGER): \
0057 case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
0058 default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
0059 } \
0060 }
0061
0062 bool PSVM::ARITH_OP(PSUnsignedInteger op,PSObjectPtr &trg,const PSObjectPtr &o1,const PSObjectPtr &o2)
0063 {
0064 PSInteger tmask = type(o1)|type(o2);
0065 switch(tmask) {
0066 case OT_INTEGER:{
0067 PSInteger res, i1 = _integer(o1), i2 = _integer(o2);
0068 switch(op) {
0069 case '+': res = i1 + i2; break;
0070 case '-': res = i1 - i2; break;
0071 case '/': if (i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
0072 else if (i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; }
0073 res = i1 / i2;
0074 break;
0075 case '*': res = i1 * i2; break;
0076 case '%': if (i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
0077 else if (i2 == -1 && i1 == INT_MIN) { res = 0; break; }
0078 res = i1 % i2;
0079 break;
0080 default: res = 0xDEADBEEF;
0081 }
0082 trg = res; }
0083 break;
0084 case (OT_FLOAT|OT_INTEGER):
0085 case (OT_FLOAT):{
0086 PSFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
0087 switch(op) {
0088 case '+': res = f1 + f2; break;
0089 case '-': res = f1 - f2; break;
0090 case '/': res = f1 / f2; break;
0091 case '*': res = f1 * f2; break;
0092 case '%': res = PSFloat(fmod((double)f1,(double)f2)); break;
0093 default: res = 0x0f;
0094 }
0095 trg = res; }
0096 break;
0097 default:
0098 if(op == '+' && (tmask & _RT_STRING)){
0099 if(!StringCat(o1, o2, trg)) return false;
0100 }
0101 else if(!ArithMetaMethod(op,o1,o2,trg)) {
0102 return false;
0103 }
0104 }
0105 return true;
0106 }
0107
0108 PSVM::PSVM(PSSharedState *ss)
0109 {
0110 _sharedstate=ss;
0111 _suspended = PSFalse;
0112 _suspended_target = -1;
0113 _suspended_root = PSFalse;
0114 _suspended_traps = -1;
0115 _foreignptr = NULL;
0116 _nnativecalls = 0;
0117 _nmetamethodscall = 0;
0118 _lasterror.Null();
0119 _errorhandler.Null();
0120 _debughook = false;
0121 _debughook_native = NULL;
0122 _debughook_closure.Null();
0123 _openouters = NULL;
0124 ci = NULL;
0125 _releasehook = NULL;
0126 INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
0127 }
0128
0129 void PSVM::Finalize()
0130 {
0131 if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
0132 if(_openouters) CloseOuters(&_stack._vals[0]);
0133 _roottable.Null();
0134 _lasterror.Null();
0135 _errorhandler.Null();
0136 _debughook = false;
0137 _debughook_native = NULL;
0138 _debughook_closure.Null();
0139 temp_reg.Null();
0140 _callstackdata.resize(0);
0141 PSInteger size=_stack.size();
0142 for(PSInteger i=0;i<size;i++)
0143 _stack[i].Null();
0144 }
0145
0146 PSVM::~PSVM()
0147 {
0148 Finalize();
0149 REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
0150 }
0151
0152 bool PSVM::ArithMetaMethod(PSInteger op,const PSObjectPtr &o1,const PSObjectPtr &o2,PSObjectPtr &dest)
0153 {
0154 PSMetaMethod mm;
0155 switch(op){
0156 case _SC('+'): mm=MT_ADD; break;
0157 case _SC('-'): mm=MT_SUB; break;
0158 case _SC('/'): mm=MT_DIV; break;
0159 case _SC('*'): mm=MT_MUL; break;
0160 case _SC('%'): mm=MT_MODULO; break;
0161 default: mm = MT_ADD; assert(0); break;
0162 }
0163 if(is_delegable(o1) && _delegable(o1)->_delegate) {
0164
0165 PSObjectPtr closure;
0166 if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {
0167 Push(o1);Push(o2);
0168 return CallMetaMethod(closure,mm,2,dest);
0169 }
0170 }
0171 Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2));
0172 return false;
0173 }
0174
0175 bool PSVM::NEG_OP(PSObjectPtr &trg,const PSObjectPtr &o)
0176 {
0177
0178 switch(type(o)) {
0179 case OT_INTEGER:
0180 trg = -_integer(o);
0181 return true;
0182 case OT_FLOAT:
0183 trg = -_float(o);
0184 return true;
0185 case OT_TABLE:
0186 case OT_USERDATA:
0187 case OT_INSTANCE:
0188 if(_delegable(o)->_delegate) {
0189 PSObjectPtr closure;
0190 if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {
0191 Push(o);
0192 if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;
0193 _Swap(trg,temp_reg);
0194 return true;
0195
0196 }
0197 }
0198 default:break;
0199 }
0200 Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
0201 return false;
0202 }
0203
0204 #define _RET_SUCCEED(exp) { result = (exp); return true; }
0205 bool PSVM::ObjCmp(const PSObjectPtr &o1,const PSObjectPtr &o2,PSInteger &result)
0206 {
0207 PSObjectType t1 = type(o1), t2 = type(o2);
0208 if(t1 == t2) {
0209 if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0);
0210 PSObjectPtr res;
0211 switch(t1){
0212 case OT_STRING:
0213 _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));
0214 case OT_INTEGER:
0215 _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1);
0216 case OT_FLOAT:
0217 _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
0218 case OT_TABLE:
0219 case OT_USERDATA:
0220 case OT_INSTANCE:
0221 if(_delegable(o1)->_delegate) {
0222 PSObjectPtr closure;
0223 if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {
0224 Push(o1);Push(o2);
0225 if(CallMetaMethod(closure,MT_CMP,2,res)) {
0226 if(type(res) != OT_INTEGER) {
0227 Raise_Error(_SC("_cmp must return an integer"));
0228 return false;
0229 }
0230 _RET_SUCCEED(_integer(res))
0231 }
0232 return false;
0233 }
0234 }
0235
0236 default:
0237 _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
0238 }
0239 assert(0);
0240
0241
0242
0243 }
0244 else{
0245 if(ps_isnumeric(o1) && ps_isnumeric(o2)){
0246 if((t1==OT_INTEGER) && (t2==OT_FLOAT)) {
0247 if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
0248 else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
0249 _RET_SUCCEED(1);
0250 }
0251 else{
0252 if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }
0253 else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }
0254 _RET_SUCCEED(1);
0255 }
0256 }
0257 else if(t1==OT_NULL) {_RET_SUCCEED(-1);}
0258 else if(t2==OT_NULL) {_RET_SUCCEED(1);}
0259 else { Raise_CompareError(o1,o2); return false; }
0260
0261 }
0262 assert(0);
0263 _RET_SUCCEED(0);
0264 }
0265
0266 bool PSVM::CMP_OP(CmpOP op, const PSObjectPtr &o1,const PSObjectPtr &o2,PSObjectPtr &res)
0267 {
0268 PSInteger r;
0269 if(ObjCmp(o1,o2,r)) {
0270 switch(op) {
0271 case CMP_G: res = (r > 0); return true;
0272 case CMP_GE: res = (r >= 0); return true;
0273 case CMP_L: res = (r < 0); return true;
0274 case CMP_LE: res = (r <= 0); return true;
0275 case CMP_3W: res = r; return true;
0276 }
0277 assert(0);
0278 }
0279 return false;
0280 }
0281
0282 bool PSVM::ToString(const PSObjectPtr &o,PSObjectPtr &res)
0283 {
0284 switch(type(o)) {
0285 case OT_STRING:
0286 res = o;
0287 return true;
0288 case OT_FLOAT:
0289 scsprintf(_sp(ps_rsl(NUMBER_MAX_CHAR+1)),ps_rsl(NUMBER_MAX_CHAR),_SC("%g"),_float(o));
0290 break;
0291 case OT_INTEGER:
0292 scsprintf(_sp(ps_rsl(NUMBER_MAX_CHAR+1)),ps_rsl(NUMBER_MAX_CHAR),_PRINT_INT_FMT,_integer(o));
0293 break;
0294 case OT_BOOL:
0295 scsprintf(_sp(ps_rsl(6)),ps_rsl(6),_integer(o)?_SC("true"):_SC("false"));
0296 break;
0297 case OT_TABLE:
0298 case OT_USERDATA:
0299 case OT_INSTANCE:
0300 if(_delegable(o)->_delegate) {
0301 PSObjectPtr closure;
0302 if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {
0303 Push(o);
0304 if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;
0305 if(type(res) == OT_STRING)
0306 return true;
0307 }
0308 else {
0309 return false;
0310 }
0311 }
0312 }
0313 default:
0314 scsprintf(_sp(ps_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR)),ps_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
0315 }
0316 res = PSString::Create(_ss(this),_spval);
0317 return true;
0318 }
0319
0320
0321 bool PSVM::StringCat(const PSObjectPtr &str,const PSObjectPtr &obj,PSObjectPtr &dest)
0322 {
0323 PSObjectPtr a, b;
0324 if(!ToString(str, a)) return false;
0325 if(!ToString(obj, b)) return false;
0326 PSInteger l = _string(a)->_len , ol = _string(b)->_len;
0327 PSChar *s = _sp(ps_rsl(l + ol + 1));
0328 memcpy(s, _stringval(a), ps_rsl(l));
0329 memcpy(s + l, _stringval(b), ps_rsl(ol));
0330 dest = PSString::Create(_ss(this), _spval, l + ol);
0331 return true;
0332 }
0333
0334 bool PSVM::TypeOf(const PSObjectPtr &obj1,PSObjectPtr &dest)
0335 {
0336 if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
0337 PSObjectPtr closure;
0338 if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {
0339 Push(obj1);
0340 return CallMetaMethod(closure,MT_TYPEOF,1,dest);
0341 }
0342 }
0343 dest = PSString::Create(_ss(this),GetTypeName(obj1));
0344 return true;
0345 }
0346
0347 bool PSVM::Init(PSVM *friendvm, PSInteger stacksize)
0348 {
0349 _stack.resize(stacksize);
0350 _alloccallsstacksize = 4;
0351 _callstackdata.resize(_alloccallsstacksize);
0352 _callsstacksize = 0;
0353 _callsstack = &_callstackdata[0];
0354 _stackbase = 0;
0355 _top = 0;
0356 if(!friendvm) {
0357 _roottable = PSTable::Create(_ss(this), 0);
0358 ps_base_register(this);
0359 }
0360 else {
0361 _roottable = friendvm->_roottable;
0362 _errorhandler = friendvm->_errorhandler;
0363 _debughook = friendvm->_debughook;
0364 _debughook_native = friendvm->_debughook_native;
0365 _debughook_closure = friendvm->_debughook_closure;
0366 }
0367
0368
0369 return true;
0370 }
0371
0372
0373 bool PSVM::StartCall(PSClosure *closure,PSInteger target,PSInteger args,PSInteger stackbase,bool tailcall)
0374 {
0375 PSFunctionProto *func = closure->_function;
0376
0377 PSInteger paramssize = func->_nparameters;
0378 const PSInteger newtop = stackbase + func->_stacksize;
0379 PSInteger nargs = args;
0380 if(func->_varparams)
0381 {
0382 paramssize--;
0383 if (nargs < paramssize) {
0384 Raise_Error(_SC("wrong number of parameters"));
0385 return false;
0386 }
0387
0388
0389 PSInteger nvargs = nargs - paramssize;
0390 PSArray *arr = PSArray::Create(_ss(this),nvargs);
0391 PSInteger pbase = stackbase+paramssize;
0392 for(PSInteger n = 0; n < nvargs; n++) {
0393 arr->_values[n] = _stack._vals[pbase];
0394 _stack._vals[pbase].Null();
0395 pbase++;
0396
0397 }
0398 _stack._vals[stackbase+paramssize] = arr;
0399
0400 }
0401 else if (paramssize != nargs) {
0402 PSInteger ndef = func->_ndefaultparams;
0403 PSInteger diff;
0404 if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
0405 for(PSInteger n = ndef - diff; n < ndef; n++) {
0406 _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
0407 }
0408 }
0409 else {
0410 Raise_Error(_SC("wrong number of parameters"));
0411 return false;
0412 }
0413 }
0414
0415 if(closure->_env) {
0416 _stack._vals[stackbase] = closure->_env->_obj;
0417 }
0418
0419 if(!EnterFrame(stackbase, newtop, tailcall)) return false;
0420
0421 ci->_closure = closure;
0422 ci->_literals = func->_literals;
0423 ci->_ip = func->_instructions;
0424 ci->_target = (PSInt32)target;
0425
0426 if (_debughook) {
0427 CallDebugHook(_SC('c'));
0428 }
0429
0430 if (closure->_function->_bgenerator) {
0431 PSFunctionProto *f = closure->_function;
0432 PSGenerator *gen = PSGenerator::Create(_ss(this), closure);
0433 if(!gen->Yield(this,f->_stacksize))
0434 return false;
0435 PSObjectPtr temp;
0436 Return(1, target, temp);
0437 STK(target) = gen;
0438 }
0439
0440
0441 return true;
0442 }
0443
0444 bool PSVM::Return(PSInteger _arg0, PSInteger _arg1, PSObjectPtr &retval)
0445 {
0446 PSBool _isroot = ci->_root;
0447 PSInteger callerbase = _stackbase - ci->_prevstkbase;
0448
0449 if (_debughook) {
0450 for(PSInteger i=0; i<ci->_ncalls; i++) {
0451 CallDebugHook(_SC('r'));
0452 }
0453 }
0454
0455 PSObjectPtr *dest;
0456 if (_isroot) {
0457 dest = &(retval);
0458 } else if (ci->_target == -1) {
0459 dest = NULL;
0460 } else {
0461 dest = &_stack._vals[callerbase + ci->_target];
0462 }
0463 if (dest) {
0464 if(_arg0 != 0xFF) {
0465 *dest = _stack._vals[_stackbase+_arg1];
0466 }
0467 else {
0468 dest->Null();
0469 }
0470
0471 }
0472 LeaveFrame();
0473 return _isroot ? true : false;
0474 }
0475
0476 #define _RET_ON_FAIL(exp) { if(!exp) return false; }
0477
0478 bool PSVM::PLOCAL_INC(PSInteger op,PSObjectPtr &target, PSObjectPtr &a, PSObjectPtr &incr)
0479 {
0480 PSObjectPtr trg;
0481 _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));
0482 target = a;
0483 a = trg;
0484 return true;
0485 }
0486
0487 bool PSVM::DerefInc(PSInteger op,PSObjectPtr &target, PSObjectPtr &self, PSObjectPtr &key, PSObjectPtr &incr, bool postfix,PSInteger selfidx)
0488 {
0489 PSObjectPtr tmp, tself = self, tkey = key;
0490 if (!Get(tself, tkey, tmp, 0, selfidx)) { return false; }
0491 _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
0492 if (!Set(tself, tkey, target,selfidx)) { return false; }
0493 if (postfix) target = tmp;
0494 return true;
0495 }
0496
0497 #define arg0 (_i_._arg0)
0498 #define sarg0 ((PSInteger)*((const signed char *)&_i_._arg0))
0499 #define arg1 (_i_._arg1)
0500 #define sarg1 (*((const PSInt32 *)&_i_._arg1))
0501 #define arg2 (_i_._arg2)
0502 #define arg3 (_i_._arg3)
0503 #define sarg3 ((PSInteger)*((const signed char *)&_i_._arg3))
0504
0505 PSRESULT PSVM::Suspend()
0506 {
0507 if (_suspended)
0508 return ps_throwerror(this, _SC("cannot suspend an already suspended vm"));
0509 if (_nnativecalls!=2)
0510 return ps_throwerror(this, _SC("cannot suspend through native calls/metamethods"));
0511 return PS_SUSPEND_FLAG;
0512 }
0513
0514
0515 #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
0516 bool PSVM::FOREACH_OP(PSObjectPtr &o1,PSObjectPtr &o2,PSObjectPtr
0517 &o3,PSObjectPtr &o4,PSInteger PS_UNUSED_ARG(arg_2),int exitpos,int &jump)
0518 {
0519 PSInteger nrefidx;
0520 switch(type(o1)) {
0521 case OT_TABLE:
0522 if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);
0523 o4 = (PSInteger)nrefidx; _FINISH(1);
0524 case OT_ARRAY:
0525 if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);
0526 o4 = (PSInteger) nrefidx; _FINISH(1);
0527 case OT_STRING:
0528 if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
0529 o4 = (PSInteger)nrefidx; _FINISH(1);
0530 case OT_CLASS:
0531 if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
0532 o4 = (PSInteger)nrefidx; _FINISH(1);
0533 case OT_USERDATA:
0534 case OT_INSTANCE:
0535 if(_delegable(o1)->_delegate) {
0536 PSObjectPtr itr;
0537 PSObjectPtr closure;
0538 if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {
0539 Push(o1);
0540 Push(o4);
0541 if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {
0542 o4 = o2 = itr;
0543 if(type(itr) == OT_NULL) _FINISH(exitpos);
0544 if(!Get(o1, itr, o3, 0, DONT_FALL_BACK)) {
0545 Raise_Error(_SC("_nexti returned an invalid idx"));
0546 return false;
0547 }
0548 _FINISH(1);
0549 }
0550 else {
0551 return false;
0552 }
0553 }
0554 Raise_Error(_SC("_nexti failed"));
0555 return false;
0556 }
0557 break;
0558 case OT_GENERATOR:
0559 if(_generator(o1)->_state == PSGenerator::eDead) _FINISH(exitpos);
0560 if(_generator(o1)->_state == PSGenerator::eSuspended) {
0561 PSInteger idx = 0;
0562 if(type(o4) == OT_INTEGER) {
0563 idx = _integer(o4) + 1;
0564 }
0565 o2 = idx;
0566 o4 = idx;
0567 _generator(o1)->Resume(this, o3);
0568 _FINISH(0);
0569 }
0570 default:
0571 Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
0572 }
0573 return false;
0574 }
0575
0576 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
0577
0578 #define PS_THROW() { goto exception_trap; }
0579
0580 #define _GUARD(exp) { if(!exp) { PS_THROW();} }
0581
0582 bool PSVM::CLOSURE_OP(PSObjectPtr &target, PSFunctionProto *func)
0583 {
0584 PSInteger nouters;
0585 PSClosure *closure = PSClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE));
0586 if((nouters = func->_noutervalues)) {
0587 for(PSInteger i = 0; i<nouters; i++) {
0588 PSOuterVar &v = func->_outervalues[i];
0589 switch(v._type){
0590 case otLOCAL:
0591 FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));
0592 break;
0593 case otOUTER:
0594 closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];
0595 break;
0596 }
0597 }
0598 }
0599 PSInteger ndefparams;
0600 if((ndefparams = func->_ndefaultparams)) {
0601 for(PSInteger i = 0; i < ndefparams; i++) {
0602 PSInteger spos = func->_defaultparams[i];
0603 closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
0604 }
0605 }
0606 target = closure;
0607 return true;
0608
0609 }
0610
0611
0612 bool PSVM::CLASS_OP(PSObjectPtr &target,PSInteger baseclass,PSInteger attributes)
0613 {
0614 PSClass *base = NULL;
0615 PSObjectPtr attrs;
0616 if(baseclass != -1) {
0617 if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
0618 base = _class(_stack._vals[_stackbase + baseclass]);
0619 }
0620 if(attributes != MAX_FUNC_STACKSIZE) {
0621 attrs = _stack._vals[_stackbase+attributes];
0622 }
0623 target = PSClass::Create(_ss(this),base);
0624 if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
0625 int nparams = 2;
0626 PSObjectPtr ret;
0627 Push(target); Push(attrs);
0628 if(!Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false)) {
0629 Pop(nparams);
0630 return false;
0631 }
0632 Pop(nparams);
0633 }
0634 _class(target)->_attributes = attrs;
0635 return true;
0636 }
0637
0638 bool PSVM::IsEqual(const PSObjectPtr &o1,const PSObjectPtr &o2,bool &res)
0639 {
0640 if(type(o1) == type(o2)) {
0641 res = (_rawval(o1) == _rawval(o2));
0642 }
0643 else {
0644 if(ps_isnumeric(o1) && ps_isnumeric(o2)) {
0645 res = (tofloat(o1) == tofloat(o2));
0646 }
0647 else {
0648 res = false;
0649 }
0650 }
0651 return true;
0652 }
0653
0654 bool PSVM::IsFalse(PSObjectPtr &o)
0655 {
0656 if(((type(o) & PSOBJECT_CANBEFALSE)
0657 && ( ((type(o) == OT_FLOAT) && (_float(o) == PSFloat(0.0))) ))
0658 #if !defined(PSUSEDOUBLE) || (defined(PSUSEDOUBLE) && defined(_PS64))
0659 || (_integer(o) == 0) )
0660 #else
0661 || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) )
0662 #endif
0663 {
0664 return true;
0665 }
0666 return false;
0667 }
0668 extern PSInstructionDesc g_InstrDesc[];
0669 bool PSVM::Execute(PSObjectPtr &closure, PSInteger nargs, PSInteger stackbase,PSObjectPtr &outres, PSBool raiseerror,ExecutionType et)
0670 {
0671 if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
0672 _nnativecalls++;
0673 AutoDec ad(&_nnativecalls);
0674 PSInteger traps = 0;
0675 CallInfo *prevci = ci;
0676
0677 switch(et) {
0678 case ET_CALL: {
0679 temp_reg = closure;
0680 if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) {
0681
0682 if(ci == NULL) CallErrorHandler(_lasterror);
0683 return false;
0684 }
0685 if(ci == prevci) {
0686 outres = STK(_top-nargs);
0687 return true;
0688 }
0689 ci->_root = PSTrue;
0690 }
0691 break;
0692 case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = PSTrue; traps += ci->_etraps; break;
0693 case ET_RESUME_VM:
0694 case ET_RESUME_THROW_VM:
0695 traps = _suspended_traps;
0696 ci->_root = _suspended_root;
0697 _suspended = PSFalse;
0698 if(et == ET_RESUME_THROW_VM) { PS_THROW(); }
0699 break;
0700 }
0701
0702 exception_restore:
0703
0704 {
0705 for(;;)
0706 {
0707 const PSInstruction &_i_ = *ci->_ip++;
0708
0709
0710 switch(_i_.op)
0711 {
0712 case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
0713 case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
0714 case _OP_LOADINT:
0715 #ifndef _PS64
0716 TARGET = (PSInteger)arg1; continue;
0717 #else
0718 TARGET = (PSInteger)((PSInt32)arg1); continue;
0719 #endif
0720 case _OP_LOADFLOAT: TARGET = *((const PSFloat *)&arg1); continue;
0721 case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
0722 case _OP_TAILCALL:{
0723 PSObjectPtr &t = STK(arg1);
0724 if (type(t) == OT_CLOSURE
0725 && (!_closure(t)->_function->_bgenerator)){
0726 PSObjectPtr clo = t;
0727 if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
0728 for (PSInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
0729 _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
0730 continue;
0731 }
0732 }
0733 case _OP_CALL: {
0734 PSObjectPtr clo = STK(arg1);
0735 switch (type(clo)) {
0736 case OT_CLOSURE:
0737 _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
0738 continue;
0739 case OT_NATIVECLOSURE: {
0740 bool suspend;
0741 _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
0742 if(suspend){
0743 _suspended = PSTrue;
0744 _suspended_target = sarg0;
0745 _suspended_root = ci->_root;
0746 _suspended_traps = traps;
0747 outres = clo;
0748 return true;
0749 }
0750 if(sarg0 != -1) {
0751 STK(arg0) = clo;
0752 }
0753 }
0754 continue;
0755 case OT_CLASS:{
0756 PSObjectPtr inst;
0757 _GUARD(CreateClassInstance(_class(clo),inst,clo));
0758 if(sarg0 != -1) {
0759 STK(arg0) = inst;
0760 }
0761 PSInteger stkbase;
0762 switch(type(clo)) {
0763 case OT_CLOSURE:
0764 stkbase = _stackbase+arg2;
0765 _stack._vals[stkbase] = inst;
0766 _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
0767 break;
0768 case OT_NATIVECLOSURE:
0769 bool suspend;
0770 stkbase = _stackbase+arg2;
0771 _stack._vals[stkbase] = inst;
0772 _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
0773 break;
0774 default: break;
0775 }
0776 }
0777 break;
0778 case OT_TABLE:
0779 case OT_USERDATA:
0780 case OT_INSTANCE:{
0781 PSObjectPtr closure;
0782 if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
0783 Push(clo);
0784 for (PSInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
0785 if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) PS_THROW();
0786 if(sarg0 != -1) {
0787 STK(arg0) = clo;
0788 }
0789 break;
0790 }
0791
0792
0793
0794 }
0795 default:
0796 Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
0797 PS_THROW();
0798 }
0799 }
0800 continue;
0801 case _OP_PREPCALL:
0802 case _OP_PREPCALLK: {
0803 PSObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
0804 PSObjectPtr &o = STK(arg2);
0805 if (!Get(o, key, temp_reg,0,arg2)) {
0806 PS_THROW();
0807 }
0808 STK(arg3) = o;
0809 _Swap(TARGET,temp_reg);
0810 }
0811 continue;
0812 case _OP_GETK:
0813 if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, 0,arg2)) { PS_THROW();}
0814 _Swap(TARGET,temp_reg);
0815 continue;
0816 case _OP_MOVE: TARGET = STK(arg1); continue;
0817 case _OP_NEWSLOT:
0818 _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
0819 if(arg0 != 0xFF) TARGET = STK(arg3);
0820 continue;
0821 case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
0822 case _OP_SET:
0823 if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { PS_THROW(); }
0824 if (arg0 != 0xFF) TARGET = STK(arg3);
0825 continue;
0826 case _OP_GET:
0827 if (!Get(STK(arg1), STK(arg2), temp_reg, 0,arg1)) { PS_THROW(); }
0828 _Swap(TARGET,temp_reg);
0829 continue;
0830 case _OP_EQ:{
0831 bool res;
0832 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { PS_THROW(); }
0833 TARGET = res?true:false;
0834 }continue;
0835 case _OP_NE:{
0836 bool res;
0837 if(!IsEqual(STK(arg2),COND_LITERAL,res)) { PS_THROW(); }
0838 TARGET = (!res)?true:false;
0839 } continue;
0840 case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
0841 case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
0842 case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
0843 case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
0844 case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
0845 case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
0846 case _OP_RETURN:
0847 if((ci)->_generator) {
0848 (ci)->_generator->Kill();
0849 }
0850 if(Return(arg0, arg1, temp_reg)){
0851 assert(traps==0);
0852
0853 _Swap(outres,temp_reg);
0854 return true;
0855 }
0856 continue;
0857 case _OP_LOADNULLS:{ for(PSInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
0858 case _OP_LOADROOT: {
0859 PSWeakRef *w = _closure(ci->_closure)->_root;
0860 if(type(w->_obj) != OT_NULL) {
0861 TARGET = w->_obj;
0862 } else {
0863 TARGET = _roottable;
0864 }
0865 }
0866 continue;
0867 case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
0868 case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
0869 case _OP_JMP: ci->_ip += (sarg1); continue;
0870
0871 case _OP_JCMP:
0872 _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
0873 if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
0874 continue;
0875 case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
0876 case _OP_GETOUTER: {
0877 PSClosure *cur_cls = _closure(ci->_closure);
0878 PSOuter *otr = _outer(cur_cls->_outervalues[arg1]);
0879 TARGET = *(otr->_valptr);
0880 }
0881 continue;
0882 case _OP_SETOUTER: {
0883 PSClosure *cur_cls = _closure(ci->_closure);
0884 PSOuter *otr = _outer(cur_cls->_outervalues[arg1]);
0885 *(otr->_valptr) = STK(arg2);
0886 if(arg0 != 0xFF) {
0887 TARGET = STK(arg2);
0888 }
0889 }
0890 continue;
0891 case _OP_NEWOBJ:
0892 switch(arg3) {
0893 case NOT_TABLE: TARGET = PSTable::Create(_ss(this), arg1); continue;
0894 case NOT_ARRAY: TARGET = PSArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
0895 case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
0896 default: assert(0); continue;
0897 }
0898 case _OP_APPENDARRAY:
0899 {
0900 PSObject val;
0901 val._unVal.raw = 0;
0902 switch(arg2) {
0903 case AAT_STACK:
0904 val = STK(arg1); break;
0905 case AAT_LITERAL:
0906 val = ci->_literals[arg1]; break;
0907 case AAT_INT:
0908 val._type = OT_INTEGER;
0909 #ifndef _PS64
0910 val._unVal.nInteger = (PSInteger)arg1;
0911 #else
0912 val._unVal.nInteger = (PSInteger)((PSInt32)arg1);
0913 #endif
0914 break;
0915 case AAT_FLOAT:
0916 val._type = OT_FLOAT;
0917 val._unVal.fFloat = *((const PSFloat *)&arg1);
0918 break;
0919 case AAT_BOOL:
0920 val._type = OT_BOOL;
0921 val._unVal.nInteger = arg1;
0922 break;
0923 default: val._type = OT_INTEGER; assert(0); break;
0924
0925 }
0926 _array(STK(arg0))->Append(val); continue;
0927 }
0928 case _OP_COMPARITH: {
0929 PSInteger selfidx = (((PSUnsignedInteger)arg1&0xFFFF0000)>>16);
0930 _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
0931 }
0932 continue;
0933 case _OP_INC: {PSObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
0934 case _OP_INCL: {
0935 PSObjectPtr &a = STK(arg1);
0936 if(type(a) == OT_INTEGER) {
0937 a._unVal.nInteger = _integer(a) + sarg3;
0938 }
0939 else {
0940 PSObjectPtr o(sarg3);
0941 _ARITH_(+,a,a,o);
0942 }
0943 } continue;
0944 case _OP_PINC: {PSObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
0945 case _OP_PINCL: {
0946 PSObjectPtr &a = STK(arg1);
0947 if(type(a) == OT_INTEGER) {
0948 TARGET = a;
0949 a._unVal.nInteger = _integer(a) + sarg3;
0950 }
0951 else {
0952 PSObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));
0953 }
0954
0955 } continue;
0956 case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue;
0957 case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | GET_FLAG_RAW, DONT_FALL_BACK) ? true : false; continue;
0958 case _OP_INSTANCEOF:
0959 if(type(STK(arg1)) != OT_CLASS)
0960 {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); PS_THROW();}
0961 TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
0962 continue;
0963 case _OP_AND:
0964 if(IsFalse(STK(arg2))) {
0965 TARGET = STK(arg2);
0966 ci->_ip += (sarg1);
0967 }
0968 continue;
0969 case _OP_OR:
0970 if(!IsFalse(STK(arg2))) {
0971 TARGET = STK(arg2);
0972 ci->_ip += (sarg1);
0973 }
0974 continue;
0975 case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
0976 case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
0977 case _OP_BWNOT:
0978 if(type(STK(arg1)) == OT_INTEGER) {
0979 PSInteger t = _integer(STK(arg1));
0980 TARGET = PSInteger(~t);
0981 continue;
0982 }
0983 Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
0984 PS_THROW();
0985 case _OP_CLOSURE: {
0986 PSClosure *c = ci->_closure._unVal.pClosure;
0987 PSFunctionProto *fp = c->_function;
0988 if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { PS_THROW(); }
0989 continue;
0990 }
0991 case _OP_YIELD:{
0992 if(ci->_generator) {
0993 if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
0994 _GUARD(ci->_generator->Yield(this,arg2));
0995 traps -= ci->_etraps;
0996 if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);
0997 }
0998 else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); PS_THROW();}
0999 if(Return(arg0, arg1, temp_reg)){
1000 assert(traps == 0);
1001 outres = temp_reg;
1002 return true;
1003 }
1004
1005 }
1006 continue;
1007 case _OP_RESUME:
1008 if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); PS_THROW();}
1009 _GUARD(_generator(STK(arg1))->Resume(this, TARGET));
1010 traps += ci->_etraps;
1011 continue;
1012 case _OP_FOREACH:{ int tojump;
1013 _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
1014 ci->_ip += tojump; }
1015 continue;
1016 case _OP_POSTFOREACH:
1017 assert(type(STK(arg0)) == OT_GENERATOR);
1018 if(_generator(STK(arg0))->_state == PSGenerator::eDead)
1019 ci->_ip += (sarg1 - 1);
1020 continue;
1021 case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
1022 case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
1023 case _OP_PUSHTRAP:{
1024 PSInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
1025 _etraps.push_back(PSExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
1026 ci->_etraps++;
1027 }
1028 continue;
1029 case _OP_POPTRAP: {
1030 for(PSInteger i = 0; i < arg0; i++) {
1031 _etraps.pop_back(); traps--;
1032 ci->_etraps--;
1033 }
1034 }
1035 continue;
1036 case _OP_THROW: Raise_Error(TARGET); PS_THROW(); continue;
1037 case _OP_NEWSLOTA:
1038 _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : PSObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
1039 continue;
1040 case _OP_GETBASE:{
1041 PSClosure *clo = _closure(ci->_closure);
1042 if(clo->_base) {
1043 TARGET = clo->_base;
1044 }
1045 else {
1046 TARGET.Null();
1047 }
1048 continue;
1049 }
1050 case _OP_CLOSE:
1051 if(_openouters) CloseOuters(&(STK(arg1)));
1052 continue;
1053 }
1054
1055 }
1056 }
1057 exception_trap:
1058 {
1059 PSObjectPtr currerror = _lasterror;
1060
1061
1062 PSInteger last_top = _top;
1063
1064 if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
1065
1066 while( ci ) {
1067 if(ci->_etraps > 0) {
1068 PSExceptionTrap &et = _etraps.top();
1069 ci->_ip = et._ip;
1070 _top = et._stacksize;
1071 _stackbase = et._stackbase;
1072 _stack._vals[_stackbase + et._extarget] = currerror;
1073 _etraps.pop_back(); traps--; ci->_etraps--;
1074 while(last_top >= _top) _stack._vals[last_top--].Null();
1075 goto exception_restore;
1076 }
1077 else if (_debughook) {
1078
1079
1080 for(PSInteger i = 0; i < ci->_ncalls; i++) {
1081 CallDebugHook(_SC('r'));
1082 }
1083 }
1084 if(ci->_generator) ci->_generator->Kill();
1085 bool mustbreak = ci && ci->_root;
1086 LeaveFrame();
1087 if(mustbreak) break;
1088 }
1089
1090 _lasterror = currerror;
1091 return false;
1092 }
1093 assert(0);
1094 }
1095
1096 bool PSVM::CreateClassInstance(PSClass *theclass, PSObjectPtr &inst, PSObjectPtr &constructor)
1097 {
1098 inst = theclass->CreateInstance();
1099 if(!theclass->GetConstructor(constructor)) {
1100 constructor.Null();
1101 }
1102 return true;
1103 }
1104
1105 void PSVM::CallErrorHandler(PSObjectPtr &error)
1106 {
1107 if(type(_errorhandler) != OT_NULL) {
1108 PSObjectPtr out;
1109 Push(_roottable); Push(error);
1110 Call(_errorhandler, 2, _top-2, out,PSFalse);
1111 Pop(2);
1112 }
1113 }
1114
1115
1116 void PSVM::CallDebugHook(PSInteger type,PSInteger forcedline)
1117 {
1118 _debughook = false;
1119 PSFunctionProto *func=_closure(ci->_closure)->_function;
1120 if(_debughook_native) {
1121 const PSChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
1122 const PSChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
1123 PSInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
1124 _debughook_native(this,type,src,line,fname);
1125 }
1126 else {
1127 PSObjectPtr temp_reg;
1128 PSInteger nparams=5;
1129 Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
1130 Call(_debughook_closure,nparams,_top-nparams,temp_reg,PSFalse);
1131 Pop(nparams);
1132 }
1133 _debughook = true;
1134 }
1135
1136 bool PSVM::CallNative(PSNativeClosure *nclosure, PSInteger nargs, PSInteger newbase, PSObjectPtr &retval, bool &suspend)
1137 {
1138 PSInteger nparamscheck = nclosure->_nparamscheck;
1139 PSInteger newtop = newbase + nargs + nclosure->_noutervalues;
1140
1141 if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
1142 Raise_Error(_SC("Native stack overflow"));
1143 return false;
1144 }
1145
1146 if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
1147 ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
1148 {
1149 Raise_Error(_SC("wrong number of parameters"));
1150 return false;
1151 }
1152
1153 PSInteger tcs;
1154 PSIntVec &tc = nclosure->_typecheck;
1155 if((tcs = tc.size())) {
1156 for(PSInteger i = 0; i < nargs && i < tcs; i++) {
1157 if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
1158 Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
1159 return false;
1160 }
1161 }
1162 }
1163
1164 if(!EnterFrame(newbase, newtop, false)) return false;
1165 ci->_closure = nclosure;
1166
1167 PSInteger outers = nclosure->_noutervalues;
1168 for (PSInteger i = 0; i < outers; i++) {
1169 _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
1170 }
1171 if(nclosure->_env) {
1172 _stack._vals[newbase] = nclosure->_env->_obj;
1173 }
1174
1175 _nnativecalls++;
1176 PSInteger ret = (nclosure->_function)(this);
1177 _nnativecalls--;
1178
1179 suspend = false;
1180 if (ret == PS_SUSPEND_FLAG) {
1181 suspend = true;
1182 }
1183 else if (ret < 0) {
1184 LeaveFrame();
1185 Raise_Error(_lasterror);
1186 return false;
1187 }
1188 if(ret) {
1189 retval = _stack._vals[_top-1];
1190 }
1191 else {
1192 retval.Null();
1193 }
1194
1195 LeaveFrame();
1196 return true;
1197 }
1198
1199 #define FALLBACK_OK 0
1200 #define FALLBACK_NO_MATCH 1
1201 #define FALLBACK_ERROR 2
1202
1203 bool PSVM::Get(const PSObjectPtr &self, const PSObjectPtr &key, PSObjectPtr &dest, PSUnsignedInteger getflags, PSInteger selfidx)
1204 {
1205 switch(type(self)){
1206 case OT_TABLE:
1207 if(_table(self)->Get(key,dest))return true;
1208 break;
1209 case OT_ARRAY:
1210 if (ps_isnumeric(key)) { if (_array(self)->Get(tointeger(key), dest)) { return true; } if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); return false; }
1211 break;
1212 case OT_INSTANCE:
1213 if(_instance(self)->Get(key,dest)) return true;
1214 break;
1215 case OT_CLASS:
1216 if(_class(self)->Get(key,dest)) return true;
1217 break;
1218 case OT_STRING:
1219 if(ps_isnumeric(key)){
1220 PSInteger n = tointeger(key);
1221 PSInteger len = _string(self)->_len;
1222 if (n < 0) { n += len; }
1223 if (n >= 0 && n < len) {
1224 dest = PSInteger(_stringval(self)[n]);
1225 return true;
1226 }
1227 if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
1228 return false;
1229 }
1230 break;
1231 default:break;
1232 }
1233 if ((getflags & GET_FLAG_RAW) == 0) {
1234 switch(FallBackGet(self,key,dest)) {
1235 case FALLBACK_OK: return true;
1236 case FALLBACK_NO_MATCH: break;
1237 case FALLBACK_ERROR: return false;
1238 }
1239 if(InvokeDefaultDelegate(self,key,dest)) {
1240 return true;
1241 }
1242 }
1243
1244 if(selfidx == 0) {
1245 PSWeakRef *w = _closure(ci->_closure)->_root;
1246 if(type(w->_obj) != OT_NULL)
1247 {
1248 if(Get(*((const PSObjectPtr *)&w->_obj),key,dest,0,DONT_FALL_BACK)) return true;
1249 }
1250
1251 }
1252
1253 if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
1254 return false;
1255 }
1256
1257 bool PSVM::InvokeDefaultDelegate(const PSObjectPtr &self,const PSObjectPtr &key,PSObjectPtr &dest)
1258 {
1259 PSTable *ddel = NULL;
1260 switch(type(self)) {
1261 case OT_CLASS: ddel = _class_ddel; break;
1262 case OT_TABLE: ddel = _table_ddel; break;
1263 case OT_ARRAY: ddel = _array_ddel; break;
1264 case OT_STRING: ddel = _string_ddel; break;
1265 case OT_INSTANCE: ddel = _instance_ddel; break;
1266 case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
1267 case OT_GENERATOR: ddel = _generator_ddel; break;
1268 case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;
1269 case OT_THREAD: ddel = _thread_ddel; break;
1270 case OT_WEAKREF: ddel = _weakref_ddel; break;
1271 default: return false;
1272 }
1273 return ddel->Get(key,dest);
1274 }
1275
1276
1277 PSInteger PSVM::FallBackGet(const PSObjectPtr &self,const PSObjectPtr &key,PSObjectPtr &dest)
1278 {
1279 switch(type(self)){
1280 case OT_TABLE:
1281 case OT_USERDATA:
1282
1283 if(_delegable(self)->_delegate) {
1284 if(Get(PSObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK;
1285 }
1286 else {
1287 return FALLBACK_NO_MATCH;
1288 }
1289
1290 case OT_INSTANCE: {
1291 PSObjectPtr closure;
1292 if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
1293 Push(self);Push(key);
1294 _nmetamethodscall++;
1295 AutoDec ad(&_nmetamethodscall);
1296 if(Call(closure, 2, _top - 2, dest, PSFalse)) {
1297 Pop(2);
1298 return FALLBACK_OK;
1299 }
1300 else {
1301 Pop(2);
1302 if(type(_lasterror) != OT_NULL) {
1303 return FALLBACK_ERROR;
1304 }
1305 }
1306 }
1307 }
1308 break;
1309 default: break;
1310 }
1311
1312 return FALLBACK_NO_MATCH;
1313 }
1314
1315 bool PSVM::Set(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val,PSInteger selfidx)
1316 {
1317 switch(type(self)){
1318 case OT_TABLE:
1319 if(_table(self)->Set(key,val)) return true;
1320 break;
1321 case OT_INSTANCE:
1322 if(_instance(self)->Set(key,val)) return true;
1323 break;
1324 case OT_ARRAY:
1325 if(!ps_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
1326 if(!_array(self)->Set(tointeger(key),val)) {
1327 Raise_IdxError(key);
1328 return false;
1329 }
1330 return true;
1331 default:
1332 Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
1333 return false;
1334 }
1335
1336 switch(FallBackSet(self,key,val)) {
1337 case FALLBACK_OK: return true;
1338 case FALLBACK_NO_MATCH: break;
1339 case FALLBACK_ERROR: return false;
1340 }
1341 if(selfidx == 0) {
1342 if(_table(_roottable)->Set(key,val))
1343 return true;
1344 }
1345 Raise_IdxError(key);
1346 return false;
1347 }
1348
1349 PSInteger PSVM::FallBackSet(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val)
1350 {
1351 switch(type(self)) {
1352 case OT_TABLE:
1353 if(_table(self)->_delegate) {
1354 if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;
1355 }
1356
1357 case OT_INSTANCE:
1358 case OT_USERDATA:{
1359 PSObjectPtr closure;
1360 PSObjectPtr t;
1361 if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
1362 Push(self);Push(key);Push(val);
1363 _nmetamethodscall++;
1364 AutoDec ad(&_nmetamethodscall);
1365 if(Call(closure, 3, _top - 3, t, PSFalse)) {
1366 Pop(3);
1367 return FALLBACK_OK;
1368 }
1369 else {
1370 if(type(_lasterror) != OT_NULL) {
1371
1372 Pop(3);
1373 return FALLBACK_ERROR;
1374 }
1375 }
1376 }
1377 }
1378 break;
1379 default: break;
1380 }
1381
1382 return FALLBACK_NO_MATCH;
1383 }
1384
1385 bool PSVM::Clone(const PSObjectPtr &self,PSObjectPtr &target)
1386 {
1387 PSObjectPtr temp_reg;
1388 PSObjectPtr newobj;
1389 switch(type(self)){
1390 case OT_TABLE:
1391 newobj = _table(self)->Clone();
1392 goto cloned_mt;
1393 case OT_INSTANCE: {
1394 newobj = _instance(self)->Clone(_ss(this));
1395 cloned_mt:
1396 PSObjectPtr closure;
1397 if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
1398 Push(newobj);
1399 Push(self);
1400 if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
1401 return false;
1402 }
1403 }
1404 target = newobj;
1405 return true;
1406 case OT_ARRAY:
1407 target = _array(self)->Clone();
1408 return true;
1409 default:
1410 Raise_Error(_SC("cloning a %s"), GetTypeName(self));
1411 return false;
1412 }
1413 }
1414
1415 bool PSVM::NewSlotA(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val,const PSObjectPtr &attrs,bool bstatic,bool raw)
1416 {
1417 if(type(self) != OT_CLASS) {
1418 Raise_Error(_SC("object must be a class"));
1419 return false;
1420 }
1421 PSClass *c = _class(self);
1422 if(!raw) {
1423 PSObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
1424 if(type(mm) != OT_NULL ) {
1425 Push(self); Push(key); Push(val);
1426 Push(attrs);
1427 Push(bstatic);
1428 return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);
1429 }
1430 }
1431 if(!NewSlot(self, key, val,bstatic))
1432 return false;
1433 if(type(attrs) != OT_NULL) {
1434 c->SetAttributes(key,attrs);
1435 }
1436 return true;
1437 }
1438
1439 bool PSVM::NewSlot(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val,bool bstatic)
1440 {
1441 if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
1442 switch(type(self)) {
1443 case OT_TABLE: {
1444 bool rawcall = true;
1445 if(_table(self)->_delegate) {
1446 PSObjectPtr res;
1447 if(!_table(self)->Get(key,res)) {
1448 PSObjectPtr closure;
1449 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
1450 Push(self);Push(key);Push(val);
1451 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
1452 return false;
1453 }
1454 rawcall = false;
1455 }
1456 else {
1457 rawcall = true;
1458 }
1459 }
1460 }
1461 if(rawcall) _table(self)->NewSlot(key,val);
1462
1463 break;}
1464 case OT_INSTANCE: {
1465 PSObjectPtr res;
1466 PSObjectPtr closure;
1467 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
1468 Push(self);Push(key);Push(val);
1469 if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
1470 return false;
1471 }
1472 break;
1473 }
1474 Raise_Error(_SC("class instances do not support the new slot operator"));
1475 return false;
1476 break;}
1477 case OT_CLASS:
1478 if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
1479 if(_class(self)->_locked) {
1480 Raise_Error(_SC("trying to modify a class that has already been instantiated"));
1481 return false;
1482 }
1483 else {
1484 PSObjectPtr oval = PrintObjVal(key);
1485 Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
1486 return false;
1487 }
1488 }
1489 break;
1490 default:
1491 Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
1492 return false;
1493 break;
1494 }
1495 return true;
1496 }
1497
1498
1499
1500 bool PSVM::DeleteSlot(const PSObjectPtr &self,const PSObjectPtr &key,PSObjectPtr &res)
1501 {
1502 switch(type(self)) {
1503 case OT_TABLE:
1504 case OT_INSTANCE:
1505 case OT_USERDATA: {
1506 PSObjectPtr t;
1507
1508 PSObjectPtr closure;
1509 if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
1510 Push(self);Push(key);
1511 return CallMetaMethod(closure,MT_DELSLOT,2,res);
1512 }
1513 else {
1514 if(type(self) == OT_TABLE) {
1515 if(_table(self)->Get(key,t)) {
1516 _table(self)->Remove(key);
1517 }
1518 else {
1519 Raise_IdxError((const PSObject &)key);
1520 return false;
1521 }
1522 }
1523 else {
1524 Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
1525 return false;
1526 }
1527 }
1528 res = t;
1529 }
1530 break;
1531 default:
1532 Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
1533 return false;
1534 }
1535 return true;
1536 }
1537
1538 bool PSVM::Call(PSObjectPtr &closure,PSInteger nparams,PSInteger stackbase,PSObjectPtr &outres,PSBool raiseerror)
1539 {
1540 #ifdef _DEBUG
1541 PSInteger prevstackbase = _stackbase;
1542 #endif
1543 switch(type(closure)) {
1544 case OT_CLOSURE:
1545 return Execute(closure, nparams, stackbase, outres, raiseerror);
1546 break;
1547 case OT_NATIVECLOSURE:{
1548 bool suspend;
1549 return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
1550
1551 }
1552 break;
1553 case OT_CLASS: {
1554 PSObjectPtr constr;
1555 PSObjectPtr temp;
1556 CreateClassInstance(_class(closure),outres,constr);
1557 PSObjectType ctype = type(constr);
1558 if (ctype == OT_NATIVECLOSURE || ctype == OT_CLOSURE) {
1559 _stack[stackbase] = outres;
1560 return Call(constr,nparams,stackbase,temp,raiseerror);
1561 }
1562 return true;
1563 }
1564 break;
1565 default:
1566 return false;
1567 }
1568 #ifdef _DEBUG
1569 if(!_suspended) {
1570 assert(_stackbase == prevstackbase);
1571 }
1572 #endif
1573 return true;
1574 }
1575
1576 bool PSVM::CallMetaMethod(PSObjectPtr &closure,PSMetaMethod PS_UNUSED_ARG(mm),PSInteger nparams,PSObjectPtr &outres)
1577 {
1578
1579
1580 _nmetamethodscall++;
1581 if(Call(closure, nparams, _top - nparams, outres, PSFalse)) {
1582 _nmetamethodscall--;
1583 Pop(nparams);
1584 return true;
1585 }
1586 _nmetamethodscall--;
1587
1588 Pop(nparams);
1589 return false;
1590 }
1591
1592 void PSVM::FindOuter(PSObjectPtr &target, PSObjectPtr *stackindex)
1593 {
1594 PSOuter **pp = &_openouters;
1595 PSOuter *p;
1596 PSOuter *otr;
1597
1598 while ((p = *pp) != NULL && p->_valptr >= stackindex) {
1599 if (p->_valptr == stackindex) {
1600 target = PSObjectPtr(p);
1601 return;
1602 }
1603 pp = &p->_next;
1604 }
1605 otr = PSOuter::Create(_ss(this), stackindex);
1606 otr->_next = *pp;
1607 otr->_idx = (stackindex - _stack._vals);
1608 __ObjAddRef(otr);
1609 *pp = otr;
1610 target = PSObjectPtr(otr);
1611 }
1612
1613 bool PSVM::EnterFrame(PSInteger newbase, PSInteger newtop, bool tailcall)
1614 {
1615 if( !tailcall ) {
1616 if( _callsstacksize == _alloccallsstacksize ) {
1617 GrowCallStack();
1618 }
1619 ci = &_callsstack[_callsstacksize++];
1620 ci->_prevstkbase = (PSInt32)(newbase - _stackbase);
1621 ci->_prevtop = (PSInt32)(_top - _stackbase);
1622 ci->_etraps = 0;
1623 ci->_ncalls = 1;
1624 ci->_generator = NULL;
1625 ci->_root = PSFalse;
1626 }
1627 else {
1628 ci->_ncalls++;
1629 }
1630
1631 _stackbase = newbase;
1632 _top = newtop;
1633 if(newtop + MIN_STACK_OVERHEAD > (PSInteger)_stack.size()) {
1634 if(_nmetamethodscall) {
1635 Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod"));
1636 return false;
1637 }
1638 _stack.resize(newtop + (MIN_STACK_OVERHEAD << 2));
1639 RelocateOuters();
1640 }
1641 return true;
1642 }
1643
1644 void PSVM::LeaveFrame() {
1645 PSInteger last_top = _top;
1646 PSInteger last_stackbase = _stackbase;
1647 PSInteger css = --_callsstacksize;
1648
1649
1650 ci->_closure.Null();
1651 _stackbase -= ci->_prevstkbase;
1652 _top = _stackbase + ci->_prevtop;
1653 ci = (css) ? &_callsstack[css-1] : NULL;
1654
1655 if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
1656 while (last_top >= _top) {
1657 _stack._vals[last_top--].Null();
1658 }
1659 }
1660
1661 void PSVM::RelocateOuters()
1662 {
1663 PSOuter *p = _openouters;
1664 while (p) {
1665 p->_valptr = _stack._vals + p->_idx;
1666 p = p->_next;
1667 }
1668 }
1669
1670 void PSVM::CloseOuters(PSObjectPtr *stackindex) {
1671 PSOuter *p;
1672 while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
1673 p->_value = *(p->_valptr);
1674 p->_valptr = &p->_value;
1675 _openouters = p->_next;
1676 __ObjRelease(p);
1677 }
1678 }
1679
1680 void PSVM::Remove(PSInteger n) {
1681 n = (n >= 0)?n + _stackbase - 1:_top + n;
1682 for(PSInteger i = n; i < _top; i++){
1683 _stack[i] = _stack[i+1];
1684 }
1685 _stack[_top].Null();
1686 _top--;
1687 }
1688
1689 void PSVM::Pop() {
1690 _stack[--_top].Null();
1691 }
1692
1693 void PSVM::Pop(PSInteger n) {
1694 for(PSInteger i = 0; i < n; i++){
1695 _stack[--_top].Null();
1696 }
1697 }
1698
1699 void PSVM::PushNull() { _stack[_top++].Null(); }
1700 void PSVM::Push(const PSObjectPtr &o) { _stack[_top++] = o; }
1701 PSObjectPtr &PSVM::Top() { return _stack[_top-1]; }
1702 PSObjectPtr &PSVM::PopGet() { return _stack[--_top]; }
1703 PSObjectPtr &PSVM::GetUp(PSInteger n) { return _stack[_top+n]; }
1704 PSObjectPtr &PSVM::GetAt(PSInteger n) { return _stack[n]; }
1705
1706 #ifdef _DEBUG_DUMP
1707 void PSVM::dumpstack(PSInteger stackbase,bool dumpall)
1708 {
1709 PSInteger size=dumpall?_stack.size():_top;
1710 PSInteger n=0;
1711 scprintf(_SC("\n>>>>stack dump<<<<\n"));
1712 CallInfo &ci=_callsstack[_callsstacksize-1];
1713 scprintf(_SC("IP: %p\n"),ci._ip);
1714 scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
1715 scprintf(_SC("prev top: %d\n"),ci._prevtop);
1716 for(PSInteger i=0;i<size;i++){
1717 PSObjectPtr &obj=_stack[i];
1718 if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
1719 scprintf(_SC("[%d]:"),n);
1720 switch(type(obj)){
1721 case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
1722 case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break;
1723 case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
1724 case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
1725 case OT_NULL: scprintf(_SC("NULL")); break;
1726 case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
1727 case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break;
1728 case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
1729 case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;
1730 case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
1731 case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break;
1732 case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;
1733 case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
1734 case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;
1735 case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break;
1736 case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
1737 default:
1738 assert(0);
1739 break;
1740 };
1741 scprintf(_SC("\n"));
1742 ++n;
1743 }
1744 }
1745
1746
1747
1748 #endif