updated squirrel version
[supertux.git] / src / squirrel / squirrel / sqobject.cpp
1 /*
2         see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include "sqvm.h"
6 #include "sqstring.h"
7 #include "sqarray.h"
8 #include "sqtable.h"
9 #include "squserdata.h"
10 #include "sqfuncproto.h"
11 #include "sqclass.h"
12 #include "sqclosure.h"
13
14 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,int len)
15 {
16         SQString *str=ADD_STRING(ss,s,len);
17         str->_sharedstate=ss;
18         return str;
19 }
20
21 void SQString::Release()
22 {
23         REMOVE_STRING(_sharedstate,this);
24 }
25
26 unsigned int TranslateIndex(const SQObjectPtr &idx)
27 {
28         switch(type(idx)){
29                 case OT_NULL:
30                         return 0;
31                 case OT_INTEGER:
32                         return (unsigned int)_integer(idx);
33         }
34         assert(0);
35         return 0;
36 }
37
38 bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {
39         if(_delegate) {
40                 return _delegate->Get((*_ss(this)->_metamethods)[mm],res);
41         }
42         return false;
43 }
44
45 bool SQGenerator::Yield(SQVM *v)
46 {
47         if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}
48         if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
49         int size = v->_top-v->_stackbase;
50         _ci=*v->ci;
51         _stack.resize(size);
52         for(int n =0; n<size; n++) {
53                 _stack._vals[n] = v->_stack[v->_stackbase+n];
54                 v->_stack[v->_stackbase+n] = _null_;
55         }
56         int nvargs = v->ci->_vargs.size;
57         int vargsbase = v->ci->_vargs.base;
58         for(int j = nvargs - 1; j >= 0; j--) {
59                 _vargsstack.push_back(v->_vargsstack[vargsbase+j]);
60         }
61         _ci._generator=_null_;
62         for(int i=0;i<_ci._etraps;i++) {
63                 _etraps.push_back(v->_etraps.top());
64                 v->_etraps.pop_back();
65         }
66         _state=eSuspended;
67         return true;
68 }
69
70 bool SQGenerator::Resume(SQVM *v,int target)
71 {
72         int size=_stack.size();
73         if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
74         if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
75         int prevtop=v->_top-v->_stackbase;
76         PUSH_CALLINFO(v,_ci);
77         int oldstackbase=v->_stackbase;
78         v->_stackbase=v->_top;
79         v->ci->_target=target;
80         v->ci->_generator=SQObjectPtr(this);
81         v->ci->_vargs.size = _vargsstack.size();
82         
83         for(int i=0;i<_ci._etraps;i++) {
84                 v->_etraps.push_back(_etraps.top());
85                 _etraps.pop_back();
86         }
87         for(int n =0; n<size; n++) {
88                 v->_stack[v->_stackbase+n] = _stack._vals[n];
89                 _stack._vals[0] = _null_;
90         }
91         while(_vargsstack.size()) {
92                 v->_vargsstack.push_back(_vargsstack.back());
93                 _vargsstack.pop_back();
94         }
95         v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;
96         v->_top=v->_stackbase+size;
97         v->ci->_prevtop=prevtop;
98         v->ci->_prevstkbase=v->_stackbase-oldstackbase;
99         _state=eRunning;
100         return true;
101 }
102
103 void SQArray::Extend(const SQArray *a){
104         int xlen;
105         if((xlen=a->Size()))
106                 for(int i=0;i<xlen;i++)
107                         Append(a->_values[i]);
108 }
109
110 const SQChar* SQFunctionProto::GetLocal(SQVM *vm,unsigned int stackbase,unsigned int nseq,unsigned int nop)
111 {
112         unsigned int nvars=_localvarinfos.size();
113         const SQChar *res=NULL; 
114         if(nvars>=nseq){
115                 for(unsigned int i=0;i<nvars;i++){
116                         if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
117                         {
118                                 if(nseq==0){
119                                         vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
120                                         res=_stringval(_localvarinfos[i]._name);
121                                         break;
122                                 }
123                                 nseq--;
124                         }
125                 }
126         }
127         return res;
128 }
129
130 int SQFunctionProto::GetLine(SQInstruction *curr)
131 {
132         int op=(curr-_instructions._vals);
133         int line=_lineinfos[0]._line;
134         for(unsigned int i=1;i<_lineinfos.size();i++){
135                 if(_lineinfos[i]._op>=op)
136                         return line;
137                 line=_lineinfos[i]._line;
138         }
139         return line;
140 }
141
142 //#define _ERROR_TRAP() error_trap:
143 #define _CHECK_IO(exp)  { if(!exp)return false; }
144 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,int size)
145 {
146         if(write(up,dest,size) != size) {
147                 v->Raise_Error(_SC("io error (write function failure)"));
148                 return false;
149         }
150         return true;
151 }
152
153 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,int size)
154 {
155         if(size && read(up,dest,size) != size) {
156                 v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
157                 return false;
158         }
159         return true;
160 }
161
162 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,int tag)
163 {
164         return SafeWrite(v,write,up,&tag,sizeof(tag));
165 }
166
167 bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,int tag)
168 {
169         int t;
170         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
171         if(t != tag){
172                 v->Raise_Error(_SC("invalid or corrupted closure stream"));
173                 return false;
174         }
175         return true;
176 }
177
178 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
179 {
180         _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));
181         switch(type(o)){
182         case OT_STRING:
183                 _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
184                 _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));
185                 break;
186         case OT_INTEGER:
187                 _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
188         case OT_FLOAT:
189                 _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
190         case OT_NULL:
191                 break;
192         default:
193                 v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
194                 return false;
195         }
196         return true;
197 }
198
199 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
200 {
201         SQObjectType t;
202         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));
203         switch(t){
204         case OT_STRING:{
205                 int len;
206                 _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
207                 _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));
208                 o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
209                                    }
210                 break;
211         case OT_INTEGER:{
212                 SQInteger i;
213                 _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
214                                         }
215         case OT_FLOAT:{
216                 SQFloat f;
217                 _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
218                                   }
219         case OT_NULL:
220                 o=_null_;
221                 break;
222         default:
223                 v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
224                 return false;
225         }
226         return true;
227 }
228
229 bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
230 {
231         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
232         _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
233         _CHECK_IO(_funcproto(_function)->Save(v,up,write));
234         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
235         return true;
236 }
237
238 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
239 {
240         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
241         _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
242         _CHECK_IO(_funcproto(_function)->Load(v,up,read));
243         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
244         return true;
245 }
246
247 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
248 {
249         int i,nsize=_literals.size();
250         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
251         _CHECK_IO(WriteObject(v,up,write,_sourcename));
252         _CHECK_IO(WriteObject(v,up,write,_name));
253         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
254         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
255         for(i=0;i<nsize;i++){
256                 _CHECK_IO(WriteObject(v,up,write,_literals[i]));
257         }
258         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
259         nsize=_parameters.size();
260         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
261         for(i=0;i<nsize;i++){
262                 _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
263         }
264         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
265         nsize=_outervalues.size();
266         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
267         for(i=0;i<nsize;i++){
268                 _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(unsigned int)));
269                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
270                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
271         }
272         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
273         nsize=_localvarinfos.size();
274         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
275         for(i=0;i<nsize;i++){
276                 SQLocalVarInfo &lvi=_localvarinfos[i];
277                 _CHECK_IO(WriteObject(v,up,write,lvi._name));
278                 _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(unsigned int)));
279                 _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(unsigned int)));
280                 _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(unsigned int)));
281         }
282         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
283         nsize=_lineinfos.size();
284         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
285         _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));
286         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
287         nsize=_instructions.size();
288         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
289         _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));
290         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
291         nsize=_functions.size();
292         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
293         for(i=0;i<nsize;i++){
294                 _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
295         }
296         _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
297         _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
298         _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
299         return true;
300 }
301
302 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
303 {
304         int i, nsize = _literals.size();
305         SQObjectPtr o;
306         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
307         _CHECK_IO(ReadObject(v, up, read, _sourcename));
308         _CHECK_IO(ReadObject(v, up, read, _name));
309         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
310         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
311         for(i = 0;i < nsize; i++){
312                 _CHECK_IO(ReadObject(v, up, read, o));
313                 _literals.push_back(o);
314         }
315         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
316         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
317         for(i = 0; i < nsize; i++){
318                 _CHECK_IO(ReadObject(v, up, read, o));
319                 _parameters.push_back(o);
320         }
321         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
322         _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));
323         for(i = 0; i < nsize; i++){
324                 unsigned int type;
325                 SQObjectPtr name;
326                 _CHECK_IO(SafeRead(v,read,up, &type, sizeof(unsigned int)));
327                 _CHECK_IO(ReadObject(v, up, read, o));
328                 _CHECK_IO(ReadObject(v, up, read, name));
329                 _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));
330         }
331         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
332         _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));
333         for(i = 0; i < nsize; i++){
334                 SQLocalVarInfo lvi;
335                 _CHECK_IO(ReadObject(v, up, read, lvi._name));
336                 _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(unsigned int)));
337                 _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(unsigned int)));
338                 _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(unsigned int)));
339                 _localvarinfos.push_back(lvi);
340         }
341         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
342         _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));
343         _lineinfos.resize(nsize);
344         _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));
345         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
346         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
347         _instructions.resize(nsize);
348         _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));
349         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
350         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
351         for(i = 0; i < nsize; i++){
352                 o = SQFunctionProto::Create();
353                 _CHECK_IO(_funcproto(o)->Load(v, up, read));
354                 _functions.push_back(o);
355         }
356         _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));
357         _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));
358         _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));
359         return true;
360 }
361
362 #ifndef NO_GARBAGE_COLLECTOR
363
364 #define START_MARK()    if(!(_uiRef&MARK_FLAG)){ \
365                 _uiRef|=MARK_FLAG;
366
367 #define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
368                 AddToChain(chain, this); }
369
370 void SQVM::Mark(SQCollectable **chain)
371 {
372         START_MARK()
373                 SQSharedState::MarkObject(_lasterror,chain);
374                 SQSharedState::MarkObject(_errorhandler,chain);
375                 SQSharedState::MarkObject(_debughook,chain);
376                 SQSharedState::MarkObject(_roottable, chain);
377                 SQSharedState::MarkObject(temp_reg, chain);
378                 for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
379                 for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
380         END_MARK()
381 }
382
383 void SQArray::Mark(SQCollectable **chain)
384 {
385         START_MARK()
386                 int len = _values.size();
387                 for(int i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
388         END_MARK()
389 }
390 void SQTable::Mark(SQCollectable **chain)
391 {
392         START_MARK()
393                 if(_delegate) _delegate->Mark(chain);
394                 int len = _numofnodes;
395                 for(int i = 0; i < len; i++){
396                         SQSharedState::MarkObject(_nodes[i].key, chain);
397                         SQSharedState::MarkObject(_nodes[i].val, chain);
398                 }
399         END_MARK()
400 }
401
402 void SQClass::Mark(SQCollectable **chain)
403 {
404         START_MARK()
405                 _members->Mark(chain);
406                 if(_base) _base->Mark(chain);
407                 SQSharedState::MarkObject(_attributes, chain);
408                 for(unsigned int i =0; i< _defaultvalues.size(); i++) {
409                         SQSharedState::MarkObject(_defaultvalues[i].val, chain);
410                         SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
411                 }
412                 for(unsigned int j =0; j< _methods.size(); j++) {
413                         SQSharedState::MarkObject(_methods[j].val, chain);
414                         SQSharedState::MarkObject(_methods[j].attrs, chain);
415                 }
416                 for(unsigned int k =0; k< _metamethods.size(); k++) {
417                         SQSharedState::MarkObject(_metamethods[k], chain);
418                 }
419         END_MARK()
420 }
421
422 void SQInstance::Mark(SQCollectable **chain)
423 {
424         START_MARK()
425                 _class->Mark(chain);
426                 for(unsigned int i =0; i< _values.size(); i++) {
427                         SQSharedState::MarkObject(_values[i], chain);
428                 }
429         END_MARK()
430 }
431
432 void SQGenerator::Mark(SQCollectable **chain)
433 {
434         START_MARK()
435                 for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
436                 for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
437                 SQSharedState::MarkObject(_closure, chain);
438         END_MARK()
439 }
440
441 void SQClosure::Mark(SQCollectable **chain)
442 {
443         START_MARK()
444                 for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
445         END_MARK()
446 }
447
448 void SQNativeClosure::Mark(SQCollectable **chain)
449 {
450         START_MARK()
451                 for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
452         END_MARK()
453 }
454
455 void SQUserData::Mark(SQCollectable **chain){
456         START_MARK()
457                 if(_delegate) _delegate->Mark(chain);
458         END_MARK()
459 }
460
461 void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
462
463 #endif
464