Back to home page

Enduro/X

 
 

    


0001 /*

0002     see copyright notice in pscript.h

0003 */
0004 #include "pspcheader.h"
0005 #ifndef NO_COMPILER
0006 #include "pscompiler.h"
0007 #include "psstring.h"
0008 #include "psfuncproto.h"
0009 #include "pstable.h"
0010 #include "psopcodes.h"
0011 #include "psfuncstate.h"
0012 
0013 #ifdef _DEBUG_DUMP
0014 PSInstructionDesc g_InstrDesc[]={
0015     {_SC("_OP_LINE")},
0016     {_SC("_OP_LOAD")},
0017     {_SC("_OP_LOADINT")},
0018     {_SC("_OP_LOADFLOAT")},
0019     {_SC("_OP_DLOAD")},
0020     {_SC("_OP_TAILCALL")},
0021     {_SC("_OP_CALL")},
0022     {_SC("_OP_PREPCALL")},
0023     {_SC("_OP_PREPCALLK")},
0024     {_SC("_OP_GETK")},
0025     {_SC("_OP_MOVE")},
0026     {_SC("_OP_NEWSLOT")},
0027     {_SC("_OP_DELETE")},
0028     {_SC("_OP_SET")},
0029     {_SC("_OP_GET")},
0030     {_SC("_OP_EQ")},
0031     {_SC("_OP_NE")},
0032     {_SC("_OP_ADD")},
0033     {_SC("_OP_SUB")},
0034     {_SC("_OP_MUL")},
0035     {_SC("_OP_DIV")},
0036     {_SC("_OP_MOD")},
0037     {_SC("_OP_BITW")},
0038     {_SC("_OP_RETURN")},
0039     {_SC("_OP_LOADNULLS")},
0040     {_SC("_OP_LOADROOT")},
0041     {_SC("_OP_LOADBOOL")},
0042     {_SC("_OP_DMOVE")},
0043     {_SC("_OP_JMP")},
0044     {_SC("_OP_JCMP")},
0045     {_SC("_OP_JZ")},
0046     {_SC("_OP_SETOUTER")},
0047     {_SC("_OP_GETOUTER")},
0048     {_SC("_OP_NEWOBJ")},
0049     {_SC("_OP_APPENDARRAY")},
0050     {_SC("_OP_COMPARITH")},
0051     {_SC("_OP_INC")},
0052     {_SC("_OP_INCL")},
0053     {_SC("_OP_PINC")},
0054     {_SC("_OP_PINCL")},
0055     {_SC("_OP_CMP")},
0056     {_SC("_OP_EXISTS")},
0057     {_SC("_OP_INSTANCEOF")},
0058     {_SC("_OP_AND")},
0059     {_SC("_OP_OR")},
0060     {_SC("_OP_NEG")},
0061     {_SC("_OP_NOT")},
0062     {_SC("_OP_BWNOT")},
0063     {_SC("_OP_CLOSURE")},
0064     {_SC("_OP_YIELD")},
0065     {_SC("_OP_RESUME")},
0066     {_SC("_OP_FOREACH")},
0067     {_SC("_OP_POSTFOREACH")},
0068     {_SC("_OP_CLONE")},
0069     {_SC("_OP_TYPEOF")},
0070     {_SC("_OP_PUSHTRAP")},
0071     {_SC("_OP_POPTRAP")},
0072     {_SC("_OP_THROW")},
0073     {_SC("_OP_NEWSLOTA")},
0074     {_SC("_OP_GETBASE")},
0075     {_SC("_OP_CLOSE")},
0076 };
0077 #endif
0078 void DumpLiteral(PSObjectPtr &o)
0079 {
0080     switch(type(o)){
0081         case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
0082         case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
0083         case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
0084         case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
0085         default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler

0086     }
0087 }
0088 
0089 PSFuncState::PSFuncState(PSSharedState *ss,PSFuncState *parent,CompilerErrorFunc efunc,void *ed)
0090 {
0091         _nliterals = 0;
0092         _literals = PSTable::Create(ss,0);
0093         _strings =  PSTable::Create(ss,0);
0094         _sharedstate = ss;
0095         _lastline = 0;
0096         _optimization = true;
0097         _parent = parent;
0098         _stacksize = 0;
0099         _traps = 0;
0100         _returnexp = 0;
0101         _varparams = false;
0102         _errfunc = efunc;
0103         _errtarget = ed;
0104         _bgenerator = false;
0105         _outers = 0;
0106         _ss = ss;
0107 
0108 }
0109 
0110 void PSFuncState::Error(const PSChar *err)
0111 {
0112     _errfunc(_errtarget,err);
0113 }
0114 
0115 #ifdef _DEBUG_DUMP
0116 void PSFuncState::Dump(PSFunctionProto *func)
0117 {
0118     PSUnsignedInteger n=0,i;
0119     PSInteger si;
0120     scprintf(_SC("PSInstruction sizeof %d\n"),sizeof(PSInstruction));
0121     scprintf(_SC("PSObject sizeof %d\n"),sizeof(PSObject));
0122     scprintf(_SC("--------------------------------------------------------------------\n"));
0123     scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
0124     scprintf(_SC("-----LITERALS\n"));
0125     PSObjectPtr refidx,key,val;
0126     PSInteger idx;
0127     PSObjectPtrVec templiterals;
0128     templiterals.resize(_nliterals);
0129     while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
0130         refidx=idx;
0131         templiterals[_integer(val)]=key;
0132     }
0133     for(i=0;i<templiterals.size();i++){
0134         scprintf(_SC("[%d] "),n);
0135         DumpLiteral(templiterals[i]);
0136         scprintf(_SC("\n"));
0137         n++;
0138     }
0139     scprintf(_SC("-----PARAMS\n"));
0140     if(_varparams)
0141         scprintf(_SC("<<VARPARAMS>>\n"));
0142     n=0;
0143     for(i=0;i<_parameters.size();i++){
0144         scprintf(_SC("[%d] "),n);
0145         DumpLiteral(_parameters[i]);
0146         scprintf(_SC("\n"));
0147         n++;
0148     }
0149     scprintf(_SC("-----LOCALS\n"));
0150     for(si=0;si<func->_nlocalvarinfos;si++){
0151         PSLocalVarInfo lvi=func->_localvarinfos[si];
0152         scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
0153         n++;
0154     }
0155     scprintf(_SC("-----LINE INFO\n"));
0156     for(i=0;i<_lineinfos.size();i++){
0157         PSLineInfo li=_lineinfos[i];
0158         scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
0159         n++;
0160     }
0161     scprintf(_SC("-----dump\n"));
0162     n=0;
0163     for(i=0;i<_instructions.size();i++){
0164         PSInstruction &inst=_instructions[i];
0165         if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
0166 
0167             PSInteger lidx = inst._arg1;
0168             scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
0169             if(lidx >= 0xFFFFFFFF)
0170                 scprintf(_SC("null"));
0171             else {
0172                 PSInteger refidx;
0173                 PSObjectPtr val,key,refo;
0174                 while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
0175                     refo = refidx;
0176                 }
0177                 DumpLiteral(key);
0178             }
0179             if(inst.op != _OP_DLOAD) {
0180                 scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
0181             }
0182             else {
0183                 scprintf(_SC(" %d "),inst._arg2);
0184                 lidx = inst._arg3;
0185                 if(lidx >= 0xFFFFFFFF)
0186                     scprintf(_SC("null"));
0187                 else {
0188                     PSInteger refidx;
0189                     PSObjectPtr val,key,refo;
0190                     while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
0191                         refo = refidx;
0192                 }
0193                 DumpLiteral(key);
0194                 scprintf(_SC("\n"));
0195             }
0196             }
0197         }
0198         else if(inst.op==_OP_LOADFLOAT) {
0199             scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((PSFloat*)&inst._arg1),inst._arg2,inst._arg3);
0200         }
0201     /*  else if(inst.op==_OP_ARITH){

0202             scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);

0203         }*/
0204         else {
0205             scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
0206         }
0207         n++;
0208     }
0209     scprintf(_SC("-----\n"));
0210     scprintf(_SC("stack size[%d]\n"),func->_stacksize);
0211     scprintf(_SC("--------------------------------------------------------------------\n\n"));
0212 }
0213 #endif
0214 
0215 PSInteger PSFuncState::GetNumericConstant(const PSInteger cons)
0216 {
0217     return GetConstant(PSObjectPtr(cons));
0218 }
0219 
0220 PSInteger PSFuncState::GetNumericConstant(const PSFloat cons)
0221 {
0222     return GetConstant(PSObjectPtr(cons));
0223 }
0224 
0225 PSInteger PSFuncState::GetConstant(const PSObject &cons)
0226 {
0227     PSObjectPtr val;
0228     if(!_table(_literals)->Get(cons,val))
0229     {
0230         val = _nliterals;
0231         _table(_literals)->NewSlot(cons,val);
0232         _nliterals++;
0233         if(_nliterals > MAX_LITERALS) {
0234             val.Null();
0235             Error(_SC("internal compiler error: too many literals"));
0236         }
0237     }
0238     return _integer(val);
0239 }
0240 
0241 void PSFuncState::SetIntructionParams(PSInteger pos,PSInteger arg0,PSInteger arg1,PSInteger arg2,PSInteger arg3)
0242 {
0243     _instructions[pos]._arg0=(unsigned char)*((PSUnsignedInteger *)&arg0);
0244     _instructions[pos]._arg1=(PSInt32)*((PSUnsignedInteger *)&arg1);
0245     _instructions[pos]._arg2=(unsigned char)*((PSUnsignedInteger *)&arg2);
0246     _instructions[pos]._arg3=(unsigned char)*((PSUnsignedInteger *)&arg3);
0247 }
0248 
0249 void PSFuncState::SetIntructionParam(PSInteger pos,PSInteger arg,PSInteger val)
0250 {
0251     switch(arg){
0252         case 0:_instructions[pos]._arg0=(unsigned char)*((PSUnsignedInteger *)&val);break;
0253         case 1:case 4:_instructions[pos]._arg1=(PSInt32)*((PSUnsignedInteger *)&val);break;
0254         case 2:_instructions[pos]._arg2=(unsigned char)*((PSUnsignedInteger *)&val);break;
0255         case 3:_instructions[pos]._arg3=(unsigned char)*((PSUnsignedInteger *)&val);break;
0256     };
0257 }
0258 
0259 PSInteger PSFuncState::AllocStackPos()
0260 {
0261     PSInteger npos=_vlocals.size();
0262     _vlocals.push_back(PSLocalVarInfo());
0263     if(_vlocals.size()>((PSUnsignedInteger)_stacksize)) {
0264         if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
0265         _stacksize=_vlocals.size();
0266     }
0267     return npos;
0268 }
0269 
0270 PSInteger PSFuncState::PushTarget(PSInteger n)
0271 {
0272     if(n!=-1){
0273         _targetstack.push_back(n);
0274         return n;
0275     }
0276     n=AllocStackPos();
0277     _targetstack.push_back(n);
0278     return n;
0279 }
0280 
0281 PSInteger PSFuncState::GetUpTarget(PSInteger n){
0282     return _targetstack[((_targetstack.size()-1)-n)];
0283 }
0284 
0285 PSInteger PSFuncState::TopTarget(){
0286     return _targetstack.back();
0287 }
0288 PSInteger PSFuncState::PopTarget()
0289 {
0290     PSUnsignedInteger npos=_targetstack.back();
0291     assert(npos < _vlocals.size());
0292     PSLocalVarInfo &t = _vlocals[npos];
0293     if(type(t._name)==OT_NULL){
0294         _vlocals.pop_back();
0295     }
0296     _targetstack.pop_back();
0297     return npos;
0298 }
0299 
0300 PSInteger PSFuncState::GetStackSize()
0301 {
0302     return _vlocals.size();
0303 }
0304 
0305 PSInteger PSFuncState::CountOuters(PSInteger stacksize)
0306 {
0307     PSInteger outers = 0;
0308     PSInteger k = _vlocals.size() - 1;
0309     while(k >= stacksize) {
0310         PSLocalVarInfo &lvi = _vlocals[k];
0311         k--;
0312         if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer

0313             outers++;
0314         }
0315     }
0316     return outers;
0317 }
0318 
0319 void PSFuncState::SetStackSize(PSInteger n)
0320 {
0321     PSInteger size=_vlocals.size();
0322     while(size>n){
0323         size--;
0324         PSLocalVarInfo lvi = _vlocals.back();
0325         if(type(lvi._name)!=OT_NULL){
0326             if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer

0327                 _outers--;
0328             }
0329             lvi._end_op = GetCurrentPos();
0330             _localvarinfos.push_back(lvi);
0331         }
0332         _vlocals.pop_back();
0333     }
0334 }
0335 
0336 bool PSFuncState::IsConstant(const PSObject &name,PSObject &e)
0337 {
0338     PSObjectPtr val;
0339     if(_table(_sharedstate->_consts)->Get(name,val)) {
0340         e = val;
0341         return true;
0342     }
0343     return false;
0344 }
0345 
0346 bool PSFuncState::IsLocal(PSUnsignedInteger stkpos)
0347 {
0348     if(stkpos>=_vlocals.size())return false;
0349     else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
0350     return false;
0351 }
0352 
0353 PSInteger PSFuncState::PushLocalVariable(const PSObject &name)
0354 {
0355     PSInteger pos=_vlocals.size();
0356     PSLocalVarInfo lvi;
0357     lvi._name=name;
0358     lvi._start_op=GetCurrentPos()+1;
0359     lvi._pos=_vlocals.size();
0360     _vlocals.push_back(lvi);
0361     if(_vlocals.size()>((PSUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
0362     return pos;
0363 }
0364 
0365 
0366 
0367 PSInteger PSFuncState::GetLocalVariable(const PSObject &name)
0368 {
0369     PSInteger locals=_vlocals.size();
0370     while(locals>=1){
0371         PSLocalVarInfo &lvi = _vlocals[locals-1];
0372         if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
0373             return locals-1;
0374         }
0375         locals--;
0376     }
0377     return -1;
0378 }
0379 
0380 void PSFuncState::MarkLocalAsOuter(PSInteger pos)
0381 {
0382     PSLocalVarInfo &lvi = _vlocals[pos];
0383     lvi._end_op = UINT_MINUS_ONE;
0384     _outers++;
0385 }
0386 
0387 PSInteger PSFuncState::GetOuterVariable(const PSObject &name)
0388 {
0389     PSInteger outers = _outervalues.size();
0390     for(PSInteger i = 0; i<outers; i++) {
0391         if(_string(_outervalues[i]._name) == _string(name))
0392             return i;
0393     }
0394     PSInteger pos=-1;
0395     if(_parent) {
0396         pos = _parent->GetLocalVariable(name);
0397         if(pos == -1) {
0398             pos = _parent->GetOuterVariable(name);
0399             if(pos != -1) {
0400                 _outervalues.push_back(PSOuterVar(name,PSObjectPtr(PSInteger(pos)),otOUTER)); //local

0401                 return _outervalues.size() - 1;
0402             }
0403         }
0404         else {
0405             _parent->MarkLocalAsOuter(pos);
0406             _outervalues.push_back(PSOuterVar(name,PSObjectPtr(PSInteger(pos)),otLOCAL)); //local

0407             return _outervalues.size() - 1;
0408 
0409 
0410         }
0411     }
0412     return -1;
0413 }
0414 
0415 void PSFuncState::AddParameter(const PSObject &name)
0416 {
0417     PushLocalVariable(name);
0418     _parameters.push_back(name);
0419 }
0420 
0421 void PSFuncState::AddLineInfos(PSInteger line,bool lineop,bool force)
0422 {
0423     if(_lastline!=line || force){
0424         PSLineInfo li;
0425         li._line=line;li._op=(GetCurrentPos()+1);
0426         if(lineop)AddInstruction(_OP_LINE,0,line);
0427         if(_lastline!=line) {
0428             _lineinfos.push_back(li);
0429         }
0430         _lastline=line;
0431     }
0432 }
0433 
0434 void PSFuncState::DiscardTarget()
0435 {
0436     PSInteger discardedtarget = PopTarget();
0437     PSInteger size = _instructions.size();
0438     if(size > 0 && _optimization){
0439         PSInstruction &pi = _instructions[size-1];//previous instruction

0440         switch(pi.op) {
0441         case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
0442             if(pi._arg0 == discardedtarget) {
0443                 pi._arg0 = 0xFF;
0444             }
0445         }
0446     }
0447 }
0448 
0449 void PSFuncState::AddInstruction(PSInstruction &i)
0450 {
0451     PSInteger size = _instructions.size();
0452     if(size > 0 && _optimization){ //simple optimizer

0453         PSInstruction &pi = _instructions[size-1];//previous instruction

0454         switch(i.op) {
0455         case _OP_JZ:
0456             if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
0457                 pi.op = _OP_JCMP;
0458                 pi._arg0 = (unsigned char)pi._arg1;
0459                 pi._arg1 = i._arg1;
0460                 return;
0461             }
0462             break;
0463         case _OP_SET:
0464         case _OP_NEWSLOT:
0465             if(i._arg0 == i._arg3) {
0466                 i._arg0 = 0xFF;
0467             }
0468             break;
0469         case _OP_SETOUTER:
0470             if(i._arg0 == i._arg2) {
0471                 i._arg0 = 0xFF;
0472             }
0473             break;
0474         case _OP_RETURN:
0475             if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
0476                 pi.op = _OP_TAILCALL;
0477             } else if(pi.op == _OP_CLOSE){
0478                 pi = i;
0479                 return;
0480             }
0481         break;
0482         case _OP_GET:
0483             if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
0484                 pi._arg1 = pi._arg1;
0485                 pi._arg2 = (unsigned char)i._arg1;
0486                 pi.op = _OP_GETK;
0487                 pi._arg0 = i._arg0;
0488 
0489                 return;
0490             }
0491         break;
0492         case _OP_PREPCALL:
0493             if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
0494                 pi.op = _OP_PREPCALLK;
0495                 pi._arg0 = i._arg0;
0496                 pi._arg1 = pi._arg1;
0497                 pi._arg2 = i._arg2;
0498                 pi._arg3 = i._arg3;
0499                 return;
0500             }
0501             break;
0502         case _OP_APPENDARRAY: {
0503             PSInteger aat = -1;
0504             switch(pi.op) {
0505             case _OP_LOAD: aat = AAT_LITERAL; break;
0506             case _OP_LOADINT: aat = AAT_INT; break;
0507             case _OP_LOADBOOL: aat = AAT_BOOL; break;
0508             case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
0509             default: break;
0510             }
0511             if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
0512                 pi.op = _OP_APPENDARRAY;
0513                 pi._arg0 = i._arg0;
0514                 pi._arg1 = pi._arg1;
0515                 pi._arg2 = (unsigned char)aat;
0516                 pi._arg3 = MAX_FUNC_STACKSIZE;
0517                 return;
0518             }
0519                               }
0520             break;
0521         case _OP_MOVE:
0522             switch(pi.op) {
0523             case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
0524             case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
0525 
0526                 if(pi._arg0 == i._arg1)
0527                 {
0528                     pi._arg0 = i._arg0;
0529                     _optimization = false;
0530                     //_result_elimination = false;

0531                     return;
0532                 }
0533             }
0534 
0535             if(pi.op == _OP_MOVE)
0536             {
0537                 pi.op = _OP_DMOVE;
0538                 pi._arg2 = i._arg0;
0539                 pi._arg3 = (unsigned char)i._arg1;
0540                 return;
0541             }
0542             break;
0543         case _OP_LOAD:
0544             if(pi.op == _OP_LOAD && i._arg1 < 256) {
0545                 pi.op = _OP_DLOAD;
0546                 pi._arg2 = i._arg0;
0547                 pi._arg3 = (unsigned char)i._arg1;
0548                 return;
0549             }
0550             break;
0551         case _OP_EQ:case _OP_NE:
0552             if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
0553             {
0554                 pi.op = i.op;
0555                 pi._arg0 = i._arg0;
0556                 pi._arg1 = pi._arg1;
0557                 pi._arg2 = i._arg2;
0558                 pi._arg3 = MAX_FUNC_STACKSIZE;
0559                 return;
0560             }
0561             break;
0562         case _OP_LOADNULLS:
0563             if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
0564 
0565                 pi._arg1 = pi._arg1 + 1;
0566                 pi.op = _OP_LOADNULLS;
0567                 return;
0568             }
0569             break;
0570         case _OP_LINE:
0571             if(pi.op == _OP_LINE) {
0572                 _instructions.pop_back();
0573                 _lineinfos.pop_back();
0574             }
0575             break;
0576         }
0577     }
0578     _optimization = true;
0579     _instructions.push_back(i);
0580 }
0581 
0582 PSObject PSFuncState::CreateString(const PSChar *s,PSInteger len)
0583 {
0584     PSObjectPtr ns(PSString::Create(_sharedstate,s,len));
0585     _table(_strings)->NewSlot(ns,(PSInteger)1);
0586     return ns;
0587 }
0588 
0589 PSObject PSFuncState::CreateTable()
0590 {
0591     PSObjectPtr nt(PSTable::Create(_sharedstate,0));
0592     _table(_strings)->NewSlot(nt,(PSInteger)1);
0593     return nt;
0594 }
0595 
0596 PSFunctionProto *PSFuncState::BuildProto()
0597 {
0598 
0599     PSFunctionProto *f=PSFunctionProto::Create(_ss,_instructions.size(),
0600         _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
0601         _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
0602 
0603     PSObjectPtr refidx,key,val;
0604     PSInteger idx;
0605 
0606     f->_stacksize = _stacksize;
0607     f->_sourcename = _sourcename;
0608     f->_bgenerator = _bgenerator;
0609     f->_name = _name;
0610 
0611     while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
0612         f->_literals[_integer(val)]=key;
0613         refidx=idx;
0614     }
0615 
0616     for(PSUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
0617     for(PSUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
0618     for(PSUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
0619     for(PSUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
0620     for(PSUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
0621     for(PSUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
0622 
0623     memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(PSInstruction));
0624 
0625     f->_varparams = _varparams;
0626 
0627     return f;
0628 }
0629 
0630 PSFuncState *PSFuncState::PushChildState(PSSharedState *ss)
0631 {
0632     PSFuncState *child = (PSFuncState *)ps_malloc(sizeof(PSFuncState));
0633     new (child) PSFuncState(ss,this,_errfunc,_errtarget);
0634     _childstates.push_back(child);
0635     return child;
0636 }
0637 
0638 void PSFuncState::PopChildState()
0639 {
0640     PSFuncState *child = _childstates.back();
0641     ps_delete(child,PSFuncState);
0642     _childstates.pop_back();
0643 }
0644 
0645 PSFuncState::~PSFuncState()
0646 {
0647     while(_childstates.size() > 0)
0648     {
0649         PopChildState();
0650     }
0651 }
0652 
0653 #endif