New grow and skid sounds from remaxim
[supertux.git] / src / squirrel / squirrel / sqfuncstate.cpp
index 9823fd3..d8354b0 100644 (file)
@@ -13,6 +13,9 @@
 SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_LINE")},
        {_SC("_OP_LOAD")},
+       {_SC("_OP_LOADINT")},
+       {_SC("_OP_LOADFLOAT")},
+       {_SC("_OP_DLOAD")},
        {_SC("_OP_TAILCALL")},
        {_SC("_OP_CALL")},
        {_SC("_OP_PREPCALL")},
@@ -30,6 +33,7 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_RETURN")},
        {_SC("_OP_LOADNULLS")},
        {_SC("_OP_LOADROOTTABLE")},
+       {_SC("_OP_LOADBOOL")},
        {_SC("_OP_DMOVE")},
        {_SC("_OP_JMP")},
        {_SC("_OP_JNZ")},
@@ -59,6 +63,7 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_YIELD")},
        {_SC("_OP_RESUME")},
        {_SC("_OP_FOREACH")},
+       {_SC("_OP_POSTFOREACH")},
        {_SC("_OP_DELEGATE")},
        {_SC("_OP_CLONE")},
        {_SC("_OP_TYPEOF")},
@@ -66,8 +71,7 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_POPTRAP")},
        {_SC("_OP_THROW")},
        {_SC("_OP_CLASS")},
-       {_SC("_OP_NEWSLOTA")},
-       {_SC("_OP_LOADBOOL")}
+       {_SC("_OP_NEWSLOTA")}
 };
 #endif
 void DumpLiteral(SQObjectPtr &o)
@@ -76,10 +80,12 @@ void DumpLiteral(SQObjectPtr &o)
                case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
                case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
                case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
+               case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
+               default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler
        }
 }
 
-SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
 {
                _nliterals = 0;
                _literals = SQTable::Create(ss,0);
@@ -87,7 +93,6 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *pa
                _sharedstate = ss;
                _lastline = 0;
                _optimization = true;
-               _func = func;
                _parent = parent;
                _stacksize = 0;
                _traps = 0;
@@ -95,6 +100,7 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *pa
                _varparams = false;
                _errfunc = efunc;
                _errtarget = ed;
+               _bgenerator = false;
 
 }
 
@@ -104,10 +110,10 @@ void SQFuncState::Error(const SQChar *err)
 }
 
 #ifdef _DEBUG_DUMP
-void SQFuncState::Dump()
+void SQFuncState::Dump(SQFunctionProto *func)
 {
-       unsigned int n=0,i;
-       SQFunctionProto *func=_funcproto(_func);
+       SQUnsignedInteger n=0,i;
+       SQInteger si;
        scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
        scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
        scprintf(_SC("--------------------------------------------------------------------\n"));
@@ -117,7 +123,7 @@ void SQFuncState::Dump()
        SQInteger idx;
        SQObjectPtrVec templiterals;
        templiterals.resize(_nliterals);
-       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
+       while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
                refidx=idx;
                templiterals[_integer(val)]=key;
        }
@@ -138,8 +144,8 @@ void SQFuncState::Dump()
                n++;
        }
        scprintf(_SC("-----LOCALS\n"));
-       for(i=0;i<func->_localvarinfos.size();i++){
-               SQLocalVarInfo lvi=func->_localvarinfos[i];
+       for(si=0;si<func->_nlocalvarinfos;si++){
+               SQLocalVarInfo lvi=func->_localvarinfos[si];
                scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
                n++;
        }
@@ -153,21 +159,41 @@ void SQFuncState::Dump()
        n=0;
        for(i=0;i<_instructions.size();i++){
                SQInstruction &inst=_instructions[i];
-               if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
+               if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
                        
-                       int lidx = inst._arg1;
+                       SQInteger lidx = inst._arg1;
                        scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
                        if(lidx >= 0xFFFFFFFF)
                                scprintf(_SC("null"));
                        else {
-                               int refidx;
+                               SQInteger refidx;
                                SQObjectPtr val,key,refo;
-                               while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {
+                               while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
                                        refo = refidx;  
                                }
                                DumpLiteral(key);
                        }
-                       scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
+                       if(inst.op != _OP_DLOAD) {
+                               scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
+                       }
+                       else {
+                               scprintf(_SC(" %d "),inst._arg2);
+                               lidx = inst._arg3;
+                               if(lidx >= 0xFFFFFFFF)
+                                       scprintf(_SC("null"));
+                               else {
+                                       SQInteger refidx;
+                                       SQObjectPtr val,key,refo;
+                                       while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+                                               refo = refidx;  
+                               }
+                               DumpLiteral(key);
+                               scprintf(_SC("\n"));
+                       }
+                       }
+               }
+               else if(inst.op==_OP_LOADFLOAT) {
+                       scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
                }
                else if(inst.op==_OP_ARITH){
                        scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
@@ -181,24 +207,19 @@ void SQFuncState::Dump()
        scprintf(_SC("--------------------------------------------------------------------\n\n"));
 }
 #endif
-/*int SQFuncState::GetStringConstant(SQObjectPtr &cons)
-{
-       return GetConstant(cons);
-}*/
 
-int SQFuncState::GetNumericConstant(const SQInteger cons)
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
 {
        return GetConstant(SQObjectPtr(cons));
 }
 
-int SQFuncState::GetNumericConstant(const SQFloat cons)
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
 {
        return GetConstant(SQObjectPtr(cons));
 }
 
-int SQFuncState::GetConstant(const SQObject &cons)
+SQInteger SQFuncState::GetConstant(const SQObject &cons)
 {
-       int n=0;
        SQObjectPtr val;
        if(!_table(_literals)->Get(cons,val))
        {
@@ -213,37 +234,36 @@ int SQFuncState::GetConstant(const SQObject &cons)
        return _integer(val);
 }
 
-void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)
+void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
 {
-       _instructions[pos]._arg0=*((unsigned int *)&arg0);
-       _instructions[pos]._arg1=*((unsigned int *)&arg1);
-       _instructions[pos]._arg2=*((unsigned int *)&arg2);
-       _instructions[pos]._arg3=*((unsigned int *)&arg3);
+       _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
+       _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
+       _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
+       _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
 }
 
-void SQFuncState::SetIntructionParam(int pos,int arg,int val)
+void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
 {
        switch(arg){
-               case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;
-               case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;
-               case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;
-               case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;
-               case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;
+               case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
+               case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
+               case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
+               case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
        };
 }
 
-int SQFuncState::AllocStackPos()
+SQInteger SQFuncState::AllocStackPos()
 {
-       int npos=_vlocals.size();
+       SQInteger npos=_vlocals.size();
        _vlocals.push_back(SQLocalVarInfo());
-       if(_vlocals.size()>((unsigned int)_stacksize)) {
+       if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
                if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
                _stacksize=_vlocals.size();
        }
        return npos;
 }
 
-int SQFuncState::PushTarget(int n)
+SQInteger SQFuncState::PushTarget(SQInteger n)
 {
        if(n!=-1){
                _targetstack.push_back(n);
@@ -254,16 +274,16 @@ int SQFuncState::PushTarget(int n)
        return n;
 }
 
-int SQFuncState::GetUpTarget(int n){
+SQInteger SQFuncState::GetUpTarget(SQInteger n){
        return _targetstack[((_targetstack.size()-1)-n)];
 }
 
-int SQFuncState::TopTarget(){
+SQInteger SQFuncState::TopTarget(){
        return _targetstack.back();
 }
-int SQFuncState::PopTarget()
+SQInteger SQFuncState::PopTarget()
 {
-       int npos=_targetstack.back();
+       SQInteger npos=_targetstack.back();
        SQLocalVarInfo t=_vlocals[_targetstack.back()];
        if(type(t._name)==OT_NULL){
                _vlocals.pop_back();
@@ -272,14 +292,14 @@ int SQFuncState::PopTarget()
        return npos;
 }
 
-int SQFuncState::GetStackSize()
+SQInteger SQFuncState::GetStackSize()
 {
        return _vlocals.size();
 }
 
-void SQFuncState::SetStackSize(int n)
+void SQFuncState::SetStackSize(SQInteger n)
 {
-       int size=_vlocals.size();
+       SQInteger size=_vlocals.size();
        while(size>n){
                size--;
                SQLocalVarInfo lvi=_vlocals.back();
@@ -291,29 +311,39 @@ void SQFuncState::SetStackSize(int n)
        }
 }
 
-bool SQFuncState::IsLocal(unsigned int stkpos)
+bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
+{
+       SQObjectPtr val;
+       if(_table(_sharedstate->_consts)->Get(name,val)) {
+               e = val;
+               return true;
+       }
+       return false;
+}
+
+bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
 {
        if(stkpos>=_vlocals.size())return false;
        else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
        return false;
 }
 
-int SQFuncState::PushLocalVariable(const SQObject &name)
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
 {
-       int pos=_vlocals.size();
+       SQInteger pos=_vlocals.size();
        SQLocalVarInfo lvi;
        lvi._name=name;
        lvi._start_op=GetCurrentPos()+1;
        lvi._pos=_vlocals.size();
        _vlocals.push_back(lvi);
-       if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();
+       if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
        
        return pos;
 }
 
-int SQFuncState::GetLocalVariable(const SQObject &name)
+SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
 {
-       int locals=_vlocals.size();
+       SQInteger locals=_vlocals.size();
        while(locals>=1){
                if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
                        return locals-1;
@@ -323,10 +353,10 @@ int SQFuncState::GetLocalVariable(const SQObject &name)
        return -1;
 }
 
-int SQFuncState::GetOuterVariable(const SQObject &name)
+SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
 {
-       int outers = _outervalues.size();
-       for(int i = 0; i<outers; i++) {
+       SQInteger outers = _outervalues.size();
+       for(SQInteger i = 0; i<outers; i++) {
                if(_string(_outervalues[i]._name) == _string(name))
                        return i;
        }
@@ -335,8 +365,7 @@ int SQFuncState::GetOuterVariable(const SQObject &name)
 
 void SQFuncState::AddOuterValue(const SQObject &name)
 {
-       //AddParameter(name);
-       int pos=-1;
+       SQInteger pos=-1;
        if(_parent) { 
                pos = _parent->GetLocalVariable(name);
                if(pos == -1) {
@@ -360,7 +389,7 @@ void SQFuncState::AddParameter(const SQObject &name)
        _parameters.push_back(name);
 }
 
-void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
+void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
 {
        if(_lastline!=line || force){
                SQLineInfo li;
@@ -373,7 +402,7 @@ void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
 
 void SQFuncState::AddInstruction(SQInstruction &i)
 {
-       int size = _instructions.size();
+       SQInteger size = _instructions.size();
        if(size > 0 && _optimization){ //simple optimizer
                SQInstruction &pi = _instructions[size-1];//previous instruction
                switch(i.op) {
@@ -428,7 +457,14 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                return;
                        }
                        break;
-
+               case _OP_LOAD:
+                       if(pi.op == _OP_LOAD && i._arg1 < 256) {
+                               pi.op = _OP_DLOAD;
+                               pi._arg2 = i._arg0;
+                               pi._arg3 = (unsigned char)i._arg1;
+                               return;
+                       }
+                       break;
                case _OP_EQ:case _OP_NE:
                        if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
                        {
@@ -441,7 +477,6 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                        }
                        break;
                case _OP_LOADNULLS:
-               //case _OP_LOADNULL:
                        if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
                                
                                pi._arg1 = pi._arg1 + 1;
@@ -461,42 +496,57 @@ void SQFuncState::AddInstruction(SQInstruction &i)
        _instructions.push_back(i);
 }
 
-SQObject SQFuncState::CreateString(const SQChar *s,int len)
+SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
 {
        SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
-       _table(_strings)->NewSlot(ns,1);
+       _table(_strings)->NewSlot(ns,(SQInteger)1);
        return ns;
 }
 
-void SQFuncState::Finalize()
+SQObject SQFuncState::CreateTable()
+{
+       SQObjectPtr nt(SQTable::Create(_sharedstate,0));
+       _table(_strings)->NewSlot(nt,(SQInteger)1);
+       return nt;
+}
+
+SQFunctionProto *SQFuncState::BuildProto()
 {
-       SQFunctionProto *f=_funcproto(_func);
-       f->_literals.resize(_nliterals);
+       SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
+               _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
+               _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
+
        SQObjectPtr refidx,key,val;
        SQInteger idx;
-       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
+
+       f->_stacksize = _stacksize;
+       f->_sourcename = _sourcename;
+       f->_bgenerator = _bgenerator;
+       f->_name = _name;
+
+       while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
                f->_literals[_integer(val)]=key;
                refidx=idx;
        }
-       f->_functions.resize(_functions.size());
-       f->_functions.copy(_functions);
-       f->_parameters.resize(_parameters.size());
-       f->_parameters.copy(_parameters);
-       f->_outervalues.resize(_outervalues.size());
-       f->_outervalues.copy(_outervalues);
-       f->_instructions.resize(_instructions.size());
-       f->_instructions.copy(_instructions);
-       f->_localvarinfos.resize(_localvarinfos.size());
-       f->_localvarinfos.copy(_localvarinfos);
-       f->_lineinfos.resize(_lineinfos.size());
-       f->_lineinfos.copy(_lineinfos);
+
+       for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
+       for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
+       for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
+       for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
+       for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
+       for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];
+
+       memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
+
        f->_varparams = _varparams;
+
+       return f;
 }
 
-SQFuncState *SQFuncState::PushChildState(SQSharedState *ss,SQFunctionProto *func)
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
 {
        SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
-       new (child) SQFuncState(ss,func,this,_errfunc,_errtarget);
+       new (child) SQFuncState(ss,this,_errfunc,_errtarget);
        _childstates.push_back(child);
        return child;
 }