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