Made Mr_Tree graphic smaller, from 99 to 85 pixels.
[supertux.git] / src / squirrel / squirrel / sqfuncstate.cpp
index b070809..9e16026 100644 (file)
@@ -13,6 +13,7 @@
 SQInstructionDesc g_InstrDesc[]={\r
        {_SC("_OP_LINE")},\r
        {_SC("_OP_LOAD")},\r
+       {_SC("_OP_DLOAD")},\r
        {_SC("_OP_TAILCALL")},\r
        {_SC("_OP_CALL")},\r
        {_SC("_OP_PREPCALL")},\r
@@ -30,6 +31,7 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_RETURN")},\r
        {_SC("_OP_LOADNULLS")},\r
        {_SC("_OP_LOADROOTTABLE")},\r
+       {_SC("_OP_LOADBOOL")},\r
        {_SC("_OP_DMOVE")},\r
        {_SC("_OP_JMP")},\r
        {_SC("_OP_JNZ")},\r
@@ -66,8 +68,7 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_POPTRAP")},\r
        {_SC("_OP_THROW")},\r
        {_SC("_OP_CLASS")},\r
-       {_SC("_OP_NEWSLOTA")},\r
-       {_SC("_OP_LOADBOOL")}\r
+       {_SC("_OP_NEWSLOTA")}\r
 };\r
 #endif\r
 void DumpLiteral(SQObjectPtr &o)\r
@@ -79,26 +80,34 @@ void DumpLiteral(SQObjectPtr &o)
        }\r
 }\r
 \r
-SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)\r
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)\r
 {\r
                _nliterals = 0;\r
                _literals = SQTable::Create(ss,0);\r
+               _strings =  SQTable::Create(ss,0);\r
                _sharedstate = ss;\r
                _lastline = 0;\r
                _optimization = true;\r
-               _func = func;\r
                _parent = parent;\r
                _stacksize = 0;\r
                _traps = 0;\r
                _returnexp = 0;\r
                _varparams = false;\r
+               _errfunc = efunc;\r
+               _errtarget = ed;\r
+               _bgenerator = false;\r
+\r
+}\r
+\r
+void SQFuncState::Error(const SQChar *err)\r
+{\r
+       _errfunc(_errtarget,err);\r
 }\r
 \r
 #ifdef _DEBUG_DUMP\r
-void SQFuncState::Dump()\r
+void SQFuncState::Dump(SQFunctionProto *func)\r
 {\r
-       unsigned int n=0,i;\r
-       SQFunctionProto *func=_funcproto(_func);\r
+       SQUnsignedInteger n=0,i;\r
        scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));\r
        scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));\r
        scprintf(_SC("--------------------------------------------------------------------\n"));\r
@@ -108,7 +117,7 @@ void SQFuncState::Dump()
        SQInteger idx;\r
        SQObjectPtrVec templiterals;\r
        templiterals.resize(_nliterals);\r
-       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
+       while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {\r
                refidx=idx;\r
                templiterals[_integer(val)]=key;\r
        }\r
@@ -144,21 +153,38 @@ void SQFuncState::Dump()
        n=0;\r
        for(i=0;i<_instructions.size();i++){\r
                SQInstruction &inst=_instructions[i];\r
-               if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){\r
+               if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){\r
                        \r
-                       int lidx = inst._arg1;\r
+                       SQInteger lidx = inst._arg1;\r
                        scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);\r
                        if(lidx >= 0xFFFFFFFF)\r
                                scprintf(_SC("null"));\r
                        else {\r
-                               int refidx;\r
+                               SQInteger refidx;\r
                                SQObjectPtr val,key,refo;\r
-                               while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
+                               while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
                                        refo = refidx;  \r
                                }\r
                                DumpLiteral(key);\r
                        }\r
-                       scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);\r
+                       if(inst.op != _OP_DLOAD) {\r
+                               scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);\r
+                       }\r
+                       else {\r
+                               scprintf(_SC(" %d "),inst._arg2);\r
+                               lidx = inst._arg3;\r
+                               if(lidx >= 0xFFFFFFFF)\r
+                                       scprintf(_SC("null"));\r
+                               else {\r
+                                       SQInteger refidx;\r
+                                       SQObjectPtr val,key,refo;\r
+                                       while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
+                                               refo = refidx;  \r
+                               }\r
+                               DumpLiteral(key);\r
+                               scprintf(_SC("\n"));\r
+                       }\r
+                       }\r
                }\r
                else if(inst.op==_OP_ARITH){\r
                        scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
@@ -172,66 +198,65 @@ void SQFuncState::Dump()
        scprintf(_SC("--------------------------------------------------------------------\n\n"));\r
 }\r
 #endif\r
-int SQFuncState::GetStringConstant(const SQChar *cons)\r
-{\r
-       return GetConstant(SQString::Create(_sharedstate,cons));\r
-}\r
 \r
-int SQFuncState::GetNumericConstant(const SQInteger cons)\r
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)\r
 {\r
-       return GetConstant(cons);\r
+       return GetConstant(SQObjectPtr(cons));\r
 }\r
 \r
-int SQFuncState::GetNumericConstant(const SQFloat cons)\r
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)\r
 {\r
-       return GetConstant(cons);\r
+       return GetConstant(SQObjectPtr(cons));\r
 }\r
 \r
-int SQFuncState::GetConstant(SQObjectPtr cons)\r
+SQInteger SQFuncState::GetConstant(const SQObject &cons)\r
 {\r
-       int n=0;\r
+       SQInteger n=0;\r
        SQObjectPtr val;\r
        if(!_table(_literals)->Get(cons,val))\r
        {\r
                val = _nliterals;\r
                _table(_literals)->NewSlot(cons,val);\r
                _nliterals++;\r
-               if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));\r
+               if(_nliterals > MAX_LITERALS) {\r
+                       val.Null();\r
+                       Error(_SC("internal compiler error: too many literals"));\r
+               }\r
        }\r
        return _integer(val);\r
 }\r
 \r
-void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)\r
+void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)\r
 {\r
-       _instructions[pos]._arg0=*((unsigned int *)&arg0);\r
-       _instructions[pos]._arg1=*((unsigned int *)&arg1);\r
-       _instructions[pos]._arg2=*((unsigned int *)&arg2);\r
-       _instructions[pos]._arg3=*((unsigned int *)&arg3);\r
+       _instructions[pos]._arg0=*((SQUnsignedInteger *)&arg0);\r
+       _instructions[pos]._arg1=*((SQUnsignedInteger *)&arg1);\r
+       _instructions[pos]._arg2=*((SQUnsignedInteger *)&arg2);\r
+       _instructions[pos]._arg3=*((SQUnsignedInteger *)&arg3);\r
 }\r
 \r
-void SQFuncState::SetIntructionParam(int pos,int arg,int val)\r
+void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)\r
 {\r
        switch(arg){\r
-               case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;\r
-               case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
-               case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;\r
-               case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;\r
-               case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
+               case 0:_instructions[pos]._arg0=*((SQUnsignedInteger *)&val);break;\r
+               case 1:_instructions[pos]._arg1=*((SQUnsignedInteger *)&val);break;\r
+               case 2:_instructions[pos]._arg2=*((SQUnsignedInteger *)&val);break;\r
+               case 3:_instructions[pos]._arg3=*((SQUnsignedInteger *)&val);break;\r
+               case 4:_instructions[pos]._arg1=*((SQUnsignedInteger *)&val);break;\r
        };\r
 }\r
 \r
-int SQFuncState::AllocStackPos()\r
+SQInteger SQFuncState::AllocStackPos()\r
 {\r
-       int npos=_vlocals.size();\r
+       SQInteger npos=_vlocals.size();\r
        _vlocals.push_back(SQLocalVarInfo());\r
-       if(_vlocals.size()>((unsigned int)_stacksize)) {\r
-               if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));\r
+       if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {\r
+               if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));\r
                _stacksize=_vlocals.size();\r
        }\r
        return npos;\r
 }\r
 \r
-int SQFuncState::PushTarget(int n)\r
+SQInteger SQFuncState::PushTarget(SQInteger n)\r
 {\r
        if(n!=-1){\r
                _targetstack.push_back(n);\r
@@ -242,16 +267,16 @@ int SQFuncState::PushTarget(int n)
        return n;\r
 }\r
 \r
-int SQFuncState::GetUpTarget(int n){\r
+SQInteger SQFuncState::GetUpTarget(SQInteger n){\r
        return _targetstack[((_targetstack.size()-1)-n)];\r
 }\r
 \r
-int SQFuncState::TopTarget(){\r
+SQInteger SQFuncState::TopTarget(){\r
        return _targetstack.back();\r
 }\r
-int SQFuncState::PopTarget()\r
+SQInteger SQFuncState::PopTarget()\r
 {\r
-       int npos=_targetstack.back();\r
+       SQInteger npos=_targetstack.back();\r
        SQLocalVarInfo t=_vlocals[_targetstack.back()];\r
        if(type(t._name)==OT_NULL){\r
                _vlocals.pop_back();\r
@@ -260,14 +285,14 @@ int SQFuncState::PopTarget()
        return npos;\r
 }\r
 \r
-int SQFuncState::GetStackSize()\r
+SQInteger SQFuncState::GetStackSize()\r
 {\r
        return _vlocals.size();\r
 }\r
 \r
-void SQFuncState::SetStackSize(int n)\r
+void SQFuncState::SetStackSize(SQInteger n)\r
 {\r
-       int size=_vlocals.size();\r
+       SQInteger size=_vlocals.size();\r
        while(size>n){\r
                size--;\r
                SQLocalVarInfo lvi=_vlocals.back();\r
@@ -279,29 +304,29 @@ void SQFuncState::SetStackSize(int n)
        }\r
 }\r
 \r
-bool SQFuncState::IsLocal(unsigned int stkpos)\r
+bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)\r
 {\r
        if(stkpos>=_vlocals.size())return false;\r
        else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;\r
        return false;\r
 }\r
 \r
-int SQFuncState::PushLocalVariable(const SQObjectPtr &name)\r
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name)\r
 {\r
-       int pos=_vlocals.size();\r
+       SQInteger pos=_vlocals.size();\r
        SQLocalVarInfo lvi;\r
        lvi._name=name;\r
        lvi._start_op=GetCurrentPos()+1;\r
        lvi._pos=_vlocals.size();\r
        _vlocals.push_back(lvi);\r
-       if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();\r
+       if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();\r
        \r
        return pos;\r
 }\r
 \r
-int SQFuncState::GetLocalVariable(const SQObjectPtr &name)\r
+SQInteger SQFuncState::GetLocalVariable(const SQObject &name)\r
 {\r
-       int locals=_vlocals.size();\r
+       SQInteger locals=_vlocals.size();\r
        while(locals>=1){\r
                if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){\r
                        return locals-1;\r
@@ -311,20 +336,19 @@ int SQFuncState::GetLocalVariable(const SQObjectPtr &name)
        return -1;\r
 }\r
 \r
-int SQFuncState::GetOuterVariable(const SQObjectPtr &name)\r
+SQInteger SQFuncState::GetOuterVariable(const SQObject &name)\r
 {\r
-       int outers = _outervalues.size();\r
-       for(int i = 0; i<outers; i++) {\r
+       SQInteger outers = _outervalues.size();\r
+       for(SQInteger i = 0; i<outers; i++) {\r
                if(_string(_outervalues[i]._name) == _string(name))\r
                        return i;\r
        }\r
        return -1;\r
 }\r
 \r
-void SQFuncState::AddOuterValue(const SQObjectPtr &name)\r
+void SQFuncState::AddOuterValue(const SQObject &name)\r
 {\r
-       //AddParameter(name);\r
-       int pos=-1;\r
+       SQInteger pos=-1;\r
        if(_parent) { \r
                pos = _parent->GetLocalVariable(name);\r
                if(pos == -1) {\r
@@ -342,13 +366,13 @@ void SQFuncState::AddOuterValue(const SQObjectPtr &name)
        _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global\r
 }\r
 \r
-void SQFuncState::AddParameter(const SQObjectPtr &name)\r
+void SQFuncState::AddParameter(const SQObject &name)\r
 {\r
        PushLocalVariable(name);\r
        _parameters.push_back(name);\r
 }\r
 \r
-void SQFuncState::AddLineInfos(int line,bool lineop,bool force)\r
+void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)\r
 {\r
        if(_lastline!=line || force){\r
                SQLineInfo li;\r
@@ -361,7 +385,7 @@ void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
 \r
 void SQFuncState::AddInstruction(SQInstruction &i)\r
 {\r
-       int size = _instructions.size();\r
+       SQInteger size = _instructions.size();\r
        if(size > 0 && _optimization){ //simple optimizer\r
                SQInstruction &pi = _instructions[size-1];//previous instruction\r
                switch(i.op) {\r
@@ -416,7 +440,14 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                return;\r
                        }\r
                        break;\r
-\r
+               case _OP_LOAD:\r
+                       if(pi.op == _OP_LOAD && i._arg1 < 256) {\r
+                               pi.op = _OP_DLOAD;\r
+                               pi._arg2 = i._arg0;\r
+                               pi._arg3 = (unsigned char)i._arg1;\r
+                               return;\r
+                       }\r
+                       break;\r
                case _OP_EQ:case _OP_NE:\r
                        if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))\r
                        {\r
@@ -429,7 +460,6 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                        }\r
                        break;\r
                case _OP_LOADNULLS:\r
-               //case _OP_LOADNULL:\r
                        if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {\r
                                \r
                                pi._arg1 = pi._arg1 + 1;\r
@@ -449,23 +479,30 @@ void SQFuncState::AddInstruction(SQInstruction &i)
        _instructions.push_back(i);\r
 }\r
 \r
-SQObject SQFuncState::CreateString(const SQChar *s)\r
+SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)\r
 {\r
-       SQObjectPtr ns(SQString::Create(_sharedstate,s));\r
-       _stringrefs.push_back(ns);\r
+       SQObjectPtr ns(SQString::Create(_sharedstate,s,len));\r
+       _table(_strings)->NewSlot(ns,1);\r
        return ns;\r
 }\r
 \r
-void SQFuncState::Finalize()\r
+SQFunctionProto *SQFuncState::BuildProto()\r
 {\r
-       SQFunctionProto *f=_funcproto(_func);\r
+       SQFunctionProto *f=SQFunctionProto::Create();\r
        f->_literals.resize(_nliterals);\r
        SQObjectPtr refidx,key,val;\r
        SQInteger idx;\r
-       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
+\r
+       f->_stacksize = _stacksize;\r
+       f->_sourcename = _sourcename;\r
+       f->_bgenerator = _bgenerator;\r
+       f->_name = _name;\r
+\r
+       while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {\r
                f->_literals[_integer(val)]=key;\r
                refidx=idx;\r
        }\r
+\r
        f->_functions.resize(_functions.size());\r
        f->_functions.copy(_functions);\r
        f->_parameters.resize(_parameters.size());\r
@@ -479,4 +516,29 @@ void SQFuncState::Finalize()
        f->_lineinfos.resize(_lineinfos.size());\r
        f->_lineinfos.copy(_lineinfos);\r
        f->_varparams = _varparams;\r
+\r
+       return f;\r
+}\r
+\r
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)\r
+{\r
+       SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));\r
+       new (child) SQFuncState(ss,this,_errfunc,_errtarget);\r
+       _childstates.push_back(child);\r
+       return child;\r
+}\r
+\r
+void SQFuncState::PopChildState()\r
+{\r
+       SQFuncState *child = _childstates.back();\r
+       sq_delete(child,SQFuncState);\r
+       _childstates.pop_back();\r
+}\r
+\r
+SQFuncState::~SQFuncState()\r
+{\r
+       while(_childstates.size() > 0)\r
+       {\r
+               PopChildState();\r
+       }\r
 }\r