1 /*
2 see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include "sqvm.h"
6 #include "sqstring.h"
7 #include "sqtable.h"
8 #include "sqarray.h"
9 #include "sqfuncproto.h"
10 #include "sqclosure.h"
11 #include "squserdata.h"
12 #include "sqcompiler.h"
13 #include "sqfuncstate.h"
14 #include "sqclass.h"
15
sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr ** o)16 static bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o)
17 {
18 *o = &stack_get(v,idx);
19 if(sq_type(**o) != type){
20 SQObjectPtr oval = v->PrintObjVal(**o);
21 v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
22 return false;
23 }
24 return true;
25 }
26
27 #define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
28
29 #define sq_aux_paramscheck(v,count) \
30 { \
31 if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
32 }
33
34
sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)35 SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
36 {
37 SQUnsignedInteger buf_size = 100 *sizeof(SQChar);
38 scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type));
39 return sq_throwerror(v, _ss(v)->GetScratchPad(-1));
40 }
41
sq_open(SQInteger initialstacksize)42 HSQUIRRELVM sq_open(SQInteger initialstacksize)
43 {
44 SQSharedState *ss;
45 SQVM *v;
46 sq_new(ss, SQSharedState);
47 ss->Init();
48 v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
49 new (v) SQVM(ss);
50 ss->_root_vm = v;
51 if(v->Init(NULL, initialstacksize)) {
52 return v;
53 } else {
54 sq_delete(v, SQVM);
55 return NULL;
56 }
57 return v;
58 }
59
sq_newthread(HSQUIRRELVM friendvm,SQInteger initialstacksize)60 HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
61 {
62 SQSharedState *ss;
63 SQVM *v;
64 ss=_ss(friendvm);
65
66 v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
67 new (v) SQVM(ss);
68
69 if(v->Init(friendvm, initialstacksize)) {
70 friendvm->Push(v);
71 return v;
72 } else {
73 sq_delete(v, SQVM);
74 return NULL;
75 }
76 }
77
sq_getvmstate(HSQUIRRELVM v)78 SQInteger sq_getvmstate(HSQUIRRELVM v)
79 {
80 if(v->_suspended)
81 return SQ_VMSTATE_SUSPENDED;
82 else {
83 if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
84 else return SQ_VMSTATE_IDLE;
85 }
86 }
87
sq_seterrorhandler(HSQUIRRELVM v)88 void sq_seterrorhandler(HSQUIRRELVM v)
89 {
90 SQObject o = stack_get(v, -1);
91 if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
92 v->_errorhandler = o;
93 v->Pop();
94 }
95 }
96
sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)97 void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)
98 {
99 v->_debughook_native = hook;
100 v->_debughook_closure.Null();
101 v->_debughook = hook?true:false;
102 }
103
sq_setdebughook(HSQUIRRELVM v)104 void sq_setdebughook(HSQUIRRELVM v)
105 {
106 SQObject o = stack_get(v,-1);
107 if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
108 v->_debughook_closure = o;
109 v->_debughook_native = NULL;
110 v->_debughook = !sq_isnull(o);
111 v->Pop();
112 }
113 }
114
sq_close(HSQUIRRELVM v)115 void sq_close(HSQUIRRELVM v)
116 {
117 SQSharedState *ss = _ss(v);
118 _thread(ss->_root_vm)->Finalize();
119 sq_delete(ss, SQSharedState);
120 }
121
sq_getversion()122 SQInteger sq_getversion()
123 {
124 return SQUIRREL_VERSION_NUMBER;
125 }
126
sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar * sourcename,SQBool raiseerror)127 SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
128 {
129 SQObjectPtr o;
130 #ifndef NO_COMPILER
131 if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
132 v->Push(SQClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE)));
133 return SQ_OK;
134 }
135 return SQ_ERROR;
136 #else
137 return sq_throwerror(v,_SC("this is a no compiler build"));
138 #endif
139 }
140
sq_enabledebuginfo(HSQUIRRELVM v,SQBool enable)141 void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)
142 {
143 _ss(v)->_debuginfo = enable?true:false;
144 }
145
sq_notifyallexceptions(HSQUIRRELVM v,SQBool enable)146 void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
147 {
148 _ss(v)->_notifyallexceptions = enable?true:false;
149 }
150
sq_addref(HSQUIRRELVM v,HSQOBJECT * po)151 void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
152 {
153 if(!ISREFCOUNTED(sq_type(*po))) return;
154 #ifdef NO_GARBAGE_COLLECTOR
155 __AddRef(po->_type,po->_unVal);
156 #else
157 _ss(v)->_refs_table.AddRef(*po);
158 #endif
159 }
160
sq_getrefcount(HSQUIRRELVM v,HSQOBJECT * po)161 SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)
162 {
163 if(!ISREFCOUNTED(sq_type(*po))) return 0;
164 #ifdef NO_GARBAGE_COLLECTOR
165 return po->_unVal.pRefCounted->_uiRef;
166 #else
167 return _ss(v)->_refs_table.GetRefCount(*po);
168 #endif
169 }
170
sq_release(HSQUIRRELVM v,HSQOBJECT * po)171 SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
172 {
173 if(!ISREFCOUNTED(sq_type(*po))) return SQTrue;
174 #ifdef NO_GARBAGE_COLLECTOR
175 bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;
176 __Release(po->_type,po->_unVal);
177 return ret; //the ret val doesn't work(and cannot be fixed)
178 #else
179 return _ss(v)->_refs_table.Release(*po);
180 #endif
181 }
182
sq_getvmrefcount(HSQUIRRELVM SQ_UNUSED_ARG (v),const HSQOBJECT * po)183 SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM SQ_UNUSED_ARG(v), const HSQOBJECT *po)
184 {
185 if (!ISREFCOUNTED(sq_type(*po))) return 0;
186 return po->_unVal.pRefCounted->_uiRef;
187 }
188
sq_objtostring(const HSQOBJECT * o)189 const SQChar *sq_objtostring(const HSQOBJECT *o)
190 {
191 if(sq_type(*o) == OT_STRING) {
192 return _stringval(*o);
193 }
194 return NULL;
195 }
196
sq_objtointeger(const HSQOBJECT * o)197 SQInteger sq_objtointeger(const HSQOBJECT *o)
198 {
199 if(sq_isnumeric(*o)) {
200 return tointeger(*o);
201 }
202 return 0;
203 }
204
sq_objtofloat(const HSQOBJECT * o)205 SQFloat sq_objtofloat(const HSQOBJECT *o)
206 {
207 if(sq_isnumeric(*o)) {
208 return tofloat(*o);
209 }
210 return 0;
211 }
212
sq_objtobool(const HSQOBJECT * o)213 SQBool sq_objtobool(const HSQOBJECT *o)
214 {
215 if(sq_isbool(*o)) {
216 return _integer(*o);
217 }
218 return SQFalse;
219 }
220
sq_objtouserpointer(const HSQOBJECT * o)221 SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)
222 {
223 if(sq_isuserpointer(*o)) {
224 return _userpointer(*o);
225 }
226 return 0;
227 }
228
sq_pushnull(HSQUIRRELVM v)229 void sq_pushnull(HSQUIRRELVM v)
230 {
231 v->PushNull();
232 }
233
sq_pushstring(HSQUIRRELVM v,const SQChar * s,SQInteger len)234 void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
235 {
236 if(s)
237 v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
238 else v->PushNull();
239 }
240
sq_pushinteger(HSQUIRRELVM v,SQInteger n)241 void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
242 {
243 v->Push(n);
244 }
245
sq_pushbool(HSQUIRRELVM v,SQBool b)246 void sq_pushbool(HSQUIRRELVM v,SQBool b)
247 {
248 v->Push(b?true:false);
249 }
250
sq_pushfloat(HSQUIRRELVM v,SQFloat n)251 void sq_pushfloat(HSQUIRRELVM v,SQFloat n)
252 {
253 v->Push(n);
254 }
255
sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)256 void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)
257 {
258 v->Push(p);
259 }
260
sq_pushthread(HSQUIRRELVM v,HSQUIRRELVM thread)261 void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread)
262 {
263 v->Push(thread);
264 }
265
sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)266 SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)
267 {
268 SQUserData *ud = SQUserData::Create(_ss(v), size + SQ_ALIGNMENT);
269 v->Push(ud);
270 return (SQUserPointer)sq_aligning(ud + 1);
271 }
272
sq_newtable(HSQUIRRELVM v)273 void sq_newtable(HSQUIRRELVM v)
274 {
275 v->Push(SQTable::Create(_ss(v), 0));
276 }
277
sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)278 void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)
279 {
280 v->Push(SQTable::Create(_ss(v), initialcapacity));
281 }
282
sq_newarray(HSQUIRRELVM v,SQInteger size)283 void sq_newarray(HSQUIRRELVM v,SQInteger size)
284 {
285 v->Push(SQArray::Create(_ss(v), size));
286 }
287
sq_newclass(HSQUIRRELVM v,SQBool hasbase)288 SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
289 {
290 SQClass *baseclass = NULL;
291 if(hasbase) {
292 SQObjectPtr &base = stack_get(v,-1);
293 if(sq_type(base) != OT_CLASS)
294 return sq_throwerror(v,_SC("invalid base type"));
295 baseclass = _class(base);
296 }
297 SQClass *newclass = SQClass::Create(_ss(v), baseclass);
298 if(baseclass) v->Pop();
299 v->Push(newclass);
300 return SQ_OK;
301 }
302
sq_instanceof(HSQUIRRELVM v)303 SQBool sq_instanceof(HSQUIRRELVM v)
304 {
305 SQObjectPtr &inst = stack_get(v,-1);
306 SQObjectPtr &cl = stack_get(v,-2);
307 if(sq_type(inst) != OT_INSTANCE || sq_type(cl) != OT_CLASS)
308 return sq_throwerror(v,_SC("invalid param type"));
309 return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse;
310 }
311
sq_arrayappend(HSQUIRRELVM v,SQInteger idx)312 SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)
313 {
314 sq_aux_paramscheck(v,2);
315 SQObjectPtr *arr;
316 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
317 _array(*arr)->Append(v->GetUp(-1));
318 v->Pop();
319 return SQ_OK;
320 }
321
sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)322 SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
323 {
324 sq_aux_paramscheck(v, 1);
325 SQObjectPtr *arr;
326 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
327 if(_array(*arr)->Size() > 0) {
328 if(pushval != 0){ v->Push(_array(*arr)->Top()); }
329 _array(*arr)->Pop();
330 return SQ_OK;
331 }
332 return sq_throwerror(v, _SC("empty array"));
333 }
334
sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)335 SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)
336 {
337 sq_aux_paramscheck(v,1);
338 SQObjectPtr *arr;
339 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
340 if(newsize >= 0) {
341 _array(*arr)->Resize(newsize);
342 return SQ_OK;
343 }
344 return sq_throwerror(v,_SC("negative size"));
345 }
346
347
sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)348 SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)
349 {
350 sq_aux_paramscheck(v, 1);
351 SQObjectPtr *o;
352 _GETSAFE_OBJ(v, idx, OT_ARRAY,o);
353 SQArray *arr = _array(*o);
354 if(arr->Size() > 0) {
355 SQObjectPtr t;
356 SQInteger size = arr->Size();
357 SQInteger n = size >> 1; size -= 1;
358 for(SQInteger i = 0; i < n; i++) {
359 t = arr->_values[i];
360 arr->_values[i] = arr->_values[size-i];
361 arr->_values[size-i] = t;
362 }
363 return SQ_OK;
364 }
365 return SQ_OK;
366 }
367
sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)368 SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
369 {
370 sq_aux_paramscheck(v, 1);
371 SQObjectPtr *arr;
372 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
373 return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
374 }
375
sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)376 SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
377 {
378 sq_aux_paramscheck(v, 1);
379 SQObjectPtr *arr;
380 _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
381 SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
382 v->Pop();
383 return ret;
384 }
385
sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)386 void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
387 {
388 SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars);
389 nc->_nparamscheck = 0;
390 for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
391 nc->_outervalues[i] = v->Top();
392 v->Pop();
393 }
394 v->Push(SQObjectPtr(nc));
395 }
396
sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger * nparams,SQUnsignedInteger * nfreevars)397 SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
398 {
399 SQObject o = stack_get(v, idx);
400 if(sq_type(o) == OT_CLOSURE) {
401 SQClosure *c = _closure(o);
402 SQFunctionProto *proto = c->_function;
403 *nparams = (SQUnsignedInteger)proto->_nparameters;
404 *nfreevars = (SQUnsignedInteger)proto->_noutervalues;
405 return SQ_OK;
406 }
407 else if(sq_type(o) == OT_NATIVECLOSURE)
408 {
409 SQNativeClosure *c = _nativeclosure(o);
410 *nparams = (SQUnsignedInteger)c->_nparamscheck;
411 *nfreevars = c->_noutervalues;
412 return SQ_OK;
413 }
414 return sq_throwerror(v,_SC("the object is not a closure"));
415 }
416
sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar * name)417 SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
418 {
419 SQObject o = stack_get(v, idx);
420 if(sq_isnativeclosure(o)) {
421 SQNativeClosure *nc = _nativeclosure(o);
422 nc->_name = SQString::Create(_ss(v),name);
423 return SQ_OK;
424 }
425 return sq_throwerror(v,_SC("the object is not a nativeclosure"));
426 }
427
sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar * typemask)428 SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)
429 {
430 SQObject o = stack_get(v, -1);
431 if(!sq_isnativeclosure(o))
432 return sq_throwerror(v, _SC("native closure expected"));
433 SQNativeClosure *nc = _nativeclosure(o);
434 nc->_nparamscheck = nparamscheck;
435 if(typemask) {
436 SQIntVec res;
437 if(!CompileTypemask(res, typemask))
438 return sq_throwerror(v, _SC("invalid typemask"));
439 nc->_typecheck.copy(res);
440 }
441 else {
442 nc->_typecheck.resize(0);
443 }
444 if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
445 nc->_nparamscheck = nc->_typecheck.size();
446 }
447 return SQ_OK;
448 }
449
sq_bindenv(HSQUIRRELVM v,SQInteger idx)450 SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
451 {
452 SQObjectPtr &o = stack_get(v,idx);
453 if(!sq_isnativeclosure(o) &&
454 !sq_isclosure(o))
455 return sq_throwerror(v,_SC("the target is not a closure"));
456 SQObjectPtr &env = stack_get(v,-1);
457 if(!sq_istable(env) &&
458 !sq_isarray(env) &&
459 !sq_isclass(env) &&
460 !sq_isinstance(env))
461 return sq_throwerror(v,_SC("invalid environment"));
462 SQWeakRef *w = _refcounted(env)->GetWeakRef(sq_type(env));
463 SQObjectPtr ret;
464 if(sq_isclosure(o)) {
465 SQClosure *c = _closure(o)->Clone();
466 __ObjRelease(c->_env);
467 c->_env = w;
468 __ObjAddRef(c->_env);
469 if(_closure(o)->_base) {
470 c->_base = _closure(o)->_base;
471 __ObjAddRef(c->_base);
472 }
473 ret = c;
474 }
475 else { //then must be a native closure
476 SQNativeClosure *c = _nativeclosure(o)->Clone();
477 __ObjRelease(c->_env);
478 c->_env = w;
479 __ObjAddRef(c->_env);
480 ret = c;
481 }
482 v->Pop();
483 v->Push(ret);
484 return SQ_OK;
485 }
486
sq_getclosurename(HSQUIRRELVM v,SQInteger idx)487 SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx)
488 {
489 SQObjectPtr &o = stack_get(v,idx);
490 if(!sq_isnativeclosure(o) &&
491 !sq_isclosure(o))
492 return sq_throwerror(v,_SC("the target is not a closure"));
493 if(sq_isnativeclosure(o))
494 {
495 v->Push(_nativeclosure(o)->_name);
496 }
497 else { //closure
498 v->Push(_closure(o)->_function->_name);
499 }
500 return SQ_OK;
501 }
502
sq_setclosureroot(HSQUIRRELVM v,SQInteger idx)503 SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx)
504 {
505 SQObjectPtr &c = stack_get(v,idx);
506 SQObject o = stack_get(v, -1);
507 if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
508 if(sq_istable(o)) {
509 _closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE));
510 v->Pop();
511 return SQ_OK;
512 }
513 return sq_throwerror(v, _SC("invalid type"));
514 }
515
sq_getclosureroot(HSQUIRRELVM v,SQInteger idx)516 SQRESULT sq_getclosureroot(HSQUIRRELVM v,SQInteger idx)
517 {
518 SQObjectPtr &c = stack_get(v,idx);
519 if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
520 v->Push(_closure(c)->_root->_obj);
521 return SQ_OK;
522 }
523
sq_clear(HSQUIRRELVM v,SQInteger idx)524 SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)
525 {
526 SQObject &o=stack_get(v,idx);
527 switch(sq_type(o)) {
528 case OT_TABLE: _table(o)->Clear(); break;
529 case OT_ARRAY: _array(o)->Resize(0); break;
530 default:
531 return sq_throwerror(v, _SC("clear only works on table and array"));
532 break;
533
534 }
535 return SQ_OK;
536 }
537
sq_pushroottable(HSQUIRRELVM v)538 void sq_pushroottable(HSQUIRRELVM v)
539 {
540 v->Push(v->_roottable);
541 }
542
sq_pushregistrytable(HSQUIRRELVM v)543 void sq_pushregistrytable(HSQUIRRELVM v)
544 {
545 v->Push(_ss(v)->_registry);
546 }
547
sq_pushconsttable(HSQUIRRELVM v)548 void sq_pushconsttable(HSQUIRRELVM v)
549 {
550 v->Push(_ss(v)->_consts);
551 }
552
sq_setroottable(HSQUIRRELVM v)553 SQRESULT sq_setroottable(HSQUIRRELVM v)
554 {
555 SQObject o = stack_get(v, -1);
556 if(sq_istable(o) || sq_isnull(o)) {
557 v->_roottable = o;
558 v->Pop();
559 return SQ_OK;
560 }
561 return sq_throwerror(v, _SC("invalid type"));
562 }
563
sq_setconsttable(HSQUIRRELVM v)564 SQRESULT sq_setconsttable(HSQUIRRELVM v)
565 {
566 SQObject o = stack_get(v, -1);
567 if(sq_istable(o)) {
568 _ss(v)->_consts = o;
569 v->Pop();
570 return SQ_OK;
571 }
572 return sq_throwerror(v, _SC("invalid type, expected table"));
573 }
574
sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)575 void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
576 {
577 v->_foreignptr = p;
578 }
579
sq_getforeignptr(HSQUIRRELVM v)580 SQUserPointer sq_getforeignptr(HSQUIRRELVM v)
581 {
582 return v->_foreignptr;
583 }
584
sq_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p)585 void sq_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p)
586 {
587 _ss(v)->_foreignptr = p;
588 }
589
sq_getsharedforeignptr(HSQUIRRELVM v)590 SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v)
591 {
592 return _ss(v)->_foreignptr;
593 }
594
sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)595 void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
596 {
597 v->_releasehook = hook;
598 }
599
sq_getvmreleasehook(HSQUIRRELVM v)600 SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v)
601 {
602 return v->_releasehook;
603 }
604
sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)605 void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
606 {
607 _ss(v)->_releasehook = hook;
608 }
609
sq_getsharedreleasehook(HSQUIRRELVM v)610 SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v)
611 {
612 return _ss(v)->_releasehook;
613 }
614
sq_push(HSQUIRRELVM v,SQInteger idx)615 void sq_push(HSQUIRRELVM v,SQInteger idx)
616 {
617 v->Push(stack_get(v, idx));
618 }
619
sq_gettype(HSQUIRRELVM v,SQInteger idx)620 SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
621 {
622 return sq_type(stack_get(v, idx));
623 }
624
sq_typeof(HSQUIRRELVM v,SQInteger idx)625 SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx)
626 {
627 SQObjectPtr &o = stack_get(v, idx);
628 SQObjectPtr res;
629 if(!v->TypeOf(o,res)) {
630 return SQ_ERROR;
631 }
632 v->Push(res);
633 return SQ_OK;
634 }
635
sq_tostring(HSQUIRRELVM v,SQInteger idx)636 SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)
637 {
638 SQObjectPtr &o = stack_get(v, idx);
639 SQObjectPtr res;
640 if(!v->ToString(o,res)) {
641 return SQ_ERROR;
642 }
643 v->Push(res);
644 return SQ_OK;
645 }
646
sq_tobool(HSQUIRRELVM v,SQInteger idx,SQBool * b)647 void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
648 {
649 SQObjectPtr &o = stack_get(v, idx);
650 *b = SQVM::IsFalse(o)?SQFalse:SQTrue;
651 }
652
sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger * i)653 SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)
654 {
655 SQObjectPtr &o = stack_get(v, idx);
656 if(sq_isnumeric(o)) {
657 *i = tointeger(o);
658 return SQ_OK;
659 }
660 if(sq_isbool(o)) {
661 *i = SQVM::IsFalse(o)?SQFalse:SQTrue;
662 return SQ_OK;
663 }
664 return SQ_ERROR;
665 }
666
sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat * f)667 SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f)
668 {
669 SQObjectPtr &o = stack_get(v, idx);
670 if(sq_isnumeric(o)) {
671 *f = tofloat(o);
672 return SQ_OK;
673 }
674 return SQ_ERROR;
675 }
676
sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool * b)677 SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)
678 {
679 SQObjectPtr &o = stack_get(v, idx);
680 if(sq_isbool(o)) {
681 *b = _integer(o);
682 return SQ_OK;
683 }
684 return SQ_ERROR;
685 }
686
sq_getstringandsize(HSQUIRRELVM v,SQInteger idx,const SQChar ** c,SQInteger * size)687 SQRESULT sq_getstringandsize(HSQUIRRELVM v,SQInteger idx,const SQChar **c,SQInteger *size)
688 {
689 SQObjectPtr *o = NULL;
690 _GETSAFE_OBJ(v, idx, OT_STRING,o);
691 *c = _stringval(*o);
692 *size = _string(*o)->_len;
693 return SQ_OK;
694 }
695
sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar ** c)696 SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)
697 {
698 SQObjectPtr *o = NULL;
699 _GETSAFE_OBJ(v, idx, OT_STRING,o);
700 *c = _stringval(*o);
701 return SQ_OK;
702 }
703
sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM * thread)704 SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)
705 {
706 SQObjectPtr *o = NULL;
707 _GETSAFE_OBJ(v, idx, OT_THREAD,o);
708 *thread = _thread(*o);
709 return SQ_OK;
710 }
711
sq_clone(HSQUIRRELVM v,SQInteger idx)712 SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)
713 {
714 SQObjectPtr &o = stack_get(v,idx);
715 v->PushNull();
716 if(!v->Clone(o, stack_get(v, -1))){
717 v->Pop();
718 return SQ_ERROR;
719 }
720 return SQ_OK;
721 }
722
sq_getsize(HSQUIRRELVM v,SQInteger idx)723 SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
724 {
725 SQObjectPtr &o = stack_get(v, idx);
726 SQObjectType type = sq_type(o);
727 switch(type) {
728 case OT_STRING: return _string(o)->_len;
729 case OT_TABLE: return _table(o)->CountUsed();
730 case OT_ARRAY: return _array(o)->Size();
731 case OT_USERDATA: return _userdata(o)->_size;
732 case OT_INSTANCE: return _instance(o)->_class->_udsize;
733 case OT_CLASS: return _class(o)->_udsize;
734 default:
735 return sq_aux_invalidtype(v, type);
736 }
737 }
738
sq_gethash(HSQUIRRELVM v,SQInteger idx)739 SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)
740 {
741 SQObjectPtr &o = stack_get(v, idx);
742 return HashObj(o);
743 }
744
sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p,SQUserPointer * typetag)745 SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)
746 {
747 SQObjectPtr *o = NULL;
748 _GETSAFE_OBJ(v, idx, OT_USERDATA,o);
749 (*p) = _userdataval(*o);
750 if(typetag) *typetag = _userdata(*o)->_typetag;
751 return SQ_OK;
752 }
753
sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)754 SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)
755 {
756 SQObjectPtr &o = stack_get(v,idx);
757 switch(sq_type(o)) {
758 case OT_USERDATA: _userdata(o)->_typetag = typetag; break;
759 case OT_CLASS: _class(o)->_typetag = typetag; break;
760 default: return sq_throwerror(v,_SC("invalid object type"));
761 }
762 return SQ_OK;
763 }
764
sq_getobjtypetag(const HSQOBJECT * o,SQUserPointer * typetag)765 SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag)
766 {
767 switch(sq_type(*o)) {
768 case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
769 case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
770 case OT_CLASS: *typetag = _class(*o)->_typetag; break;
771 default: return SQ_ERROR;
772 }
773 return SQ_OK;
774 }
775
sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer * typetag)776 SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)
777 {
778 SQObjectPtr &o = stack_get(v,idx);
779 if (SQ_FAILED(sq_getobjtypetag(&o, typetag)))
780 return SQ_ERROR;// this is not an error it should be a bool but would break backward compatibility
781 return SQ_OK;
782 }
783
sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p)784 SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)
785 {
786 SQObjectPtr *o = NULL;
787 _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
788 (*p) = _userpointer(*o);
789 return SQ_OK;
790 }
791
sq_setinstanceup(HSQUIRRELVM v,SQInteger idx,SQUserPointer p)792 SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)
793 {
794 SQObjectPtr &o = stack_get(v,idx);
795 if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
796 _instance(o)->_userpointer = p;
797 return SQ_OK;
798 }
799
sq_setclassudsize(HSQUIRRELVM v,SQInteger idx,SQInteger udsize)800 SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
801 {
802 SQObjectPtr &o = stack_get(v,idx);
803 if(sq_type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));
804 if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));
805 _class(o)->_udsize = udsize;
806 return SQ_OK;
807 }
808
809
sq_getinstanceup(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p,SQUserPointer typetag)810 SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)
811 {
812 SQObjectPtr &o = stack_get(v,idx);
813 if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
814 (*p) = _instance(o)->_userpointer;
815 if(typetag != 0) {
816 SQClass *cl = _instance(o)->_class;
817 do{
818 if(cl->_typetag == typetag)
819 return SQ_OK;
820 cl = cl->_base;
821 }while(cl != NULL);
822 return sq_throwerror(v,_SC("invalid type tag"));
823 }
824 return SQ_OK;
825 }
826
sq_gettop(HSQUIRRELVM v)827 SQInteger sq_gettop(HSQUIRRELVM v)
828 {
829 return (v->_top) - v->_stackbase;
830 }
831
sq_settop(HSQUIRRELVM v,SQInteger newtop)832 void sq_settop(HSQUIRRELVM v, SQInteger newtop)
833 {
834 SQInteger top = sq_gettop(v);
835 if(top > newtop)
836 sq_pop(v, top - newtop);
837 else
838 while(top++ < newtop) sq_pushnull(v);
839 }
840
sq_pop(HSQUIRRELVM v,SQInteger nelemstopop)841 void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
842 {
843 assert(v->_top >= nelemstopop);
844 v->Pop(nelemstopop);
845 }
846
sq_poptop(HSQUIRRELVM v)847 void sq_poptop(HSQUIRRELVM v)
848 {
849 assert(v->_top >= 1);
850 v->Pop();
851 }
852
853
sq_remove(HSQUIRRELVM v,SQInteger idx)854 void sq_remove(HSQUIRRELVM v, SQInteger idx)
855 {
856 v->Remove(idx);
857 }
858
sq_cmp(HSQUIRRELVM v)859 SQInteger sq_cmp(HSQUIRRELVM v)
860 {
861 SQInteger res;
862 v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
863 return res;
864 }
865
sq_newslot(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)866 SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
867 {
868 sq_aux_paramscheck(v, 3);
869 SQObjectPtr &self = stack_get(v, idx);
870 if(sq_type(self) == OT_TABLE || sq_type(self) == OT_CLASS) {
871 SQObjectPtr &key = v->GetUp(-2);
872 if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
873 v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);
874 v->Pop(2);
875 }
876 return SQ_OK;
877 }
878
sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)879 SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
880 {
881 sq_aux_paramscheck(v, 2);
882 SQObjectPtr *self;
883 _GETSAFE_OBJ(v, idx, OT_TABLE,self);
884 SQObjectPtr &key = v->GetUp(-1);
885 if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
886 SQObjectPtr res;
887 if(!v->DeleteSlot(*self, key, res)){
888 v->Pop();
889 return SQ_ERROR;
890 }
891 if(pushval) v->GetUp(-1) = res;
892 else v->Pop();
893 return SQ_OK;
894 }
895
sq_set(HSQUIRRELVM v,SQInteger idx)896 SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)
897 {
898 SQObjectPtr &self = stack_get(v, idx);
899 if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {
900 v->Pop(2);
901 return SQ_OK;
902 }
903 return SQ_ERROR;
904 }
905
sq_rawset(HSQUIRRELVM v,SQInteger idx)906 SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)
907 {
908 SQObjectPtr &self = stack_get(v, idx);
909 SQObjectPtr &key = v->GetUp(-2);
910 if(sq_type(key) == OT_NULL) {
911 v->Pop(2);
912 return sq_throwerror(v, _SC("null key"));
913 }
914 switch(sq_type(self)) {
915 case OT_TABLE:
916 _table(self)->NewSlot(key, v->GetUp(-1));
917 v->Pop(2);
918 return SQ_OK;
919 break;
920 case OT_CLASS:
921 _class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false);
922 v->Pop(2);
923 return SQ_OK;
924 break;
925 case OT_INSTANCE:
926 if(_instance(self)->Set(key, v->GetUp(-1))) {
927 v->Pop(2);
928 return SQ_OK;
929 }
930 break;
931 case OT_ARRAY:
932 if(v->Set(self, key, v->GetUp(-1),false)) {
933 v->Pop(2);
934 return SQ_OK;
935 }
936 break;
937 default:
938 v->Pop(2);
939 return sq_throwerror(v, _SC("rawset works only on array/table/class and instance"));
940 }
941 v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
942 }
943
sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)944 SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
945 {
946 SQObjectPtr &self = stack_get(v, idx);
947 if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
948 SQObjectPtr &key = v->GetUp(-3);
949 if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
950 if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) {
951 v->Pop(3);
952 return SQ_ERROR;
953 }
954 v->Pop(3);
955 return SQ_OK;
956 }
957
sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)958 SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
959 {
960 SQObjectPtr &self = stack_get(v, idx);
961 if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
962 SQObjectPtr &key = v->GetUp(-3);
963 if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
964 if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) {
965 v->Pop(3);
966 return SQ_ERROR;
967 }
968 v->Pop(3);
969 return SQ_OK;
970 }
971
sq_setdelegate(HSQUIRRELVM v,SQInteger idx)972 SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)
973 {
974 SQObjectPtr &self = stack_get(v, idx);
975 SQObjectPtr &mt = v->GetUp(-1);
976 SQObjectType type = sq_type(self);
977 switch(type) {
978 case OT_TABLE:
979 if(sq_type(mt) == OT_TABLE) {
980 if(!_table(self)->SetDelegate(_table(mt))) {
981 return sq_throwerror(v, _SC("delagate cycle"));
982 }
983 v->Pop();
984 }
985 else if(sq_type(mt)==OT_NULL) {
986 _table(self)->SetDelegate(NULL); v->Pop(); }
987 else return sq_aux_invalidtype(v,type);
988 break;
989 case OT_USERDATA:
990 if(sq_type(mt)==OT_TABLE) {
991 _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
992 else if(sq_type(mt)==OT_NULL) {
993 _userdata(self)->SetDelegate(NULL); v->Pop(); }
994 else return sq_aux_invalidtype(v, type);
995 break;
996 default:
997 return sq_aux_invalidtype(v, type);
998 break;
999 }
1000 return SQ_OK;
1001 }
1002
sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)1003 SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
1004 {
1005 sq_aux_paramscheck(v, 2);
1006 SQObjectPtr *self;
1007 _GETSAFE_OBJ(v, idx, OT_TABLE,self);
1008 SQObjectPtr &key = v->GetUp(-1);
1009 SQObjectPtr t;
1010 if(_table(*self)->Get(key,t)) {
1011 _table(*self)->Remove(key);
1012 }
1013 if(pushval != 0)
1014 v->GetUp(-1) = t;
1015 else
1016 v->Pop();
1017 return SQ_OK;
1018 }
1019
sq_getdelegate(HSQUIRRELVM v,SQInteger idx)1020 SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
1021 {
1022 SQObjectPtr &self=stack_get(v,idx);
1023 switch(sq_type(self)){
1024 case OT_TABLE:
1025 case OT_USERDATA:
1026 if(!_delegable(self)->_delegate){
1027 v->PushNull();
1028 break;
1029 }
1030 v->Push(SQObjectPtr(_delegable(self)->_delegate));
1031 break;
1032 default: return sq_throwerror(v,_SC("wrong type")); break;
1033 }
1034 return SQ_OK;
1035
1036 }
1037
sq_get(HSQUIRRELVM v,SQInteger idx)1038 SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)
1039 {
1040 SQObjectPtr &self=stack_get(v,idx);
1041 SQObjectPtr &obj = v->GetUp(-1);
1042 if(v->Get(self,obj,obj,false,DONT_FALL_BACK))
1043 return SQ_OK;
1044 v->Pop();
1045 return SQ_ERROR;
1046 }
1047
sq_rawget(HSQUIRRELVM v,SQInteger idx)1048 SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)
1049 {
1050 SQObjectPtr &self=stack_get(v,idx);
1051 SQObjectPtr &obj = v->GetUp(-1);
1052 switch(sq_type(self)) {
1053 case OT_TABLE:
1054 if(_table(self)->Get(obj,obj))
1055 return SQ_OK;
1056 break;
1057 case OT_CLASS:
1058 if(_class(self)->Get(obj,obj))
1059 return SQ_OK;
1060 break;
1061 case OT_INSTANCE:
1062 if(_instance(self)->Get(obj,obj))
1063 return SQ_OK;
1064 break;
1065 case OT_ARRAY:{
1066 if(sq_isnumeric(obj)){
1067 if(_array(self)->Get(tointeger(obj),obj)) {
1068 return SQ_OK;
1069 }
1070 }
1071 else {
1072 v->Pop();
1073 return sq_throwerror(v,_SC("invalid index type for an array"));
1074 }
1075 }
1076 break;
1077 default:
1078 v->Pop();
1079 return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
1080 }
1081 v->Pop();
1082 return sq_throwerror(v,_SC("the index doesn't exist"));
1083 }
1084
sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT * po)1085 SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
1086 {
1087 *po=stack_get(v,idx);
1088 return SQ_OK;
1089 }
1090
sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)1091 const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
1092 {
1093 SQUnsignedInteger cstksize=v->_callsstacksize;
1094 SQUnsignedInteger lvl=(cstksize-level)-1;
1095 SQInteger stackbase=v->_stackbase;
1096 if(lvl<cstksize){
1097 for(SQUnsignedInteger i=0;i<level;i++){
1098 SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
1099 stackbase-=ci._prevstkbase;
1100 }
1101 SQVM::CallInfo &ci=v->_callsstack[lvl];
1102 if(sq_type(ci._closure)!=OT_CLOSURE)
1103 return NULL;
1104 SQClosure *c=_closure(ci._closure);
1105 SQFunctionProto *func=c->_function;
1106 if(func->_noutervalues > (SQInteger)idx) {
1107 v->Push(*_outer(c->_outervalues[idx])->_valptr);
1108 return _stringval(func->_outervalues[idx]._name);
1109 }
1110 idx -= func->_noutervalues;
1111 return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
1112 }
1113 return NULL;
1114 }
1115
sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)1116 void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
1117 {
1118 v->Push(SQObjectPtr(obj));
1119 }
1120
sq_resetobject(HSQOBJECT * po)1121 void sq_resetobject(HSQOBJECT *po)
1122 {
1123 po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
1124 }
1125
sq_throwerror(HSQUIRRELVM v,const SQChar * err)1126 SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
1127 {
1128 v->_lasterror=SQString::Create(_ss(v),err);
1129 return SQ_ERROR;
1130 }
1131
sq_throwobject(HSQUIRRELVM v)1132 SQRESULT sq_throwobject(HSQUIRRELVM v)
1133 {
1134 v->_lasterror = v->GetUp(-1);
1135 v->Pop();
1136 return SQ_ERROR;
1137 }
1138
1139
sq_reseterror(HSQUIRRELVM v)1140 void sq_reseterror(HSQUIRRELVM v)
1141 {
1142 v->_lasterror.Null();
1143 }
1144
sq_getlasterror(HSQUIRRELVM v)1145 void sq_getlasterror(HSQUIRRELVM v)
1146 {
1147 v->Push(v->_lasterror);
1148 }
1149
sq_reservestack(HSQUIRRELVM v,SQInteger nsize)1150 SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)
1151 {
1152 if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
1153 if(v->_nmetamethodscall) {
1154 return sq_throwerror(v,_SC("cannot resize stack while in a metamethod"));
1155 }
1156 v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
1157 }
1158 return SQ_OK;
1159 }
1160
sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)1161 SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)
1162 {
1163 if (sq_type(v->GetUp(-1)) == OT_GENERATOR)
1164 {
1165 v->PushNull(); //retval
1166 if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, SQVM::ET_RESUME_GENERATOR))
1167 {v->Raise_Error(v->_lasterror); return SQ_ERROR;}
1168 if(!retval)
1169 v->Pop();
1170 return SQ_OK;
1171 }
1172 return sq_throwerror(v,_SC("only generators can be resumed"));
1173 }
1174
sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)1175 SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
1176 {
1177 SQObjectPtr res;
1178 if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
1179
1180 if(!v->_suspended) {
1181 v->Pop(params);//pop args
1182 }
1183 if(retval){
1184 v->Push(res); return SQ_OK;
1185 }
1186 return SQ_OK;
1187 }
1188 else {
1189 v->Pop(params);
1190 return SQ_ERROR;
1191 }
1192 if(!v->_suspended)
1193 v->Pop(params);
1194 return sq_throwerror(v,_SC("call failed"));
1195 }
1196
sq_tailcall(HSQUIRRELVM v,SQInteger nparams)1197 SQRESULT sq_tailcall(HSQUIRRELVM v, SQInteger nparams)
1198 {
1199 SQObjectPtr &res = v->GetUp(-(nparams + 1));
1200 if (sq_type(res) != OT_CLOSURE) {
1201 return sq_throwerror(v, _SC("only closure can be tail called"));
1202 }
1203 SQClosure *clo = _closure(res);
1204 if (clo->_function->_bgenerator)
1205 {
1206 return sq_throwerror(v, _SC("generators cannot be tail called"));
1207 }
1208
1209 SQInteger stackbase = (v->_top - nparams) - v->_stackbase;
1210 if (!v->TailCall(clo, stackbase, nparams)) {
1211 return SQ_ERROR;
1212 }
1213 return SQ_TAILCALL_FLAG;
1214 }
1215
sq_suspendvm(HSQUIRRELVM v)1216 SQRESULT sq_suspendvm(HSQUIRRELVM v)
1217 {
1218 return v->Suspend();
1219 }
1220
sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror)1221 SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror)
1222 {
1223 SQObjectPtr ret;
1224 if(!v->_suspended)
1225 return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));
1226 SQInteger target = v->_suspended_target;
1227 if(wakeupret) {
1228 if(target != -1) {
1229 v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
1230 }
1231 v->Pop();
1232 } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }
1233 SQObjectPtr dummy;
1234 if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {
1235 return SQ_ERROR;
1236 }
1237 if(retval)
1238 v->Push(ret);
1239 return SQ_OK;
1240 }
1241
sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)1242 void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
1243 {
1244 SQObjectPtr &ud=stack_get(v,idx);
1245 switch(sq_type(ud) ) {
1246 case OT_USERDATA: _userdata(ud)->_hook = hook; break;
1247 case OT_INSTANCE: _instance(ud)->_hook = hook; break;
1248 case OT_CLASS: _class(ud)->_hook = hook; break;
1249 default: return;
1250 }
1251 }
1252
sq_getreleasehook(HSQUIRRELVM v,SQInteger idx)1253 SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx)
1254 {
1255 SQObjectPtr &ud=stack_get(v,idx);
1256 switch(sq_type(ud) ) {
1257 case OT_USERDATA: return _userdata(ud)->_hook; break;
1258 case OT_INSTANCE: return _instance(ud)->_hook; break;
1259 case OT_CLASS: return _class(ud)->_hook; break;
1260 default: return NULL;
1261 }
1262 }
1263
sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)1264 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
1265 {
1266 _ss(v)->_compilererrorhandler = f;
1267 }
1268
sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)1269 SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
1270 {
1271 SQObjectPtr *o = NULL;
1272 _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
1273 unsigned short tag = SQ_BYTECODE_STREAM_TAG;
1274 if(_closure(*o)->_function->_noutervalues)
1275 return sq_throwerror(v,_SC("a closure with free variables bound cannot be serialized"));
1276 if(w(up,&tag,2) != 2)
1277 return sq_throwerror(v,_SC("io error"));
1278 if(!_closure(*o)->Save(v,up,w))
1279 return SQ_ERROR;
1280 return SQ_OK;
1281 }
1282
sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)1283 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
1284 {
1285 SQObjectPtr closure;
1286
1287 unsigned short tag;
1288 if(r(up,&tag,2) != 2)
1289 return sq_throwerror(v,_SC("io error"));
1290 if(tag != SQ_BYTECODE_STREAM_TAG)
1291 return sq_throwerror(v,_SC("invalid stream"));
1292 if(!SQClosure::Load(v,up,r,closure))
1293 return SQ_ERROR;
1294 v->Push(closure);
1295 return SQ_OK;
1296 }
1297
sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)1298 SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
1299 {
1300 return _ss(v)->GetScratchPad(minsize);
1301 }
1302
sq_resurrectunreachable(HSQUIRRELVM v)1303 SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
1304 {
1305 #ifndef NO_GARBAGE_COLLECTOR
1306 _ss(v)->ResurrectUnreachable(v);
1307 return SQ_OK;
1308 #else
1309 return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));
1310 #endif
1311 }
1312
sq_collectgarbage(HSQUIRRELVM v)1313 SQInteger sq_collectgarbage(HSQUIRRELVM v)
1314 {
1315 #ifndef NO_GARBAGE_COLLECTOR
1316 return _ss(v)->CollectGarbage(v);
1317 #else
1318 return -1;
1319 #endif
1320 }
1321
sq_getcallee(HSQUIRRELVM v)1322 SQRESULT sq_getcallee(HSQUIRRELVM v)
1323 {
1324 if(v->_callsstacksize > 1)
1325 {
1326 v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
1327 return SQ_OK;
1328 }
1329 return sq_throwerror(v,_SC("no closure in the calls stack"));
1330 }
1331
sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)1332 const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
1333 {
1334 SQObjectPtr &self=stack_get(v,idx);
1335 const SQChar *name = NULL;
1336 switch(sq_type(self))
1337 {
1338 case OT_CLOSURE:{
1339 SQClosure *clo = _closure(self);
1340 SQFunctionProto *fp = clo->_function;
1341 if(((SQUnsignedInteger)fp->_noutervalues) > nval) {
1342 v->Push(*(_outer(clo->_outervalues[nval])->_valptr));
1343 SQOuterVar &ov = fp->_outervalues[nval];
1344 name = _stringval(ov._name);
1345 }
1346 }
1347 break;
1348 case OT_NATIVECLOSURE:{
1349 SQNativeClosure *clo = _nativeclosure(self);
1350 if(clo->_noutervalues > nval) {
1351 v->Push(clo->_outervalues[nval]);
1352 name = _SC("@NATIVE");
1353 }
1354 }
1355 break;
1356 default: break; //shutup compiler
1357 }
1358 return name;
1359 }
1360
sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)1361 SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
1362 {
1363 SQObjectPtr &self=stack_get(v,idx);
1364 switch(sq_type(self))
1365 {
1366 case OT_CLOSURE:{
1367 SQFunctionProto *fp = _closure(self)->_function;
1368 if(((SQUnsignedInteger)fp->_noutervalues) > nval){
1369 *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
1370 }
1371 else return sq_throwerror(v,_SC("invalid free var index"));
1372 }
1373 break;
1374 case OT_NATIVECLOSURE:
1375 if(_nativeclosure(self)->_noutervalues > nval){
1376 _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);
1377 }
1378 else return sq_throwerror(v,_SC("invalid free var index"));
1379 break;
1380 default:
1381 return sq_aux_invalidtype(v, sq_type(self));
1382 }
1383 v->Pop();
1384 return SQ_OK;
1385 }
1386
sq_setattributes(HSQUIRRELVM v,SQInteger idx)1387 SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)
1388 {
1389 SQObjectPtr *o = NULL;
1390 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1391 SQObjectPtr &key = stack_get(v,-2);
1392 SQObjectPtr &val = stack_get(v,-1);
1393 SQObjectPtr attrs;
1394 if(sq_type(key) == OT_NULL) {
1395 attrs = _class(*o)->_attributes;
1396 _class(*o)->_attributes = val;
1397 v->Pop(2);
1398 v->Push(attrs);
1399 return SQ_OK;
1400 }else if(_class(*o)->GetAttributes(key,attrs)) {
1401 _class(*o)->SetAttributes(key,val);
1402 v->Pop(2);
1403 v->Push(attrs);
1404 return SQ_OK;
1405 }
1406 return sq_throwerror(v,_SC("wrong index"));
1407 }
1408
sq_getattributes(HSQUIRRELVM v,SQInteger idx)1409 SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
1410 {
1411 SQObjectPtr *o = NULL;
1412 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1413 SQObjectPtr &key = stack_get(v,-1);
1414 SQObjectPtr attrs;
1415 if(sq_type(key) == OT_NULL) {
1416 attrs = _class(*o)->_attributes;
1417 v->Pop();
1418 v->Push(attrs);
1419 return SQ_OK;
1420 }
1421 else if(_class(*o)->GetAttributes(key,attrs)) {
1422 v->Pop();
1423 v->Push(attrs);
1424 return SQ_OK;
1425 }
1426 return sq_throwerror(v,_SC("wrong index"));
1427 }
1428
sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE * handle)1429 SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
1430 {
1431 SQObjectPtr *o = NULL;
1432 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1433 SQObjectPtr &key = stack_get(v,-1);
1434 SQTable *m = _class(*o)->_members;
1435 SQObjectPtr val;
1436 if(m->Get(key,val)) {
1437 handle->_static = _isfield(val) ? SQFalse : SQTrue;
1438 handle->_index = _member_idx(val);
1439 v->Pop();
1440 return SQ_OK;
1441 }
1442 return sq_throwerror(v,_SC("wrong index"));
1443 }
1444
_getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr & self,const HSQMEMBERHANDLE * handle,SQObjectPtr * & val)1445 SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val)
1446 {
1447 switch(sq_type(self)) {
1448 case OT_INSTANCE: {
1449 SQInstance *i = _instance(self);
1450 if(handle->_static) {
1451 SQClass *c = i->_class;
1452 val = &c->_methods[handle->_index].val;
1453 }
1454 else {
1455 val = &i->_values[handle->_index];
1456
1457 }
1458 }
1459 break;
1460 case OT_CLASS: {
1461 SQClass *c = _class(self);
1462 if(handle->_static) {
1463 val = &c->_methods[handle->_index].val;
1464 }
1465 else {
1466 val = &c->_defaultvalues[handle->_index].val;
1467 }
1468 }
1469 break;
1470 default:
1471 return sq_throwerror(v,_SC("wrong type(expected class or instance)"));
1472 }
1473 return SQ_OK;
1474 }
1475
sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE * handle)1476 SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
1477 {
1478 SQObjectPtr &self = stack_get(v,idx);
1479 SQObjectPtr *val = NULL;
1480 if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
1481 return SQ_ERROR;
1482 }
1483 v->Push(_realval(*val));
1484 return SQ_OK;
1485 }
1486
sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE * handle)1487 SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
1488 {
1489 SQObjectPtr &self = stack_get(v,idx);
1490 SQObjectPtr &newval = stack_get(v,-1);
1491 SQObjectPtr *val = NULL;
1492 if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
1493 return SQ_ERROR;
1494 }
1495 *val = newval;
1496 v->Pop();
1497 return SQ_OK;
1498 }
1499
sq_getbase(HSQUIRRELVM v,SQInteger idx)1500 SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
1501 {
1502 SQObjectPtr *o = NULL;
1503 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1504 if(_class(*o)->_base)
1505 v->Push(SQObjectPtr(_class(*o)->_base));
1506 else
1507 v->PushNull();
1508 return SQ_OK;
1509 }
1510
sq_getclass(HSQUIRRELVM v,SQInteger idx)1511 SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)
1512 {
1513 SQObjectPtr *o = NULL;
1514 _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
1515 v->Push(SQObjectPtr(_instance(*o)->_class));
1516 return SQ_OK;
1517 }
1518
sq_createinstance(HSQUIRRELVM v,SQInteger idx)1519 SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)
1520 {
1521 SQObjectPtr *o = NULL;
1522 _GETSAFE_OBJ(v, idx, OT_CLASS,o);
1523 v->Push(_class(*o)->CreateInstance());
1524 return SQ_OK;
1525 }
1526
sq_weakref(HSQUIRRELVM v,SQInteger idx)1527 void sq_weakref(HSQUIRRELVM v,SQInteger idx)
1528 {
1529 SQObject &o=stack_get(v,idx);
1530 if(ISREFCOUNTED(sq_type(o))) {
1531 v->Push(_refcounted(o)->GetWeakRef(sq_type(o)));
1532 return;
1533 }
1534 v->Push(o);
1535 }
1536
sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)1537 SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
1538 {
1539 SQObjectPtr &o = stack_get(v,idx);
1540 if(sq_type(o) != OT_WEAKREF) {
1541 return sq_throwerror(v,_SC("the object must be a weakref"));
1542 }
1543 v->Push(_weakref(o)->_obj);
1544 return SQ_OK;
1545 }
1546
sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)1547 SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
1548 {
1549 SQSharedState *ss = _ss(v);
1550 switch(t) {
1551 case OT_TABLE: v->Push(ss->_table_default_delegate); break;
1552 case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
1553 case OT_STRING: v->Push(ss->_string_default_delegate); break;
1554 case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
1555 case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
1556 case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
1557 case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
1558 case OT_CLASS: v->Push(ss->_class_default_delegate); break;
1559 case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
1560 case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
1561 default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
1562 }
1563 return SQ_OK;
1564 }
1565
sq_next(HSQUIRRELVM v,SQInteger idx)1566 SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
1567 {
1568 SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
1569 if(sq_type(o) == OT_GENERATOR) {
1570 return sq_throwerror(v,_SC("cannot iterate a generator"));
1571 }
1572 int faketojump;
1573 if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
1574 return SQ_ERROR;
1575 if(faketojump != 666) {
1576 v->Push(realkey);
1577 v->Push(val);
1578 return SQ_OK;
1579 }
1580 return SQ_ERROR;
1581 }
1582
1583 struct BufState{
1584 const SQChar *buf;
1585 SQInteger ptr;
1586 SQInteger size;
1587 };
1588
buf_lexfeed(SQUserPointer file)1589 SQInteger buf_lexfeed(SQUserPointer file)
1590 {
1591 BufState *buf=(BufState*)file;
1592 if(buf->size<(buf->ptr+1))
1593 return 0;
1594 return buf->buf[buf->ptr++];
1595 }
1596
sq_compilebuffer(HSQUIRRELVM v,const SQChar * s,SQInteger size,const SQChar * sourcename,SQBool raiseerror)1597 SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
1598 BufState buf;
1599 buf.buf = s;
1600 buf.size = size;
1601 buf.ptr = 0;
1602 return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
1603 }
1604
sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)1605 void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
1606 {
1607 dest->Push(stack_get(src,idx));
1608 }
1609
sq_setprintfunc(HSQUIRRELVM v,SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)1610 void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)
1611 {
1612 _ss(v)->_printfunc = printfunc;
1613 _ss(v)->_errorfunc = errfunc;
1614 }
1615
sq_getprintfunc(HSQUIRRELVM v)1616 SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
1617 {
1618 return _ss(v)->_printfunc;
1619 }
1620
sq_geterrorfunc(HSQUIRRELVM v)1621 SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)
1622 {
1623 return _ss(v)->_errorfunc;
1624 }
1625
sq_malloc(SQUnsignedInteger size)1626 void *sq_malloc(SQUnsignedInteger size)
1627 {
1628 return SQ_MALLOC(size);
1629 }
1630
sq_realloc(void * p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)1631 void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
1632 {
1633 return SQ_REALLOC(p,oldsize,newsize);
1634 }
1635
sq_free(void * p,SQUnsignedInteger size)1636 void sq_free(void *p,SQUnsignedInteger size)
1637 {
1638 SQ_FREE(p,size);
1639 }
1640