1 /*
2 see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #ifndef NO_COMPILER
6 #include "sqcompiler.h"
7 #include "sqstring.h"
8 #include "sqfuncproto.h"
9 #include "sqtable.h"
10 #include "sqopcodes.h"
11 #include "sqfuncstate.h"
12
13 #ifdef _DEBUG_DUMP
14 SQInstructionDesc g_InstrDesc[]={
15 {_SC("_OP_LINE")},
16 {_SC("_OP_LOAD")},
17 {_SC("_OP_LOADINT")},
18 {_SC("_OP_LOADFLOAT")},
19 {_SC("_OP_DLOAD")},
20 {_SC("_OP_TAILCALL")},
21 {_SC("_OP_CALL")},
22 {_SC("_OP_PREPCALL")},
23 {_SC("_OP_PREPCALLK")},
24 {_SC("_OP_GETK")},
25 {_SC("_OP_MOVE")},
26 {_SC("_OP_NEWSLOT")},
27 {_SC("_OP_DELETE")},
28 {_SC("_OP_SET")},
29 {_SC("_OP_GET")},
30 {_SC("_OP_EQ")},
31 {_SC("_OP_NE")},
32 {_SC("_OP_ADD")},
33 {_SC("_OP_SUB")},
34 {_SC("_OP_MUL")},
35 {_SC("_OP_DIV")},
36 {_SC("_OP_MOD")},
37 {_SC("_OP_BITW")},
38 {_SC("_OP_RETURN")},
39 {_SC("_OP_LOADNULLS")},
40 {_SC("_OP_LOADROOT")},
41 {_SC("_OP_LOADBOOL")},
42 {_SC("_OP_DMOVE")},
43 {_SC("_OP_JMP")},
44 {_SC("_OP_JCMP")},
45 {_SC("_OP_JZ")},
46 {_SC("_OP_SETOUTER")},
47 {_SC("_OP_GETOUTER")},
48 {_SC("_OP_NEWOBJ")},
49 {_SC("_OP_APPENDARRAY")},
50 {_SC("_OP_COMPARITH")},
51 {_SC("_OP_INC")},
52 {_SC("_OP_INCL")},
53 {_SC("_OP_PINC")},
54 {_SC("_OP_PINCL")},
55 {_SC("_OP_CMP")},
56 {_SC("_OP_EXISTS")},
57 {_SC("_OP_INSTANCEOF")},
58 {_SC("_OP_AND")},
59 {_SC("_OP_OR")},
60 {_SC("_OP_NEG")},
61 {_SC("_OP_NOT")},
62 {_SC("_OP_BWNOT")},
63 {_SC("_OP_CLOSURE")},
64 {_SC("_OP_YIELD")},
65 {_SC("_OP_RESUME")},
66 {_SC("_OP_FOREACH")},
67 {_SC("_OP_POSTFOREACH")},
68 {_SC("_OP_CLONE")},
69 {_SC("_OP_TYPEOF")},
70 {_SC("_OP_PUSHTRAP")},
71 {_SC("_OP_POPTRAP")},
72 {_SC("_OP_THROW")},
73 {_SC("_OP_NEWSLOTA")},
74 {_SC("_OP_GETBASE")},
75 {_SC("_OP_CLOSE")},
76 };
77 #endif
DumpLiteral(SQObjectPtr & o)78 void DumpLiteral(SQObjectPtr &o)
79 {
80 switch(sqtype(o)){
81 case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
82 case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
83 case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
84 case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
85 default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
86 }
87 }
88
SQFuncState(SQSharedState * ss,SQFuncState * parent,CompilerErrorFunc efunc,void * ed)89 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
90 {
91 _nliterals = 0;
92 _literals = SQTable::Create(ss,0);
93 _strings = SQTable::Create(ss,0);
94 _sharedstate = ss;
95 _lastline = 0;
96 _optimization = true;
97 _parent = parent;
98 _stacksize = 0;
99 _traps = 0;
100 _returnexp = 0;
101 _varparams = false;
102 _errfunc = efunc;
103 _errtarget = ed;
104 _bgenerator = false;
105 _outers = 0;
106 _ss = ss;
107
108 }
109
Error(const SQChar * err)110 void SQFuncState::Error(const SQChar *err)
111 {
112 _errfunc(_errtarget,err);
113 }
114
115 #ifdef _DEBUG_DUMP
Dump(SQFunctionProto * func)116 void SQFuncState::Dump(SQFunctionProto *func)
117 {
118 SQUnsignedInteger n=0,i;
119 SQInteger si;
120 scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
121 scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
122 scprintf(_SC("--------------------------------------------------------------------\n"));
123 scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
124 scprintf(_SC("-----LITERALS\n"));
125 SQObjectPtr refidx,key,val;
126 SQInteger idx;
127 SQObjectPtrVec templiterals;
128 templiterals.resize(_nliterals);
129 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
130 refidx=idx;
131 templiterals[_integer(val)]=key;
132 }
133 for(i=0;i<templiterals.size();i++){
134 scprintf(_SC("[%d] "),n);
135 DumpLiteral(templiterals[i]);
136 scprintf(_SC("\n"));
137 n++;
138 }
139 scprintf(_SC("-----PARAMS\n"));
140 if(_varparams)
141 scprintf(_SC("<<VARPARAMS>>\n"));
142 n=0;
143 for(i=0;i<_parameters.size();i++){
144 scprintf(_SC("[%d] "),n);
145 DumpLiteral(_parameters[i]);
146 scprintf(_SC("\n"));
147 n++;
148 }
149 scprintf(_SC("-----LOCALS\n"));
150 for(si=0;si<func->_nlocalvarinfos;si++){
151 SQLocalVarInfo lvi=func->_localvarinfos[si];
152 scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
153 n++;
154 }
155 scprintf(_SC("-----LINE INFO\n"));
156 for(i=0;i<_lineinfos.size();i++){
157 SQLineInfo li=_lineinfos[i];
158 scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
159 n++;
160 }
161 scprintf(_SC("-----dump\n"));
162 n=0;
163 for(i=0;i<_instructions.size();i++){
164 SQInstruction &inst=_instructions[i];
165 if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
166
167 SQInteger lidx = inst._arg1;
168 scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
169 if(lidx >= 0xFFFFFFFF)
170 scprintf(_SC("null"));
171 else {
172 SQInteger refidx;
173 SQObjectPtr val,key,refo;
174 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
175 refo = refidx;
176 }
177 DumpLiteral(key);
178 }
179 if(inst.op != _OP_DLOAD) {
180 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
181 }
182 else {
183 scprintf(_SC(" %d "),inst._arg2);
184 lidx = inst._arg3;
185 if(lidx >= 0xFFFFFFFF)
186 scprintf(_SC("null"));
187 else {
188 SQInteger refidx;
189 SQObjectPtr val,key,refo;
190 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
191 refo = refidx;
192 }
193 DumpLiteral(key);
194 scprintf(_SC("\n"));
195 }
196 }
197 }
198 else if(inst.op==_OP_LOADFLOAT) {
199 scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
200 }
201 /* else if(inst.op==_OP_ARITH){
202 scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
203 }*/
204 else {
205 scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
206 }
207 n++;
208 }
209 scprintf(_SC("-----\n"));
210 scprintf(_SC("stack size[%d]\n"),func->_stacksize);
211 scprintf(_SC("--------------------------------------------------------------------\n\n"));
212 }
213 #endif
214
GetNumericConstant(const SQInteger cons)215 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
216 {
217 return GetConstant(SQObjectPtr(cons));
218 }
219
GetNumericConstant(const SQFloat cons)220 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
221 {
222 return GetConstant(SQObjectPtr(cons));
223 }
224
GetConstant(const SQObject & cons)225 SQInteger SQFuncState::GetConstant(const SQObject &cons)
226 {
227 SQObjectPtr val;
228 if(!_table(_literals)->Get(cons,val))
229 {
230 val = _nliterals;
231 _table(_literals)->NewSlot(cons,val);
232 _nliterals++;
233 if(_nliterals > MAX_LITERALS) {
234 val.Null();
235 Error(_SC("internal compiler error: too many literals"));
236 }
237 }
238 return _integer(val);
239 }
240
SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)241 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
242 {
243 _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
244 _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
245 _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
246 _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
247 }
248
SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)249 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
250 {
251 switch(arg){
252 case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
253 case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
254 case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
255 case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
256 };
257 }
258
AllocStackPos()259 SQInteger SQFuncState::AllocStackPos()
260 {
261 SQInteger npos=_vlocals.size();
262 _vlocals.push_back(SQLocalVarInfo());
263 if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
264 if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
265 _stacksize=_vlocals.size();
266 }
267 return npos;
268 }
269
PushTarget(SQInteger n)270 SQInteger SQFuncState::PushTarget(SQInteger n)
271 {
272 if(n!=-1){
273 _targetstack.push_back(n);
274 return n;
275 }
276 n=AllocStackPos();
277 _targetstack.push_back(n);
278 return n;
279 }
280
GetUpTarget(SQInteger n)281 SQInteger SQFuncState::GetUpTarget(SQInteger n){
282 return _targetstack[((_targetstack.size()-1)-n)];
283 }
284
TopTarget()285 SQInteger SQFuncState::TopTarget(){
286 return _targetstack.back();
287 }
PopTarget()288 SQInteger SQFuncState::PopTarget()
289 {
290 SQUnsignedInteger npos=_targetstack.back();
291 assert(npos < _vlocals.size());
292 SQLocalVarInfo &t = _vlocals[npos];
293 if(sqtype(t._name)==OT_NULL){
294 _vlocals.pop_back();
295 }
296 _targetstack.pop_back();
297 return npos;
298 }
299
GetStackSize()300 SQInteger SQFuncState::GetStackSize()
301 {
302 return _vlocals.size();
303 }
304
CountOuters(SQInteger stacksize)305 SQInteger SQFuncState::CountOuters(SQInteger stacksize)
306 {
307 SQInteger outers = 0;
308 SQInteger k = _vlocals.size() - 1;
309 while(k >= stacksize) {
310 SQLocalVarInfo &lvi = _vlocals[k];
311 k--;
312 if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
313 outers++;
314 }
315 }
316 return outers;
317 }
318
SetStackSize(SQInteger n)319 void SQFuncState::SetStackSize(SQInteger n)
320 {
321 SQInteger size=_vlocals.size();
322 while(size>n){
323 size--;
324 SQLocalVarInfo lvi = _vlocals.back();
325 if(sqtype(lvi._name)!=OT_NULL){
326 if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
327 _outers--;
328 }
329 lvi._end_op = GetCurrentPos();
330 _localvarinfos.push_back(lvi);
331 }
332 _vlocals.pop_back();
333 }
334 }
335
IsConstant(const SQObject & name,SQObject & e)336 bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
337 {
338 SQObjectPtr val;
339 if(_table(_sharedstate->_consts)->Get(name,val)) {
340 e = val;
341 return true;
342 }
343 return false;
344 }
345
IsLocal(SQUnsignedInteger stkpos)346 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
347 {
348 if(stkpos>=_vlocals.size())return false;
349 else if(sqtype(_vlocals[stkpos]._name)!=OT_NULL)return true;
350 return false;
351 }
352
PushLocalVariable(const SQObject & name)353 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
354 {
355 SQInteger pos=_vlocals.size();
356 SQLocalVarInfo lvi;
357 lvi._name=name;
358 lvi._start_op=GetCurrentPos()+1;
359 lvi._pos=_vlocals.size();
360 _vlocals.push_back(lvi);
361 if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
362 return pos;
363 }
364
365
366
GetLocalVariable(const SQObject & name)367 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
368 {
369 SQInteger locals=_vlocals.size();
370 while(locals>=1){
371 SQLocalVarInfo &lvi = _vlocals[locals-1];
372 if(sqtype(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
373 return locals-1;
374 }
375 locals--;
376 }
377 return -1;
378 }
379
MarkLocalAsOuter(SQInteger pos)380 void SQFuncState::MarkLocalAsOuter(SQInteger pos)
381 {
382 SQLocalVarInfo &lvi = _vlocals[pos];
383 lvi._end_op = UINT_MINUS_ONE;
384 _outers++;
385 }
386
GetOuterVariable(const SQObject & name)387 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
388 {
389 SQInteger outers = _outervalues.size();
390 for(SQInteger i = 0; i<outers; i++) {
391 if(_string(_outervalues[i]._name) == _string(name))
392 return i;
393 }
394 SQInteger pos=-1;
395 if(_parent) {
396 pos = _parent->GetLocalVariable(name);
397 if(pos == -1) {
398 pos = _parent->GetOuterVariable(name);
399 if(pos != -1) {
400 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
401 return _outervalues.size() - 1;
402 }
403 }
404 else {
405 _parent->MarkLocalAsOuter(pos);
406 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
407 return _outervalues.size() - 1;
408
409
410 }
411 }
412 return -1;
413 }
414
AddParameter(const SQObject & name)415 void SQFuncState::AddParameter(const SQObject &name)
416 {
417 PushLocalVariable(name);
418 _parameters.push_back(name);
419 }
420
AddLineInfos(SQInteger line,bool lineop,bool force)421 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
422 {
423 if(_lastline!=line || force){
424 SQLineInfo li;
425 li._line=line;li._op=(GetCurrentPos()+1);
426 if(lineop)AddInstruction(_OP_LINE,0,line);
427 if(_lastline!=line) {
428 _lineinfos.push_back(li);
429 }
430 _lastline=line;
431 }
432 }
433
DiscardTarget()434 void SQFuncState::DiscardTarget()
435 {
436 SQInteger discardedtarget = PopTarget();
437 SQInteger size = _instructions.size();
438 if(size > 0 && _optimization){
439 SQInstruction &pi = _instructions[size-1];//previous instruction
440 switch(pi.op) {
441 case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
442 if(pi._arg0 == discardedtarget) {
443 pi._arg0 = 0xFF;
444 }
445 }
446 }
447 }
448
AddInstruction(SQInstruction & i)449 void SQFuncState::AddInstruction(SQInstruction &i)
450 {
451 SQInteger size = _instructions.size();
452 if(size > 0 && _optimization){ //simple optimizer
453 SQInstruction &pi = _instructions[size-1];//previous instruction
454 switch(i.op) {
455 case _OP_JZ:
456 if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
457 pi.op = _OP_JCMP;
458 pi._arg0 = (unsigned char)pi._arg1;
459 pi._arg1 = i._arg1;
460 return;
461 }
462 break;
463 case _OP_SET:
464 case _OP_NEWSLOT:
465 if(i._arg0 == i._arg3) {
466 i._arg0 = 0xFF;
467 }
468 break;
469 case _OP_SETOUTER:
470 if(i._arg0 == i._arg2) {
471 i._arg0 = 0xFF;
472 }
473 break;
474 case _OP_RETURN:
475 if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
476 pi.op = _OP_TAILCALL;
477 } else if(pi.op == _OP_CLOSE){
478 pi = i;
479 return;
480 }
481 break;
482 case _OP_GET:
483 if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
484 pi._arg1 = pi._arg1;
485 pi._arg2 = (unsigned char)i._arg1;
486 pi.op = _OP_GETK;
487 pi._arg0 = i._arg0;
488
489 return;
490 }
491 break;
492 case _OP_PREPCALL:
493 if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
494 pi.op = _OP_PREPCALLK;
495 pi._arg0 = i._arg0;
496 pi._arg1 = pi._arg1;
497 pi._arg2 = i._arg2;
498 pi._arg3 = i._arg3;
499 return;
500 }
501 break;
502 case _OP_APPENDARRAY: {
503 SQInteger aat = -1;
504 switch(pi.op) {
505 case _OP_LOAD: aat = AAT_LITERAL; break;
506 case _OP_LOADINT: aat = AAT_INT; break;
507 case _OP_LOADBOOL: aat = AAT_BOOL; break;
508 case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
509 default: break;
510 }
511 if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
512 pi.op = _OP_APPENDARRAY;
513 pi._arg0 = i._arg0;
514 pi._arg1 = pi._arg1;
515 pi._arg2 = (unsigned char)aat;
516 pi._arg3 = MAX_FUNC_STACKSIZE;
517 return;
518 }
519 }
520 break;
521 case _OP_MOVE:
522 switch(pi.op) {
523 case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
524 case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
525
526 if(pi._arg0 == i._arg1)
527 {
528 pi._arg0 = i._arg0;
529 _optimization = false;
530 //_result_elimination = false;
531 return;
532 }
533 }
534
535 if(pi.op == _OP_MOVE)
536 {
537 pi.op = _OP_DMOVE;
538 pi._arg2 = i._arg0;
539 pi._arg3 = (unsigned char)i._arg1;
540 return;
541 }
542 break;
543 case _OP_LOAD:
544 if(pi.op == _OP_LOAD && i._arg1 < 256) {
545 pi.op = _OP_DLOAD;
546 pi._arg2 = i._arg0;
547 pi._arg3 = (unsigned char)i._arg1;
548 return;
549 }
550 break;
551 case _OP_EQ:case _OP_NE:
552 if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
553 {
554 pi.op = i.op;
555 pi._arg0 = i._arg0;
556 pi._arg1 = pi._arg1;
557 pi._arg2 = i._arg2;
558 pi._arg3 = MAX_FUNC_STACKSIZE;
559 return;
560 }
561 break;
562 case _OP_LOADNULLS:
563 if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
564
565 pi._arg1 = pi._arg1 + 1;
566 pi.op = _OP_LOADNULLS;
567 return;
568 }
569 break;
570 case _OP_LINE:
571 if(pi.op == _OP_LINE) {
572 _instructions.pop_back();
573 _lineinfos.pop_back();
574 }
575 break;
576 }
577 }
578 _optimization = true;
579 _instructions.push_back(i);
580 }
581
CreateString(const SQChar * s,SQInteger len)582 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
583 {
584 SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
585 _table(_strings)->NewSlot(ns,(SQInteger)1);
586 return ns;
587 }
588
CreateTable()589 SQObject SQFuncState::CreateTable()
590 {
591 SQObjectPtr nt(SQTable::Create(_sharedstate,0));
592 _table(_strings)->NewSlot(nt,(SQInteger)1);
593 return nt;
594 }
595
BuildProto()596 SQFunctionProto *SQFuncState::BuildProto()
597 {
598
599 SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
600 _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
601 _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
602
603 SQObjectPtr refidx,key,val;
604 SQInteger idx;
605
606 f->_stacksize = _stacksize;
607 f->_sourcename = _sourcename;
608 f->_bgenerator = _bgenerator;
609 f->_name = _name;
610
611 while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
612 f->_literals[_integer(val)]=key;
613 refidx=idx;
614 }
615
616 for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
617 for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
618 for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
619 for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
620 for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
621 for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
622
623 memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
624
625 f->_varparams = _varparams;
626
627 return f;
628 }
629
PushChildState(SQSharedState * ss)630 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
631 {
632 SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
633 new (child) SQFuncState(ss,this,_errfunc,_errtarget);
634 _childstates.push_back(child);
635 return child;
636 }
637
PopChildState()638 void SQFuncState::PopChildState()
639 {
640 SQFuncState *child = _childstates.back();
641 sq_delete(child,SQFuncState);
642 _childstates.pop_back();
643 }
644
~SQFuncState()645 SQFuncState::~SQFuncState()
646 {
647 while(_childstates.size() > 0)
648 {
649 PopChildState();
650 }
651 }
652
653 #endif
654