0001
0002
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;
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
0202
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) {
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) {
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));
0401 return _outervalues.size() - 1;
0402 }
0403 }
0404 else {
0405 _parent->MarkLocalAsOuter(pos);
0406 _outervalues.push_back(PSOuterVar(name,PSObjectPtr(PSInteger(pos)),otLOCAL));
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];
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){
0453 PSInstruction &pi = _instructions[size-1];
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
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