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