fix cr/lfs and remove trailing whitespaces...
[supertux.git] / src / squirrel / squirrel / sqcompiler.cpp
index 464a0c0..a6bab09 100644 (file)
-/*\r
-       see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <stdarg.h>\r
-#include <setjmp.h>\r
-#include "sqopcodes.h"\r
-#include "sqstring.h"\r
-#include "sqfuncproto.h"\r
-#include "sqcompiler.h"\r
-#include "sqfuncstate.h"\r
-#include "sqlexer.h"\r
-#include "sqvm.h"\r
-\r
-#define DEREF_NO_DEREF -1\r
-#define DEREF_FIELD            -2\r
-\r
-struct ExpState\r
-{\r
-       ExpState()\r
-       {\r
-               _deref = DEREF_NO_DEREF;\r
-               _freevar = false;\r
-               _class_or_delete = false;\r
-               _funcarg = false;\r
-       }\r
-       bool _class_or_delete;\r
-       bool _funcarg;\r
-       bool _freevar;\r
-       SQInteger _deref;\r
-};\r
-\r
-typedef sqvector<ExpState> ExpStateVec;\r
-\r
-#define _exst (_expstates.top())\r
-\r
-#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
-                                                       SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \\r
-                                                       _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);\r
-\r
-#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \\r
-                                       __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \\r
-                                       if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \\r
-                                       if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \\r
-                                       _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}\r
-\r
-class SQCompiler\r
-{\r
-public:\r
-       SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)\r
-       {\r
-               _vm=v;\r
-               _lex.Init(_ss(v), rg, up,ThrowError,this);\r
-               _sourcename = SQString::Create(_ss(v), sourcename);\r
-               _lineinfo = lineinfo;_raiseerror = raiseerror;\r
-               compilererror = NULL;\r
-       }\r
-       static void ThrowError(void *ud, const SQChar *s) {\r
-               SQCompiler *c = (SQCompiler *)ud;\r
-               c->Error(s);\r
-       }\r
-       void Error(const SQChar *s, ...)\r
-       {\r
-               static SQChar temp[256];\r
-               va_list vl;\r
-               va_start(vl, s);\r
-               scvsprintf(temp, s, vl);\r
-               va_end(vl);\r
-               compilererror = temp;\r
-               longjmp(_errorjmp,1);\r
-       }\r
-       void Lex(){     _token = _lex.Lex();}\r
-       void PushExpState(){ _expstates.push_back(ExpState()); }\r
-       bool IsDerefToken(SQInteger tok)\r
-       {\r
-               switch(tok){\r
-               case _SC('='): case _SC('('): case TK_NEWSLOT:\r
-               case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;\r
-               }\r
-               return false;\r
-       }\r
-       ExpState PopExpState()\r
-       {\r
-               ExpState ret = _expstates.top();\r
-               _expstates.pop_back();\r
-               return ret;\r
-       }\r
-       SQObject Expect(SQInteger tok)\r
-       {\r
-               \r
-               if(_token != tok) {\r
-                       if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {\r
-                               //ret = SQString::Create(_ss(_vm),_SC("constructor"));\r
-                               //do nothing\r
-                       }\r
-                       else {\r
-                               const SQChar *etypename;\r
-                               if(tok > 255) {\r
-                                       switch(tok)\r
-                                       {\r
-                                       case TK_IDENTIFIER:\r
-                                               etypename = _SC("IDENTIFIER");\r
-                                               break;\r
-                                       case TK_STRING_LITERAL:\r
-                                               etypename = _SC("STRING_LITERAL");\r
-                                               break;\r
-                                       case TK_INTEGER:\r
-                                               etypename = _SC("INTEGER");\r
-                                               break;\r
-                                       case TK_FLOAT:\r
-                                               etypename = _SC("FLOAT");\r
-                                               break;\r
-                                       default:\r
-                                               etypename = _lex.Tok2Str(tok);\r
-                                       }\r
-                                       Error(_SC("expected '%s'"), etypename);\r
-                               }\r
-                               Error(_SC("expected '%c'"), tok);\r
-                       }\r
-               }\r
-               SQObjectPtr ret;\r
-               switch(tok)\r
-               {\r
-               case TK_IDENTIFIER:\r
-                       ret = _fs->CreateString(_lex._svalue);\r
-                       break;\r
-               case TK_STRING_LITERAL:\r
-                       ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);\r
-                       break;\r
-               case TK_INTEGER:\r
-                       ret = SQObjectPtr(_lex._nvalue);\r
-                       break;\r
-               case TK_FLOAT:\r
-                       ret = SQObjectPtr(_lex._fvalue);\r
-                       break;\r
-               }\r
-               Lex();\r
-               return ret;\r
-       }\r
-       bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }\r
-       void OptionalSemicolon()\r
-       {\r
-               if(_token == _SC(';')) { Lex(); return; }\r
-               if(!IsEndOfStatement()) {\r
-                       Error(_SC("end of statement expected (; or lf)"));\r
-               }\r
-       }\r
-       void MoveIfCurrentTargetIsLocal() {\r
-               SQInteger trg = _fs->TopTarget();\r
-               if(_fs->IsLocal(trg)) {\r
-                       trg = _fs->PopTarget(); //no pops the target and move it\r
-                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);\r
-               }\r
-       }\r
-       bool Compile(SQObjectPtr &o)\r
-       {\r
-               _debugline = 1;\r
-               _debugop = 0;\r
-\r
-               SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);\r
-               funcstate._name = SQString::Create(_ss(_vm), _SC("main"));\r
-               _fs = &funcstate;\r
-               _fs->AddParameter(_fs->CreateString(_SC("this")));\r
-               _fs->_sourcename = _sourcename;\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               if(setjmp(_errorjmp) == 0) {\r
-                       Lex();\r
-                       while(_token > 0){\r
-                               Statement();\r
-                               if(_lex._prevtoken != _SC('}')) OptionalSemicolon();\r
-                       }\r
-                       CleanStack(stacksize);\r
-                       _fs->AddLineInfos(_lex._currentline, _lineinfo, true);\r
-                       _fs->AddInstruction(_OP_RETURN, 0xFF);\r
-                       _fs->SetStackSize(0);\r
-                       o =_fs->BuildProto();\r
-#ifdef _DEBUG_DUMP\r
-                       _fs->Dump(_funcproto(o));\r
-#endif\r
-               }\r
-               else {\r
-                       if(_raiseerror && _ss(_vm)->_compilererrorhandler) {\r
-                               _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
-                                       _lex._currentline, _lex._currentcolumn);\r
-                       }\r
-                       _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);\r
-                       return false;\r
-               }\r
-               return true;\r
-       }\r
-       void Statements()\r
-       {\r
-               while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {\r
-                       Statement();\r
-                       if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
-               }\r
-       }\r
-       void Statement()\r
-       {\r
-               _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
-               switch(_token){\r
-               case _SC(';'):  Lex();                                  break;\r
-               case TK_IF:             IfStatement();                  break;\r
-               case TK_WHILE:          WhileStatement();               break;\r
-               case TK_DO:             DoWhileStatement();             break;\r
-               case TK_FOR:            ForStatement();                 break;\r
-               case TK_FOREACH:        ForEachStatement();             break;\r
-               case TK_SWITCH: SwitchStatement();              break;\r
-               case TK_LOCAL:          LocalDeclStatement();   break;\r
-               case TK_RETURN:\r
-               case TK_YIELD: {\r
-                       SQOpcode op;\r
-                       if(_token == TK_RETURN) {\r
-                               op = _OP_RETURN;\r
-                               \r
-                       }\r
-                       else {\r
-                               op = _OP_YIELD;\r
-                               _fs->_bgenerator = true;\r
-                       }\r
-                       Lex();\r
-                       if(!IsEndOfStatement()) {\r
-                               SQInteger retexp = _fs->GetCurrentPos()+1;\r
-                               CommaExpr();\r
-                               if(op == _OP_RETURN && _fs->_traps > 0)\r
-                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);\r
-                               _fs->_returnexp = retexp;\r
-                               _fs->AddInstruction(op, 1, _fs->PopTarget());\r
-                       }\r
-                       else{ \r
-                               if(op == _OP_RETURN && _fs->_traps > 0)\r
-                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);\r
-                               _fs->_returnexp = -1;\r
-                               _fs->AddInstruction(op, 0xFF); \r
-                       }\r
-                       break;}\r
-               case TK_BREAK:\r
-                       if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));\r
-                       if(_fs->_breaktargets.top() > 0){\r
-                               _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);\r
-                       }\r
-                       _fs->AddInstruction(_OP_JMP, 0, -1234);\r
-                       _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());\r
-                       Lex();\r
-                       break;\r
-               case TK_CONTINUE:\r
-                       if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));\r
-                       if(_fs->_continuetargets.top() > 0) {\r
-                               _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);\r
-                       }\r
-                       _fs->AddInstruction(_OP_JMP, 0, -1234);\r
-                       _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());\r
-                       Lex();\r
-                       break;\r
-               case TK_FUNCTION:\r
-                       FunctionStatement();\r
-                       break;\r
-               case TK_CLASS:\r
-                       ClassStatement();\r
-                       break;\r
-               case _SC('{'):{\r
-                               SQInteger stacksize = _fs->GetStackSize();\r
-                               Lex();\r
-                               Statements();\r
-                               Expect(_SC('}'));\r
-                               _fs->SetStackSize(stacksize);\r
-                       }\r
-                       break;\r
-               case TK_TRY:\r
-                       TryCatchStatement();\r
-                       break;\r
-               case TK_THROW:\r
-                       Lex();\r
-                       CommaExpr();\r
-                       _fs->AddInstruction(_OP_THROW, _fs->PopTarget());\r
-                       break;\r
-               default:\r
-                       CommaExpr();\r
-                       _fs->PopTarget();\r
-                       break;\r
-               }\r
-               _fs->SnoozeOpt();\r
-       }\r
-       void EmitDerefOp(SQOpcode op)\r
-       {\r
-               SQInteger val = _fs->PopTarget();\r
-               SQInteger key = _fs->PopTarget();\r
-               SQInteger src = _fs->PopTarget();\r
-        _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);\r
-       }\r
-       void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)\r
-       {\r
-               SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
-               SQInteger p1 = _fs->PopTarget(); //key in OP_GET\r
-               _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);\r
-       }\r
-       void EmitCompoundArith(SQInteger tok,bool deref)\r
-       {\r
-               SQInteger oper;\r
-               switch(tok){\r
-               case TK_MINUSEQ: oper = '-'; break;\r
-               case TK_PLUSEQ: oper = '+'; break;\r
-               case TK_MULEQ: oper = '*'; break;\r
-               case TK_DIVEQ: oper = '/'; break;\r
-               case TK_MODEQ: oper = '%'; break;\r
-               default: oper = 0; //shut up compiler\r
-                       assert(0); break;\r
-               };\r
-               if(deref) {\r
-                       SQInteger val = _fs->PopTarget();\r
-                       SQInteger key = _fs->PopTarget();\r
-                       SQInteger src = _fs->PopTarget();\r
-                       //mixes dest obj and source val in the arg1(hack?)\r
-                       _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);\r
-               }\r
-               else {\r
-                       Emit2ArgsOP(_OP_COMPARITHL, oper);\r
-               }\r
-       }\r
-       void CommaExpr()\r
-       {\r
-               for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());\r
-       }\r
-       ExpState Expression(bool funcarg = false)\r
-       {\r
-               PushExpState();\r
-               _exst._class_or_delete = false;\r
-               _exst._funcarg = funcarg;\r
-               LogicalOrExp();\r
-               switch(_token)  {\r
-               case _SC('='):\r
-               case TK_NEWSLOT:\r
-               case TK_MINUSEQ:\r
-               case TK_PLUSEQ:\r
-               case TK_MULEQ:\r
-               case TK_DIVEQ:\r
-               case TK_MODEQ:\r
-               {\r
-                               SQInteger op = _token;\r
-                               SQInteger ds = _exst._deref;\r
-                               bool freevar = _exst._freevar;\r
-                               if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));\r
-                               Lex(); Expression();\r
-\r
-                               switch(op){\r
-                               case TK_NEWSLOT:\r
-                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
-                                       if(ds == DEREF_FIELD)\r
-                                               EmitDerefOp(_OP_NEWSLOT);\r
-                                       else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                               Error(_SC("can't 'create' a local slot"));\r
-                                       break;\r
-                               case _SC('='): //ASSIGN\r
-                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
-                                       if(ds == DEREF_FIELD)\r
-                                               EmitDerefOp(_OP_SET);\r
-                                       else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                               SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
-                                               SQInteger p1 = _fs->TopTarget(); //key in OP_GET\r
-                                               _fs->AddInstruction(_OP_MOVE, p1, p2);\r
-                                       }\r
-                                       break;\r
-                               case TK_MINUSEQ:\r
-                               case TK_PLUSEQ:\r
-                               case TK_MULEQ:\r
-                               case TK_DIVEQ:\r
-                               case TK_MODEQ:\r
-                                       EmitCompoundArith(op,ds == DEREF_FIELD);\r
-                                       break;\r
-                               }\r
-                       }\r
-                       break;\r
-               case _SC('?'): {\r
-                       Lex();\r
-                       _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
-                       SQInteger jzpos = _fs->GetCurrentPos();\r
-                       SQInteger trg = _fs->PushTarget();\r
-                       Expression();\r
-                       SQInteger first_exp = _fs->PopTarget();\r
-                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
-                       SQInteger endfirstexp = _fs->GetCurrentPos();\r
-                       _fs->AddInstruction(_OP_JMP, 0, 0);\r
-                       Expect(_SC(':'));\r
-                       SQInteger jmppos = _fs->GetCurrentPos();\r
-                       Expression();\r
-                       SQInteger second_exp = _fs->PopTarget();\r
-                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
-                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
-                       _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);\r
-                       _fs->SnoozeOpt();\r
-                       }\r
-                       break;\r
-               }\r
-               return PopExpState();\r
-       }\r
-       void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0)\r
-       {\r
-               Lex(); (this->*f)();\r
-               SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();\r
-               _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);\r
-       }\r
-       void LogicalOrExp()\r
-       {\r
-               LogicalAndExp();\r
-               for(;;) if(_token == TK_OR) {\r
-                       SQInteger first_exp = _fs->PopTarget();\r
-                       SQInteger trg = _fs->PushTarget();\r
-                       _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);\r
-                       SQInteger jpos = _fs->GetCurrentPos();\r
-                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
-                       Lex(); LogicalOrExp();\r
-                       _fs->SnoozeOpt();\r
-                       SQInteger second_exp = _fs->PopTarget();\r
-                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
-                       _fs->SnoozeOpt();\r
-                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
-                       break;\r
-               }else return;\r
-       }\r
-       void LogicalAndExp()\r
-       {\r
-               BitwiseOrExp();\r
-               for(;;) switch(_token) {\r
-               case TK_AND: {\r
-                       SQInteger first_exp = _fs->PopTarget();\r
-                       SQInteger trg = _fs->PushTarget();\r
-                       _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);\r
-                       SQInteger jpos = _fs->GetCurrentPos();\r
-                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
-                       Lex(); LogicalAndExp();\r
-                       _fs->SnoozeOpt();\r
-                       SQInteger second_exp = _fs->PopTarget();\r
-                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
-                       _fs->SnoozeOpt();\r
-                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
-                       break;\r
-                       }\r
-               case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;\r
-               case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;\r
-               default:\r
-                       return;\r
-               }\r
-       }\r
-       void BitwiseOrExp()\r
-       {\r
-               BitwiseXorExp();\r
-               for(;;) if(_token == _SC('|'))\r
-               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);\r
-               }else return;\r
-       }\r
-       void BitwiseXorExp()\r
-       {\r
-               BitwiseAndExp();\r
-               for(;;) if(_token == _SC('^'))\r
-               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);\r
-               }else return;\r
-       }\r
-       void BitwiseAndExp()\r
-       {\r
-               CompExp();\r
-               for(;;) if(_token == _SC('&'))\r
-               {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);\r
-               }else return;\r
-       }\r
-       void CompExp()\r
-       {\r
-               ShiftExp();\r
-               for(;;) switch(_token) {\r
-               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;\r
-               case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;\r
-               case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;\r
-               case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;\r
-               case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;\r
-               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;\r
-               default: return;        \r
-               }\r
-       }\r
-       void ShiftExp()\r
-       {\r
-               PlusExp();\r
-               for(;;) switch(_token) {\r
-               case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;\r
-               case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;\r
-               case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;\r
-               default: return;        \r
-               }\r
-       }\r
-       void PlusExp()\r
-       {\r
-               MultExp();\r
-               for(;;) switch(_token) {\r
-               case _SC('+'): case _SC('-'):\r
-                       BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;\r
-               default: return;\r
-               }\r
-       }\r
-       \r
-       void MultExp()\r
-       {\r
-               PrefixedExpr();\r
-               for(;;) switch(_token) {\r
-               case _SC('*'): case _SC('/'): case _SC('%'):\r
-                       BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;\r
-               default: return;\r
-               }\r
-       }\r
-       //if 'pos' != -1 the previous variable is a local variable\r
-       void PrefixedExpr()\r
-       {\r
-               SQInteger pos = Factor();\r
-               for(;;) {\r
-                       switch(_token) {\r
-                       case _SC('.'): {\r
-                               pos = -1;\r
-                               Lex(); \r
-                               if(_token == TK_PARENT) {\r
-                                       Lex();\r
-                                       if(!NeedGet())\r
-                                               Error(_SC("parent cannot be set"));\r
-                                       SQInteger src = _fs->PopTarget();\r
-                                       _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);\r
-                               }\r
-                               else {\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
-                                       if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                               }\r
-                               _exst._deref = DEREF_FIELD;\r
-                               _exst._freevar = false;\r
-                               }\r
-                               break;\r
-                       case _SC('['):\r
-                               if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));\r
-                               Lex(); Expression(); Expect(_SC(']')); \r
-                               pos = -1;\r
-                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                               _exst._deref = DEREF_FIELD;\r
-                               _exst._freevar = false;\r
-                               break;\r
-                       case TK_MINUSMINUS:\r
-                       case TK_PLUSPLUS:\r
-                       if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { \r
-                               SQInteger tok = _token; Lex();\r
-                               if(pos < 0)\r
-                                       Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);\r
-                               else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                       SQInteger src = _fs->PopTarget();\r
-                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);\r
-                               }\r
-                               \r
-                       }\r
-                       return;\r
-                       break;  \r
-                       case _SC('('): \r
-                               {\r
-                               if(_exst._deref != DEREF_NO_DEREF) {\r
-                                       if(pos<0) {\r
-                                               SQInteger key = _fs->PopTarget(); //key\r
-                                               SQInteger table = _fs->PopTarget(); //table etc...\r
-                                               SQInteger closure = _fs->PushTarget();\r
-                                               SQInteger ttarget = _fs->PushTarget();\r
-                                               _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);\r
-                                       }\r
-                                       else{\r
-                                               _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
-                                       }\r
-                               }\r
-                               else\r
-                                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
-                               _exst._deref = DEREF_NO_DEREF;\r
-                               Lex();\r
-                               FunctionCallArgs();\r
-                                }\r
-                               break;\r
-                       default: return;\r
-                       }\r
-               }\r
-       }\r
-       SQInteger Factor()\r
-       {\r
-               switch(_token)\r
-               {\r
-               case TK_STRING_LITERAL: {\r
-                               //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));\r
-                               Lex(); \r
-                       }\r
-                       break;\r
-               case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;\r
-               case TK_VARGV: { Lex();\r
-                       Expect(_SC('['));\r
-                       Expression();\r
-                       Expect(_SC(']'));\r
-                       SQInteger src = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);\r
-                                          }\r
-                       break;\r
-               case TK_IDENTIFIER:\r
-               case TK_CONSTRUCTOR:\r
-               case TK_THIS:{\r
-                       _exst._freevar = false;\r
-                       SQObject id;\r
-                               switch(_token) {\r
-                                       case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;\r
-                                       case TK_THIS: id = _fs->CreateString(_SC("this")); break;\r
-                                       case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;\r
-                               }\r
-                               SQInteger pos = -1;\r
-                               Lex();\r
-                               if((pos = _fs->GetLocalVariable(id)) == -1) {\r
-                                       //checks if is a free variable\r
-                                       if((pos = _fs->GetOuterVariable(id)) != -1) {\r
-                                               _exst._deref = _fs->PushTarget();\r
-                                               _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);        \r
-                                               _exst._freevar = true;\r
-                                       } else {\r
-                                               _fs->PushTarget(0);\r
-                                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-                                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                                               _exst._deref = DEREF_FIELD;\r
-                                       }\r
-                               }\r
-                               else{\r
-                                       _fs->PushTarget(pos);\r
-                                       _exst._deref = pos;\r
-                               }\r
-                               return _exst._deref;\r
-                       }\r
-                       break;\r
-               case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;\r
-               case TK_DOUBLE_COLON:  // "::"\r
-                       _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());\r
-                       _exst._deref = DEREF_FIELD;\r
-                       _token = _SC('.'); //hack\r
-                       return -1;\r
-                       break;\r
-               case TK_NULL: \r
-                       _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
-                       Lex();\r
-                       break;\r
-               case TK_INTEGER: {\r
-                       if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?\r
-                               _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);\r
-                       }\r
-                       else {\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));\r
-                       }\r
-                       Lex();\r
-                                                }\r
-                       break;\r
-               case TK_FLOAT: \r
-                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
-                       Lex();\r
-                       break;\r
-               case TK_TRUE: case TK_FALSE:\r
-                       _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);\r
-                       Lex();\r
-                       break;\r
-               case _SC('['): {\r
-                               _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());\r
-                               SQInteger apos = _fs->GetCurrentPos(),key = 0;\r
-                               Lex();\r
-                               while(_token != _SC(']')) {\r
-                    Expression(); \r
-                                       if(_token == _SC(',')) Lex();\r
-                                       SQInteger val = _fs->PopTarget();\r
-                                       SQInteger array = _fs->TopTarget();\r
-                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val);\r
-                                       key++;\r
-                               }\r
-                               _fs->SetIntructionParam(apos, 1, key);\r
-                               Lex();\r
-                       }\r
-                       break;\r
-               case _SC('{'):{\r
-                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
-                       Lex();ParseTableOrClass(_SC(','));\r
-                                }\r
-                       break;\r
-               case TK_FUNCTION: FunctionExp(_token);break;\r
-               case TK_CLASS: Lex(); ClassExp();break;\r
-               case _SC('-'): UnaryOP(_OP_NEG); break;\r
-               case _SC('!'): UnaryOP(_OP_NOT); break;\r
-               case _SC('~'): UnaryOP(_OP_BWNOT); break;\r
-               case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;\r
-               case TK_RESUME : UnaryOP(_OP_RESUME); break;\r
-               case TK_CLONE : UnaryOP(_OP_CLONE); break;\r
-               case TK_MINUSMINUS : \r
-               case TK_PLUSPLUS :PrefixIncDec(_token); break;\r
-               case TK_DELETE : DeleteExpr(); break;\r
-               case TK_DELEGATE : DelegateExpr(); break;\r
-               case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));\r
-                       break;\r
-               default: Error(_SC("expression expected"));\r
-               }\r
-               return -1;\r
-       }\r
-       void UnaryOP(SQOpcode op)\r
-       {\r
-               Lex(); PrefixedExpr();\r
-               SQInteger src = _fs->PopTarget();\r
-               _fs->AddInstruction(op, _fs->PushTarget(), src);\r
-       }\r
-       bool NeedGet()\r
-       {\r
-               switch(_token) {\r
-               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
-               case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:\r
-                       return false;\r
-               }\r
-               return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));\r
-       }\r
-       \r
-       void FunctionCallArgs()\r
-       {\r
-               SQInteger nargs = 1;//this\r
-                while(_token != _SC(')')) {\r
-                        Expression(true);\r
-                        MoveIfCurrentTargetIsLocal();\r
-                        nargs++; \r
-                        if(_token == _SC(',')){ \r
-                                Lex(); \r
-                                if(_token == ')') Error(_SC("expression expected, found ')'"));\r
-                        }\r
-                }\r
-                Lex();\r
-                for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();\r
-                SQInteger stackbase = _fs->PopTarget();\r
-                SQInteger closure = _fs->PopTarget();\r
-         _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
-       }\r
-       void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')\r
-       {\r
-               SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;\r
-               \r
-               while(_token != terminator) {\r
-                       bool hasattrs = false;\r
-                       bool isstatic = false;\r
-                       //check if is an attribute\r
-                       if(separator == ';') {\r
-                               if(_token == TK_ATTR_OPEN) {\r
-                                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();\r
-                                       ParseTableOrClass(',',TK_ATTR_CLOSE);\r
-                                       hasattrs = true;\r
-                               }\r
-                               if(_token == TK_STATIC) {\r
-                                       isstatic = true;\r
-                                       Lex();\r
-                               }\r
-                       }\r
-                       switch(_token) {\r
-                               case TK_FUNCTION:\r
-                               case TK_CONSTRUCTOR:{\r
-                                       SQInteger tk = _token;\r
-                                       Lex();\r
-                                       SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));\r
-                                       Expect(_SC('('));\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-                                       CreateFunction(id);\r
-                                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
-                                                                 }\r
-                                                                 break;\r
-                               case _SC('['):\r
-                                       Lex(); CommaExpr(); Expect(_SC(']'));\r
-                                       Expect(_SC('=')); Expression();\r
-                                       break;\r
-                               default :\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
-                                       Expect(_SC('=')); Expression();\r
-                       }\r
-\r
-                       if(_token == separator) Lex();//optional comma/semicolon\r
-                       nkeys++;\r
-                       SQInteger val = _fs->PopTarget();\r
-                       SQInteger key = _fs->PopTarget();\r
-                       SQInteger attrs = hasattrs ? _fs->PopTarget():-1;\r
-                       assert(hasattrs && attrs == key-1 || !hasattrs);\r
-                       unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);\r
-                       SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE\r
-                       _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);\r
-                       //_fs->PopTarget();\r
-               }\r
-               if(separator == _SC(',')) //hack recognizes a table from the separator\r
-                       _fs->SetIntructionParam(tpos, 1, nkeys);\r
-               Lex();\r
-       }\r
-       void LocalDeclStatement()\r
-       {\r
-               SQObject varname;\r
-               do {\r
-                       Lex(); varname = Expect(TK_IDENTIFIER);\r
-                       if(_token == _SC('=')) {\r
-                               Lex(); Expression();\r
-                               SQInteger src = _fs->PopTarget();\r
-                               SQInteger dest = _fs->PushTarget();\r
-                               if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);\r
-                       }\r
-                       else{\r
-                               _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
-                       }\r
-                       _fs->PopTarget();\r
-                       _fs->PushLocalVariable(varname);\r
-               \r
-               } while(_token == _SC(','));\r
-       }\r
-       void IfStatement()\r
-       {\r
-               SQInteger jmppos;\r
-               bool haselse = false;\r
-               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
-               SQInteger jnepos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               \r
-               Statement();\r
-               //\r
-               if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
-               \r
-               CleanStack(stacksize);\r
-               SQInteger endifblock = _fs->GetCurrentPos();\r
-               if(_token == TK_ELSE){\r
-                       haselse = true;\r
-                       stacksize = _fs->GetStackSize();\r
-                       _fs->AddInstruction(_OP_JMP);\r
-                       jmppos = _fs->GetCurrentPos();\r
-                       Lex();\r
-                       Statement(); OptionalSemicolon();\r
-                       CleanStack(stacksize);\r
-                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
-               }\r
-               _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
-       }\r
-       void WhileStatement()\r
-       {\r
-               SQInteger jzpos, jmppos;\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               jmppos = _fs->GetCurrentPos();\r
-               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               \r
-               BEGIN_BREAKBLE_BLOCK();\r
-               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
-               jzpos = _fs->GetCurrentPos();\r
-               stacksize = _fs->GetStackSize();\r
-               \r
-               Statement();\r
-               \r
-               CleanStack(stacksize);\r
-               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
-               _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
-               \r
-               END_BREAKBLE_BLOCK(jmppos);\r
-       }\r
-       void DoWhileStatement()\r
-       {\r
-               Lex();\r
-               SQInteger jzpos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               BEGIN_BREAKBLE_BLOCK()\r
-               Statement();\r
-               CleanStack(stacksize);\r
-               Expect(TK_WHILE);\r
-               SQInteger continuetrg = _fs->GetCurrentPos();\r
-               Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);\r
-               END_BREAKBLE_BLOCK(continuetrg);\r
-       }\r
-       void ForStatement()\r
-       {\r
-               Lex();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               Expect(_SC('('));\r
-               if(_token == TK_LOCAL) LocalDeclStatement();\r
-               else if(_token != _SC(';')){\r
-                       CommaExpr();\r
-                       _fs->PopTarget();\r
-               }\r
-               Expect(_SC(';'));\r
-               _fs->SnoozeOpt();\r
-               SQInteger jmppos = _fs->GetCurrentPos();\r
-               SQInteger jzpos = -1;\r
-               if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }\r
-               Expect(_SC(';'));\r
-               _fs->SnoozeOpt();\r
-               SQInteger expstart = _fs->GetCurrentPos() + 1;\r
-               if(_token != _SC(')')) {\r
-                       CommaExpr();\r
-                       _fs->PopTarget();\r
-               }\r
-               Expect(_SC(')'));\r
-               _fs->SnoozeOpt();\r
-               SQInteger expend = _fs->GetCurrentPos();\r
-               SQInteger expsize = (expend - expstart) + 1;\r
-               SQInstructionVec exp;\r
-               if(expsize > 0) {\r
-                       for(SQInteger i = 0; i < expsize; i++)\r
-                               exp.push_back(_fs->GetInstruction(expstart + i));\r
-                       _fs->PopInstructions(expsize);\r
-               }\r
-               BEGIN_BREAKBLE_BLOCK()\r
-               Statement();\r
-               SQInteger continuetrg = _fs->GetCurrentPos();\r
-               if(expsize > 0) {\r
-                       for(SQInteger i = 0; i < expsize; i++)\r
-                               _fs->AddInstruction(exp[i]);\r
-               }\r
-               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);\r
-               if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
-               CleanStack(stacksize);\r
-               \r
-               END_BREAKBLE_BLOCK(continuetrg);\r
-       }\r
-       void ForEachStatement()\r
-       {\r
-               SQObject idxname, valname;\r
-               Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);\r
-               if(_token == _SC(',')) {\r
-                       idxname = valname;\r
-                       Lex(); valname = Expect(TK_IDENTIFIER);\r
-               }\r
-               else{\r
-                       idxname = _fs->CreateString(_SC("@INDEX@"));\r
-               }\r
-               Expect(TK_IN);\r
-               \r
-               //save the stack size\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               //put the table in the stack(evaluate the table expression)\r
-               Expression(); Expect(_SC(')'));\r
-               SQInteger container = _fs->TopTarget();\r
-               //push the index local var\r
-               SQInteger indexpos = _fs->PushLocalVariable(idxname);\r
-               _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);\r
-               //push the value local var\r
-               SQInteger valuepos = _fs->PushLocalVariable(valname);\r
-               _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);\r
-               //push reference index\r
-               SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible\r
-               _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);\r
-               SQInteger jmppos = _fs->GetCurrentPos();\r
-               _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);\r
-               SQInteger foreachpos = _fs->GetCurrentPos();\r
-               //generate the statement code\r
-               BEGIN_BREAKBLE_BLOCK()\r
-               Statement();\r
-               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
-               _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);\r
-               //restore the local variable stack(remove index,val and ref idx)\r
-               CleanStack(stacksize);\r
-               END_BREAKBLE_BLOCK(foreachpos - 1);\r
-       }\r
-       void SwitchStatement()\r
-       {\r
-               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               Expect(_SC('{'));\r
-               SQInteger expr = _fs->TopTarget();\r
-               bool bfirst = true;\r
-               SQInteger tonextcondjmp = -1;\r
-               SQInteger skipcondjmp = -1;\r
-               SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();\r
-               _fs->_breaktargets.push_back(0);\r
-               while(_token == TK_CASE) {\r
-                       //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one\r
-                       if(!bfirst) {\r
-                               _fs->AddInstruction(_OP_JMP, 0, 0);\r
-                               skipcondjmp = _fs->GetCurrentPos();\r
-                               _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
-                       }\r
-                       //condition\r
-                       Lex(); Expression(); Expect(_SC(':'));\r
-                       SQInteger trg = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_EQ, trg, trg, expr);\r
-                       _fs->AddInstruction(_OP_JZ, trg, 0);\r
-                       //end condition\r
-                       if(skipcondjmp != -1) {\r
-                               _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));\r
-                       }\r
-                       tonextcondjmp = _fs->GetCurrentPos();\r
-                       SQInteger stacksize = _fs->GetStackSize();\r
-                       Statements();\r
-                       _fs->SetStackSize(stacksize);\r
-                       bfirst = false;\r
-               }\r
-               if(tonextcondjmp != -1)\r
-                       _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
-               if(_token == TK_DEFAULT) {\r
-               //      _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
-                       Lex(); Expect(_SC(':'));\r
-                       SQInteger stacksize = _fs->GetStackSize();\r
-                       Statements();\r
-                       _fs->SetStackSize(stacksize);\r
-               }\r
-               Expect(_SC('}'));\r
-               _fs->PopTarget();\r
-               __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;\r
-               if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);\r
-               _fs->_breaktargets.pop_back();\r
-               \r
-       }\r
-       void FunctionStatement()\r
-       {\r
-               SQObject id;\r
-               Lex(); id = Expect(TK_IDENTIFIER);\r
-               _fs->PushTarget(0);\r
-               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-               if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
-               \r
-               while(_token == TK_DOUBLE_COLON) {\r
-                       Lex();\r
-                       id = Expect(TK_IDENTIFIER);\r
-                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-                       if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
-               }\r
-               Expect(_SC('('));\r
-               CreateFunction(id);\r
-               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
-               EmitDerefOp(_OP_NEWSLOT);\r
-               _fs->PopTarget();\r
-       }\r
-       void ClassStatement()\r
-       {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
-               PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));\r
-               if(es._deref == DEREF_FIELD) {\r
-                       ClassExp();\r
-                       EmitDerefOp(_OP_NEWSLOT);\r
-                       _fs->PopTarget();\r
-               }\r
-               else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
-       }\r
-       void TryCatchStatement()\r
-       {\r
-               SQObject exid;\r
-               Lex();\r
-               _fs->AddInstruction(_OP_PUSHTRAP,0,0);\r
-               _fs->_traps++;\r
-               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;\r
-               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;\r
-               SQInteger trappos = _fs->GetCurrentPos();\r
-               Statement();\r
-               _fs->_traps--;\r
-               _fs->AddInstruction(_OP_POPTRAP, 1, 0);\r
-               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;\r
-               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;\r
-               _fs->AddInstruction(_OP_JMP, 0, 0);\r
-               SQInteger jmppos = _fs->GetCurrentPos();\r
-               _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));\r
-               Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               SQInteger ex_target = _fs->PushLocalVariable(exid);\r
-               _fs->SetIntructionParam(trappos, 0, ex_target);\r
-               Statement();\r
-               _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);\r
-               CleanStack(stacksize);\r
-       }\r
-       void FunctionExp(SQInteger ftype)\r
-       {\r
-               Lex(); Expect(_SC('('));\r
-               CreateFunction(_null_);\r
-               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);\r
-       }\r
-       void ClassExp()\r
-       {\r
-               SQInteger base = -1;\r
-               SQInteger attrs = -1;\r
-               if(_token == TK_EXTENDS) {\r
-                       Lex(); Expression();\r
-                       base = _fs->TopTarget();\r
-               }\r
-               if(_token == TK_ATTR_OPEN) {\r
-                       Lex();\r
-                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
-                       ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);\r
-                       attrs = _fs->TopTarget();\r
-               }\r
-               Expect(_SC('{'));\r
-               if(attrs != -1) _fs->PopTarget();\r
-               if(base != -1) _fs->PopTarget();\r
-               _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);\r
-               ParseTableOrClass(_SC(';'));\r
-       }\r
-       void DelegateExpr()\r
-       {\r
-               Lex(); CommaExpr();\r
-               Expect(_SC(':'));\r
-               CommaExpr();\r
-               SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget();\r
-               _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);\r
-       }\r
-       void DeleteExpr()\r
-       {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
-               PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));\r
-               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);\r
-               else Error(_SC("cannot delete a local"));\r
-       }\r
-       void PrefixIncDec(SQInteger token)\r
-       {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
-               PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);\r
-               else {\r
-                       SQInteger src = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);\r
-               }\r
-       }\r
-       void CreateFunction(SQObject &name)\r
-       {\r
-               \r
-               SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));\r
-               funcstate->_name = name;\r
-               SQObject paramname;\r
-               funcstate->AddParameter(_fs->CreateString(_SC("this")));\r
-               funcstate->_sourcename = _sourcename;\r
-               while(_token!=_SC(')')) {\r
-                       if(_token == TK_VARPARAMS) {\r
-                               funcstate->_varparams = true;\r
-                               Lex();\r
-                               if(_token != _SC(')')) Error(_SC("expected ')'"));\r
-                               break;\r
-                       }\r
-                       else {\r
-                               paramname = Expect(TK_IDENTIFIER);\r
-                               funcstate->AddParameter(paramname);\r
-                               if(_token == _SC(',')) Lex();\r
-                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
-                       }\r
-               }\r
-               Expect(_SC(')'));\r
-               //outer values\r
-               if(_token == _SC(':')) {\r
-                       Lex(); Expect(_SC('('));\r
-                       while(_token != _SC(')')) {\r
-                               paramname = Expect(TK_IDENTIFIER);\r
-                               //outers are treated as implicit local variables\r
-                               funcstate->AddOuterValue(paramname);\r
-                               if(_token == _SC(',')) Lex();\r
-                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
-                       }\r
-                       Lex();\r
-               }\r
-               \r
-               SQFuncState *currchunk = _fs;\r
-               _fs = funcstate;\r
-               Statement();\r
-               funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);\r
-        funcstate->AddInstruction(_OP_RETURN, -1);\r
-               funcstate->SetStackSize(0);\r
-               //_fs->->_stacksize = _fs->_stacksize;\r
-               SQFunctionProto *func = funcstate->BuildProto();\r
-#ifdef _DEBUG_DUMP\r
-               funcstate->Dump(func);\r
-#endif\r
-               _fs = currchunk;\r
-               _fs->_functions.push_back(func);\r
-               _fs->PopChildState();\r
-       }\r
-       void CleanStack(SQInteger stacksize)\r
-       {\r
-               if(_fs->GetStackSize() != stacksize)\r
-                       _fs->SetStackSize(stacksize);\r
-       }\r
-       void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)\r
-       {\r
-               while(ntoresolve > 0) {\r
-                       SQInteger pos = funcstate->_unresolvedbreaks.back();\r
-                       funcstate->_unresolvedbreaks.pop_back();\r
-                       //set the jmp instruction\r
-                       funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);\r
-                       ntoresolve--;\r
-               }\r
-       }\r
-       void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)\r
-       {\r
-               while(ntoresolve > 0) {\r
-                       SQInteger pos = funcstate->_unresolvedcontinues.back();\r
-                       funcstate->_unresolvedcontinues.pop_back();\r
-                       //set the jmp instruction\r
-                       funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);\r
-                       ntoresolve--;\r
-               }\r
-       }\r
-private:\r
-       SQInteger _token;\r
-       SQFuncState *_fs;\r
-       SQObjectPtr _sourcename;\r
-       SQLexer _lex;\r
-       bool _lineinfo;\r
-       bool _raiseerror;\r
-       SQInteger _debugline;\r
-       SQInteger _debugop;\r
-       ExpStateVec _expstates;\r
-       SQChar *compilererror;\r
-       jmp_buf _errorjmp;\r
-       SQVM *_vm;\r
-};\r
-\r
-bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)\r
-{\r
-       SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);\r
-       return p.Compile(out);\r
-}\r
+/*
+       see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <stdarg.h>
+#include <setjmp.h>
+#include "sqopcodes.h"
+#include "sqstring.h"
+#include "sqfuncproto.h"
+#include "sqcompiler.h"
+#include "sqfuncstate.h"
+#include "sqlexer.h"
+#include "sqvm.h"
+
+#define DEREF_NO_DEREF -1
+#define DEREF_FIELD            -2
+
+struct ExpState
+{
+       ExpState()
+       {
+               _deref = DEREF_NO_DEREF;
+               _freevar = false;
+               _class_or_delete = false;
+               _funcarg = false;
+       }
+       bool _class_or_delete;
+       bool _funcarg;
+       bool _freevar;
+       SQInteger _deref;
+};
+
+typedef sqvector<ExpState> ExpStateVec;
+
+#define _exst (_expstates.top())
+
+#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
+                                                       SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
+                                                       _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
+
+#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
+                                       __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
+                                       if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
+                                       if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
+                                       _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
+
+class SQCompiler
+{
+public:
+       SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
+       {
+               _vm=v;
+               _lex.Init(_ss(v), rg, up,ThrowError,this);
+               _sourcename = SQString::Create(_ss(v), sourcename);
+               _lineinfo = lineinfo;_raiseerror = raiseerror;
+               compilererror = NULL;
+       }
+       static void ThrowError(void *ud, const SQChar *s) {
+               SQCompiler *c = (SQCompiler *)ud;
+               c->Error(s);
+       }
+       void Error(const SQChar *s, ...)
+       {
+               static SQChar temp[256];
+               va_list vl;
+               va_start(vl, s);
+               scvsprintf(temp, s, vl);
+               va_end(vl);
+               compilererror = temp;
+               longjmp(_errorjmp,1);
+       }
+       void Lex(){     _token = _lex.Lex();}
+       void PushExpState(){ _expstates.push_back(ExpState()); }
+       bool IsDerefToken(SQInteger tok)
+       {
+               switch(tok){
+               case _SC('='): case _SC('('): case TK_NEWSLOT:
+               case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;
+               }
+               return false;
+       }
+       ExpState PopExpState()
+       {
+               ExpState ret = _expstates.top();
+               _expstates.pop_back();
+               return ret;
+       }
+       SQObject Expect(SQInteger tok)
+       {
+
+               if(_token != tok) {
+                       if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
+                               //ret = SQString::Create(_ss(_vm),_SC("constructor"));
+                               //do nothing
+                       }
+                       else {
+                               const SQChar *etypename;
+                               if(tok > 255) {
+                                       switch(tok)
+                                       {
+                                       case TK_IDENTIFIER:
+                                               etypename = _SC("IDENTIFIER");
+                                               break;
+                                       case TK_STRING_LITERAL:
+                                               etypename = _SC("STRING_LITERAL");
+                                               break;
+                                       case TK_INTEGER:
+                                               etypename = _SC("INTEGER");
+                                               break;
+                                       case TK_FLOAT:
+                                               etypename = _SC("FLOAT");
+                                               break;
+                                       default:
+                                               etypename = _lex.Tok2Str(tok);
+                                       }
+                                       Error(_SC("expected '%s'"), etypename);
+                               }
+                               Error(_SC("expected '%c'"), tok);
+                       }
+               }
+               SQObjectPtr ret;
+               switch(tok)
+               {
+               case TK_IDENTIFIER:
+                       ret = _fs->CreateString(_lex._svalue);
+                       break;
+               case TK_STRING_LITERAL:
+                       ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
+                       break;
+               case TK_INTEGER:
+                       ret = SQObjectPtr(_lex._nvalue);
+                       break;
+               case TK_FLOAT:
+                       ret = SQObjectPtr(_lex._fvalue);
+                       break;
+               }
+               Lex();
+               return ret;
+       }
+       bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
+       void OptionalSemicolon()
+       {
+               if(_token == _SC(';')) { Lex(); return; }
+               if(!IsEndOfStatement()) {
+                       Error(_SC("end of statement expected (; or lf)"));
+               }
+       }
+       void MoveIfCurrentTargetIsLocal() {
+               SQInteger trg = _fs->TopTarget();
+               if(_fs->IsLocal(trg)) {
+                       trg = _fs->PopTarget(); //no pops the target and move it
+                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
+               }
+       }
+       bool Compile(SQObjectPtr &o)
+       {
+               _debugline = 1;
+               _debugop = 0;
+
+               SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
+               funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
+               _fs = &funcstate;
+               _fs->AddParameter(_fs->CreateString(_SC("this")));
+               _fs->_sourcename = _sourcename;
+               SQInteger stacksize = _fs->GetStackSize();
+               if(setjmp(_errorjmp) == 0) {
+                       Lex();
+                       while(_token > 0){
+                               Statement();
+                               if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
+                       }
+                       CleanStack(stacksize);
+                       _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
+                       _fs->AddInstruction(_OP_RETURN, 0xFF);
+                       _fs->SetStackSize(0);
+                       o =_fs->BuildProto();
+#ifdef _DEBUG_DUMP
+                       _fs->Dump(_funcproto(o));
+#endif
+               }
+               else {
+                       if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
+                               _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
+                                       _lex._currentline, _lex._currentcolumn);
+                       }
+                       _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
+                       return false;
+               }
+               return true;
+       }
+       void Statements()
+       {
+               while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
+                       Statement();
+                       if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+               }
+       }
+       void Statement()
+       {
+               _fs->AddLineInfos(_lex._currentline, _lineinfo);
+               switch(_token){
+               case _SC(';'):  Lex();                                  break;
+               case TK_IF:             IfStatement();                  break;
+               case TK_WHILE:          WhileStatement();               break;
+               case TK_DO:             DoWhileStatement();             break;
+               case TK_FOR:            ForStatement();                 break;
+               case TK_FOREACH:        ForEachStatement();             break;
+               case TK_SWITCH: SwitchStatement();              break;
+               case TK_LOCAL:          LocalDeclStatement();   break;
+               case TK_RETURN:
+               case TK_YIELD: {
+                       SQOpcode op;
+                       if(_token == TK_RETURN) {
+                               op = _OP_RETURN;
+
+                       }
+                       else {
+                               op = _OP_YIELD;
+                               _fs->_bgenerator = true;
+                       }
+                       Lex();
+                       if(!IsEndOfStatement()) {
+                               SQInteger retexp = _fs->GetCurrentPos()+1;
+                               CommaExpr();
+                               if(op == _OP_RETURN && _fs->_traps > 0)
+                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
+                               _fs->_returnexp = retexp;
+                               _fs->AddInstruction(op, 1, _fs->PopTarget());
+                       }
+                       else{
+                               if(op == _OP_RETURN && _fs->_traps > 0)
+                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
+                               _fs->_returnexp = -1;
+                               _fs->AddInstruction(op, 0xFF);
+                       }
+                       break;}
+               case TK_BREAK:
+                       if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
+                       if(_fs->_breaktargets.top() > 0){
+                               _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
+                       }
+                       _fs->AddInstruction(_OP_JMP, 0, -1234);
+                       _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
+                       Lex();
+                       break;
+               case TK_CONTINUE:
+                       if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
+                       if(_fs->_continuetargets.top() > 0) {
+                               _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
+                       }
+                       _fs->AddInstruction(_OP_JMP, 0, -1234);
+                       _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
+                       Lex();
+                       break;
+               case TK_FUNCTION:
+                       FunctionStatement();
+                       break;
+               case TK_CLASS:
+                       ClassStatement();
+                       break;
+               case _SC('{'):{
+                               SQInteger stacksize = _fs->GetStackSize();
+                               Lex();
+                               Statements();
+                               Expect(_SC('}'));
+                               _fs->SetStackSize(stacksize);
+                       }
+                       break;
+               case TK_TRY:
+                       TryCatchStatement();
+                       break;
+               case TK_THROW:
+                       Lex();
+                       CommaExpr();
+                       _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
+                       break;
+               default:
+                       CommaExpr();
+                       _fs->PopTarget();
+                       break;
+               }
+               _fs->SnoozeOpt();
+       }
+       void EmitDerefOp(SQOpcode op)
+       {
+               SQInteger val = _fs->PopTarget();
+               SQInteger key = _fs->PopTarget();
+               SQInteger src = _fs->PopTarget();
+        _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
+       }
+       void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
+       {
+               SQInteger p2 = _fs->PopTarget(); //src in OP_GET
+               SQInteger p1 = _fs->PopTarget(); //key in OP_GET
+               _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
+       }
+       void EmitCompoundArith(SQInteger tok,bool deref)
+       {
+               SQInteger oper;
+               switch(tok){
+               case TK_MINUSEQ: oper = '-'; break;
+               case TK_PLUSEQ: oper = '+'; break;
+               case TK_MULEQ: oper = '*'; break;
+               case TK_DIVEQ: oper = '/'; break;
+               case TK_MODEQ: oper = '%'; break;
+               default: oper = 0; //shut up compiler
+                       assert(0); break;
+               };
+               if(deref) {
+                       SQInteger val = _fs->PopTarget();
+                       SQInteger key = _fs->PopTarget();
+                       SQInteger src = _fs->PopTarget();
+                       //mixes dest obj and source val in the arg1(hack?)
+                       _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);
+               }
+               else {
+                       Emit2ArgsOP(_OP_COMPARITHL, oper);
+               }
+       }
+       void CommaExpr()
+       {
+               for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
+       }
+       ExpState Expression(bool funcarg = false)
+       {
+               PushExpState();
+               _exst._class_or_delete = false;
+               _exst._funcarg = funcarg;
+               LogicalOrExp();
+               switch(_token)  {
+               case _SC('='):
+               case TK_NEWSLOT:
+               case TK_MINUSEQ:
+               case TK_PLUSEQ:
+               case TK_MULEQ:
+               case TK_DIVEQ:
+               case TK_MODEQ:
+               {
+                               SQInteger op = _token;
+                               SQInteger ds = _exst._deref;
+                               bool freevar = _exst._freevar;
+                               if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));
+                               Lex(); Expression();
+
+                               switch(op){
+                               case TK_NEWSLOT:
+                                       if(freevar) Error(_SC("free variables cannot be modified"));
+                                       if(ds == DEREF_FIELD)
+                                               EmitDerefOp(_OP_NEWSLOT);
+                                       else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+                                               Error(_SC("can't 'create' a local slot"));
+                                       break;
+                               case _SC('='): //ASSIGN
+                                       if(freevar) Error(_SC("free variables cannot be modified"));
+                                       if(ds == DEREF_FIELD)
+                                               EmitDerefOp(_OP_SET);
+                                       else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+                                               SQInteger p2 = _fs->PopTarget(); //src in OP_GET
+                                               SQInteger p1 = _fs->TopTarget(); //key in OP_GET
+                                               _fs->AddInstruction(_OP_MOVE, p1, p2);
+                                       }
+                                       break;
+                               case TK_MINUSEQ:
+                               case TK_PLUSEQ:
+                               case TK_MULEQ:
+                               case TK_DIVEQ:
+                               case TK_MODEQ:
+                                       EmitCompoundArith(op,ds == DEREF_FIELD);
+                                       break;
+                               }
+                       }
+                       break;
+               case _SC('?'): {
+                       Lex();
+                       _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+                       SQInteger jzpos = _fs->GetCurrentPos();
+                       SQInteger trg = _fs->PushTarget();
+                       Expression();
+                       SQInteger first_exp = _fs->PopTarget();
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+                       SQInteger endfirstexp = _fs->GetCurrentPos();
+                       _fs->AddInstruction(_OP_JMP, 0, 0);
+                       Expect(_SC(':'));
+                       SQInteger jmppos = _fs->GetCurrentPos();
+                       Expression();
+                       SQInteger second_exp = _fs->PopTarget();
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+                       _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
+                       _fs->SnoozeOpt();
+                       }
+                       break;
+               }
+               return PopExpState();
+       }
+       void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0)
+       {
+               Lex(); (this->*f)();
+               SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
+               _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
+       }
+       void LogicalOrExp()
+       {
+               LogicalAndExp();
+               for(;;) if(_token == TK_OR) {
+                       SQInteger first_exp = _fs->PopTarget();
+                       SQInteger trg = _fs->PushTarget();
+                       _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
+                       SQInteger jpos = _fs->GetCurrentPos();
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+                       Lex(); LogicalOrExp();
+                       _fs->SnoozeOpt();
+                       SQInteger second_exp = _fs->PopTarget();
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+                       _fs->SnoozeOpt();
+                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
+                       break;
+               }else return;
+       }
+       void LogicalAndExp()
+       {
+               BitwiseOrExp();
+               for(;;) switch(_token) {
+               case TK_AND: {
+                       SQInteger first_exp = _fs->PopTarget();
+                       SQInteger trg = _fs->PushTarget();
+                       _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
+                       SQInteger jpos = _fs->GetCurrentPos();
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+                       Lex(); LogicalAndExp();
+                       _fs->SnoozeOpt();
+                       SQInteger second_exp = _fs->PopTarget();
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+                       _fs->SnoozeOpt();
+                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
+                       break;
+                       }
+               case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;
+               case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;
+               default:
+                       return;
+               }
+       }
+       void BitwiseOrExp()
+       {
+               BitwiseXorExp();
+               for(;;) if(_token == _SC('|'))
+               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
+               }else return;
+       }
+       void BitwiseXorExp()
+       {
+               BitwiseAndExp();
+               for(;;) if(_token == _SC('^'))
+               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
+               }else return;
+       }
+       void BitwiseAndExp()
+       {
+               CompExp();
+               for(;;) if(_token == _SC('&'))
+               {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);
+               }else return;
+       }
+       void CompExp()
+       {
+               ShiftExp();
+               for(;;) switch(_token) {
+               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;
+               case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
+               case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
+               case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
+               case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
+               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;
+               default: return;
+               }
+       }
+       void ShiftExp()
+       {
+               PlusExp();
+               for(;;) switch(_token) {
+               case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
+               case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
+               case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
+               default: return;
+               }
+       }
+       void PlusExp()
+       {
+               MultExp();
+               for(;;) switch(_token) {
+               case _SC('+'): case _SC('-'):
+                       BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;
+               default: return;
+               }
+       }
+
+       void MultExp()
+       {
+               PrefixedExpr();
+               for(;;) switch(_token) {
+               case _SC('*'): case _SC('/'): case _SC('%'):
+                       BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;
+               default: return;
+               }
+       }
+       //if 'pos' != -1 the previous variable is a local variable
+       void PrefixedExpr()
+       {
+               SQInteger pos = Factor();
+               for(;;) {
+                       switch(_token) {
+                       case _SC('.'): {
+                               pos = -1;
+                               Lex();
+                               if(_token == TK_PARENT) {
+                                       Lex();
+                                       if(!NeedGet())
+                                               Error(_SC("parent cannot be set"));
+                                       SQInteger src = _fs->PopTarget();
+                                       _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
+                               }
+                               else {
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
+                                       if(NeedGet()) Emit2ArgsOP(_OP_GET);
+                               }
+                               _exst._deref = DEREF_FIELD;
+                               _exst._freevar = false;
+                               }
+                               break;
+                       case _SC('['):
+                               if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
+                               Lex(); Expression(); Expect(_SC(']'));
+                               pos = -1;
+                               if(NeedGet()) Emit2ArgsOP(_OP_GET);
+                               _exst._deref = DEREF_FIELD;
+                               _exst._freevar = false;
+                               break;
+                       case TK_MINUSMINUS:
+                       case TK_PLUSPLUS:
+                       if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
+                               SQInteger tok = _token; Lex();
+                               if(pos < 0)
+                                       Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
+                               else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+                                       SQInteger src = _fs->PopTarget();
+                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
+                               }
+
+                       }
+                       return;
+                       break;
+                       case _SC('('):
+                               {
+                               if(_exst._deref != DEREF_NO_DEREF) {
+                                       if(pos<0) {
+                                               SQInteger key = _fs->PopTarget(); //key
+                                               SQInteger table = _fs->PopTarget(); //table etc...
+                                               SQInteger closure = _fs->PushTarget();
+                                               SQInteger ttarget = _fs->PushTarget();
+                                               _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
+                                       }
+                                       else{
+                                               _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+                                       }
+                               }
+                               else
+                                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+                               _exst._deref = DEREF_NO_DEREF;
+                               Lex();
+                               FunctionCallArgs();
+                                }
+                               break;
+                       default: return;
+                       }
+               }
+       }
+       SQInteger Factor()
+       {
+               switch(_token)
+               {
+               case TK_STRING_LITERAL: {
+                               //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
+                               Lex();
+                       }
+                       break;
+               case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
+               case TK_VARGV: { Lex();
+                       Expect(_SC('['));
+                       Expression();
+                       Expect(_SC(']'));
+                       SQInteger src = _fs->PopTarget();
+                       _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);
+                                          }
+                       break;
+               case TK_IDENTIFIER:
+               case TK_CONSTRUCTOR:
+               case TK_THIS:{
+                       _exst._freevar = false;
+                       SQObject id;
+                               switch(_token) {
+                                       case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
+                                       case TK_THIS: id = _fs->CreateString(_SC("this")); break;
+                                       case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;
+                               }
+                               SQInteger pos = -1;
+                               Lex();
+                               if((pos = _fs->GetLocalVariable(id)) == -1) {
+                                       //checks if is a free variable
+                                       if((pos = _fs->GetOuterVariable(id)) != -1) {
+                                               _exst._deref = _fs->PushTarget();
+                                               _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
+                                               _exst._freevar = true;
+                                       } else {
+                                               _fs->PushTarget(0);
+                                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+                                               if(NeedGet()) Emit2ArgsOP(_OP_GET);
+                                               _exst._deref = DEREF_FIELD;
+                                       }
+                               }
+                               else{
+                                       _fs->PushTarget(pos);
+                                       _exst._deref = pos;
+                               }
+                               return _exst._deref;
+                       }
+                       break;
+               case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;
+               case TK_DOUBLE_COLON:  // "::"
+                       _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());
+                       _exst._deref = DEREF_FIELD;
+                       _token = _SC('.'); //hack
+                       return -1;
+                       break;
+               case TK_NULL:
+                       _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+                       Lex();
+                       break;
+               case TK_INTEGER: {
+                       if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?
+                               _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);
+                       }
+                       else {
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));
+                       }
+                       Lex();
+                                                }
+                       break;
+               case TK_FLOAT:
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+                       Lex();
+                       break;
+               case TK_TRUE: case TK_FALSE:
+                       _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
+                       Lex();
+                       break;
+               case _SC('['): {
+                               _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());
+                               SQInteger apos = _fs->GetCurrentPos(),key = 0;
+                               Lex();
+                               while(_token != _SC(']')) {
+                    Expression();
+                                       if(_token == _SC(',')) Lex();
+                                       SQInteger val = _fs->PopTarget();
+                                       SQInteger array = _fs->TopTarget();
+                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val);
+                                       key++;
+                               }
+                               _fs->SetIntructionParam(apos, 1, key);
+                               Lex();
+                       }
+                       break;
+               case _SC('{'):{
+                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
+                       Lex();ParseTableOrClass(_SC(','));
+                                }
+                       break;
+               case TK_FUNCTION: FunctionExp(_token);break;
+               case TK_CLASS: Lex(); ClassExp();break;
+               case _SC('-'): UnaryOP(_OP_NEG); break;
+               case _SC('!'): UnaryOP(_OP_NOT); break;
+               case _SC('~'): UnaryOP(_OP_BWNOT); break;
+               case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;
+               case TK_RESUME : UnaryOP(_OP_RESUME); break;
+               case TK_CLONE : UnaryOP(_OP_CLONE); break;
+               case TK_MINUSMINUS :
+               case TK_PLUSPLUS :PrefixIncDec(_token); break;
+               case TK_DELETE : DeleteExpr(); break;
+               case TK_DELEGATE : DelegateExpr(); break;
+               case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
+                       break;
+               default: Error(_SC("expression expected"));
+               }
+               return -1;
+       }
+       void UnaryOP(SQOpcode op)
+       {
+               Lex(); PrefixedExpr();
+               SQInteger src = _fs->PopTarget();
+               _fs->AddInstruction(op, _fs->PushTarget(), src);
+       }
+       bool NeedGet()
+       {
+               switch(_token) {
+               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:
+               case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:
+                       return false;
+               }
+               return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));
+       }
+
+       void FunctionCallArgs()
+       {
+               SQInteger nargs = 1;//this
+                while(_token != _SC(')')) {
+                        Expression(true);
+                        MoveIfCurrentTargetIsLocal();
+                        nargs++;
+                        if(_token == _SC(',')){
+                                Lex();
+                                if(_token == ')') Error(_SC("expression expected, found ')'"));
+                        }
+                }
+                Lex();
+                for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
+                SQInteger stackbase = _fs->PopTarget();
+                SQInteger closure = _fs->PopTarget();
+         _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
+       }
+       void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')
+       {
+               SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
+
+               while(_token != terminator) {
+                       bool hasattrs = false;
+                       bool isstatic = false;
+                       //check if is an attribute
+                       if(separator == ';') {
+                               if(_token == TK_ATTR_OPEN) {
+                                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();
+                                       ParseTableOrClass(',',TK_ATTR_CLOSE);
+                                       hasattrs = true;
+                               }
+                               if(_token == TK_STATIC) {
+                                       isstatic = true;
+                                       Lex();
+                               }
+                       }
+                       switch(_token) {
+                               case TK_FUNCTION:
+                               case TK_CONSTRUCTOR:{
+                                       SQInteger tk = _token;
+                                       Lex();
+                                       SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
+                                       Expect(_SC('('));
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+                                       CreateFunction(id);
+                                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+                                                                 }
+                                                                 break;
+                               case _SC('['):
+                                       Lex(); CommaExpr(); Expect(_SC(']'));
+                                       Expect(_SC('=')); Expression();
+                                       break;
+                               default :
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
+                                       Expect(_SC('=')); Expression();
+                       }
+
+                       if(_token == separator) Lex();//optional comma/semicolon
+                       nkeys++;
+                       SQInteger val = _fs->PopTarget();
+                       SQInteger key = _fs->PopTarget();
+                       SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
+                       assert(hasattrs && attrs == key-1 || !hasattrs);
+                       unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
+                       SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
+                       _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);
+                       //_fs->PopTarget();
+               }
+               if(separator == _SC(',')) //hack recognizes a table from the separator
+                       _fs->SetIntructionParam(tpos, 1, nkeys);
+               Lex();
+       }
+       void LocalDeclStatement()
+       {
+               SQObject varname;
+               do {
+                       Lex(); varname = Expect(TK_IDENTIFIER);
+                       if(_token == _SC('=')) {
+                               Lex(); Expression();
+                               SQInteger src = _fs->PopTarget();
+                               SQInteger dest = _fs->PushTarget();
+                               if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
+                       }
+                       else{
+                               _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+                       }
+                       _fs->PopTarget();
+                       _fs->PushLocalVariable(varname);
+
+               } while(_token == _SC(','));
+       }
+       void IfStatement()
+       {
+               SQInteger jmppos;
+               bool haselse = false;
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+               SQInteger jnepos = _fs->GetCurrentPos();
+               SQInteger stacksize = _fs->GetStackSize();
+
+               Statement();
+               //
+               if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
+
+               CleanStack(stacksize);
+               SQInteger endifblock = _fs->GetCurrentPos();
+               if(_token == TK_ELSE){
+                       haselse = true;
+                       stacksize = _fs->GetStackSize();
+                       _fs->AddInstruction(_OP_JMP);
+                       jmppos = _fs->GetCurrentPos();
+                       Lex();
+                       Statement(); OptionalSemicolon();
+                       CleanStack(stacksize);
+                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+               }
+               _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
+       }
+       void WhileStatement()
+       {
+               SQInteger jzpos, jmppos;
+               SQInteger stacksize = _fs->GetStackSize();
+               jmppos = _fs->GetCurrentPos();
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+
+               BEGIN_BREAKBLE_BLOCK();
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+               jzpos = _fs->GetCurrentPos();
+               stacksize = _fs->GetStackSize();
+
+               Statement();
+
+               CleanStack(stacksize);
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+               _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+
+               END_BREAKBLE_BLOCK(jmppos);
+       }
+       void DoWhileStatement()
+       {
+               Lex();
+               SQInteger jzpos = _fs->GetCurrentPos();
+               SQInteger stacksize = _fs->GetStackSize();
+               BEGIN_BREAKBLE_BLOCK()
+               Statement();
+               CleanStack(stacksize);
+               Expect(TK_WHILE);
+               SQInteger continuetrg = _fs->GetCurrentPos();
+               Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+               _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);
+               END_BREAKBLE_BLOCK(continuetrg);
+       }
+       void ForStatement()
+       {
+               Lex();
+               SQInteger stacksize = _fs->GetStackSize();
+               Expect(_SC('('));
+               if(_token == TK_LOCAL) LocalDeclStatement();
+               else if(_token != _SC(';')){
+                       CommaExpr();
+                       _fs->PopTarget();
+               }
+               Expect(_SC(';'));
+               _fs->SnoozeOpt();
+               SQInteger jmppos = _fs->GetCurrentPos();
+               SQInteger jzpos = -1;
+               if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
+               Expect(_SC(';'));
+               _fs->SnoozeOpt();
+               SQInteger expstart = _fs->GetCurrentPos() + 1;
+               if(_token != _SC(')')) {
+                       CommaExpr();
+                       _fs->PopTarget();
+               }
+               Expect(_SC(')'));
+               _fs->SnoozeOpt();
+               SQInteger expend = _fs->GetCurrentPos();
+               SQInteger expsize = (expend - expstart) + 1;
+               SQInstructionVec exp;
+               if(expsize > 0) {
+                       for(SQInteger i = 0; i < expsize; i++)
+                               exp.push_back(_fs->GetInstruction(expstart + i));
+                       _fs->PopInstructions(expsize);
+               }
+               BEGIN_BREAKBLE_BLOCK()
+               Statement();
+               SQInteger continuetrg = _fs->GetCurrentPos();
+               if(expsize > 0) {
+                       for(SQInteger i = 0; i < expsize; i++)
+                               _fs->AddInstruction(exp[i]);
+               }
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
+               if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+               CleanStack(stacksize);
+
+               END_BREAKBLE_BLOCK(continuetrg);
+       }
+       void ForEachStatement()
+       {
+               SQObject idxname, valname;
+               Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
+               if(_token == _SC(',')) {
+                       idxname = valname;
+                       Lex(); valname = Expect(TK_IDENTIFIER);
+               }
+               else{
+                       idxname = _fs->CreateString(_SC("@INDEX@"));
+               }
+               Expect(TK_IN);
+
+               //save the stack size
+               SQInteger stacksize = _fs->GetStackSize();
+               //put the table in the stack(evaluate the table expression)
+               Expression(); Expect(_SC(')'));
+               SQInteger container = _fs->TopTarget();
+               //push the index local var
+               SQInteger indexpos = _fs->PushLocalVariable(idxname);
+               _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
+               //push the value local var
+               SQInteger valuepos = _fs->PushLocalVariable(valname);
+               _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
+               //push reference index
+               SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
+               _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
+               SQInteger jmppos = _fs->GetCurrentPos();
+               _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
+               SQInteger foreachpos = _fs->GetCurrentPos();
+               //generate the statement code
+               BEGIN_BREAKBLE_BLOCK()
+               Statement();
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+               _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
+               //restore the local variable stack(remove index,val and ref idx)
+               CleanStack(stacksize);
+               END_BREAKBLE_BLOCK(foreachpos - 1);
+       }
+       void SwitchStatement()
+       {
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+               Expect(_SC('{'));
+               SQInteger expr = _fs->TopTarget();
+               bool bfirst = true;
+               SQInteger tonextcondjmp = -1;
+               SQInteger skipcondjmp = -1;
+               SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
+               _fs->_breaktargets.push_back(0);
+               while(_token == TK_CASE) {
+                       //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one
+                       if(!bfirst) {
+                               _fs->AddInstruction(_OP_JMP, 0, 0);
+                               skipcondjmp = _fs->GetCurrentPos();
+                               _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+                       }
+                       //condition
+                       Lex(); Expression(); Expect(_SC(':'));
+                       SQInteger trg = _fs->PopTarget();
+                       _fs->AddInstruction(_OP_EQ, trg, trg, expr);
+                       _fs->AddInstruction(_OP_JZ, trg, 0);
+                       //end condition
+                       if(skipcondjmp != -1) {
+                               _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
+                       }
+                       tonextcondjmp = _fs->GetCurrentPos();
+                       SQInteger stacksize = _fs->GetStackSize();
+                       Statements();
+                       _fs->SetStackSize(stacksize);
+                       bfirst = false;
+               }
+               if(tonextcondjmp != -1)
+                       _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+               if(_token == TK_DEFAULT) {
+               //      _fs->AddLineInfos(_lex._currentline, _lineinfo);
+                       Lex(); Expect(_SC(':'));
+                       SQInteger stacksize = _fs->GetStackSize();
+                       Statements();
+                       _fs->SetStackSize(stacksize);
+               }
+               Expect(_SC('}'));
+               _fs->PopTarget();
+               __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
+               if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
+               _fs->_breaktargets.pop_back();
+
+       }
+       void FunctionStatement()
+       {
+               SQObject id;
+               Lex(); id = Expect(TK_IDENTIFIER);
+               _fs->PushTarget(0);
+               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+               if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+
+               while(_token == TK_DOUBLE_COLON) {
+                       Lex();
+                       id = Expect(TK_IDENTIFIER);
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+                       if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+               }
+               Expect(_SC('('));
+               CreateFunction(id);
+               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+               EmitDerefOp(_OP_NEWSLOT);
+               _fs->PopTarget();
+       }
+       void ClassStatement()
+       {
+               ExpState es;
+               Lex(); PushExpState();
+               _exst._class_or_delete = true;
+               _exst._funcarg = false;
+               PrefixedExpr();
+               es = PopExpState();
+               if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));
+               if(es._deref == DEREF_FIELD) {
+                       ClassExp();
+                       EmitDerefOp(_OP_NEWSLOT);
+                       _fs->PopTarget();
+               }
+               else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
+       }
+       void TryCatchStatement()
+       {
+               SQObject exid;
+               Lex();
+               _fs->AddInstruction(_OP_PUSHTRAP,0,0);
+               _fs->_traps++;
+               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
+               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
+               SQInteger trappos = _fs->GetCurrentPos();
+               Statement();
+               _fs->_traps--;
+               _fs->AddInstruction(_OP_POPTRAP, 1, 0);
+               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
+               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
+               _fs->AddInstruction(_OP_JMP, 0, 0);
+               SQInteger jmppos = _fs->GetCurrentPos();
+               _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
+               Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
+               SQInteger stacksize = _fs->GetStackSize();
+               SQInteger ex_target = _fs->PushLocalVariable(exid);
+               _fs->SetIntructionParam(trappos, 0, ex_target);
+               Statement();
+               _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
+               CleanStack(stacksize);
+       }
+       void FunctionExp(SQInteger ftype)
+       {
+               Lex(); Expect(_SC('('));
+               CreateFunction(_null_);
+               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
+       }
+       void ClassExp()
+       {
+               SQInteger base = -1;
+               SQInteger attrs = -1;
+               if(_token == TK_EXTENDS) {
+                       Lex(); Expression();
+                       base = _fs->TopTarget();
+               }
+               if(_token == TK_ATTR_OPEN) {
+                       Lex();
+                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
+                       ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
+                       attrs = _fs->TopTarget();
+               }
+               Expect(_SC('{'));
+               if(attrs != -1) _fs->PopTarget();
+               if(base != -1) _fs->PopTarget();
+               _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);
+               ParseTableOrClass(_SC(';'));
+       }
+       void DelegateExpr()
+       {
+               Lex(); CommaExpr();
+               Expect(_SC(':'));
+               CommaExpr();
+               SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget();
+               _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);
+       }
+       void DeleteExpr()
+       {
+               ExpState es;
+               Lex(); PushExpState();
+               _exst._class_or_delete = true;
+               _exst._funcarg = false;
+               PrefixedExpr();
+               es = PopExpState();
+               if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));
+               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);
+               else Error(_SC("cannot delete a local"));
+       }
+       void PrefixIncDec(SQInteger token)
+       {
+               ExpState es;
+               Lex(); PushExpState();
+               _exst._class_or_delete = true;
+               _exst._funcarg = false;
+               PrefixedExpr();
+               es = PopExpState();
+               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);
+               else {
+                       SQInteger src = _fs->PopTarget();
+                       _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
+               }
+       }
+       void CreateFunction(SQObject &name)
+       {
+
+               SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
+               funcstate->_name = name;
+               SQObject paramname;
+               funcstate->AddParameter(_fs->CreateString(_SC("this")));
+               funcstate->_sourcename = _sourcename;
+               while(_token!=_SC(')')) {
+                       if(_token == TK_VARPARAMS) {
+                               funcstate->_varparams = true;
+                               Lex();
+                               if(_token != _SC(')')) Error(_SC("expected ')'"));
+                               break;
+                       }
+                       else {
+                               paramname = Expect(TK_IDENTIFIER);
+                               funcstate->AddParameter(paramname);
+                               if(_token == _SC(',')) Lex();
+                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
+                       }
+               }
+               Expect(_SC(')'));
+               //outer values
+               if(_token == _SC(':')) {
+                       Lex(); Expect(_SC('('));
+                       while(_token != _SC(')')) {
+                               paramname = Expect(TK_IDENTIFIER);
+                               //outers are treated as implicit local variables
+                               funcstate->AddOuterValue(paramname);
+                               if(_token == _SC(',')) Lex();
+                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
+                       }
+                       Lex();
+               }
+
+               SQFuncState *currchunk = _fs;
+               _fs = funcstate;
+               Statement();
+               funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
+        funcstate->AddInstruction(_OP_RETURN, -1);
+               funcstate->SetStackSize(0);
+               //_fs->->_stacksize = _fs->_stacksize;
+               SQFunctionProto *func = funcstate->BuildProto();
+#ifdef _DEBUG_DUMP
+               funcstate->Dump(func);
+#endif
+               _fs = currchunk;
+               _fs->_functions.push_back(func);
+               _fs->PopChildState();
+       }
+       void CleanStack(SQInteger stacksize)
+       {
+               if(_fs->GetStackSize() != stacksize)
+                       _fs->SetStackSize(stacksize);
+       }
+       void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
+       {
+               while(ntoresolve > 0) {
+                       SQInteger pos = funcstate->_unresolvedbreaks.back();
+                       funcstate->_unresolvedbreaks.pop_back();
+                       //set the jmp instruction
+                       funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
+                       ntoresolve--;
+               }
+       }
+       void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
+       {
+               while(ntoresolve > 0) {
+                       SQInteger pos = funcstate->_unresolvedcontinues.back();
+                       funcstate->_unresolvedcontinues.pop_back();
+                       //set the jmp instruction
+                       funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
+                       ntoresolve--;
+               }
+       }
+private:
+       SQInteger _token;
+       SQFuncState *_fs;
+       SQObjectPtr _sourcename;
+       SQLexer _lex;
+       bool _lineinfo;
+       bool _raiseerror;
+       SQInteger _debugline;
+       SQInteger _debugop;
+       ExpStateVec _expstates;
+       SQChar *compilererror;
+       jmp_buf _errorjmp;
+       SQVM *_vm;
+};
+
+bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
+{
+       SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
+       return p.Compile(out);
+}