fix cr/lfs and remove trailing whitespaces...
[supertux.git] / src / squirrel / squirrel / sqfuncstate.cpp
index d9b3585..2ceb1b4 100644 (file)
@@ -13,6 +13,8 @@
 SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_LINE")},
        {_SC("_OP_LOAD")},
+       {_SC("_OP_LOADINT")},
+       {_SC("_OP_DLOAD")},
        {_SC("_OP_TAILCALL")},
        {_SC("_OP_CALL")},
        {_SC("_OP_PREPCALL")},
@@ -30,6 +32,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")},
@@ -66,8 +69,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,30 +78,38 @@ 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;
-               default: break;
+               default: assert(0); break; //shut up compiler
        }
 }
 
-SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
 {
                _nliterals = 0;
                _literals = SQTable::Create(ss,0);
+               _strings =  SQTable::Create(ss,0);
                _sharedstate = ss;
                _lastline = 0;
                _optimization = true;
-               _func = func;
                _parent = parent;
                _stacksize = 0;
                _traps = 0;
                _returnexp = 0;
                _varparams = false;
+               _errfunc = efunc;
+               _errtarget = ed;
+               _bgenerator = false;
+
+}
+
+void SQFuncState::Error(const SQChar *err)
+{
+       _errfunc(_errtarget,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;
        scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
        scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
        scprintf(_SC("--------------------------------------------------------------------\n"));
@@ -109,7 +119,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;
        }
@@ -145,26 +155,43 @@ 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 ){
-                       
-                       int lidx = inst._arg1;
+               if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
+
+                       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)) {
-                                       refo = refidx;  
+                               while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+                                       refo = refidx;
+                               }
+                               DumpLiteral(key);
+                       }
+                       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"));
+                       }
                        }
-                       scprintf(_SC(" %d %d \n"),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);
                }
-               else 
+               else
                        scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
                n++;
        }
@@ -173,66 +200,63 @@ void SQFuncState::Dump()
        scprintf(_SC("--------------------------------------------------------------------\n\n"));
 }
 #endif
-int SQFuncState::GetStringConstant(const SQChar *cons)
-{
-       return GetConstant(SQString::Create(_sharedstate,cons));
-}
 
-int SQFuncState::GetNumericConstant(const SQInteger cons)
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
 {
-       return GetConstant(cons);
+       return GetConstant(SQObjectPtr(cons));
 }
 
-int SQFuncState::GetNumericConstant(const SQFloat cons)
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
 {
-       return GetConstant(cons);
+       return GetConstant(SQObjectPtr(cons));
 }
 
-int SQFuncState::GetConstant(SQObjectPtr cons)
+SQInteger SQFuncState::GetConstant(const SQObject &cons)
 {
-       // int n=0;
        SQObjectPtr val;
        if(!_table(_literals)->Get(cons,val))
        {
                val = _nliterals;
                _table(_literals)->NewSlot(cons,val);
                _nliterals++;
-               if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));
+               if(_nliterals > MAX_LITERALS) {
+                       val.Null();
+                       Error(_SC("internal compiler error: too many literals"));
+               }
        }
        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(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));
+       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);
@@ -243,16 +267,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();
@@ -261,14 +285,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();
@@ -280,29 +304,29 @@ void SQFuncState::SetStackSize(int n)
        }
 }
 
-bool SQFuncState::IsLocal(unsigned int stkpos)
+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 SQObjectPtr &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 SQObjectPtr &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;
@@ -312,21 +336,20 @@ int SQFuncState::GetLocalVariable(const SQObjectPtr &name)
        return -1;
 }
 
-int SQFuncState::GetOuterVariable(const SQObjectPtr &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;
        }
        return -1;
 }
 
-void SQFuncState::AddOuterValue(const SQObjectPtr &name)
+void SQFuncState::AddOuterValue(const SQObject &name)
 {
-       //AddParameter(name);
-       int pos=-1;
-       if(_parent) { 
+       SQInteger pos=-1;
+       if(_parent) {
                pos = _parent->GetLocalVariable(name);
                if(pos == -1) {
                        pos = _parent->GetOuterVariable(name);
@@ -339,17 +362,17 @@ void SQFuncState::AddOuterValue(const SQObjectPtr &name)
                        _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
                        return;
                }
-       }       
+       }
        _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
 }
 
-void SQFuncState::AddParameter(const SQObjectPtr &name)
+void SQFuncState::AddParameter(const SQObject &name)
 {
        PushLocalVariable(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;
@@ -362,7 +385,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) {
@@ -377,7 +400,7 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                pi._arg2 = (unsigned char)i._arg1;
                                pi.op = _OP_GETK;
                                pi._arg0 = i._arg0;
-                               
+
                                return;
                        }
                break;
@@ -401,7 +424,7 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                return;
                        }
                        break;
-               case _OP_MOVE: 
+               case _OP_MOVE:
                        if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
                        {
                                pi._arg0 = i._arg0;
@@ -417,7 +440,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) ))
                        {
@@ -430,9 +460,8 @@ 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;
                                pi.op = _OP_LOADNULLS;
                                return;
@@ -450,23 +479,30 @@ void SQFuncState::AddInstruction(SQInstruction &i)
        _instructions.push_back(i);
 }
 
-SQObject SQFuncState::CreateString(const SQChar *s)
+SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
 {
-       SQObjectPtr ns(SQString::Create(_sharedstate,s));
-       _stringrefs.push_back(ns);
+       SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
+       _table(_strings)->NewSlot(ns,(SQInteger)1);
        return ns;
 }
 
-void SQFuncState::Finalize()
+SQFunctionProto *SQFuncState::BuildProto()
 {
-       SQFunctionProto *f=_funcproto(_func);
+       SQFunctionProto *f=SQFunctionProto::Create();
        f->_literals.resize(_nliterals);
        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());
@@ -480,4 +516,29 @@ void SQFuncState::Finalize()
        f->_lineinfos.resize(_lineinfos.size());
        f->_lineinfos.copy(_lineinfos);
        f->_varparams = _varparams;
+
+       return f;
+}
+
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
+{
+       SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
+       new (child) SQFuncState(ss,this,_errfunc,_errtarget);
+       _childstates.push_back(child);
+       return child;
+}
+
+void SQFuncState::PopChildState()
+{
+       SQFuncState *child = _childstates.back();
+       sq_delete(child,SQFuncState);
+       _childstates.pop_back();
+}
+
+SQFuncState::~SQFuncState()
+{
+       while(_childstates.size() > 0)
+       {
+               PopChildState();
+       }
 }