Update to SQUIRREL 3.0.4
[supertux.git] / external / squirrel / squirrel / sqcompiler.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 461c2bc..a8dbee6
@@ -2,6 +2,7 @@
        see copyright notice in squirrel.h\r
 */\r
 #include "sqpcheader.h"\r
+#ifndef NO_COMPILER\r
 #include <stdarg.h>\r
 #include <setjmp.h>\r
 #include "sqopcodes.h"\r
 #include "sqvm.h"\r
 #include "sqtable.h"\r
 \r
-#define DEREF_NO_DEREF -1\r
-#define DEREF_FIELD            -2\r
+#define EXPR   1\r
+#define OBJECT 2\r
+#define BASE   3\r
+#define LOCAL  4\r
+#define OUTER  5\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
+struct SQExpState {\r
+  SQInteger  etype;       /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */\r
+  SQInteger  epos;        /* expr. location on stack; -1 for OBJECT and BASE */\r
+  bool       donot_get;   /* signal not to deref the next value */\r
+};\r
+\r
+struct SQScope {\r
+       SQInteger outers;\r
+       SQInteger stacksize;\r
 };\r
 \r
-typedef sqvector<ExpState> ExpStateVec;\r
+#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \\r
+                                        _scope.outers = _fs->_outers; \\r
+                                        _scope.stacksize = _fs->GetStackSize();\r
+\r
+#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       if(_fs->CountOuters(_scope.stacksize)) { \\r
+                                                               _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \\r
+                                                       } \\r
+                                               }\r
 \r
-#define _exst (_expstates.top())\r
+#define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       _fs->SetStackSize(_scope.stacksize); \\r
+                                               } \\r
+                                               _scope = __oldscope__; \\r
+                                       }\r
+\r
+#define END_SCOPE() {  SQInteger oldouters = _fs->_outers;\\r
+                                               if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       _fs->SetStackSize(_scope.stacksize); \\r
+                                                       if(oldouters != _fs->_outers) { \\r
+                                                               _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \\r
+                                                       } \\r
+                                               } \\r
+                                               _scope = __oldscope__; \\r
+                                       }\r
 \r
 #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
                                                        SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \\r
@@ -54,6 +76,8 @@ public:
                _lex.Init(_ss(v), rg, up,ThrowError,this);\r
                _sourcename = SQString::Create(_ss(v), sourcename);\r
                _lineinfo = lineinfo;_raiseerror = raiseerror;\r
+               _scope.outers = 0;\r
+               _scope.stacksize = 0;\r
                compilererror = NULL;\r
        }\r
        static void ThrowError(void *ud, const SQChar *s) {\r
@@ -71,27 +95,11 @@ public:
                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
@@ -162,15 +170,17 @@ public:
                funcstate._name = SQString::Create(_ss(_vm), _SC("main"));\r
                _fs = &funcstate;\r
                _fs->AddParameter(_fs->CreateString(_SC("this")));\r
+               _fs->AddParameter(_fs->CreateString(_SC("vargv")));\r
+               _fs->_varparams = true;\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
+                               if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
                        }\r
-                       CleanStack(stacksize);\r
+                       _fs->SetStackSize(stacksize);\r
                        _fs->AddLineInfos(_lex._currentline, _lineinfo, true);\r
                        _fs->AddInstruction(_OP_RETURN, 0xFF);\r
                        _fs->SetStackSize(0);\r
@@ -196,7 +206,7 @@ public:
                        if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
                }\r
        }\r
-       void Statement()\r
+       void Statement(bool closeframe = true)\r
        {\r
                _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
                switch(_token){\r
@@ -213,7 +223,6 @@ public:
                        SQOpcode op;\r
                        if(_token == TK_RETURN) {\r
                                op = _OP_RETURN;\r
-                               \r
                        }\r
                        else {\r
                                op = _OP_YIELD;\r
@@ -226,13 +235,13 @@ public:
                                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
+                               _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());\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
+                               _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); \r
                        }\r
                        break;}\r
                case TK_BREAK:\r
@@ -240,6 +249,7 @@ public:
                        if(_fs->_breaktargets.top() > 0){\r
                                _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);\r
                        }\r
+                       RESOLVE_OUTERS();\r
                        _fs->AddInstruction(_OP_JMP, 0, -1234);\r
                        _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());\r
                        Lex();\r
@@ -249,6 +259,7 @@ public:
                        if(_fs->_continuetargets.top() > 0) {\r
                                _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);\r
                        }\r
+                       RESOLVE_OUTERS();\r
                        _fs->AddInstruction(_OP_JMP, 0, -1234);\r
                        _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());\r
                        Lex();\r
@@ -263,11 +274,16 @@ public:
                        EnumStatement();\r
                        break;\r
                case _SC('{'):{\r
-                               SQInteger stacksize = _fs->GetStackSize();\r
+                               BEGIN_SCOPE();\r
                                Lex();\r
                                Statements();\r
                                Expect(_SC('}'));\r
-                               _fs->SetStackSize(stacksize);\r
+                               if(closeframe) {\r
+                                       END_SCOPE();\r
+                               }\r
+                               else {\r
+                                       END_SCOPE_NO_CLOSE();\r
+                               }\r
                        }\r
                        break;\r
                case TK_TRY:\r
@@ -293,7 +309,8 @@ public:
                        break;\r
                default:\r
                        CommaExpr();\r
-                       _fs->PopTarget();\r
+                       _fs->DiscardTarget();\r
+                       //_fs->PopTarget();\r
                        break;\r
                }\r
                _fs->SnoozeOpt();\r
@@ -311,38 +328,49 @@ public:
                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
+       void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)\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
+               /* Generate code depending on the expression type */\r
+               switch(etype) {\r
+               case LOCAL:{\r
+                       SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
+                       SQInteger p1 = _fs->PopTarget(); //key in OP_GET\r
+                       _fs->PushTarget(p1);\r
+                       //EmitCompArithLocal(tok, p1, p1, p2);\r
+                       _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);\r
+                                  }\r
+                       break;\r
+               case OBJECT:\r
+               case BASE:\r
+                       {\r
+                               SQInteger val = _fs->PopTarget();\r
+                               SQInteger key = _fs->PopTarget();\r
+                               SQInteger src = _fs->PopTarget();\r
+                               /* _OP_COMPARITH mixes dest obj and source val in the arg1 */\r
+                               _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));\r
+                       }\r
+                       break;\r
+               case OUTER:\r
+                       {\r
+                               SQInteger val = _fs->TopTarget();\r
+                               SQInteger tmp = _fs->PushTarget();\r
+                               _fs->AddInstruction(_OP_GETOUTER,   tmp, pos);\r
+                               _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);\r
+                               _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp);\r
+                       }\r
+                       break;\r
                }\r
        }\r
        void CommaExpr()\r
        {\r
                for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());\r
        }\r
-       ExpState Expression(bool funcarg = false)\r
+       void Expression()\r
        {\r
-               PushExpState();\r
-               _exst._class_or_delete = false;\r
-               _exst._funcarg = funcarg;\r
+                SQExpState es = _es;\r
+               _es.etype     = EXPR;\r
+               _es.epos      = -1;\r
+               _es.donot_get = false;\r
                LogicalOrExp();\r
                switch(_token)  {\r
                case _SC('='):\r
@@ -351,40 +379,49 @@ public:
                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
+               case TK_MODEQ:{\r
+                       SQInteger op = _token;\r
+                       SQInteger ds = _es.etype;\r
+                       SQInteger pos = _es.epos;\r
+                       if(ds == EXPR) 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
+                       switch(op){\r
+                       case TK_NEWSLOT:\r
+                               if(ds == OBJECT || ds == BASE)\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
+                               switch(ds) {\r
+                               case LOCAL:\r
+                                       {\r
+                                               SQInteger src = _fs->PopTarget();\r
+                                               SQInteger dst = _fs->TopTarget();\r
+                                               _fs->AddInstruction(_OP_MOVE, dst, src);\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
+                               case OBJECT:\r
+                               case BASE:\r
+                                       EmitDerefOp(_OP_SET);\r
                                        break;\r
+                               case OUTER:\r
+                                       {\r
+                                               SQInteger src = _fs->PopTarget();\r
+                                               SQInteger dst = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);\r
+                                       }\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, pos);\r
+                               break;\r
+                       }\r
                        }\r
                        break;\r
                case _SC('?'): {\r
@@ -408,9 +445,9 @@ public:
                        }\r
                        break;\r
                }\r
-               return PopExpState();\r
+               _es = es;\r
        }\r
-       void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0)\r
+       template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)\r
        {\r
                Lex(); (this->*f)();\r
                SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();\r
@@ -474,21 +511,29 @@ public:
        }\r
        void BitwiseAndExp()\r
        {\r
-               CompExp();\r
+               EqExp();\r
                for(;;) if(_token == _SC('&'))\r
-               {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);\r
+               {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);\r
                }else return;\r
        }\r
+       void EqExp()\r
+       {\r
+               CompExp();\r
+               for(;;) switch(_token) {\r
+               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;\r
+               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;\r
+               case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;\r
+               default: return;        \r
+               }\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
@@ -502,12 +547,38 @@ public:
                default: return;        \r
                }\r
        }\r
+       SQOpcode ChooseArithOpByToken(SQInteger tok)\r
+       {\r
+               switch(tok) {\r
+                       case TK_PLUSEQ: case '+': return _OP_ADD;\r
+                       case TK_MINUSEQ: case '-': return _OP_SUB;\r
+                       case TK_MULEQ: case '*': return _OP_MUL;\r
+                       case TK_DIVEQ: case '/': return _OP_DIV;\r
+                       case TK_MODEQ: case '%': return _OP_MOD;\r
+                       default: assert(0);\r
+               }\r
+               return _OP_ADD;\r
+       }\r
+       SQInteger ChooseCompArithCharByToken(SQInteger tok)\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
+               return oper;\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
+                       BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;\r
                default: return;\r
                }\r
        }\r
@@ -517,7 +588,7 @@ public:
                PrefixedExpr();\r
                for(;;) switch(_token) {\r
                case _SC('*'): case _SC('/'): case _SC('%'):\r
-                       BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;\r
+                       BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;\r
                default: return;\r
                }\r
        }\r
@@ -525,69 +596,97 @@ public:
        void PrefixedExpr()\r
        {\r
                SQInteger pos = Factor();\r
-               \r
                for(;;) {\r
                        switch(_token) {\r
-                       case _SC('.'): {\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
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
+                               if(_es.etype==BASE) {\r
+                                       Emit2ArgsOP(_OP_GET);\r
+                                       pos = _fs->TopTarget();\r
+                                       _es.etype = EXPR;\r
+                                       _es.epos   = pos;\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
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\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
+                               if(_es.etype==BASE) {\r
+                                       Emit2ArgsOP(_OP_GET);\r
+                                       pos = _fs->TopTarget();\r
+                                       _es.etype = EXPR;\r
+                                       _es.epos   = pos;\r
+                               }\r
+                               else {\r
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\r
+                               }\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
+                                       if(IsEndOfStatement()) return;\r
+                                       SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;\r
+                                       Lex();\r
+                                       switch(_es.etype)\r
+                                       {\r
+                                               case EXPR: Error(_SC("can't '++' or '--' an expression")); break;\r
+                                               case OBJECT:\r
+                                               case BASE:\r
+                                                       Emit2ArgsOP(_OP_PINC, diff);\r
+                                                       break;\r
+                                               case LOCAL: {\r
+                                                       SQInteger src = _fs->PopTarget();\r
+                                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);\r
+                                                                       }\r
+                                                       break;\r
+                                               case OUTER: {\r
+                                                       SQInteger tmp1 = _fs->PushTarget();\r
+                                                       SQInteger tmp2 = _fs->PushTarget();\r
+                                                       _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);\r
+                                                       _fs->AddInstruction(_OP_PINCL,    tmp1, tmp2, 0, diff);\r
+                                                       _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);\r
+                                                       _fs->PopTarget();\r
+                                               }\r
+                                       }\r
                                }\r
-                               \r
-                       }\r
-                       return;\r
-                       break;  \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
+                               switch(_es.etype) {\r
+                                       case OBJECT: {\r
+                                               SQInteger key     = _fs->PopTarget();  /* location of the key */\r
+                                               SQInteger table   = _fs->PopTarget();  /* location of the object */\r
+                                               SQInteger closure = _fs->PushTarget(); /* location for the closure */\r
+                                               SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */\r
                                                _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);\r
-                                       }\r
-                                       else{\r
+                                               }\r
+                                               break;\r
+                                       case BASE:\r
+                                               //Emit2ArgsOP(_OP_GET);\r
+                                               _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
+                                               break;\r
+                                       case OUTER:\r
+                                               _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);\r
+                                               _fs->AddInstruction(_OP_MOVE,     _fs->PushTarget(), 0);\r
+                                               break;\r
+                                       default:\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
+                               _es.etype = EXPR;\r
                                Lex();\r
                                FunctionCallArgs();\r
-                                }\r
                                break;\r
                        default: return;\r
                        }\r
@@ -595,123 +694,116 @@ public:
        }\r
        SQInteger Factor()\r
        {\r
-               _exst._deref = DEREF_NO_DEREF;\r
+               _es.etype = EXPR;\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
+               case TK_STRING_LITERAL:\r
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));\r
+                       Lex(); \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
+               case TK_BASE:\r
+                       Lex();\r
+                       _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());\r
+                       _es.etype  = BASE;\r
+                       _es.epos   = _fs->TopTarget();\r
+                       return (_es.epos);\r
                        break;\r
                case TK_IDENTIFIER:\r
                case TK_CONSTRUCTOR:\r
                case TK_THIS:{\r
-                       _exst._freevar = false;\r
-                       SQObject id;\r
-                       SQObject constant;\r
+                               SQObject id;\r
+                               SQObject constant;\r
+\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_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
+\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
+                               if((pos = _fs->GetLocalVariable(id)) != -1) {\r
+                                       /* Handle a local variable (includes 'this') */\r
+                                       _fs->PushTarget(pos);\r
+                                       _es.etype  = LOCAL;\r
+                                       _es.epos   = pos;\r
+                               }\r
+\r
+                               else if((pos = _fs->GetOuterVariable(id)) != -1) {\r
+                                       /* Handle a free var */\r
+                                       if(NeedGet()) {\r
+                                               _es.epos  = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);       \r
+                                               /* _es.etype = EXPR; already default value */\r
                                        }\r
-                                       else if(_fs->IsConstant(id,constant)) { //line 634\r
-                                               SQObjectPtr constval;\r
-                                               SQObject constid;\r
-                                               if(type(constant) == OT_TABLE) {\r
-                                                       Expect('.'); constid = Expect(TK_IDENTIFIER);\r
-                                                       if(!_table(constant)->Get(constid,constval)) {\r
-                                                               constval.Null();\r
-                                                               Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid));\r
-                                                       }\r
-                                               }\r
-                                               else {\r
-                                                       constval = constant;\r
-                                               }\r
-                                               _exst._deref = _fs->PushTarget();\r
-                                               SQObjectType ctype = type(constval);\r
-                                               if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {\r
-                                                       _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));\r
-                                               }\r
-                                               else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {\r
-                                                       SQFloat f = _float(constval);\r
-                                                       _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));\r
-                                               }\r
-                                               else {\r
-                                                       _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));\r
-                                               }\r
+                                       else {\r
+                                               _es.etype = OUTER;\r
+                                               _es.epos  = pos;\r
+                                       }\r
+                               }\r
 \r
-                                               _exst._freevar = true;\r
+                               else if(_fs->IsConstant(id, constant)) {\r
+                                       /* Handle named constant */\r
+                                       SQObjectPtr constval;\r
+                                       SQObject    constid;\r
+                                       if(type(constant) == OT_TABLE) {\r
+                                               Expect('.');\r
+                                               constid = Expect(TK_IDENTIFIER);\r
+                                               if(!_table(constant)->Get(constid, constval)) {\r
+                                                       constval.Null();\r
+                                                       Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));\r
+                                               }\r
                                        }\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
+                                               constval = constant;\r
+                                       }\r
+                                       _es.epos = _fs->PushTarget();\r
+\r
+                                       /* generate direct or literal function depending on size */\r
+                                       SQObjectType ctype = type(constval);\r
+                                       switch(ctype) {\r
+                                               case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;\r
+                                               case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;\r
+                                               default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;\r
                                        }\r
+                                       _es.etype = EXPR;\r
                                }\r
-                               \r
-                               else{\r
-                                       _fs->PushTarget(pos);\r
-                                       _exst._deref = pos;\r
+                               else {\r
+                                       /* Handle a non-local variable, aka a field. Push the 'this' pointer on\r
+                                       * the virtual stack (always found in offset 0, so no instruction needs to\r
+                                       * be generated), and push the key next. Generate an _OP_LOAD instruction\r
+                                       * for the latter. If we are not using the variable as a dref expr, generate\r
+                                       * the _OP_GET instruction.\r
+                                       */\r
+                                       _fs->PushTarget(0);\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\r
                                }\r
-                               return _exst._deref;\r
+                               return _es.epos;\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
+                       _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());\r
+                       _es.etype = OBJECT;\r
+                       _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/\r
+                       _es.epos = -1;\r
+                       return _es.epos;\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
-                       if(sizeof(SQFloat) == sizeof(SQInt32)) {\r
-                               _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));\r
-                       }\r
-                       else {\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
-                       }\r
-                       Lex();\r
-                       break;\r
+               case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex();      break;\r
+               case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); 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
+                               _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);\r
                                SQInteger apos = _fs->GetCurrentPos(),key = 0;\r
                                Lex();\r
                                while(_token != _SC(']')) {\r
@@ -719,57 +811,90 @@ public:
                                        if(_token == _SC(',')) Lex();\r
                                        SQInteger val = _fs->PopTarget();\r
                                        SQInteger array = _fs->TopTarget();\r
-                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val);\r
+                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);\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
+               case _SC('{'):\r
+                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);\r
+                       Lex();ParseTableOrClass(_SC(','),_SC('}'));\r
                        break;\r
                case TK_FUNCTION: FunctionExp(_token);break;\r
+               case _SC('@'): FunctionExp(_token,true);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 _SC('-'): \r
+                       Lex(); \r
+                       switch(_token) {\r
+                       case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;\r
+                       case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;\r
+                       default: UnaryOP(_OP_NEG);\r
+                       }\r
+                       break;\r
+               case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;\r
+               case _SC('~'): \r
+                       Lex(); \r
+                       if(_token == TK_INTEGER)  { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }\r
+                       UnaryOP(_OP_BWNOT); \r
+                       break;\r
+               case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;\r
+               case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;\r
+               case TK_CLONE : Lex(); 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 EmitLoadConstInt(SQInteger value,SQInteger target)\r
+       {\r
+               if(target < 0) {\r
+                       target = _fs->PushTarget();\r
+               }\r
+               if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?\r
+                       _fs->AddInstruction(_OP_LOADINT, target,value);\r
+               }\r
+               else {\r
+                       _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));\r
+               }\r
+       }\r
+       void EmitLoadConstFloat(SQFloat value,SQInteger target)\r
+       {\r
+               if(target < 0) {\r
+                       target = _fs->PushTarget();\r
+               }\r
+               if(sizeof(SQFloat) == sizeof(SQInt32)) {\r
+                       _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));\r
+               }\r
+               else {\r
+                       _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));\r
+               }\r
+       }\r
        void UnaryOP(SQOpcode op)\r
        {\r
-               Lex(); PrefixedExpr();\r
+               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
+               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:\r
+           case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
                        return false;\r
                }\r
-               return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));\r
+               return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));\r
        }\r
-       \r
        void FunctionCallArgs()\r
        {\r
                SQInteger nargs = 1;//this\r
                 while(_token != _SC(')')) {\r
-                        Expression(true);\r
+                        Expression();\r
                         MoveIfCurrentTargetIsLocal();\r
                         nargs++; \r
                         if(_token == _SC(',')){ \r
@@ -783,17 +908,16 @@ public:
                 SQInteger closure = _fs->PopTarget();\r
          _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
        }\r
-       void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')\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
+                                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();\r
                                        ParseTableOrClass(',',TK_ATTR_CLOSE);\r
                                        hasattrs = true;\r
                                }\r
@@ -803,36 +927,45 @@ public:
                                }\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
+                       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
+                       case TK_STRING_LITERAL: //JSON\r
+                               if(separator == ',') { //only works for tables\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));\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
+                       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
+                       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
+                       if(separator == _SC(',')) { //hack recognizes a table from the separator\r
+                               _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);\r
+                       }\r
+                       else {\r
+                               _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember\r
+                       }\r
                }\r
                if(separator == _SC(',')) //hack recognizes a table from the separator\r
                        _fs->SetIntructionParam(tpos, 1, nkeys);\r
@@ -841,8 +974,20 @@ public:
        void LocalDeclStatement()\r
        {\r
                SQObject varname;\r
+               Lex();\r
+               if( _token == TK_FUNCTION) {\r
+                       Lex();\r
+                       varname = Expect(TK_IDENTIFIER);\r
+                       Expect(_SC('('));\r
+                       CreateFunction(varname,false);\r
+                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
+                       _fs->PopTarget();\r
+                       _fs->PushLocalVariable(varname);\r
+                       return;\r
+               }\r
+\r
                do {\r
-                       Lex(); varname = Expect(TK_IDENTIFIER);\r
+                       varname = Expect(TK_IDENTIFIER);\r
                        if(_token == _SC('=')) {\r
                                Lex(); Expression();\r
                                SQInteger src = _fs->PopTarget();\r
@@ -854,8 +999,8 @@ public:
                        }\r
                        _fs->PopTarget();\r
                        _fs->PushLocalVariable(varname);\r
-               \r
-               } while(_token == _SC(','));\r
+                       if(_token == _SC(',')) Lex(); else break;\r
+               } while(1);\r
        }\r
        void IfStatement()\r
        {\r
@@ -864,22 +1009,22 @@ public:
                Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
                _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
                SQInteger jnepos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                \r
                Statement();\r
                //\r
                if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
                \r
-               CleanStack(stacksize);\r
+               END_SCOPE();\r
                SQInteger endifblock = _fs->GetCurrentPos();\r
                if(_token == TK_ELSE){\r
                        haselse = true;\r
-                       stacksize = _fs->GetStackSize();\r
+                       BEGIN_SCOPE();\r
                        _fs->AddInstruction(_OP_JMP);\r
                        jmppos = _fs->GetCurrentPos();\r
                        Lex();\r
                        Statement(); OptionalSemicolon();\r
-                       CleanStack(stacksize);\r
+                       END_SCOPE();\r
                        _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
                }\r
                _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
@@ -887,18 +1032,17 @@ public:
        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
+               BEGIN_SCOPE();\r
                \r
                Statement();\r
                \r
-               CleanStack(stacksize);\r
+               END_SCOPE();\r
                _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
                _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
                \r
@@ -907,21 +1051,22 @@ public:
        void DoWhileStatement()\r
        {\r
                Lex();\r
-               SQInteger jzpos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               SQInteger jmptrg = _fs->GetCurrentPos();\r
                BEGIN_BREAKBLE_BLOCK()\r
+               BEGIN_SCOPE();\r
                Statement();\r
-               CleanStack(stacksize);\r
+               END_SCOPE();\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
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);\r
+               _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);\r
                END_BREAKBLE_BLOCK(continuetrg);\r
        }\r
        void ForStatement()\r
        {\r
                Lex();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                Expect(_SC('('));\r
                if(_token == TK_LOCAL) LocalDeclStatement();\r
                else if(_token != _SC(';')){\r
@@ -959,7 +1104,7 @@ public:
                }\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
+               END_SCOPE();\r
                \r
                END_BREAKBLE_BLOCK(continuetrg);\r
        }\r
@@ -977,7 +1122,7 @@ public:
                Expect(TK_IN);\r
                \r
                //save the stack size\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                //put the table in the stack(evaluate the table expression)\r
                Expression(); Expect(_SC(')'));\r
                SQInteger container = _fs->TopTarget();\r
@@ -1000,9 +1145,10 @@ public:
                _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
                _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);\r
                _fs->SetIntructionParam(foreachpos + 1, 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
+               //restore the local variable stack(remove index,val and ref idx)\r
+               _fs->PopTarget();\r
+               END_SCOPE();\r
        }\r
        void SwitchStatement()\r
        {\r
@@ -1015,7 +1161,6 @@ public:
                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
@@ -1031,26 +1176,24 @@ public:
                                _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));\r
                        }\r
                        tonextcondjmp = _fs->GetCurrentPos();\r
-                       SQInteger stacksize = _fs->GetStackSize();\r
+                       BEGIN_SCOPE();\r
                        Statements();\r
-                       _fs->SetStackSize(stacksize);\r
+                       END_SCOPE();\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
+                       BEGIN_SCOPE();\r
                        Statements();\r
-                       _fs->SetStackSize(stacksize);\r
+                       END_SCOPE();\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
@@ -1074,23 +1217,28 @@ public:
        }\r
        void ClassStatement()\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState es;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\r
                PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));\r
-               if(es._deref == DEREF_FIELD) {\r
+               if(_es.etype == EXPR) {\r
+                       Error(_SC("invalid class name"));\r
+               }\r
+               else if(_es.etype == OBJECT || _es.etype == BASE) {\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
+               else {\r
+                       Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
+               }\r
+               _es = es;\r
        }\r
        SQObject ExpectScalar()\r
        {\r
                SQObject val;\r
+               val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x\r
                switch(_token) {\r
                        case TK_INTEGER:\r
                                val._type = OT_INTEGER;\r
@@ -1120,14 +1268,13 @@ public:
                                }\r
                                break;\r
                        default:\r
-                       Error(_SC("scalar expected : integer,float or string"));\r
+                               Error(_SC("scalar expected : integer,float or string"));\r
                }\r
                Lex();\r
                return val;\r
        }\r
        void EnumStatement()\r
        {\r
-               \r
                Lex(); \r
                SQObject id = Expect(TK_IDENTIFIER);\r
                Expect(_SC('{'));\r
@@ -1150,15 +1297,9 @@ public:
                }\r
                SQTable *enums = _table(_ss(_vm)->_consts);\r
                SQObjectPtr strongid = id; \r
-               /*SQObjectPtr dummy;\r
-               if(enums->Get(strongid,dummy)) {\r
-                       dummy.Null(); strongid.Null();\r
-                       Error(_SC("enumeration already exists"));\r
-               }*/\r
                enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));\r
                strongid.Null();\r
                Lex();\r
-               \r
        }\r
        void TryCatchStatement()\r
        {\r
@@ -1169,7 +1310,11 @@ public:
                if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;\r
                if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;\r
                SQInteger trappos = _fs->GetCurrentPos();\r
-               Statement();\r
+               {\r
+                       BEGIN_SCOPE();\r
+                       Statement();\r
+                       END_SCOPE();\r
+               }\r
                _fs->_traps--;\r
                _fs->AddInstruction(_OP_POPTRAP, 1, 0);\r
                if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;\r
@@ -1178,17 +1323,20 @@ public:
                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
+                       BEGIN_SCOPE();\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
+                       END_SCOPE();\r
+               }\r
        }\r
-       void FunctionExp(SQInteger ftype)\r
+       void FunctionExp(SQInteger ftype,bool lambda = false)\r
        {\r
                Lex(); Expect(_SC('('));\r
-               CreateFunction(_null_);\r
+               SQObjectPtr dummy;\r
+               CreateFunction(dummy,lambda);\r
                _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);\r
        }\r
        void ClassExp()\r
@@ -1201,53 +1349,61 @@ public:
                }\r
                if(_token == TK_ATTR_OPEN) {\r
                        Lex();\r
-                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
+                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);\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
+               _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);\r
+               ParseTableOrClass(_SC(';'),_SC('}'));\r
        }\r
        void DeleteExpr()\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState es;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\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
+               if(_es.etype==EXPR) Error(_SC("can't delete an expression"));\r
+               if(_es.etype==OBJECT || _es.etype==BASE) {\r
+                       Emit2ArgsOP(_OP_DELETE);\r
+               }\r
+               else {\r
+                       Error(_SC("cannot delete an (outer) local"));\r
+               }\r
+               _es = es;\r
        }\r
        void PrefixIncDec(SQInteger token)\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState  es;\r
+               SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\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
+               if(_es.etype==EXPR) {\r
+                       Error(_SC("can't '++' or '--' an expression"));\r
+               }\r
+               else if(_es.etype==OBJECT || _es.etype==BASE) {\r
+                       Emit2ArgsOP(_OP_INC, diff);\r
+               }\r
+               else if(_es.etype==LOCAL) {\r
+                       SQInteger src = _fs->TopTarget();\r
+                       _fs->AddInstruction(_OP_INCL, src, src, 0, diff);\r
+                       \r
+               }\r
+               else if(_es.etype==OUTER) {\r
+                       SQInteger tmp = _fs->PushTarget();\r
+                       _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);\r
+                       _fs->AddInstruction(_OP_INCL,     tmp, tmp, 0, diff);\r
+                       _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);\r
                }\r
+               _es = es;\r
        }\r
-       void CreateFunction(SQObject &name)\r
+       void CreateFunction(SQObject &name,bool lambda = false)\r
        {\r
-               \r
                SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));\r
                funcstate->_name = name;\r
                SQObject paramname;\r
@@ -1257,6 +1413,7 @@ public:
                while(_token!=_SC(')')) {\r
                        if(_token == TK_VARPARAMS) {\r
                                if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));\r
+                               funcstate->AddParameter(_fs->CreateString(_SC("vargv")));\r
                                funcstate->_varparams = true;\r
                                Lex();\r
                                if(_token != _SC(')')) Error(_SC("expected ')'"));\r
@@ -1282,26 +1439,19 @@ public:
                for(SQInteger n = 0; n < defparams; n++) {\r
                        _fs->PopTarget();\r
                }\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
+                               \r
                SQFuncState *currchunk = _fs;\r
                _fs = funcstate;\r
-               Statement();\r
+               if(lambda) { \r
+                       Expression(); \r
+                       _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}\r
+               else { \r
+                       Statement(false); \r
+               }\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
+\r
                SQFunctionProto *func = funcstate->BuildProto();\r
 #ifdef _DEBUG_DUMP\r
                funcstate->Dump(func);\r
@@ -1310,11 +1460,6 @@ public:
                _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
@@ -1344,7 +1489,8 @@ private:
        bool _raiseerror;\r
        SQInteger _debugline;\r
        SQInteger _debugop;\r
-       ExpStateVec _expstates;\r
+       SQExpState   _es;\r
+       SQScope _scope;\r
        SQChar *compilererror;\r
        jmp_buf _errorjmp;\r
        SQVM *_vm;\r
@@ -1355,3 +1501,5 @@ bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcena
        SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);\r
        return p.Compile(out);\r
 }\r
+\r
+#endif\r