0001
0002
0003
0004 #include "pspcheader.h"
0005 #include "psvm.h"
0006 #include "psstring.h"
0007 #include "pstable.h"
0008 #include "psarray.h"
0009 #include "psfuncproto.h"
0010 #include "psclosure.h"
0011 #include "psuserdata.h"
0012 #include "pscompiler.h"
0013 #include "psfuncstate.h"
0014 #include "psclass.h"
0015
0016 static bool ps_aux_gettypedarg(HPSCRIPTVM v,PSInteger idx,PSObjectType type,PSObjectPtr **o)
0017 {
0018 *o = &stack_get(v,idx);
0019 if(type(**o) != type){
0020 PSObjectPtr oval = v->PrintObjVal(**o);
0021 v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
0022 return false;
0023 }
0024 return true;
0025 }
0026
0027 #define _GETSAFE_OBJ(v,idx,type,o) { if(!ps_aux_gettypedarg(v,idx,type,&o)) return PS_ERROR; }
0028
0029 #define ps_aux_paramscheck(v,count) \
0030 { \
0031 if(ps_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return PS_ERROR; }\
0032 }
0033
0034
0035 PSInteger ps_aux_invalidtype(HPSCRIPTVM v,PSObjectType type)
0036 {
0037 PSUnsignedInteger buf_size = 100 *sizeof(PSChar);
0038 scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type));
0039 return ps_throwerror(v, _ss(v)->GetScratchPad(-1));
0040 }
0041
0042 HPSCRIPTVM ps_open(PSInteger initialstacksize)
0043 {
0044 PSSharedState *ss;
0045 PSVM *v;
0046 ps_new(ss, PSSharedState);
0047 ss->Init();
0048 v = (PSVM *)PS_MALLOC(sizeof(PSVM));
0049 new (v) PSVM(ss);
0050 ss->_root_vm = v;
0051 if(v->Init(NULL, initialstacksize)) {
0052 return v;
0053 } else {
0054 ps_delete(v, PSVM);
0055 return NULL;
0056 }
0057 return v;
0058 }
0059
0060 HPSCRIPTVM ps_newthread(HPSCRIPTVM friendvm, PSInteger initialstacksize)
0061 {
0062 PSSharedState *ss;
0063 PSVM *v;
0064 ss=_ss(friendvm);
0065
0066 v= (PSVM *)PS_MALLOC(sizeof(PSVM));
0067 new (v) PSVM(ss);
0068
0069 if(v->Init(friendvm, initialstacksize)) {
0070 friendvm->Push(v);
0071 return v;
0072 } else {
0073 ps_delete(v, PSVM);
0074 return NULL;
0075 }
0076 }
0077
0078 PSInteger ps_getvmstate(HPSCRIPTVM v)
0079 {
0080 if(v->_suspended)
0081 return PS_VMSTATE_SUSPENDED;
0082 else {
0083 if(v->_callsstacksize != 0) return PS_VMSTATE_RUNNING;
0084 else return PS_VMSTATE_IDLE;
0085 }
0086 }
0087
0088 void ps_seterrorhandler(HPSCRIPTVM v)
0089 {
0090 PSObject o = stack_get(v, -1);
0091 if(ps_isclosure(o) || ps_isnativeclosure(o) || ps_isnull(o)) {
0092 v->_errorhandler = o;
0093 v->Pop();
0094 }
0095 }
0096
0097 void ps_setnativedebughook(HPSCRIPTVM v,PSDEBUGHOOK hook)
0098 {
0099 v->_debughook_native = hook;
0100 v->_debughook_closure.Null();
0101 v->_debughook = hook?true:false;
0102 }
0103
0104 void ps_setdebughook(HPSCRIPTVM v)
0105 {
0106 PSObject o = stack_get(v,-1);
0107 if(ps_isclosure(o) || ps_isnativeclosure(o) || ps_isnull(o)) {
0108 v->_debughook_closure = o;
0109 v->_debughook_native = NULL;
0110 v->_debughook = !ps_isnull(o);
0111 v->Pop();
0112 }
0113 }
0114
0115 void ps_close(HPSCRIPTVM v)
0116 {
0117 PSSharedState *ss = _ss(v);
0118 _thread(ss->_root_vm)->Finalize();
0119 ps_delete(ss, PSSharedState);
0120 }
0121
0122 PSInteger ps_getversion()
0123 {
0124 return PSCRIPT_VERSION_NUMBER;
0125 }
0126
0127 PSRESULT ps_compile(HPSCRIPTVM v,PSLEXREADFUNC read,PSUserPointer p,const PSChar *sourcename,PSBool raiseerror)
0128 {
0129 PSObjectPtr o;
0130 #ifndef NO_COMPILER
0131 if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
0132 v->Push(PSClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE)));
0133 return PS_OK;
0134 }
0135 return PS_ERROR;
0136 #else
0137 return ps_throwerror(v,_SC("this is a no compiler build"));
0138 #endif
0139 }
0140
0141 void ps_enabledebuginfo(HPSCRIPTVM v, PSBool enable)
0142 {
0143 _ss(v)->_debuginfo = enable?true:false;
0144 }
0145
0146 void ps_notifyallexceptions(HPSCRIPTVM v, PSBool enable)
0147 {
0148 _ss(v)->_notifyallexceptions = enable?true:false;
0149 }
0150
0151 void ps_addref(HPSCRIPTVM v,HPSOBJECT *po)
0152 {
0153 if(!ISREFCOUNTED(type(*po))) return;
0154 #ifdef NO_GARBAGE_COLLECTOR
0155 __AddRef(po->_type,po->_unVal);
0156 #else
0157 _ss(v)->_refs_table.AddRef(*po);
0158 #endif
0159 }
0160
0161 PSUnsignedInteger ps_getrefcount(HPSCRIPTVM v,HPSOBJECT *po)
0162 {
0163 if(!ISREFCOUNTED(type(*po))) return 0;
0164 #ifdef NO_GARBAGE_COLLECTOR
0165 return po->_unVal.pRefCounted->_uiRef;
0166 #else
0167 return _ss(v)->_refs_table.GetRefCount(*po);
0168 #endif
0169 }
0170
0171 PSBool ps_release(HPSCRIPTVM v,HPSOBJECT *po)
0172 {
0173 if(!ISREFCOUNTED(type(*po))) return PSTrue;
0174 #ifdef NO_GARBAGE_COLLECTOR
0175 bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? PSTrue : PSFalse;
0176 __Release(po->_type,po->_unVal);
0177 return ret;
0178 #else
0179 return _ss(v)->_refs_table.Release(*po);
0180 #endif
0181 }
0182
0183 PSUnsignedInteger ps_getvmrefcount(HPSCRIPTVM PS_UNUSED_ARG(v), const HPSOBJECT *po)
0184 {
0185 if (!ISREFCOUNTED(type(*po))) return 0;
0186 return po->_unVal.pRefCounted->_uiRef;
0187 }
0188
0189 const PSChar *ps_objtostring(const HPSOBJECT *o)
0190 {
0191 if(ps_type(*o) == OT_STRING) {
0192 return _stringval(*o);
0193 }
0194 return NULL;
0195 }
0196
0197 PSInteger ps_objtointeger(const HPSOBJECT *o)
0198 {
0199 if(ps_isnumeric(*o)) {
0200 return tointeger(*o);
0201 }
0202 return 0;
0203 }
0204
0205 PSFloat ps_objtofloat(const HPSOBJECT *o)
0206 {
0207 if(ps_isnumeric(*o)) {
0208 return tofloat(*o);
0209 }
0210 return 0;
0211 }
0212
0213 PSBool ps_objtobool(const HPSOBJECT *o)
0214 {
0215 if(ps_isbool(*o)) {
0216 return _integer(*o);
0217 }
0218 return PSFalse;
0219 }
0220
0221 PSUserPointer ps_objtouserpointer(const HPSOBJECT *o)
0222 {
0223 if(ps_isuserpointer(*o)) {
0224 return _userpointer(*o);
0225 }
0226 return 0;
0227 }
0228
0229 void ps_pushnull(HPSCRIPTVM v)
0230 {
0231 v->PushNull();
0232 }
0233
0234 void ps_pushstring(HPSCRIPTVM v,const PSChar *s,PSInteger len)
0235 {
0236 if(s)
0237 v->Push(PSObjectPtr(PSString::Create(_ss(v), s, len)));
0238 else v->PushNull();
0239 }
0240
0241 void ps_pushinteger(HPSCRIPTVM v,PSInteger n)
0242 {
0243 v->Push(n);
0244 }
0245
0246 void ps_pushbool(HPSCRIPTVM v,PSBool b)
0247 {
0248 v->Push(b?true:false);
0249 }
0250
0251 void ps_pushfloat(HPSCRIPTVM v,PSFloat n)
0252 {
0253 v->Push(n);
0254 }
0255
0256 void ps_pushuserpointer(HPSCRIPTVM v,PSUserPointer p)
0257 {
0258 v->Push(p);
0259 }
0260
0261 void ps_pushthread(HPSCRIPTVM v, HPSCRIPTVM thread)
0262 {
0263 v->Push(thread);
0264 }
0265
0266 PSUserPointer ps_newuserdata(HPSCRIPTVM v,PSUnsignedInteger size)
0267 {
0268 PSUserData *ud = PSUserData::Create(_ss(v), size + PS_ALIGNMENT);
0269 v->Push(ud);
0270 return (PSUserPointer)ps_aligning(ud + 1);
0271 }
0272
0273 void ps_newtable(HPSCRIPTVM v)
0274 {
0275 v->Push(PSTable::Create(_ss(v), 0));
0276 }
0277
0278 void ps_newtableex(HPSCRIPTVM v,PSInteger initialcapacity)
0279 {
0280 v->Push(PSTable::Create(_ss(v), initialcapacity));
0281 }
0282
0283 void ps_newarray(HPSCRIPTVM v,PSInteger size)
0284 {
0285 v->Push(PSArray::Create(_ss(v), size));
0286 }
0287
0288 PSRESULT ps_newclass(HPSCRIPTVM v,PSBool hasbase)
0289 {
0290 PSClass *baseclass = NULL;
0291 if(hasbase) {
0292 PSObjectPtr &base = stack_get(v,-1);
0293 if(type(base) != OT_CLASS)
0294 return ps_throwerror(v,_SC("invalid base type"));
0295 baseclass = _class(base);
0296 }
0297 PSClass *newclass = PSClass::Create(_ss(v), baseclass);
0298 if(baseclass) v->Pop();
0299 v->Push(newclass);
0300 return PS_OK;
0301 }
0302
0303 PSBool ps_instanceof(HPSCRIPTVM v)
0304 {
0305 PSObjectPtr &inst = stack_get(v,-1);
0306 PSObjectPtr &cl = stack_get(v,-2);
0307 if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)
0308 return ps_throwerror(v,_SC("invalid param type"));
0309 return _instance(inst)->InstanceOf(_class(cl))?PSTrue:PSFalse;
0310 }
0311
0312 PSRESULT ps_arrayappend(HPSCRIPTVM v,PSInteger idx)
0313 {
0314 ps_aux_paramscheck(v,2);
0315 PSObjectPtr *arr;
0316 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
0317 _array(*arr)->Append(v->GetUp(-1));
0318 v->Pop();
0319 return PS_OK;
0320 }
0321
0322 PSRESULT ps_arraypop(HPSCRIPTVM v,PSInteger idx,PSBool pushval)
0323 {
0324 ps_aux_paramscheck(v, 1);
0325 PSObjectPtr *arr;
0326 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
0327 if(_array(*arr)->Size() > 0) {
0328 if(pushval != 0){ v->Push(_array(*arr)->Top()); }
0329 _array(*arr)->Pop();
0330 return PS_OK;
0331 }
0332 return ps_throwerror(v, _SC("empty array"));
0333 }
0334
0335 PSRESULT ps_arrayresize(HPSCRIPTVM v,PSInteger idx,PSInteger newsize)
0336 {
0337 ps_aux_paramscheck(v,1);
0338 PSObjectPtr *arr;
0339 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
0340 if(newsize >= 0) {
0341 _array(*arr)->Resize(newsize);
0342 return PS_OK;
0343 }
0344 return ps_throwerror(v,_SC("negative size"));
0345 }
0346
0347
0348 PSRESULT ps_arrayreverse(HPSCRIPTVM v,PSInteger idx)
0349 {
0350 ps_aux_paramscheck(v, 1);
0351 PSObjectPtr *o;
0352 _GETSAFE_OBJ(v, idx, OT_ARRAY,o);
0353 PSArray *arr = _array(*o);
0354 if(arr->Size() > 0) {
0355 PSObjectPtr t;
0356 PSInteger size = arr->Size();
0357 PSInteger n = size >> 1; size -= 1;
0358 for(PSInteger i = 0; i < n; i++) {
0359 t = arr->_values[i];
0360 arr->_values[i] = arr->_values[size-i];
0361 arr->_values[size-i] = t;
0362 }
0363 return PS_OK;
0364 }
0365 return PS_OK;
0366 }
0367
0368 PSRESULT ps_arrayremove(HPSCRIPTVM v,PSInteger idx,PSInteger itemidx)
0369 {
0370 ps_aux_paramscheck(v, 1);
0371 PSObjectPtr *arr;
0372 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
0373 return _array(*arr)->Remove(itemidx) ? PS_OK : ps_throwerror(v,_SC("index out of range"));
0374 }
0375
0376 PSRESULT ps_arrayinsert(HPSCRIPTVM v,PSInteger idx,PSInteger destpos)
0377 {
0378 ps_aux_paramscheck(v, 1);
0379 PSObjectPtr *arr;
0380 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
0381 PSRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? PS_OK : ps_throwerror(v,_SC("index out of range"));
0382 v->Pop();
0383 return ret;
0384 }
0385
0386 void ps_newclosure(HPSCRIPTVM v,PSFUNCTION func,PSUnsignedInteger nfreevars)
0387 {
0388 PSNativeClosure *nc = PSNativeClosure::Create(_ss(v), func,nfreevars);
0389 nc->_nparamscheck = 0;
0390 for(PSUnsignedInteger i = 0; i < nfreevars; i++) {
0391 nc->_outervalues[i] = v->Top();
0392 v->Pop();
0393 }
0394 v->Push(PSObjectPtr(nc));
0395 }
0396
0397 PSRESULT ps_getclosureinfo(HPSCRIPTVM v,PSInteger idx,PSUnsignedInteger *nparams,PSUnsignedInteger *nfreevars)
0398 {
0399 PSObject o = stack_get(v, idx);
0400 if(type(o) == OT_CLOSURE) {
0401 PSClosure *c = _closure(o);
0402 PSFunctionProto *proto = c->_function;
0403 *nparams = (PSUnsignedInteger)proto->_nparameters;
0404 *nfreevars = (PSUnsignedInteger)proto->_noutervalues;
0405 return PS_OK;
0406 }
0407 else if(type(o) == OT_NATIVECLOSURE)
0408 {
0409 PSNativeClosure *c = _nativeclosure(o);
0410 *nparams = (PSUnsignedInteger)c->_nparamscheck;
0411 *nfreevars = c->_noutervalues;
0412 return PS_OK;
0413 }
0414 return ps_throwerror(v,_SC("the object is not a closure"));
0415 }
0416
0417 PSRESULT ps_setnativeclosurename(HPSCRIPTVM v,PSInteger idx,const PSChar *name)
0418 {
0419 PSObject o = stack_get(v, idx);
0420 if(ps_isnativeclosure(o)) {
0421 PSNativeClosure *nc = _nativeclosure(o);
0422 nc->_name = PSString::Create(_ss(v),name);
0423 return PS_OK;
0424 }
0425 return ps_throwerror(v,_SC("the object is not a nativeclosure"));
0426 }
0427
0428 PSRESULT ps_setparamscheck(HPSCRIPTVM v,PSInteger nparamscheck,const PSChar *typemask)
0429 {
0430 PSObject o = stack_get(v, -1);
0431 if(!ps_isnativeclosure(o))
0432 return ps_throwerror(v, _SC("native closure expected"));
0433 PSNativeClosure *nc = _nativeclosure(o);
0434 nc->_nparamscheck = nparamscheck;
0435 if(typemask) {
0436 PSIntVec res;
0437 if(!CompileTypemask(res, typemask))
0438 return ps_throwerror(v, _SC("invalid typemask"));
0439 nc->_typecheck.copy(res);
0440 }
0441 else {
0442 nc->_typecheck.resize(0);
0443 }
0444 if(nparamscheck == PS_MATCHTYPEMASKSTRING) {
0445 nc->_nparamscheck = nc->_typecheck.size();
0446 }
0447 return PS_OK;
0448 }
0449
0450 PSRESULT ps_bindenv(HPSCRIPTVM v,PSInteger idx)
0451 {
0452 PSObjectPtr &o = stack_get(v,idx);
0453 if(!ps_isnativeclosure(o) &&
0454 !ps_isclosure(o))
0455 return ps_throwerror(v,_SC("the target is not a closure"));
0456 PSObjectPtr &env = stack_get(v,-1);
0457 if(!ps_istable(env) &&
0458 !ps_isarray(env) &&
0459 !ps_isclass(env) &&
0460 !ps_isinstance(env))
0461 return ps_throwerror(v,_SC("invalid environment"));
0462 PSWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
0463 PSObjectPtr ret;
0464 if(ps_isclosure(o)) {
0465 PSClosure *c = _closure(o)->Clone();
0466 __ObjRelease(c->_env);
0467 c->_env = w;
0468 __ObjAddRef(c->_env);
0469 if(_closure(o)->_base) {
0470 c->_base = _closure(o)->_base;
0471 __ObjAddRef(c->_base);
0472 }
0473 ret = c;
0474 }
0475 else {
0476 PSNativeClosure *c = _nativeclosure(o)->Clone();
0477 __ObjRelease(c->_env);
0478 c->_env = w;
0479 __ObjAddRef(c->_env);
0480 ret = c;
0481 }
0482 v->Pop();
0483 v->Push(ret);
0484 return PS_OK;
0485 }
0486
0487 PSRESULT ps_getclosurename(HPSCRIPTVM v,PSInteger idx)
0488 {
0489 PSObjectPtr &o = stack_get(v,idx);
0490 if(!ps_isnativeclosure(o) &&
0491 !ps_isclosure(o))
0492 return ps_throwerror(v,_SC("the target is not a closure"));
0493 if(ps_isnativeclosure(o))
0494 {
0495 v->Push(_nativeclosure(o)->_name);
0496 }
0497 else {
0498 v->Push(_closure(o)->_function->_name);
0499 }
0500 return PS_OK;
0501 }
0502
0503 PSRESULT ps_setclosureroot(HPSCRIPTVM v,PSInteger idx)
0504 {
0505 PSObjectPtr &c = stack_get(v,idx);
0506 PSObject o = stack_get(v, -1);
0507 if(!ps_isclosure(c)) return ps_throwerror(v, _SC("closure expected"));
0508 if(ps_istable(o)) {
0509 _closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE));
0510 v->Pop();
0511 return PS_OK;
0512 }
0513 return ps_throwerror(v, _SC("ivalid type"));
0514 }
0515
0516 PSRESULT ps_getclosureroot(HPSCRIPTVM v,PSInteger idx)
0517 {
0518 PSObjectPtr &c = stack_get(v,idx);
0519 if(!ps_isclosure(c)) return ps_throwerror(v, _SC("closure expected"));
0520 v->Push(_closure(c)->_root->_obj);
0521 return PS_OK;
0522 }
0523
0524 PSRESULT ps_clear(HPSCRIPTVM v,PSInteger idx)
0525 {
0526 PSObject &o=stack_get(v,idx);
0527 switch(type(o)) {
0528 case OT_TABLE: _table(o)->Clear(); break;
0529 case OT_ARRAY: _array(o)->Resize(0); break;
0530 default:
0531 return ps_throwerror(v, _SC("clear only works on table and array"));
0532 break;
0533
0534 }
0535 return PS_OK;
0536 }
0537
0538 void ps_pushroottable(HPSCRIPTVM v)
0539 {
0540 v->Push(v->_roottable);
0541 }
0542
0543 void ps_pushregistrytable(HPSCRIPTVM v)
0544 {
0545 v->Push(_ss(v)->_registry);
0546 }
0547
0548 void ps_pushconsttable(HPSCRIPTVM v)
0549 {
0550 v->Push(_ss(v)->_consts);
0551 }
0552
0553 PSRESULT ps_setroottable(HPSCRIPTVM v)
0554 {
0555 PSObject o = stack_get(v, -1);
0556 if(ps_istable(o) || ps_isnull(o)) {
0557 v->_roottable = o;
0558 v->Pop();
0559 return PS_OK;
0560 }
0561 return ps_throwerror(v, _SC("ivalid type"));
0562 }
0563
0564 PSRESULT ps_setconsttable(HPSCRIPTVM v)
0565 {
0566 PSObject o = stack_get(v, -1);
0567 if(ps_istable(o)) {
0568 _ss(v)->_consts = o;
0569 v->Pop();
0570 return PS_OK;
0571 }
0572 return ps_throwerror(v, _SC("ivalid type, expected table"));
0573 }
0574
0575 void ps_setforeignptr(HPSCRIPTVM v,PSUserPointer p)
0576 {
0577 v->_foreignptr = p;
0578 }
0579
0580 PSUserPointer ps_getforeignptr(HPSCRIPTVM v)
0581 {
0582 return v->_foreignptr;
0583 }
0584
0585 void ps_setsharedforeignptr(HPSCRIPTVM v,PSUserPointer p)
0586 {
0587 _ss(v)->_foreignptr = p;
0588 }
0589
0590 PSUserPointer ps_getsharedforeignptr(HPSCRIPTVM v)
0591 {
0592 return _ss(v)->_foreignptr;
0593 }
0594
0595 void ps_setvmreleasehook(HPSCRIPTVM v,PSRELEASEHOOK hook)
0596 {
0597 v->_releasehook = hook;
0598 }
0599
0600 PSRELEASEHOOK ps_getvmreleasehook(HPSCRIPTVM v)
0601 {
0602 return v->_releasehook;
0603 }
0604
0605 void ps_setsharedreleasehook(HPSCRIPTVM v,PSRELEASEHOOK hook)
0606 {
0607 _ss(v)->_releasehook = hook;
0608 }
0609
0610 PSRELEASEHOOK ps_getsharedreleasehook(HPSCRIPTVM v)
0611 {
0612 return _ss(v)->_releasehook;
0613 }
0614
0615 void ps_push(HPSCRIPTVM v,PSInteger idx)
0616 {
0617 v->Push(stack_get(v, idx));
0618 }
0619
0620 PSObjectType ps_gettype(HPSCRIPTVM v,PSInteger idx)
0621 {
0622 return type(stack_get(v, idx));
0623 }
0624
0625 PSRESULT ps_typeof(HPSCRIPTVM v,PSInteger idx)
0626 {
0627 PSObjectPtr &o = stack_get(v, idx);
0628 PSObjectPtr res;
0629 if(!v->TypeOf(o,res)) {
0630 return PS_ERROR;
0631 }
0632 v->Push(res);
0633 return PS_OK;
0634 }
0635
0636 PSRESULT ps_tostring(HPSCRIPTVM v,PSInteger idx)
0637 {
0638 PSObjectPtr &o = stack_get(v, idx);
0639 PSObjectPtr res;
0640 if(!v->ToString(o,res)) {
0641 return PS_ERROR;
0642 }
0643 v->Push(res);
0644 return PS_OK;
0645 }
0646
0647 void ps_tobool(HPSCRIPTVM v, PSInteger idx, PSBool *b)
0648 {
0649 PSObjectPtr &o = stack_get(v, idx);
0650 *b = PSVM::IsFalse(o)?PSFalse:PSTrue;
0651 }
0652
0653 PSRESULT ps_getinteger(HPSCRIPTVM v,PSInteger idx,PSInteger *i)
0654 {
0655 PSObjectPtr &o = stack_get(v, idx);
0656 if(ps_isnumeric(o)) {
0657 *i = tointeger(o);
0658 return PS_OK;
0659 }
0660 return PS_ERROR;
0661 }
0662
0663 PSRESULT ps_getfloat(HPSCRIPTVM v,PSInteger idx,PSFloat *f)
0664 {
0665 PSObjectPtr &o = stack_get(v, idx);
0666 if(ps_isnumeric(o)) {
0667 *f = tofloat(o);
0668 return PS_OK;
0669 }
0670 return PS_ERROR;
0671 }
0672
0673 PSRESULT ps_getbool(HPSCRIPTVM v,PSInteger idx,PSBool *b)
0674 {
0675 PSObjectPtr &o = stack_get(v, idx);
0676 if(ps_isbool(o)) {
0677 *b = _integer(o);
0678 return PS_OK;
0679 }
0680 return PS_ERROR;
0681 }
0682
0683 PSRESULT ps_getstring(HPSCRIPTVM v,PSInteger idx,const PSChar **c)
0684 {
0685 PSObjectPtr *o = NULL;
0686 _GETSAFE_OBJ(v, idx, OT_STRING,o);
0687 *c = _stringval(*o);
0688 return PS_OK;
0689 }
0690
0691 PSRESULT ps_getthread(HPSCRIPTVM v,PSInteger idx,HPSCRIPTVM *thread)
0692 {
0693 PSObjectPtr *o = NULL;
0694 _GETSAFE_OBJ(v, idx, OT_THREAD,o);
0695 *thread = _thread(*o);
0696 return PS_OK;
0697 }
0698
0699 PSRESULT ps_clone(HPSCRIPTVM v,PSInteger idx)
0700 {
0701 PSObjectPtr &o = stack_get(v,idx);
0702 v->PushNull();
0703 if(!v->Clone(o, stack_get(v, -1))){
0704 v->Pop();
0705 return PS_ERROR;
0706 }
0707 return PS_OK;
0708 }
0709
0710 PSInteger ps_getsize(HPSCRIPTVM v, PSInteger idx)
0711 {
0712 PSObjectPtr &o = stack_get(v, idx);
0713 PSObjectType type = type(o);
0714 switch(type) {
0715 case OT_STRING: return _string(o)->_len;
0716 case OT_TABLE: return _table(o)->CountUsed();
0717 case OT_ARRAY: return _array(o)->Size();
0718 case OT_USERDATA: return _userdata(o)->_size;
0719 case OT_INSTANCE: return _instance(o)->_class->_udsize;
0720 case OT_CLASS: return _class(o)->_udsize;
0721 default:
0722 return ps_aux_invalidtype(v, type);
0723 }
0724 }
0725
0726 PSHash ps_gethash(HPSCRIPTVM v, PSInteger idx)
0727 {
0728 PSObjectPtr &o = stack_get(v, idx);
0729 return HashObj(o);
0730 }
0731
0732 PSRESULT ps_getuserdata(HPSCRIPTVM v,PSInteger idx,PSUserPointer *p,PSUserPointer *typetag)
0733 {
0734 PSObjectPtr *o = NULL;
0735 _GETSAFE_OBJ(v, idx, OT_USERDATA,o);
0736 (*p) = _userdataval(*o);
0737 if(typetag) *typetag = _userdata(*o)->_typetag;
0738 return PS_OK;
0739 }
0740
0741 PSRESULT ps_settypetag(HPSCRIPTVM v,PSInteger idx,PSUserPointer typetag)
0742 {
0743 PSObjectPtr &o = stack_get(v,idx);
0744 switch(type(o)) {
0745 case OT_USERDATA: _userdata(o)->_typetag = typetag; break;
0746 case OT_CLASS: _class(o)->_typetag = typetag; break;
0747 default: return ps_throwerror(v,_SC("invalid object type"));
0748 }
0749 return PS_OK;
0750 }
0751
0752 PSRESULT ps_getobjtypetag(const HPSOBJECT *o,PSUserPointer * typetag)
0753 {
0754 switch(type(*o)) {
0755 case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
0756 case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
0757 case OT_CLASS: *typetag = _class(*o)->_typetag; break;
0758 default: return PS_ERROR;
0759 }
0760 return PS_OK;
0761 }
0762
0763 PSRESULT ps_gettypetag(HPSCRIPTVM v,PSInteger idx,PSUserPointer *typetag)
0764 {
0765 PSObjectPtr &o = stack_get(v,idx);
0766 if(PS_FAILED(ps_getobjtypetag(&o,typetag)))
0767 return ps_throwerror(v,_SC("invalid object type"));
0768 return PS_OK;
0769 }
0770
0771 PSRESULT ps_getuserpointer(HPSCRIPTVM v, PSInteger idx, PSUserPointer *p)
0772 {
0773 PSObjectPtr *o = NULL;
0774 _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
0775 (*p) = _userpointer(*o);
0776 return PS_OK;
0777 }
0778
0779 PSRESULT ps_setinstanceup(HPSCRIPTVM v, PSInteger idx, PSUserPointer p)
0780 {
0781 PSObjectPtr &o = stack_get(v,idx);
0782 if(type(o) != OT_INSTANCE) return ps_throwerror(v,_SC("the object is not a class instance"));
0783 _instance(o)->_userpointer = p;
0784 return PS_OK;
0785 }
0786
0787 PSRESULT ps_setclassudsize(HPSCRIPTVM v, PSInteger idx, PSInteger udsize)
0788 {
0789 PSObjectPtr &o = stack_get(v,idx);
0790 if(type(o) != OT_CLASS) return ps_throwerror(v,_SC("the object is not a class"));
0791 if(_class(o)->_locked) return ps_throwerror(v,_SC("the class is locked"));
0792 _class(o)->_udsize = udsize;
0793 return PS_OK;
0794 }
0795
0796
0797 PSRESULT ps_getinstanceup(HPSCRIPTVM v, PSInteger idx, PSUserPointer *p,PSUserPointer typetag)
0798 {
0799 PSObjectPtr &o = stack_get(v,idx);
0800 if(type(o) != OT_INSTANCE) return ps_throwerror(v,_SC("the object is not a class instance"));
0801 (*p) = _instance(o)->_userpointer;
0802 if(typetag != 0) {
0803 PSClass *cl = _instance(o)->_class;
0804 do{
0805 if(cl->_typetag == typetag)
0806 return PS_OK;
0807 cl = cl->_base;
0808 }while(cl != NULL);
0809 return ps_throwerror(v,_SC("invalid type tag"));
0810 }
0811 return PS_OK;
0812 }
0813
0814 PSInteger ps_gettop(HPSCRIPTVM v)
0815 {
0816 return (v->_top) - v->_stackbase;
0817 }
0818
0819 void ps_settop(HPSCRIPTVM v, PSInteger newtop)
0820 {
0821 PSInteger top = ps_gettop(v);
0822 if(top > newtop)
0823 ps_pop(v, top - newtop);
0824 else
0825 while(top++ < newtop) ps_pushnull(v);
0826 }
0827
0828 void ps_pop(HPSCRIPTVM v, PSInteger nelemstopop)
0829 {
0830 assert(v->_top >= nelemstopop);
0831 v->Pop(nelemstopop);
0832 }
0833
0834 void ps_poptop(HPSCRIPTVM v)
0835 {
0836 assert(v->_top >= 1);
0837 v->Pop();
0838 }
0839
0840
0841 void ps_remove(HPSCRIPTVM v, PSInteger idx)
0842 {
0843 v->Remove(idx);
0844 }
0845
0846 PSInteger ps_cmp(HPSCRIPTVM v)
0847 {
0848 PSInteger res;
0849 v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
0850 return res;
0851 }
0852
0853 PSRESULT ps_newslot(HPSCRIPTVM v, PSInteger idx, PSBool bstatic)
0854 {
0855 ps_aux_paramscheck(v, 3);
0856 PSObjectPtr &self = stack_get(v, idx);
0857 if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
0858 PSObjectPtr &key = v->GetUp(-2);
0859 if(type(key) == OT_NULL) return ps_throwerror(v, _SC("null is not a valid key"));
0860 v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);
0861 v->Pop(2);
0862 }
0863 return PS_OK;
0864 }
0865
0866 PSRESULT ps_deleteslot(HPSCRIPTVM v,PSInteger idx,PSBool pushval)
0867 {
0868 ps_aux_paramscheck(v, 2);
0869 PSObjectPtr *self;
0870 _GETSAFE_OBJ(v, idx, OT_TABLE,self);
0871 PSObjectPtr &key = v->GetUp(-1);
0872 if(type(key) == OT_NULL) return ps_throwerror(v, _SC("null is not a valid key"));
0873 PSObjectPtr res;
0874 if(!v->DeleteSlot(*self, key, res)){
0875 v->Pop();
0876 return PS_ERROR;
0877 }
0878 if(pushval) v->GetUp(-1) = res;
0879 else v->Pop();
0880 return PS_OK;
0881 }
0882
0883 PSRESULT ps_set(HPSCRIPTVM v,PSInteger idx)
0884 {
0885 PSObjectPtr &self = stack_get(v, idx);
0886 if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {
0887 v->Pop(2);
0888 return PS_OK;
0889 }
0890 return PS_ERROR;
0891 }
0892
0893 PSRESULT ps_rawset(HPSCRIPTVM v,PSInteger idx)
0894 {
0895 PSObjectPtr &self = stack_get(v, idx);
0896 PSObjectPtr &key = v->GetUp(-2);
0897 if(type(key) == OT_NULL) {
0898 v->Pop(2);
0899 return ps_throwerror(v, _SC("null key"));
0900 }
0901 switch(type(self)) {
0902 case OT_TABLE:
0903 _table(self)->NewSlot(key, v->GetUp(-1));
0904 v->Pop(2);
0905 return PS_OK;
0906 break;
0907 case OT_CLASS:
0908 _class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false);
0909 v->Pop(2);
0910 return PS_OK;
0911 break;
0912 case OT_INSTANCE:
0913 if(_instance(self)->Set(key, v->GetUp(-1))) {
0914 v->Pop(2);
0915 return PS_OK;
0916 }
0917 break;
0918 case OT_ARRAY:
0919 if(v->Set(self, key, v->GetUp(-1),false)) {
0920 v->Pop(2);
0921 return PS_OK;
0922 }
0923 break;
0924 default:
0925 v->Pop(2);
0926 return ps_throwerror(v, _SC("rawset works only on array/table/class and instance"));
0927 }
0928 v->Raise_IdxError(v->GetUp(-2));return PS_ERROR;
0929 }
0930
0931 PSRESULT ps_newmember(HPSCRIPTVM v,PSInteger idx,PSBool bstatic)
0932 {
0933 PSObjectPtr &self = stack_get(v, idx);
0934 if(type(self) != OT_CLASS) return ps_throwerror(v, _SC("new member only works with classes"));
0935 PSObjectPtr &key = v->GetUp(-3);
0936 if(type(key) == OT_NULL) return ps_throwerror(v, _SC("null key"));
0937 if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))
0938 return PS_ERROR;
0939 return PS_OK;
0940 }
0941
0942 PSRESULT ps_rawnewmember(HPSCRIPTVM v,PSInteger idx,PSBool bstatic)
0943 {
0944 PSObjectPtr &self = stack_get(v, idx);
0945 if(type(self) != OT_CLASS) return ps_throwerror(v, _SC("new member only works with classes"));
0946 PSObjectPtr &key = v->GetUp(-3);
0947 if(type(key) == OT_NULL) return ps_throwerror(v, _SC("null key"));
0948 if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))
0949 return PS_ERROR;
0950 return PS_OK;
0951 }
0952
0953 PSRESULT ps_setdelegate(HPSCRIPTVM v,PSInteger idx)
0954 {
0955 PSObjectPtr &self = stack_get(v, idx);
0956 PSObjectPtr &mt = v->GetUp(-1);
0957 PSObjectType type = type(self);
0958 switch(type) {
0959 case OT_TABLE:
0960 if(type(mt) == OT_TABLE) {
0961 if(!_table(self)->SetDelegate(_table(mt))) return ps_throwerror(v, _SC("delagate cycle")); v->Pop();}
0962 else if(type(mt)==OT_NULL) {
0963 _table(self)->SetDelegate(NULL); v->Pop(); }
0964 else return ps_aux_invalidtype(v,type);
0965 break;
0966 case OT_USERDATA:
0967 if(type(mt)==OT_TABLE) {
0968 _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
0969 else if(type(mt)==OT_NULL) {
0970 _userdata(self)->SetDelegate(NULL); v->Pop(); }
0971 else return ps_aux_invalidtype(v, type);
0972 break;
0973 default:
0974 return ps_aux_invalidtype(v, type);
0975 break;
0976 }
0977 return PS_OK;
0978 }
0979
0980 PSRESULT ps_rawdeleteslot(HPSCRIPTVM v,PSInteger idx,PSBool pushval)
0981 {
0982 ps_aux_paramscheck(v, 2);
0983 PSObjectPtr *self;
0984 _GETSAFE_OBJ(v, idx, OT_TABLE,self);
0985 PSObjectPtr &key = v->GetUp(-1);
0986 PSObjectPtr t;
0987 if(_table(*self)->Get(key,t)) {
0988 _table(*self)->Remove(key);
0989 }
0990 if(pushval != 0)
0991 v->GetUp(-1) = t;
0992 else
0993 v->Pop();
0994 return PS_OK;
0995 }
0996
0997 PSRESULT ps_getdelegate(HPSCRIPTVM v,PSInteger idx)
0998 {
0999 PSObjectPtr &self=stack_get(v,idx);
1000 switch(type(self)){
1001 case OT_TABLE:
1002 case OT_USERDATA:
1003 if(!_delegable(self)->_delegate){
1004 v->PushNull();
1005 break;
1006 }
1007 v->Push(PSObjectPtr(_delegable(self)->_delegate));
1008 break;
1009 default: return ps_throwerror(v,_SC("wrong type")); break;
1010 }
1011 return PS_OK;
1012
1013 }
1014
1015 PSRESULT ps_get(HPSCRIPTVM v,PSInteger idx)
1016 {
1017 PSObjectPtr &self=stack_get(v,idx);
1018 PSObjectPtr &obj = v->GetUp(-1);
1019 if(v->Get(self,obj,obj,false,DONT_FALL_BACK))
1020 return PS_OK;
1021 v->Pop();
1022 return PS_ERROR;
1023 }
1024
1025 PSRESULT ps_rawget(HPSCRIPTVM v,PSInteger idx)
1026 {
1027 PSObjectPtr &self=stack_get(v,idx);
1028 PSObjectPtr &obj = v->GetUp(-1);
1029 switch(type(self)) {
1030 case OT_TABLE:
1031 if(_table(self)->Get(obj,obj))
1032 return PS_OK;
1033 break;
1034 case OT_CLASS:
1035 if(_class(self)->Get(obj,obj))
1036 return PS_OK;
1037 break;
1038 case OT_INSTANCE:
1039 if(_instance(self)->Get(obj,obj))
1040 return PS_OK;
1041 break;
1042 case OT_ARRAY:{
1043 if(ps_isnumeric(obj)){
1044 if(_array(self)->Get(tointeger(obj),obj)) {
1045 return PS_OK;
1046 }
1047 }
1048 else {
1049 v->Pop();
1050 return ps_throwerror(v,_SC("invalid index type for an array"));
1051 }
1052 }
1053 break;
1054 default:
1055 v->Pop();
1056 return ps_throwerror(v,_SC("rawget works only on array/table/instance and class"));
1057 }
1058 v->Pop();
1059 return ps_throwerror(v,_SC("the index doesn't exist"));
1060 }
1061
1062 PSRESULT ps_getstackobj(HPSCRIPTVM v,PSInteger idx,HPSOBJECT *po)
1063 {
1064 *po=stack_get(v,idx);
1065 return PS_OK;
1066 }
1067
1068 const PSChar *ps_getlocal(HPSCRIPTVM v,PSUnsignedInteger level,PSUnsignedInteger idx)
1069 {
1070 PSUnsignedInteger cstksize=v->_callsstacksize;
1071 PSUnsignedInteger lvl=(cstksize-level)-1;
1072 PSInteger stackbase=v->_stackbase;
1073 if(lvl<cstksize){
1074 for(PSUnsignedInteger i=0;i<level;i++){
1075 PSVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
1076 stackbase-=ci._prevstkbase;
1077 }
1078 PSVM::CallInfo &ci=v->_callsstack[lvl];
1079 if(type(ci._closure)!=OT_CLOSURE)
1080 return NULL;
1081 PSClosure *c=_closure(ci._closure);
1082 PSFunctionProto *func=c->_function;
1083 if(func->_noutervalues > (PSInteger)idx) {
1084 v->Push(*_outer(c->_outervalues[idx])->_valptr);
1085 return _stringval(func->_outervalues[idx]._name);
1086 }
1087 idx -= func->_noutervalues;
1088 return func->GetLocal(v,stackbase,idx,(PSInteger)(ci._ip-func->_instructions)-1);
1089 }
1090 return NULL;
1091 }
1092
1093 void ps_pushobject(HPSCRIPTVM v,HPSOBJECT obj)
1094 {
1095 v->Push(PSObjectPtr(obj));
1096 }
1097
1098 void ps_resetobject(HPSOBJECT *po)
1099 {
1100 po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
1101 }
1102
1103 PSRESULT ps_throwerror(HPSCRIPTVM v,const PSChar *err)
1104 {
1105 v->_lasterror=PSString::Create(_ss(v),err);
1106 return PS_ERROR;
1107 }
1108
1109 PSRESULT ps_throwobject(HPSCRIPTVM v)
1110 {
1111 v->_lasterror = v->GetUp(-1);
1112 v->Pop();
1113 return PS_ERROR;
1114 }
1115
1116
1117 void ps_reseterror(HPSCRIPTVM v)
1118 {
1119 v->_lasterror.Null();
1120 }
1121
1122 void ps_getlasterror(HPSCRIPTVM v)
1123 {
1124 v->Push(v->_lasterror);
1125 }
1126
1127 PSRESULT ps_reservestack(HPSCRIPTVM v,PSInteger nsize)
1128 {
1129 if (((PSUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
1130 if(v->_nmetamethodscall) {
1131 return ps_throwerror(v,_SC("cannot resize stack while in a metamethod"));
1132 }
1133 v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
1134 }
1135 return PS_OK;
1136 }
1137
1138 PSRESULT ps_resume(HPSCRIPTVM v,PSBool retval,PSBool raiseerror)
1139 {
1140 if (type(v->GetUp(-1)) == OT_GENERATOR)
1141 {
1142 v->PushNull();
1143 if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, PSVM::ET_RESUME_GENERATOR))
1144 {v->Raise_Error(v->_lasterror); return PS_ERROR;}
1145 if(!retval)
1146 v->Pop();
1147 return PS_OK;
1148 }
1149 return ps_throwerror(v,_SC("only generators can be resumed"));
1150 }
1151
1152 PSRESULT ps_call(HPSCRIPTVM v,PSInteger params,PSBool retval,PSBool raiseerror)
1153 {
1154 PSObjectPtr res;
1155 if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
1156
1157 if(!v->_suspended) {
1158 v->Pop(params);
1159 }
1160 if(retval){
1161 v->Push(res); return PS_OK;
1162 }
1163 return PS_OK;
1164 }
1165 else {
1166 v->Pop(params);
1167 return PS_ERROR;
1168 }
1169 if(!v->_suspended)
1170 v->Pop(params);
1171 return ps_throwerror(v,_SC("call failed"));
1172 }
1173
1174 PSRESULT ps_suspendvm(HPSCRIPTVM v)
1175 {
1176 return v->Suspend();
1177 }
1178
1179 PSRESULT ps_wakeupvm(HPSCRIPTVM v,PSBool wakeupret,PSBool retval,PSBool raiseerror,PSBool throwerror)
1180 {
1181 PSObjectPtr ret;
1182 if(!v->_suspended)
1183 return ps_throwerror(v,_SC("cannot resume a vm that is not running any code"));
1184 PSInteger target = v->_suspended_target;
1185 if(wakeupret) {
1186 if(target != -1) {
1187 v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1);
1188 }
1189 v->Pop();
1190 } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }
1191 PSObjectPtr dummy;
1192 if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?PSVM::ET_RESUME_THROW_VM : PSVM::ET_RESUME_VM)) {
1193 return PS_ERROR;
1194 }
1195 if(retval)
1196 v->Push(ret);
1197 return PS_OK;
1198 }
1199
1200 void ps_setreleasehook(HPSCRIPTVM v,PSInteger idx,PSRELEASEHOOK hook)
1201 {
1202 if(ps_gettop(v) >= 1){
1203 PSObjectPtr &ud=stack_get(v,idx);
1204 switch( type(ud) ) {
1205 case OT_USERDATA: _userdata(ud)->_hook = hook; break;
1206 case OT_INSTANCE: _instance(ud)->_hook = hook; break;
1207 case OT_CLASS: _class(ud)->_hook = hook; break;
1208 default: break;
1209 }
1210 }
1211 }
1212
1213 PSRELEASEHOOK ps_getreleasehook(HPSCRIPTVM v,PSInteger idx)
1214 {
1215 if(ps_gettop(v) >= 1){
1216 PSObjectPtr &ud=stack_get(v,idx);
1217 switch( type(ud) ) {
1218 case OT_USERDATA: return _userdata(ud)->_hook; break;
1219 case OT_INSTANCE: return _instance(ud)->_hook; break;
1220 case OT_CLASS: return _class(ud)->_hook; break;
1221 default: break;
1222 }
1223 }
1224 return NULL;
1225 }
1226
1227 void ps_setcompilererrorhandler(HPSCRIPTVM v,PSCOMPILERERROR f)
1228 {
1229 _ss(v)->_compilererrorhandler = f;
1230 }
1231
1232 PSRESULT ps_writeclosure(HPSCRIPTVM v,PSWRITEFUNC w,PSUserPointer up)
1233 {
1234 PSObjectPtr *o = NULL;
1235 _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
1236 unsigned short tag = PS_BYTECODE_STREAM_TAG;
1237 if(_closure(*o)->_function->_noutervalues)
1238 return ps_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));
1239 if(w(up,&tag,2) != 2)
1240 return ps_throwerror(v,_SC("io error"));
1241 if(!_closure(*o)->Save(v,up,w))
1242 return PS_ERROR;
1243 return PS_OK;
1244 }
1245
1246 PSRESULT ps_readclosure(HPSCRIPTVM v,PSREADFUNC r,PSUserPointer up)
1247 {
1248 PSObjectPtr closure;
1249
1250 unsigned short tag;
1251 if(r(up,&tag,2) != 2)
1252 return ps_throwerror(v,_SC("io error"));
1253 if(tag != PS_BYTECODE_STREAM_TAG)
1254 return ps_throwerror(v,_SC("invalid stream"));
1255 if(!PSClosure::Load(v,up,r,closure))
1256 return PS_ERROR;
1257 v->Push(closure);
1258 return PS_OK;
1259 }
1260
1261 PSChar *ps_getscratchpad(HPSCRIPTVM v,PSInteger minsize)
1262 {
1263 return _ss(v)->GetScratchPad(minsize);
1264 }
1265
1266 PSRESULT ps_resurrectunreachable(HPSCRIPTVM v)
1267 {
1268 #ifndef NO_GARBAGE_COLLECTOR
1269 _ss(v)->ResurrectUnreachable(v);
1270 return PS_OK;
1271 #else
1272 return ps_throwerror(v,_SC("ps_resurrectunreachable requires a garbage collector build"));
1273 #endif
1274 }
1275
1276 PSInteger ps_collectgarbage(HPSCRIPTVM v)
1277 {
1278 #ifndef NO_GARBAGE_COLLECTOR
1279 return _ss(v)->CollectGarbage(v);
1280 #else
1281 return -1;
1282 #endif
1283 }
1284
1285 PSRESULT ps_getcallee(HPSCRIPTVM v)
1286 {
1287 if(v->_callsstacksize > 1)
1288 {
1289 v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
1290 return PS_OK;
1291 }
1292 return ps_throwerror(v,_SC("no closure in the calls stack"));
1293 }
1294
1295 const PSChar *ps_getfreevariable(HPSCRIPTVM v,PSInteger idx,PSUnsignedInteger nval)
1296 {
1297 PSObjectPtr &self=stack_get(v,idx);
1298 const PSChar *name = NULL;
1299 switch(type(self))
1300 {
1301 case OT_CLOSURE:{
1302 PSClosure *clo = _closure(self);
1303 PSFunctionProto *fp = clo->_function;
1304 if(((PSUnsignedInteger)fp->_noutervalues) > nval) {
1305 v->Push(*(_outer(clo->_outervalues[nval])->_valptr));
1306 PSOuterVar &ov = fp->_outervalues[nval];
1307 name = _stringval(ov._name);
1308 }
1309 }
1310 break;
1311 case OT_NATIVECLOSURE:{
1312 PSNativeClosure *clo = _nativeclosure(self);
1313 if(clo->_noutervalues > nval) {
1314 v->Push(clo->_outervalues[nval]);
1315 name = _SC("@NATIVE");
1316 }
1317 }
1318 break;
1319 default: break;
1320 }
1321 return name;
1322 }
1323
1324 PSRESULT ps_setfreevariable(HPSCRIPTVM v,PSInteger idx,PSUnsignedInteger nval)
1325 {
1326 PSObjectPtr &self=stack_get(v,idx);
1327 switch(type(self))
1328 {
1329 case OT_CLOSURE:{
1330 PSFunctionProto *fp = _closure(self)->_function;
1331 if(((PSUnsignedInteger)fp->_noutervalues) > nval){
1332 *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
1333 }
1334 else return ps_throwerror(v,_SC("invalid free var index"));
1335 }
1336 break;
1337 case OT_NATIVECLOSURE:
1338 if(_nativeclosure(self)->_noutervalues > nval){
1339 _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);
1340 }
1341 else return ps_throwerror(v,_SC("invalid free var index"));
1342 break;
1343 default:
1344 return ps_aux_invalidtype(v,type(self));
1345 }
1346 v->Pop();
1347 return PS_OK;
1348 }
1349
1350 PSRESULT ps_setattributes(HPSCRIPTVM v,PSInteger idx)
1351 {
1352 PSObjectPtr *o = NULL;
1353 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1354 PSObjectPtr &key = stack_get(v,-2);
1355 PSObjectPtr &val = stack_get(v,-1);
1356 PSObjectPtr attrs;
1357 if(type(key) == OT_NULL) {
1358 attrs = _class(*o)->_attributes;
1359 _class(*o)->_attributes = val;
1360 v->Pop(2);
1361 v->Push(attrs);
1362 return PS_OK;
1363 }else if(_class(*o)->GetAttributes(key,attrs)) {
1364 _class(*o)->SetAttributes(key,val);
1365 v->Pop(2);
1366 v->Push(attrs);
1367 return PS_OK;
1368 }
1369 return ps_throwerror(v,_SC("wrong index"));
1370 }
1371
1372 PSRESULT ps_getattributes(HPSCRIPTVM v,PSInteger idx)
1373 {
1374 PSObjectPtr *o = NULL;
1375 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1376 PSObjectPtr &key = stack_get(v,-1);
1377 PSObjectPtr attrs;
1378 if(type(key) == OT_NULL) {
1379 attrs = _class(*o)->_attributes;
1380 v->Pop();
1381 v->Push(attrs);
1382 return PS_OK;
1383 }
1384 else if(_class(*o)->GetAttributes(key,attrs)) {
1385 v->Pop();
1386 v->Push(attrs);
1387 return PS_OK;
1388 }
1389 return ps_throwerror(v,_SC("wrong index"));
1390 }
1391
1392 PSRESULT ps_getmemberhandle(HPSCRIPTVM v,PSInteger idx,HPSMEMBERHANDLE *handle)
1393 {
1394 PSObjectPtr *o = NULL;
1395 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1396 PSObjectPtr &key = stack_get(v,-1);
1397 PSTable *m = _class(*o)->_members;
1398 PSObjectPtr val;
1399 if(m->Get(key,val)) {
1400 handle->_static = _isfield(val) ? PSFalse : PSTrue;
1401 handle->_index = _member_idx(val);
1402 v->Pop();
1403 return PS_OK;
1404 }
1405 return ps_throwerror(v,_SC("wrong index"));
1406 }
1407
1408 PSRESULT _getmemberbyhandle(HPSCRIPTVM v,PSObjectPtr &self,const HPSMEMBERHANDLE *handle,PSObjectPtr *&val)
1409 {
1410 switch(type(self)) {
1411 case OT_INSTANCE: {
1412 PSInstance *i = _instance(self);
1413 if(handle->_static) {
1414 PSClass *c = i->_class;
1415 val = &c->_methods[handle->_index].val;
1416 }
1417 else {
1418 val = &i->_values[handle->_index];
1419
1420 }
1421 }
1422 break;
1423 case OT_CLASS: {
1424 PSClass *c = _class(self);
1425 if(handle->_static) {
1426 val = &c->_methods[handle->_index].val;
1427 }
1428 else {
1429 val = &c->_defaultvalues[handle->_index].val;
1430 }
1431 }
1432 break;
1433 default:
1434 return ps_throwerror(v,_SC("wrong type(expected class or instance)"));
1435 }
1436 return PS_OK;
1437 }
1438
1439 PSRESULT ps_getbyhandle(HPSCRIPTVM v,PSInteger idx,const HPSMEMBERHANDLE *handle)
1440 {
1441 PSObjectPtr &self = stack_get(v,idx);
1442 PSObjectPtr *val = NULL;
1443 if(PS_FAILED(_getmemberbyhandle(v,self,handle,val))) {
1444 return PS_ERROR;
1445 }
1446 v->Push(_realval(*val));
1447 return PS_OK;
1448 }
1449
1450 PSRESULT ps_setbyhandle(HPSCRIPTVM v,PSInteger idx,const HPSMEMBERHANDLE *handle)
1451 {
1452 PSObjectPtr &self = stack_get(v,idx);
1453 PSObjectPtr &newval = stack_get(v,-1);
1454 PSObjectPtr *val = NULL;
1455 if(PS_FAILED(_getmemberbyhandle(v,self,handle,val))) {
1456 return PS_ERROR;
1457 }
1458 *val = newval;
1459 v->Pop();
1460 return PS_OK;
1461 }
1462
1463 PSRESULT ps_getbase(HPSCRIPTVM v,PSInteger idx)
1464 {
1465 PSObjectPtr *o = NULL;
1466 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1467 if(_class(*o)->_base)
1468 v->Push(PSObjectPtr(_class(*o)->_base));
1469 else
1470 v->PushNull();
1471 return PS_OK;
1472 }
1473
1474 PSRESULT ps_getclass(HPSCRIPTVM v,PSInteger idx)
1475 {
1476 PSObjectPtr *o = NULL;
1477 _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
1478 v->Push(PSObjectPtr(_instance(*o)->_class));
1479 return PS_OK;
1480 }
1481
1482 PSRESULT ps_createinstance(HPSCRIPTVM v,PSInteger idx)
1483 {
1484 PSObjectPtr *o = NULL;
1485 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1486 v->Push(_class(*o)->CreateInstance());
1487 return PS_OK;
1488 }
1489
1490 void ps_weakref(HPSCRIPTVM v,PSInteger idx)
1491 {
1492 PSObject &o=stack_get(v,idx);
1493 if(ISREFCOUNTED(type(o))) {
1494 v->Push(_refcounted(o)->GetWeakRef(type(o)));
1495 return;
1496 }
1497 v->Push(o);
1498 }
1499
1500 PSRESULT ps_getweakrefval(HPSCRIPTVM v,PSInteger idx)
1501 {
1502 PSObjectPtr &o = stack_get(v,idx);
1503 if(type(o) != OT_WEAKREF) {
1504 return ps_throwerror(v,_SC("the object must be a weakref"));
1505 }
1506 v->Push(_weakref(o)->_obj);
1507 return PS_OK;
1508 }
1509
1510 PSRESULT ps_getdefaultdelegate(HPSCRIPTVM v,PSObjectType t)
1511 {
1512 PSSharedState *ss = _ss(v);
1513 switch(t) {
1514 case OT_TABLE: v->Push(ss->_table_default_delegate); break;
1515 case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
1516 case OT_STRING: v->Push(ss->_string_default_delegate); break;
1517 case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
1518 case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
1519 case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
1520 case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
1521 case OT_CLASS: v->Push(ss->_class_default_delegate); break;
1522 case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
1523 case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
1524 default: return ps_throwerror(v,_SC("the type doesn't have a default delegate"));
1525 }
1526 return PS_OK;
1527 }
1528
1529 PSRESULT ps_next(HPSCRIPTVM v,PSInteger idx)
1530 {
1531 PSObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
1532 if(type(o) == OT_GENERATOR) {
1533 return ps_throwerror(v,_SC("cannot iterate a generator"));
1534 }
1535 int faketojump;
1536 if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
1537 return PS_ERROR;
1538 if(faketojump != 666) {
1539 v->Push(realkey);
1540 v->Push(val);
1541 return PS_OK;
1542 }
1543 return PS_ERROR;
1544 }
1545
1546 struct BufState{
1547 const PSChar *buf;
1548 PSInteger ptr;
1549 PSInteger size;
1550 };
1551
1552 PSInteger buf_lexfeed(PSUserPointer file)
1553 {
1554 BufState *buf=(BufState*)file;
1555 if(buf->size<(buf->ptr+1))
1556 return 0;
1557 return buf->buf[buf->ptr++];
1558 }
1559
1560 PSRESULT ps_compilebuffer(HPSCRIPTVM v,const PSChar *s,PSInteger size,const PSChar *sourcename,PSBool raiseerror) {
1561 BufState buf;
1562 buf.buf = s;
1563 buf.size = size;
1564 buf.ptr = 0;
1565 return ps_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
1566 }
1567
1568 void ps_move(HPSCRIPTVM dest,HPSCRIPTVM src,PSInteger idx)
1569 {
1570 dest->Push(stack_get(src,idx));
1571 }
1572
1573 void ps_setprintfunc(HPSCRIPTVM v, PSPRINTFUNCTION printfunc,PSPRINTFUNCTION errfunc)
1574 {
1575 _ss(v)->_printfunc = printfunc;
1576 _ss(v)->_errorfunc = errfunc;
1577 }
1578
1579 PSPRINTFUNCTION ps_getprintfunc(HPSCRIPTVM v)
1580 {
1581 return _ss(v)->_printfunc;
1582 }
1583
1584 PSPRINTFUNCTION ps_geterrorfunc(HPSCRIPTVM v)
1585 {
1586 return _ss(v)->_errorfunc;
1587 }
1588
1589 void *ps_malloc(PSUnsignedInteger size)
1590 {
1591 return PS_MALLOC(size);
1592 }
1593
1594 void *ps_realloc(void* p,PSUnsignedInteger oldsize,PSUnsignedInteger newsize)
1595 {
1596 return PS_REALLOC(p,oldsize,newsize);
1597 }
1598
1599 void ps_free(void *p,PSUnsignedInteger size)
1600 {
1601 PS_FREE(p,size);
1602 }