Johan Wikman / SQUIRREL3

Dependents:   Squirrel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sqfuncstate.cpp Source File

sqfuncstate.cpp

00001 /*
00002     see copyright notice in squirrel.h
00003 */
00004 #include "sqpcheader.h"
00005 #ifndef NO_COMPILER
00006 #include "sqcompiler.h"
00007 #include "sqstring.h"
00008 #include "sqfuncproto.h"
00009 #include "sqtable.h"
00010 #include "sqopcodes.h"
00011 #include "sqfuncstate.h"
00012 
00013 #ifdef _DEBUG_DUMP
00014 SQInstructionDesc g_InstrDesc[]={
00015     {_SC("_OP_LINE")},
00016     {_SC("_OP_LOAD")},
00017     {_SC("_OP_LOADINT")},
00018     {_SC("_OP_LOADFLOAT")},
00019     {_SC("_OP_DLOAD")},
00020     {_SC("_OP_TAILCALL")},
00021     {_SC("_OP_CALL")},
00022     {_SC("_OP_PREPCALL")},
00023     {_SC("_OP_PREPCALLK")},
00024     {_SC("_OP_GETK")},
00025     {_SC("_OP_MOVE")},
00026     {_SC("_OP_NEWSLOT")},
00027     {_SC("_OP_DELETE")},
00028     {_SC("_OP_SET")},
00029     {_SC("_OP_GET")},
00030     {_SC("_OP_EQ")},
00031     {_SC("_OP_NE")},
00032     {_SC("_OP_ADD")},
00033     {_SC("_OP_SUB")},
00034     {_SC("_OP_MUL")},
00035     {_SC("_OP_DIV")},
00036     {_SC("_OP_MOD")},
00037     {_SC("_OP_BITW")},
00038     {_SC("_OP_RETURN")},
00039     {_SC("_OP_LOADNULLS")},
00040     {_SC("_OP_LOADROOT")},
00041     {_SC("_OP_LOADBOOL")},
00042     {_SC("_OP_DMOVE")},
00043     {_SC("_OP_JMP")},
00044     {_SC("_OP_JCMP")},
00045     {_SC("_OP_JZ")},
00046     {_SC("_OP_SETOUTER")},
00047     {_SC("_OP_GETOUTER")},
00048     {_SC("_OP_NEWOBJ")},
00049     {_SC("_OP_APPENDARRAY")},
00050     {_SC("_OP_COMPARITH")},
00051     {_SC("_OP_INC")},
00052     {_SC("_OP_INCL")},
00053     {_SC("_OP_PINC")},
00054     {_SC("_OP_PINCL")},
00055     {_SC("_OP_CMP")},
00056     {_SC("_OP_EXISTS")},
00057     {_SC("_OP_INSTANCEOF")},
00058     {_SC("_OP_AND")},
00059     {_SC("_OP_OR")},
00060     {_SC("_OP_NEG")},
00061     {_SC("_OP_NOT")},
00062     {_SC("_OP_BWNOT")},
00063     {_SC("_OP_CLOSURE")},
00064     {_SC("_OP_YIELD")},
00065     {_SC("_OP_RESUME")},
00066     {_SC("_OP_FOREACH")},
00067     {_SC("_OP_POSTFOREACH")},
00068     {_SC("_OP_CLONE")},
00069     {_SC("_OP_TYPEOF")},
00070     {_SC("_OP_PUSHTRAP")},
00071     {_SC("_OP_POPTRAP")},
00072     {_SC("_OP_THROW")},
00073     {_SC("_OP_NEWSLOTA")},
00074     {_SC("_OP_GETBASE")},
00075     {_SC("_OP_CLOSE")},
00076     {_SC("_OP_JCMP")}
00077 };
00078 #endif
00079 void DumpLiteral(SQObjectPtr &o)
00080 {
00081     switch(type(o)){
00082         case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
00083         case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
00084         case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
00085         case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
00086         default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
00087     }
00088 }
00089 
00090 SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
00091 {
00092         _nliterals = 0;
00093         _literals = SQTable::Create(ss,0);
00094         _strings =  SQTable::Create(ss,0);
00095         _sharedstate = ss;
00096         _lastline = 0;
00097         _optimization = true;
00098         _parent = parent;
00099         _stacksize = 0;
00100         _traps = 0;
00101         _returnexp = 0;
00102         _varparams = false;
00103         _errfunc = efunc;
00104         _errtarget = ed;
00105         _bgenerator = false;
00106         _outers = 0;
00107         _ss = ss;
00108 
00109 }
00110 
00111 void SQFuncState::Error(const SQChar *err)
00112 {
00113     _errfunc(_errtarget,err);
00114 }
00115 
00116 #ifdef _DEBUG_DUMP
00117 void SQFuncState::Dump(SQFunctionProto *func)
00118 {
00119     SQUnsignedInteger n=0,i;
00120     SQInteger si;
00121     scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
00122     scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
00123     scprintf(_SC("--------------------------------------------------------------------\n"));
00124     scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
00125     scprintf(_SC("-----LITERALS\n"));
00126     SQObjectPtr refidx,key,val;
00127     SQInteger idx;
00128     SQObjectPtrVec templiterals;
00129     templiterals.resize(_nliterals);
00130     while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
00131         refidx=idx;
00132         templiterals[_integer(val)]=key;
00133     }
00134     for(i=0;i<templiterals.size();i++){
00135         scprintf(_SC("[%d] "),n);
00136         DumpLiteral(templiterals[i]);
00137         scprintf(_SC("\n"));
00138         n++;
00139     }
00140     scprintf(_SC("-----PARAMS\n"));
00141     if(_varparams)
00142         scprintf(_SC("<<VARPARAMS>>\n"));
00143     n=0;
00144     for(i=0;i<_parameters.size();i++){
00145         scprintf(_SC("[%d] "),n);
00146         DumpLiteral(_parameters[i]);
00147         scprintf(_SC("\n"));
00148         n++;
00149     }
00150     scprintf(_SC("-----LOCALS\n"));
00151     for(si=0;si<func->_nlocalvarinfos;si++){
00152         SQLocalVarInfo lvi=func->_localvarinfos[si];
00153         scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
00154         n++;
00155     }
00156     scprintf(_SC("-----LINE INFO\n"));
00157     for(i=0;i<_lineinfos.size();i++){
00158         SQLineInfo li=_lineinfos[i];
00159         scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
00160         n++;
00161     }
00162     scprintf(_SC("-----dump\n"));
00163     n=0;
00164     for(i=0;i<_instructions.size();i++){
00165         SQInstruction &inst=_instructions[i];
00166         if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
00167             
00168             SQInteger lidx = inst._arg1;
00169             scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
00170             if(lidx >= 0xFFFFFFFF)
00171                 scprintf(_SC("null"));
00172             else {
00173                 SQInteger refidx;
00174                 SQObjectPtr val,key,refo;
00175                 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
00176                     refo = refidx;  
00177                 }
00178                 DumpLiteral(key);
00179             }
00180             if(inst.op != _OP_DLOAD) {
00181                 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
00182             }
00183             else {
00184                 scprintf(_SC(" %d "),inst._arg2);
00185                 lidx = inst._arg3;
00186                 if(lidx >= 0xFFFFFFFF)
00187                     scprintf(_SC("null"));
00188                 else {
00189                     SQInteger refidx;
00190                     SQObjectPtr val,key,refo;
00191                     while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
00192                         refo = refidx;  
00193                 }
00194                 DumpLiteral(key);
00195                 scprintf(_SC("\n"));
00196             }
00197             }
00198         }
00199         else if(inst.op==_OP_LOADFLOAT) {
00200             scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
00201         }
00202     /*  else if(inst.op==_OP_ARITH){
00203             scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
00204         }*/
00205         else {
00206             scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
00207         }
00208         n++;
00209     }
00210     scprintf(_SC("-----\n"));
00211     scprintf(_SC("stack size[%d]\n"),func->_stacksize);
00212     scprintf(_SC("--------------------------------------------------------------------\n\n"));
00213 }
00214 #endif
00215 
00216 SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
00217 {
00218     return GetConstant(SQObjectPtr(cons));
00219 }
00220 
00221 SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
00222 {
00223     return GetConstant(SQObjectPtr(cons));
00224 }
00225 
00226 SQInteger SQFuncState::GetConstant(const SQObject &cons)
00227 {
00228     SQObjectPtr val;
00229     if(!_table(_literals)->Get(cons,val))
00230     {
00231         val = _nliterals;
00232         _table(_literals)->NewSlot(cons,val);
00233         _nliterals++;
00234         if(_nliterals > MAX_LITERALS) {
00235             val.Null();
00236             Error(_SC("internal compiler error: too many literals"));
00237         }
00238     }
00239     return _integer(val);
00240 }
00241 
00242 void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
00243 {
00244     _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
00245     _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
00246     _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
00247     _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
00248 }
00249 
00250 void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
00251 {
00252     switch(arg){
00253         case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
00254         case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
00255         case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
00256         case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
00257     };
00258 }
00259 
00260 SQInteger SQFuncState::AllocStackPos()
00261 {
00262     SQInteger npos=_vlocals.size();
00263     _vlocals.push_back(SQLocalVarInfo());
00264     if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
00265         if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
00266         _stacksize=_vlocals.size();
00267     }
00268     return npos;
00269 }
00270 
00271 SQInteger SQFuncState::PushTarget(SQInteger n)
00272 {
00273     if(n!=-1){
00274         _targetstack.push_back(n);
00275         return n;
00276     }
00277     n=AllocStackPos();
00278     _targetstack.push_back(n);
00279     return n;
00280 }
00281 
00282 SQInteger SQFuncState::GetUpTarget(SQInteger n){
00283     return _targetstack[((_targetstack.size()-1)-n)];
00284 }
00285 
00286 SQInteger SQFuncState::TopTarget(){
00287     return _targetstack.back();
00288 }
00289 SQInteger SQFuncState::PopTarget()
00290 {
00291     SQUnsignedInteger npos=_targetstack.back();
00292     assert(npos < _vlocals.size());
00293     SQLocalVarInfo &t = _vlocals[npos];
00294     if(type(t._name)==OT_NULL){
00295         _vlocals.pop_back();
00296     }
00297     _targetstack.pop_back();
00298     return npos;
00299 }
00300 
00301 SQInteger SQFuncState::GetStackSize()
00302 {
00303     return _vlocals.size();
00304 }
00305 
00306 SQInteger SQFuncState::CountOuters(SQInteger stacksize)
00307 {
00308     SQInteger outers = 0;
00309     SQInteger k = _vlocals.size() - 1;
00310     while(k >= stacksize) {
00311         SQLocalVarInfo &lvi = _vlocals[k];
00312         k--;
00313         if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
00314             outers++;
00315         }
00316     }
00317     return outers;
00318 }
00319 
00320 void SQFuncState::SetStackSize(SQInteger n)
00321 {
00322     SQInteger size=_vlocals.size();
00323     while(size>n){
00324         size--;
00325         SQLocalVarInfo lvi = _vlocals.back();
00326         if(type(lvi._name)!=OT_NULL){
00327             if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
00328                 _outers--;
00329             }
00330             lvi._end_op = GetCurrentPos();
00331             _localvarinfos.push_back(lvi);
00332         }
00333         _vlocals.pop_back();
00334     }
00335 }
00336 
00337 bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
00338 {
00339     SQObjectPtr val;
00340     if(_table(_sharedstate->_consts)->Get(name,val)) {
00341         e = val;
00342         return true;
00343     }
00344     return false;
00345 }
00346 
00347 bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
00348 {
00349     if(stkpos>=_vlocals.size())return false;
00350     else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
00351     return false;
00352 }
00353 
00354 SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
00355 {
00356     SQInteger pos=_vlocals.size();
00357     SQLocalVarInfo lvi;
00358     lvi._name=name;
00359     lvi._start_op=GetCurrentPos()+1;
00360     lvi._pos=_vlocals.size();
00361     _vlocals.push_back(lvi);
00362     if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
00363     return pos;
00364 }
00365 
00366 
00367 
00368 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
00369 {
00370     SQInteger locals=_vlocals.size();
00371     while(locals>=1){
00372         SQLocalVarInfo &lvi = _vlocals[locals-1];
00373         if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
00374             return locals-1;
00375         }
00376         locals--;
00377     }
00378     return -1;
00379 }
00380 
00381 void SQFuncState::MarkLocalAsOuter(SQInteger pos)
00382 {
00383     SQLocalVarInfo &lvi = _vlocals[pos];
00384     lvi._end_op = UINT_MINUS_ONE;
00385     _outers++;
00386 }
00387 
00388 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
00389 {
00390     SQInteger outers = _outervalues.size();
00391     for(SQInteger i = 0; i<outers; i++) {
00392         if(_string(_outervalues[i]._name) == _string(name))
00393             return i;
00394     }
00395     SQInteger pos=-1;
00396     if(_parent) { 
00397         pos = _parent->GetLocalVariable(name);
00398         if(pos == -1) {
00399             pos = _parent->GetOuterVariable(name);
00400             if(pos != -1) {
00401                 _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
00402                 return _outervalues.size() - 1; 
00403             }
00404         }
00405         else {
00406             _parent->MarkLocalAsOuter(pos);
00407             _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
00408             return _outervalues.size() - 1;
00409             
00410             
00411         }
00412     }
00413     return -1;
00414 }
00415 
00416 void SQFuncState::AddParameter(const SQObject &name)
00417 {
00418     PushLocalVariable(name);
00419     _parameters.push_back(name);
00420 }
00421 
00422 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
00423 {
00424     if(_lastline!=line || force){
00425         SQLineInfo li;
00426         li._line=line;li._op=(GetCurrentPos()+1);
00427         if(lineop)AddInstruction(_OP_LINE,0,line);
00428         if(_lastline!=line) {
00429             _lineinfos.push_back(li);
00430         }
00431         _lastline=line;
00432     }
00433 }
00434 
00435 void SQFuncState::DiscardTarget()
00436 {
00437     SQInteger discardedtarget = PopTarget();
00438     SQInteger size = _instructions.size();
00439     if(size > 0 && _optimization){
00440         SQInstruction &pi = _instructions[size-1];//previous instruction
00441         switch(pi.op) {
00442         case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
00443             if(pi._arg0 == discardedtarget) {
00444                 pi._arg0 = 0xFF;
00445             }
00446         }
00447     }
00448 }
00449 
00450 void SQFuncState::AddInstruction(SQInstruction &i)
00451 {
00452     SQInteger size = _instructions.size();
00453     if(size > 0 && _optimization){ //simple optimizer
00454         SQInstruction &pi = _instructions[size-1];//previous instruction
00455         switch(i.op) {
00456         case _OP_JZ:
00457             if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
00458                 pi.op = _OP_JCMP;
00459                 pi._arg0 = (unsigned char)pi._arg1;
00460                 pi._arg1 = i._arg1;
00461                 return;
00462             }
00463         case _OP_SET:
00464         case _OP_NEWSLOT:
00465             if(i._arg0 == i._arg3) {
00466                 i._arg0 = 0xFF;
00467             }
00468             break;
00469         case _OP_SETOUTER:
00470             if(i._arg0 == i._arg2) {
00471                 i._arg0 = 0xFF;
00472             }
00473             break;
00474         case _OP_RETURN:
00475             if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
00476                 pi.op = _OP_TAILCALL;
00477             } else if(pi.op == _OP_CLOSE){
00478                 pi = i;
00479                 return;
00480             }
00481         break;
00482         case _OP_GET:
00483             if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
00484                 pi._arg1 = pi._arg1;
00485                 pi._arg2 = (unsigned char)i._arg1;
00486                 pi.op = _OP_GETK;
00487                 pi._arg0 = i._arg0;
00488                 
00489                 return;
00490             }
00491         break;
00492         case _OP_PREPCALL:
00493             if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
00494                 pi.op = _OP_PREPCALLK;
00495                 pi._arg0 = i._arg0;
00496                 pi._arg1 = pi._arg1;
00497                 pi._arg2 = i._arg2;
00498                 pi._arg3 = i._arg3;
00499                 return;
00500             }
00501             break;
00502         case _OP_APPENDARRAY: {
00503             SQInteger aat = -1;
00504             switch(pi.op) {
00505             case _OP_LOAD: aat = AAT_LITERAL; break;
00506             case _OP_LOADINT: aat = AAT_INT; break;
00507             case _OP_LOADBOOL: aat = AAT_BOOL; break;
00508             case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
00509             default: break;
00510             }
00511             if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
00512                 pi.op = _OP_APPENDARRAY;
00513                 pi._arg0 = i._arg0;
00514                 pi._arg1 = pi._arg1;
00515                 pi._arg2 = (unsigned char)aat;
00516                 pi._arg3 = MAX_FUNC_STACKSIZE;
00517                 return;
00518             }
00519                               }
00520             break;
00521         case _OP_MOVE:
00522             switch(pi.op) {
00523             case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
00524             case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
00525 
00526                 if(pi._arg0 == i._arg1)
00527                 {
00528                     pi._arg0 = i._arg0;
00529                     _optimization = false;
00530                     //_result_elimination = false;
00531                     return;
00532                 }
00533             }
00534 
00535             if(pi.op == _OP_MOVE)
00536             {
00537                 pi.op = _OP_DMOVE;
00538                 pi._arg2 = i._arg0;
00539                 pi._arg3 = (unsigned char)i._arg1;
00540                 return;
00541             }
00542             break;
00543         case _OP_LOAD:
00544             if(pi.op == _OP_LOAD && i._arg1 < 256) {
00545                 pi.op = _OP_DLOAD;
00546                 pi._arg2 = i._arg0;
00547                 pi._arg3 = (unsigned char)i._arg1;
00548                 return;
00549             }
00550             break;
00551         case _OP_EQ:case _OP_NE:
00552             if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
00553             {
00554                 pi.op = i.op;
00555                 pi._arg0 = i._arg0;
00556                 pi._arg1 = pi._arg1;
00557                 pi._arg2 = i._arg2;
00558                 pi._arg3 = MAX_FUNC_STACKSIZE;
00559                 return;
00560             }
00561             break;
00562         case _OP_LOADNULLS:
00563             if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
00564                 
00565                 pi._arg1 = pi._arg1 + 1;
00566                 pi.op = _OP_LOADNULLS;
00567                 return;
00568             }
00569             break;
00570         case _OP_LINE:
00571             if(pi.op == _OP_LINE) {
00572                 _instructions.pop_back();
00573                 _lineinfos.pop_back();
00574             }
00575             break;
00576         }
00577     }
00578     _optimization = true;
00579     _instructions.push_back(i);
00580 }
00581 
00582 SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
00583 {
00584     SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
00585     _table(_strings)->NewSlot(ns,(SQInteger)1);
00586     return ns;
00587 }
00588 
00589 SQObject SQFuncState::CreateTable()
00590 {
00591     SQObjectPtr nt(SQTable::Create(_sharedstate,0));
00592     _table(_strings)->NewSlot(nt,(SQInteger)1);
00593     return nt;
00594 }
00595 
00596 SQFunctionProto *SQFuncState::BuildProto()
00597 {
00598     
00599     SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
00600         _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
00601         _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
00602 
00603     SQObjectPtr refidx,key,val;
00604     SQInteger idx;
00605 
00606     f->_stacksize = _stacksize;
00607     f->_sourcename = _sourcename;
00608     f->_bgenerator = _bgenerator;
00609     f->_name = _name;
00610 
00611     while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
00612         f->_literals[_integer(val)]=key;
00613         refidx=idx;
00614     }
00615 
00616     for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
00617     for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
00618     for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
00619     for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
00620     for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
00621     for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
00622 
00623     memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
00624 
00625     f->_varparams = _varparams;
00626 
00627     return f;
00628 }
00629 
00630 SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
00631 {
00632     SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
00633     new (child) SQFuncState(ss,this,_errfunc,_errtarget);
00634     _childstates.push_back(child);
00635     return child;
00636 }
00637 
00638 void SQFuncState::PopChildState()
00639 {
00640     SQFuncState *child = _childstates.back();
00641     sq_delete(child,SQFuncState);
00642     _childstates.pop_back();
00643 }
00644 
00645 SQFuncState::~SQFuncState()
00646 {
00647     while(_childstates.size() > 0)
00648     {
00649         PopChildState();
00650     }
00651 }
00652 
00653 #endif