Update to Squirrel 3.0.6
[supertux.git] / external / squirrel / squirrel / sqfuncstate.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 525a499..aff80e5
@@ -2,9 +2,10 @@
        see copyright notice in squirrel.h\r
 */\r
 #include "sqpcheader.h"\r
+#ifndef NO_COMPILER\r
 #include "sqcompiler.h"\r
-#include "sqfuncproto.h"\r
 #include "sqstring.h"\r
+#include "sqfuncproto.h"\r
 #include "sqtable.h"\r
 #include "sqopcodes.h"\r
 #include "sqfuncstate.h"\r
@@ -28,25 +29,25 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_GET")},\r
        {_SC("_OP_EQ")},\r
        {_SC("_OP_NE")},\r
-       {_SC("_OP_ARITH")},\r
+       {_SC("_OP_ADD")},\r
+       {_SC("_OP_SUB")},\r
+       {_SC("_OP_MUL")},\r
+       {_SC("_OP_DIV")},\r
+       {_SC("_OP_MOD")},\r
        {_SC("_OP_BITW")},\r
        {_SC("_OP_RETURN")},\r
        {_SC("_OP_LOADNULLS")},\r
-       {_SC("_OP_LOADROOTTABLE")},\r
+       {_SC("_OP_LOADROOT")},\r
        {_SC("_OP_LOADBOOL")},\r
        {_SC("_OP_DMOVE")},\r
        {_SC("_OP_JMP")},\r
-       {_SC("_OP_JNZ")},\r
+       {_SC("_OP_JCMP")},\r
        {_SC("_OP_JZ")},\r
-       {_SC("_OP_LOADFREEVAR")},\r
-       {_SC("_OP_VARGC")},\r
-       {_SC("_OP_GETVARGV")},\r
-       {_SC("_OP_NEWTABLE")},\r
-       {_SC("_OP_NEWARRAY")},\r
+       {_SC("_OP_SETOUTER")},\r
+       {_SC("_OP_GETOUTER")},\r
+       {_SC("_OP_NEWOBJ")},\r
        {_SC("_OP_APPENDARRAY")},\r
-       {_SC("_OP_GETPARENT")},\r
        {_SC("_OP_COMPARITH")},\r
-       {_SC("_OP_COMPARITHL")},\r
        {_SC("_OP_INC")},\r
        {_SC("_OP_INCL")},\r
        {_SC("_OP_PINC")},\r
@@ -64,14 +65,15 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_RESUME")},\r
        {_SC("_OP_FOREACH")},\r
        {_SC("_OP_POSTFOREACH")},\r
-       {_SC("_OP_DELEGATE")},\r
        {_SC("_OP_CLONE")},\r
        {_SC("_OP_TYPEOF")},\r
        {_SC("_OP_PUSHTRAP")},\r
        {_SC("_OP_POPTRAP")},\r
        {_SC("_OP_THROW")},\r
-       {_SC("_OP_CLASS")},\r
-       {_SC("_OP_NEWSLOTA")}\r
+       {_SC("_OP_NEWSLOTA")},\r
+       {_SC("_OP_GETBASE")},\r
+       {_SC("_OP_CLOSE")},\r
+       {_SC("_OP_JCMP")}\r
 };\r
 #endif\r
 void DumpLiteral(SQObjectPtr &o)\r
@@ -79,9 +81,9 @@ void DumpLiteral(SQObjectPtr &o)
        switch(type(o)){\r
                case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;\r
                case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;\r
-               case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;\r
+               case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;\r
                case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;\r
-               default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler\r
+               default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler\r
        }\r
 }\r
 \r
@@ -101,6 +103,8 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc
                _errfunc = efunc;\r
                _errtarget = ed;\r
                _bgenerator = false;\r
+               _outers = 0;\r
+               _ss = ss;\r
 \r
 }\r
 \r
@@ -195,11 +199,12 @@ void SQFuncState::Dump(SQFunctionProto *func)
                else if(inst.op==_OP_LOADFLOAT) {\r
                        scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);\r
                }\r
-               else if(inst.op==_OP_ARITH){\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
-               }\r
-               else \r
+               }*/\r
+               else {\r
                        scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
+               }\r
                n++;\r
        }\r
        scprintf(_SC("-----\n"));\r
@@ -283,8 +288,9 @@ SQInteger SQFuncState::TopTarget(){
 }\r
 SQInteger SQFuncState::PopTarget()\r
 {\r
-       SQInteger npos=_targetstack.back();\r
-       SQLocalVarInfo t=_vlocals[_targetstack.back()];\r
+       SQUnsignedInteger npos=_targetstack.back();\r
+       assert(npos < _vlocals.size());\r
+       SQLocalVarInfo &t = _vlocals[npos];\r
        if(type(t._name)==OT_NULL){\r
                _vlocals.pop_back();\r
        }\r
@@ -297,14 +303,31 @@ SQInteger SQFuncState::GetStackSize()
        return _vlocals.size();\r
 }\r
 \r
+SQInteger SQFuncState::CountOuters(SQInteger stacksize)\r
+{\r
+       SQInteger outers = 0;\r
+       SQInteger k = _vlocals.size() - 1;\r
+       while(k >= stacksize) {\r
+               SQLocalVarInfo &lvi = _vlocals[k];\r
+               k--;\r
+               if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer\r
+                       outers++;\r
+               }\r
+       }\r
+       return outers;\r
+}\r
+\r
 void SQFuncState::SetStackSize(SQInteger n)\r
 {\r
        SQInteger size=_vlocals.size();\r
        while(size>n){\r
                size--;\r
-               SQLocalVarInfo lvi=_vlocals.back();\r
+               SQLocalVarInfo lvi = _vlocals.back();\r
                if(type(lvi._name)!=OT_NULL){\r
-                       lvi._end_op=GetCurrentPos();\r
+                       if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer\r
+                               _outers--;\r
+                       }\r
+                       lvi._end_op = GetCurrentPos();\r
                        _localvarinfos.push_back(lvi);\r
                }\r
                _vlocals.pop_back();\r
@@ -337,15 +360,17 @@ SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
        lvi._pos=_vlocals.size();\r
        _vlocals.push_back(lvi);\r
        if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();\r
-       \r
        return pos;\r
 }\r
 \r
+\r
+\r
 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)\r
 {\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
+               SQLocalVarInfo &lvi = _vlocals[locals-1];\r
+               if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){\r
                        return locals-1;\r
                }\r
                locals--;\r
@@ -353,6 +378,13 @@ SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
        return -1;\r
 }\r
 \r
+void SQFuncState::MarkLocalAsOuter(SQInteger pos)\r
+{\r
+       SQLocalVarInfo &lvi = _vlocals[pos];\r
+       lvi._end_op = UINT_MINUS_ONE;\r
+       _outers++;\r
+}\r
+\r
 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)\r
 {\r
        SQInteger outers = _outervalues.size();\r
@@ -360,11 +392,6 @@ SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
                if(_string(_outervalues[i]._name) == _string(name))\r
                        return i;\r
        }\r
-       return -1;\r
-}\r
-\r
-void SQFuncState::AddOuterValue(const SQObject &name)\r
-{\r
        SQInteger pos=-1;\r
        if(_parent) { \r
                pos = _parent->GetLocalVariable(name);\r
@@ -372,15 +399,18 @@ void SQFuncState::AddOuterValue(const SQObject &name)
                        pos = _parent->GetOuterVariable(name);\r
                        if(pos != -1) {\r
                                _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local\r
-                               return;\r
+                               return _outervalues.size() - 1; \r
                        }\r
                }\r
                else {\r
+                       _parent->MarkLocalAsOuter(pos);\r
                        _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local\r
-                       return;\r
+                       return _outervalues.size() - 1;\r
+                       \r
+                       \r
                }\r
-       }       \r
-       _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global\r
+       }\r
+       return -1;\r
 }\r
 \r
 void SQFuncState::AddParameter(const SQObject &name)\r
@@ -395,20 +425,58 @@ void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
                SQLineInfo li;\r
                li._line=line;li._op=(GetCurrentPos()+1);\r
                if(lineop)AddInstruction(_OP_LINE,0,line);\r
-               _lineinfos.push_back(li);\r
+               if(_lastline!=line) {\r
+                       _lineinfos.push_back(li);\r
+               }\r
                _lastline=line;\r
        }\r
 }\r
 \r
+void SQFuncState::DiscardTarget()\r
+{\r
+       SQInteger discardedtarget = PopTarget();\r
+       SQInteger size = _instructions.size();\r
+       if(size > 0 && _optimization){\r
+               SQInstruction &pi = _instructions[size-1];//previous instruction\r
+               switch(pi.op) {\r
+               case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:\r
+                       if(pi._arg0 == discardedtarget) {\r
+                               pi._arg0 = 0xFF;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
 void SQFuncState::AddInstruction(SQInstruction &i)\r
 {\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
+               case _OP_JZ:\r
+                       if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {\r
+                               pi.op = _OP_JCMP;\r
+                               pi._arg0 = (unsigned char)pi._arg1;\r
+                               pi._arg1 = i._arg1;\r
+                               return;\r
+                       }\r
+               case _OP_SET:\r
+               case _OP_NEWSLOT:\r
+                       if(i._arg0 == i._arg3) {\r
+                               i._arg0 = 0xFF;\r
+                       }\r
+                       break;\r
+               case _OP_SETOUTER:\r
+                       if(i._arg0 == i._arg2) {\r
+                               i._arg0 = 0xFF;\r
+                       }\r
+                       break;\r
                case _OP_RETURN:\r
                        if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {\r
                                pi.op = _OP_TAILCALL;\r
+                       } else if(pi.op == _OP_CLOSE){\r
+                               pi = i;\r
+                               return;\r
                        }\r
                break;\r
                case _OP_GET:\r
@@ -431,22 +499,37 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                return;\r
                        }\r
                        break;\r
-               case _OP_APPENDARRAY:\r
-                       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
+               case _OP_APPENDARRAY: {\r
+                       SQInteger aat = -1;\r
+                       switch(pi.op) {\r
+                       case _OP_LOAD: aat = AAT_LITERAL; break;\r
+                       case _OP_LOADINT: aat = AAT_INT; break;\r
+                       case _OP_LOADBOOL: aat = AAT_BOOL; break;\r
+                       case _OP_LOADFLOAT: aat = AAT_FLOAT; break;\r
+                       default: break;\r
+                       }\r
+                       if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
                                pi.op = _OP_APPENDARRAY;\r
                                pi._arg0 = i._arg0;\r
                                pi._arg1 = pi._arg1;\r
-                               pi._arg2 = MAX_FUNC_STACKSIZE;\r
+                               pi._arg2 = (unsigned char)aat;\r
                                pi._arg3 = MAX_FUNC_STACKSIZE;\r
                                return;\r
                        }\r
+                                                         }\r
                        break;\r
-               case _OP_MOVE: \r
-                       if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))\r
-                       {\r
-                               pi._arg0 = i._arg0;\r
-                               _optimization = false;\r
-                               return;\r
+               case _OP_MOVE:\r
+                       switch(pi.op) {\r
+                       case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:\r
+                       case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:\r
+\r
+                               if(pi._arg0 == i._arg1)\r
+                               {\r
+                                       pi._arg0 = i._arg0;\r
+                                       _optimization = false;\r
+                                       //_result_elimination = false;\r
+                                       return;\r
+                               }\r
                        }\r
 \r
                        if(pi.op == _OP_MOVE)\r
@@ -512,7 +595,8 @@ SQObject SQFuncState::CreateTable()
 \r
 SQFunctionProto *SQFuncState::BuildProto()\r
 {\r
-       SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),\r
+       \r
+       SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),\r
                _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),\r
                _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());\r
 \r
@@ -532,9 +616,9 @@ SQFunctionProto *SQFuncState::BuildProto()
        for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];\r
        for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];\r
        for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];\r
-       for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];\r
-       for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];\r
-       for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];\r
+       for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];\r
+       for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];\r
+       for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];\r
 \r
        memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));\r
 \r
@@ -565,3 +649,5 @@ SQFuncState::~SQFuncState()
                PopChildState();\r
        }\r
 }\r
+\r
+#endif\r