2 see copyright notice in squirrel.h
\r
4 #include "sqpcheader.h"
\r
6 #include "sqstring.h"
\r
9 #include "squserdata.h"
\r
10 #include "sqfuncproto.h"
\r
11 #include "sqclass.h"
\r
12 #include "sqclosure.h"
\r
14 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,int len)
\r
16 SQString *str=ADD_STRING(ss,s,len);
\r
17 str->_sharedstate=ss;
\r
21 void SQString::Release()
\r
23 REMOVE_STRING(_sharedstate,this);
\r
26 unsigned int TranslateIndex(const SQObjectPtr &idx)
\r
32 return (unsigned int)_integer(idx);
\r
38 bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {
\r
40 return _delegate->Get((*_ss(this)->_metamethods)[mm],res);
\r
45 bool SQGenerator::Yield(SQVM *v)
\r
47 if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;}
\r
48 if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
\r
49 int size = v->_top-v->_stackbase;
\r
51 _stack.resize(size);
\r
52 for(int n =0; n<size; n++) {
\r
53 _stack._vals[n] = v->_stack[v->_stackbase+n];
\r
54 v->_stack[v->_stackbase+n] = _null_;
\r
56 int nvargs = v->ci->_vargs.size;
\r
57 int vargsbase = v->ci->_vargs.base;
\r
58 for(int j = nvargs - 1; j >= 0; j--) {
\r
59 _vargsstack.push_back(v->_vargsstack[vargsbase+j]);
\r
61 _ci._generator=_null_;
\r
62 for(int i=0;i<_ci._etraps;i++) {
\r
63 _etraps.push_back(v->_etraps.top());
\r
64 v->_etraps.pop_back();
\r
70 bool SQGenerator::Resume(SQVM *v,int target)
\r
72 int size=_stack.size();
\r
73 if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
\r
74 if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
\r
75 int prevtop=v->_top-v->_stackbase;
\r
76 PUSH_CALLINFO(v,_ci);
\r
77 int oldstackbase=v->_stackbase;
\r
78 v->_stackbase=v->_top;
\r
79 v->ci->_target=target;
\r
80 v->ci->_generator=SQObjectPtr(this);
\r
81 v->ci->_vargs.size = _vargsstack.size();
\r
83 for(int i=0;i<_ci._etraps;i++) {
\r
84 v->_etraps.push_back(_etraps.top());
\r
87 for(int n =0; n<size; n++) {
\r
88 v->_stack[v->_stackbase+n] = _stack._vals[n];
\r
89 _stack._vals[0] = _null_;
\r
91 while(_vargsstack.size()) {
\r
92 v->_vargsstack.push_back(_vargsstack.back());
\r
93 _vargsstack.pop_back();
\r
95 v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;
\r
96 v->_top=v->_stackbase+size;
\r
97 v->ci->_prevtop=prevtop;
\r
98 v->ci->_prevstkbase=v->_stackbase-oldstackbase;
\r
103 void SQArray::Extend(const SQArray *a){
\r
105 if((xlen=a->Size()))
\r
106 for(int i=0;i<xlen;i++)
\r
107 Append(a->_values[i]);
\r
110 const SQChar* SQFunctionProto::GetLocal(SQVM *vm,unsigned int stackbase,unsigned int nseq,unsigned int nop)
\r
112 unsigned int nvars=_localvarinfos.size();
\r
113 const SQChar *res=NULL;
\r
115 for(unsigned int i=0;i<nvars;i++){
\r
116 if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
\r
119 vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
\r
120 res=_stringval(_localvarinfos[i]._name);
\r
130 int SQFunctionProto::GetLine(SQInstruction *curr)
\r
132 int op=(curr-_instructions._vals);
\r
133 int line=_lineinfos[0]._line;
\r
134 for(unsigned int i=1;i<_lineinfos.size();i++){
\r
135 if(_lineinfos[i]._op>=op)
\r
137 line=_lineinfos[i]._line;
\r
142 //#define _ERROR_TRAP() error_trap:
\r
143 #define _CHECK_IO(exp) { if(!exp)return false; }
\r
144 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,int size)
\r
146 if(write(up,dest,size) != size) {
\r
147 v->Raise_Error(_SC("io error (write function failure)"));
\r
153 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,int size)
\r
155 if(size && read(up,dest,size) != size) {
\r
156 v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
\r
162 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,int tag)
\r
164 return SafeWrite(v,write,up,&tag,sizeof(tag));
\r
167 bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,int tag)
\r
170 _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
\r
172 v->Raise_Error(_SC("invalid or corrupted closure stream"));
\r
178 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
\r
180 _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));
\r
183 _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
\r
184 _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));
\r
187 _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
\r
189 _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
\r
193 v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
\r
199 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
\r
202 _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));
\r
206 _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
\r
207 _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));
\r
208 o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
\r
213 _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
\r
217 _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
\r
223 v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
\r
229 bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
\r
231 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
\r
232 _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
\r
233 _CHECK_IO(_funcproto(_function)->Save(v,up,write));
\r
234 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
\r
238 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
\r
240 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
\r
241 _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
\r
242 _CHECK_IO(_funcproto(_function)->Load(v,up,read));
\r
243 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
\r
247 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
\r
249 int i,nsize=_literals.size();
\r
250 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
251 _CHECK_IO(WriteObject(v,up,write,_sourcename));
\r
252 _CHECK_IO(WriteObject(v,up,write,_name));
\r
253 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
254 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
255 for(i=0;i<nsize;i++){
\r
256 _CHECK_IO(WriteObject(v,up,write,_literals[i]));
\r
258 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
259 nsize=_parameters.size();
\r
260 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
261 for(i=0;i<nsize;i++){
\r
262 _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
\r
264 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
265 nsize=_outervalues.size();
\r
266 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
267 for(i=0;i<nsize;i++){
\r
268 _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(unsigned int)));
\r
269 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
\r
270 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
\r
272 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
273 nsize=_localvarinfos.size();
\r
274 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
275 for(i=0;i<nsize;i++){
\r
276 SQLocalVarInfo &lvi=_localvarinfos[i];
\r
277 _CHECK_IO(WriteObject(v,up,write,lvi._name));
\r
278 _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(unsigned int)));
\r
279 _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(unsigned int)));
\r
280 _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(unsigned int)));
\r
282 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
283 nsize=_lineinfos.size();
\r
284 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
285 _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));
\r
286 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
287 nsize=_instructions.size();
\r
288 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
289 _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));
\r
290 _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
\r
291 nsize=_functions.size();
\r
292 _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
\r
293 for(i=0;i<nsize;i++){
\r
294 _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
\r
296 _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
\r
297 _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
\r
298 _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
\r
302 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
\r
304 int i, nsize = _literals.size();
\r
306 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
307 _CHECK_IO(ReadObject(v, up, read, _sourcename));
\r
308 _CHECK_IO(ReadObject(v, up, read, _name));
\r
309 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
310 _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
\r
311 for(i = 0;i < nsize; i++){
\r
312 _CHECK_IO(ReadObject(v, up, read, o));
\r
313 _literals.push_back(o);
\r
315 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
316 _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
\r
317 for(i = 0; i < nsize; i++){
\r
318 _CHECK_IO(ReadObject(v, up, read, o));
\r
319 _parameters.push_back(o);
\r
321 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
322 _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));
\r
323 for(i = 0; i < nsize; i++){
\r
326 _CHECK_IO(SafeRead(v,read,up, &type, sizeof(unsigned int)));
\r
327 _CHECK_IO(ReadObject(v, up, read, o));
\r
328 _CHECK_IO(ReadObject(v, up, read, name));
\r
329 _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));
\r
331 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
332 _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));
\r
333 for(i = 0; i < nsize; i++){
\r
334 SQLocalVarInfo lvi;
\r
335 _CHECK_IO(ReadObject(v, up, read, lvi._name));
\r
336 _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(unsigned int)));
\r
337 _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(unsigned int)));
\r
338 _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(unsigned int)));
\r
339 _localvarinfos.push_back(lvi);
\r
341 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
342 _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));
\r
343 _lineinfos.resize(nsize);
\r
344 _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));
\r
345 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
346 _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
\r
347 _instructions.resize(nsize);
\r
348 _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));
\r
349 _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
\r
350 _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
\r
351 for(i = 0; i < nsize; i++){
\r
352 o = SQFunctionProto::Create();
\r
353 _CHECK_IO(_funcproto(o)->Load(v, up, read));
\r
354 _functions.push_back(o);
\r
356 _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));
\r
357 _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));
\r
358 _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));
\r
362 #ifndef NO_GARBAGE_COLLECTOR
\r
364 #define START_MARK() if(!(_uiRef&MARK_FLAG)){ \
\r
367 #define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
\r
368 AddToChain(chain, this); }
\r
370 void SQVM::Mark(SQCollectable **chain)
\r
373 SQSharedState::MarkObject(_lasterror,chain);
\r
374 SQSharedState::MarkObject(_errorhandler,chain);
\r
375 SQSharedState::MarkObject(_debughook,chain);
\r
376 SQSharedState::MarkObject(_roottable, chain);
\r
377 SQSharedState::MarkObject(temp_reg, chain);
\r
378 for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
\r
379 for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
\r
383 void SQArray::Mark(SQCollectable **chain)
\r
386 int len = _values.size();
\r
387 for(int i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
\r
390 void SQTable::Mark(SQCollectable **chain)
\r
393 if(_delegate) _delegate->Mark(chain);
\r
394 int len = _numofnodes;
\r
395 for(int i = 0; i < len; i++){
\r
396 SQSharedState::MarkObject(_nodes[i].key, chain);
\r
397 SQSharedState::MarkObject(_nodes[i].val, chain);
\r
402 void SQClass::Mark(SQCollectable **chain)
\r
405 _members->Mark(chain);
\r
406 if(_base) _base->Mark(chain);
\r
407 SQSharedState::MarkObject(_attributes, chain);
\r
408 for(unsigned int i =0; i< _defaultvalues.size(); i++) {
\r
409 SQSharedState::MarkObject(_defaultvalues[i].val, chain);
\r
410 SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
\r
412 for(unsigned int j =0; j< _methods.size(); j++) {
\r
413 SQSharedState::MarkObject(_methods[j].val, chain);
\r
414 SQSharedState::MarkObject(_methods[j].attrs, chain);
\r
416 for(unsigned int k =0; k< _metamethods.size(); k++) {
\r
417 SQSharedState::MarkObject(_metamethods[k], chain);
\r
422 void SQInstance::Mark(SQCollectable **chain)
\r
425 _class->Mark(chain);
\r
426 for(unsigned int i =0; i< _values.size(); i++) {
\r
427 SQSharedState::MarkObject(_values[i], chain);
\r
432 void SQGenerator::Mark(SQCollectable **chain)
\r
435 for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
\r
436 for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
\r
437 SQSharedState::MarkObject(_closure, chain);
\r
441 void SQClosure::Mark(SQCollectable **chain)
\r
444 for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
\r
448 void SQNativeClosure::Mark(SQCollectable **chain)
\r
451 for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
\r
455 void SQUserData::Mark(SQCollectable **chain){
\r
457 if(_delegate) _delegate->Mark(chain);
\r
461 void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
\r