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
{_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
{_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
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
_errfunc = efunc;\r
_errtarget = ed;\r
_bgenerator = false;\r
+ _outers = 0;\r
+ _ss = ss;\r
\r
}\r
\r
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
}\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
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
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
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
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
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
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
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
\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
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
PopChildState();\r
}\r
}\r
+\r
+#endif\r