4 #include "sqpcheader.h"     9 #include "sqfuncproto.h"    10 #include "sqcompiler.h"    11 #include "sqfuncstate.h"    16 #define DEREF_NO_DEREF  -1    17 #define DEREF_FIELD     -2    36 #define _exst (_expstates.top())    38 #define BEGIN_BREAKBLE_BLOCK()  SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \    39                             SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \    40                             _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);    42 #define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \    43                     __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \    44                     if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \    45                     if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \    46                     _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}    51     SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, 
const SQChar* sourcename, 
bool raiseerror, 
bool lineinfo)
    54         _lex.Init(_ss(v), rg, up,ThrowError,
this);
    55         _sourcename = SQString::Create(_ss(v), sourcename);
    56         _lineinfo = lineinfo;_raiseerror = raiseerror;
    68         scvsprintf(temp, s, vl);
    73     void Lex(){ _token = _lex.Lex();}
    78         case _SC(
'='): 
case _SC(
'('): 
case TK_NEWSLOT:
    79         case TK_MODEQ: 
case TK_MULEQ: 
case TK_DIVEQ: 
case TK_MINUSEQ: 
case TK_PLUSEQ: 
case TK_PLUSPLUS: 
case TK_MINUSMINUS: 
return true;
    86         _expstates.pop_back();
    93             if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
   103                         etypename = _SC(
"IDENTIFIER");
   105                     case TK_STRING_LITERAL:
   106                         etypename = _SC(
"STRING_LITERAL");
   109                         etypename = _SC(
"INTEGER");
   112                         etypename = _SC(
"FLOAT");
   115                         etypename = _lex.Tok2Str(tok);
   117                     Error(_SC(
"expected '%s'"), etypename);
   119                 Error(_SC(
"expected '%c'"), tok);
   126             ret = _fs->CreateString(_lex._svalue);
   128         case TK_STRING_LITERAL:
   129             ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
   132             ret = SQObjectPtr(_lex._nvalue);
   135             ret = SQObjectPtr(_lex._fvalue);
   141     bool IsEndOfStatement() { 
return ((_lex._prevtoken == _SC(
'\n')) || (_token == SQUIRREL_EOB) || (_token == _SC(
'}')) || (_token == _SC(
';'))); }
   144         if(_token == _SC(
';')) { Lex(); 
return; }
   145         if(!IsEndOfStatement()) {
   146             Error(_SC(
"end of statement expected (; or lf)"));
   150         SQInteger trg = _fs->TopTarget();
   151         if(_fs->IsLocal(trg)) {
   152             trg = _fs->PopTarget(); 
   153             _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
   161         SQFuncState funcstate(_ss(_vm), 
NULL,ThrowError,
this);
   162         funcstate._name = SQString::Create(_ss(_vm), _SC(
"main"));
   164         _fs->AddParameter(_fs->CreateString(_SC(
"this")));
   165         _fs->_sourcename = _sourcename;
   166         SQInteger stacksize = _fs->GetStackSize();
   167         if(setjmp(_errorjmp) == 0) {
   171                 if(_lex._prevtoken != _SC(
'}')) OptionalSemicolon();
   173             CleanStack(stacksize);
   174             _fs->AddLineInfos(_lex._currentline, _lineinfo, 
true);
   175             _fs->AddInstruction(_OP_RETURN, 0xFF);
   176             _fs->SetStackSize(0);
   177             o =_fs->BuildProto();
   179             _fs->Dump(_funcproto(o));
   183             if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
   184                 _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC(
"unknown"),
   185                     _lex._currentline, _lex._currentcolumn);
   187             _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
   194         while(_token != _SC(
'}') && _token != TK_DEFAULT && _token != TK_CASE) {
   196             if(_lex._prevtoken != _SC(
'}') && _lex._prevtoken != _SC(
';')) OptionalSemicolon();
   201         _fs->AddLineInfos(_lex._currentline, _lineinfo);
   203         case _SC(
';'):  Lex();                  
break;
   204         case TK_IF:     IfStatement();          
break;
   205         case TK_WHILE:      WhileStatement();       
break;
   206         case TK_DO:     DoWhileStatement();     
break;
   207         case TK_FOR:        ForStatement();         
break;
   208         case TK_FOREACH:    ForEachStatement();     
break;
   209         case TK_SWITCH: SwitchStatement();      
break;
   210         case TK_LOCAL:      LocalDeclStatement();   
break;
   214             if(_token == TK_RETURN) {
   220                 _fs->_bgenerator = 
true;
   223             if(!IsEndOfStatement()) {
   224                 SQInteger retexp = _fs->GetCurrentPos()+1;
   226                 if(op == _OP_RETURN && _fs->_traps > 0)
   227                     _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
   228                 _fs->_returnexp = retexp;
   229                 _fs->AddInstruction(op, 1, _fs->PopTarget());
   232                 if(op == _OP_RETURN && _fs->_traps > 0)
   233                     _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
   234                 _fs->_returnexp = -1;
   235                 _fs->AddInstruction(op, 0xFF);
   239             if(_fs->_breaktargets.size() <= 0)Error(_SC(
"'break' has to be in a loop block"));
   240             if(_fs->_breaktargets.top() > 0){
   241                 _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
   243             _fs->AddInstruction(_OP_JMP, 0, -1234);
   244             _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
   248             if(_fs->_continuetargets.size() <= 0)Error(_SC(
"'continue' has to be in a loop block"));
   249             if(_fs->_continuetargets.top() > 0) {
   250                 _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
   252             _fs->AddInstruction(_OP_JMP, 0, -1234);
   253             _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
   266                 SQInteger stacksize = _fs->GetStackSize();
   270                 _fs->SetStackSize(stacksize);
   279             _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
   284             SQObject 
id = Expect(TK_IDENTIFIER);
   286             SQObject val = ExpectScalar();
   288             SQTable *enums = _table(_ss(_vm)->_consts);
   289             SQObjectPtr strongid = id;
   290             enums->NewSlot(strongid,SQObjectPtr(val));
   303         SQInteger val = _fs->PopTarget();
   304         SQInteger key = _fs->PopTarget();
   305         SQInteger src = _fs->PopTarget();
   306         _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
   310         SQInteger p2 = _fs->PopTarget(); 
   311         SQInteger p1 = _fs->PopTarget(); 
   312         _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
   318         case TK_MINUSEQ: oper = 
'-'; 
break;
   319         case TK_PLUSEQ: oper = 
'+'; 
break;
   320         case TK_MULEQ: oper = 
'*'; 
break;
   321         case TK_DIVEQ: oper = 
'/'; 
break;
   322         case TK_MODEQ: oper = 
'%'; 
break;
   327             SQInteger val = _fs->PopTarget();
   328             SQInteger key = _fs->PopTarget();
   329             SQInteger src = _fs->PopTarget();
   331             _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);
   334             Emit2ArgsOP(_OP_COMPARITHL, oper);
   339         for(
Expression();_token == 
',';_fs->PopTarget(), Lex(), CommaExpr());
   344         _exst._class_or_delete = 
false;
   345         _exst._funcarg = funcarg;
   356                 SQInteger op = _token;
   357                 SQInteger ds = 
_exst._deref;
   358                 bool freevar = 
_exst._freevar;
   364                     if(freevar) Error(_SC(
"free variables cannot be modified"));
   366                         EmitDerefOp(_OP_NEWSLOT);
   368                         Error(_SC(
"can't 'create' a local slot"));
   371                     if(freevar) Error(_SC(
"free variables cannot be modified"));
   373                         EmitDerefOp(_OP_SET);
   375                         SQInteger p2 = _fs->PopTarget(); 
   376                         SQInteger p1 = _fs->TopTarget(); 
   377                         _fs->AddInstruction(_OP_MOVE, p1, p2);
   392             _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
   393             SQInteger jzpos = _fs->GetCurrentPos();
   394             SQInteger trg = _fs->PushTarget();
   396             SQInteger first_exp = _fs->PopTarget();
   397             if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
   398             SQInteger endfirstexp = _fs->GetCurrentPos();
   399             _fs->AddInstruction(_OP_JMP, 0, 0);
   401             SQInteger jmppos = _fs->GetCurrentPos();
   403             SQInteger second_exp = _fs->PopTarget();
   404             if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
   405             _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
   406             _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
   411         return PopExpState();
   416         SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
   417         _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
   422         for(;;) 
if(_token == TK_OR) {
   423             SQInteger first_exp = _fs->PopTarget();
   424             SQInteger trg = _fs->PushTarget();
   425             _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
   426             SQInteger jpos = _fs->GetCurrentPos();
   427             if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
   428             Lex(); LogicalOrExp();
   430             SQInteger second_exp = _fs->PopTarget();
   431             if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
   433             _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
   440         for(;;) 
switch(_token) {
   442             SQInteger first_exp = _fs->PopTarget();
   443             SQInteger trg = _fs->PushTarget();
   444             _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
   445             SQInteger jpos = _fs->GetCurrentPos();
   446             if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
   447             Lex(); LogicalAndExp();
   449             SQInteger second_exp = _fs->PopTarget();
   450             if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
   452             _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
   464         for(;;) 
if(_token == _SC(
'|'))
   471         for(;;) 
if(_token == _SC(
'^'))
   478         for(;;) 
if(_token == _SC(
'&'))
   485         for(;;) 
switch(_token) {
   498         for(;;) 
switch(_token) {
   508         for(;;) 
switch(_token) {
   509         case _SC(
'+'): 
case _SC(
'-'):
   518         for(;;) 
switch(_token) {
   519         case _SC(
'*'): 
case _SC(
'/'): 
case _SC(
'%'):
   527         SQInteger pos = Factor();
   533                 if(_token == TK_PARENT) {
   536                         Error(_SC(
"parent cannot be set"));
   537                     SQInteger src = _fs->PopTarget();
   538                     _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
   541                     _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
   542                     if(NeedGet()) Emit2ArgsOP(_OP_GET);
   545                 _exst._freevar = 
false;
   549                 if(_lex._prevtoken == _SC(
'\n')) Error(_SC(
"cannot brake deref/or comma needed after [exp]=exp slot declaration"));
   552                 if(NeedGet()) Emit2ArgsOP(_OP_GET);
   554                 _exst._freevar = 
false;
   559                 SQInteger tok = _token; Lex();
   561                     Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
   563                     SQInteger src = _fs->PopTarget();
   564                     _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
   574                         SQInteger key = _fs->PopTarget(); 
   575                         SQInteger table = _fs->PopTarget(); 
   576                         SQInteger closure = _fs->PushTarget();
   577                         SQInteger ttarget = _fs->PushTarget();
   578                         _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
   581                         _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
   585                     _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
   600         case TK_STRING_LITERAL: {
   602                 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
   606         case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); 
break;
   607         case TK_VARGV: { Lex();
   611             SQInteger src = _fs->PopTarget();
   612             _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);
   618             _exst._freevar = 
false;
   622                     case TK_IDENTIFIER: 
id = _fs->CreateString(_lex._svalue); 
break;
   623                     case TK_THIS: 
id = _fs->CreateString(_SC(
"this")); 
break;
   624                     case TK_CONSTRUCTOR: 
id = _fs->CreateString(_SC(
"constructor")); 
break;
   628                 if((pos = _fs->GetLocalVariable(
id)) == -1) {
   630                     if((pos = _fs->GetOuterVariable(
id)) != -1) {
   631                         _exst._deref = _fs->PushTarget();
   632                         _fs->AddInstruction(_OP_LOADFREEVAR, 
_exst._deref ,pos);
   633                         _exst._freevar = 
true;
   635                     else if(_fs->IsConstant(
id,constant)) { 
   636                         SQObjectPtr constval;
   638                         if(type(constant) == OT_TABLE) {
   639                             Expect(
'.'); constid = Expect(TK_IDENTIFIER);
   640                             if(!_table(constant)->Get(constid,constval)) {
   642                                 Error(_SC(
"invalid constant [%s.%s]"), _stringval(
id),_stringval(constid));
   648                         _exst._deref = _fs->PushTarget();
   649                         SQObjectType ctype = type(constval);
   650                         if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {
   651                             _fs->AddInstruction(_OP_LOADINT, 
_exst._deref,_integer(constval));
   653                         else if(ctype == OT_FLOAT && 
sizeof(SQFloat) == 
sizeof(SQInt32)) {
   654                             SQFloat f = _float(constval);
   655                             _fs->AddInstruction(_OP_LOADFLOAT, 
_exst._deref,*((SQInt32 *)&f));
   658                             _fs->AddInstruction(_OP_LOAD, 
_exst._deref, _fs->GetConstant(constval));
   661                         _exst._freevar = 
true;
   665                         _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(
id));
   666                         if(NeedGet()) Emit2ArgsOP(_OP_GET);
   672                     _fs->PushTarget(pos);
   678         case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); 
break;
   679         case TK_DOUBLE_COLON:  
   680             _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());
   686             _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
   690             if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { 
   691                 _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);
   694                 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));
   700             if(
sizeof(SQFloat) == 
sizeof(SQInt32)) {
   701                 _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));
   704                 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
   708         case TK_TRUE: 
case TK_FALSE:
   709             _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
   713                 _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());
   714                 SQInteger apos = _fs->GetCurrentPos(),key = 0;
   716                 while(_token != _SC(
']')) {
   718                     if(_token == _SC(
',')) Lex();
   719                     SQInteger val = _fs->PopTarget();
   720                     SQInteger array = _fs->TopTarget();
   721                     _fs->AddInstruction(_OP_APPENDARRAY, array, val);
   724                 _fs->SetIntructionParam(apos, 1, key);
   729             _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
   730             Lex();ParseTableOrClass(_SC(
','));
   733         case TK_FUNCTION: FunctionExp(_token);
break;
   734         case TK_CLASS: Lex(); ClassExp();
break;
   735         case _SC(
'-'): UnaryOP(_OP_NEG); 
break;
   736         case _SC(
'!'): UnaryOP(_OP_NOT); 
break;
   737         case _SC(
'~'): UnaryOP(_OP_BWNOT); 
break;
   738         case TK_TYPEOF : UnaryOP(_OP_TYPEOF); 
break;
   739         case TK_RESUME : UnaryOP(_OP_RESUME); 
break;
   740         case TK_CLONE : UnaryOP(_OP_CLONE); 
break;
   742         case TK_PLUSPLUS :PrefixIncDec(_token); 
break;
   743         case TK_DELETE : DeleteExpr(); 
break;
   744         case TK_DELEGATE : DelegateExpr(); 
break;
   745         case _SC(
'('): Lex(); CommaExpr(); Expect(_SC(
')'));
   747         default: Error(_SC(
"expression expected"));
   753         Lex(); PrefixedExpr();
   754         SQInteger src = _fs->PopTarget();
   755         _fs->AddInstruction(op, _fs->PushTarget(), src);
   760         case _SC(
'='): 
case _SC(
'('): 
case TK_NEWSLOT: 
case TK_PLUSPLUS: 
case TK_MINUSMINUS:
   761         case TK_PLUSEQ: 
case TK_MINUSEQ: 
case TK_MULEQ: 
case TK_DIVEQ: 
case TK_MODEQ:
   764         return (!
_exst._class_or_delete) || (
_exst._class_or_delete && (_token == _SC(
'.') || _token == _SC(
'[')));
   770          while(_token != _SC(
')')) {
   772              MoveIfCurrentTargetIsLocal();
   774              if(_token == _SC(
',')){
   776                  if(_token == 
')') Error(_SC(
"expression expected, found ')'"));
   780          for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
   781          SQInteger stackbase = _fs->PopTarget();
   782          SQInteger closure = _fs->PopTarget();
   783          _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
   787         SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
   789         while(_token != terminator) {
   790             bool hasattrs = 
false;
   791             bool isstatic = 
false;
   793             if(separator == 
';') {
   794                 if(_token == TK_ATTR_OPEN) {
   795                     _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();
   796                     ParseTableOrClass(
',',TK_ATTR_CLOSE);
   799                 if(_token == TK_STATIC) {
   806                 case TK_CONSTRUCTOR:{
   807                     SQInteger tk = _token;
   809                     SQObject 
id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC(
"constructor"));
   811                     _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(
id));
   813                     _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
   817                     Lex(); CommaExpr(); Expect(_SC(
']'));
   821                     _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
   825             if(_token == separator) Lex();
   827             SQInteger val = _fs->PopTarget();
   828             SQInteger key = _fs->PopTarget();
   829             SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
   831             assert((hasattrs && (attrs == key-1)) || !hasattrs);
   833             int flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
   834             SQInteger table = _fs->TopTarget(); 
   835             _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);
   838         if(separator == _SC(
',')) 
   839             _fs->SetIntructionParam(tpos, 1, nkeys);
   846             Lex(); varname = Expect(TK_IDENTIFIER);
   847             if(_token == _SC(
'=')) {
   849                 SQInteger src = _fs->PopTarget();
   850                 SQInteger dest = _fs->PushTarget();
   851                 if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
   854                 _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
   857             _fs->PushLocalVariable(varname);
   859         } 
while(_token == _SC(
','));
   864         bool haselse = 
false;
   865         Lex(); Expect(_SC(
'(')); CommaExpr(); Expect(_SC(
')'));
   866         _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
   867         SQInteger jnepos = _fs->GetCurrentPos();
   868         SQInteger stacksize = _fs->GetStackSize();
   872         if(_token != _SC(
'}') && _token != TK_ELSE) OptionalSemicolon();
   874         CleanStack(stacksize);
   875         SQInteger endifblock = _fs->GetCurrentPos();
   876         if(_token == TK_ELSE){
   878             stacksize = _fs->GetStackSize();
   879             _fs->AddInstruction(_OP_JMP);
   880             jmppos = _fs->GetCurrentPos();
   882             Statement(); OptionalSemicolon();
   883             CleanStack(stacksize);
   884             _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
   886         _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
   890         SQInteger jzpos, jmppos;
   891         SQInteger stacksize = _fs->GetStackSize();
   892         jmppos = _fs->GetCurrentPos();
   893         Lex(); Expect(_SC(
'(')); CommaExpr(); Expect(_SC(
')'));
   896         _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
   897         jzpos = _fs->GetCurrentPos();
   898         stacksize = _fs->GetStackSize();
   902         CleanStack(stacksize);
   903         _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
   904         _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
   911         SQInteger jzpos = _fs->GetCurrentPos();
   912         SQInteger stacksize = _fs->GetStackSize();
   915         CleanStack(stacksize);
   917         SQInteger continuetrg = _fs->GetCurrentPos();
   918         Expect(_SC(
'(')); CommaExpr(); Expect(_SC(
')'));
   919         _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);
   925         SQInteger stacksize = _fs->GetStackSize();
   927         if(_token == TK_LOCAL) LocalDeclStatement();
   928         else if(_token != _SC(
';')){
   934         SQInteger jmppos = _fs->GetCurrentPos();
   935         SQInteger jzpos = -1;
   936         if(_token != _SC(
';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
   939         SQInteger expstart = _fs->GetCurrentPos() + 1;
   940         if(_token != _SC(
')')) {
   946         SQInteger expend = _fs->GetCurrentPos();
   947         SQInteger expsize = (expend - expstart) + 1;
   948         SQInstructionVec exp;
   950             for(SQInteger i = 0; i < expsize; i++)
   951                 exp.push_back(_fs->GetInstruction(expstart + i));
   952             _fs->PopInstructions(expsize);
   956         SQInteger continuetrg = _fs->GetCurrentPos();
   958             for(SQInteger i = 0; i < expsize; i++)
   959                 _fs->AddInstruction(exp[i]);
   961         _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
   962         if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
   963         CleanStack(stacksize);
   969         SQObject idxname, valname;
   970         Lex(); Expect(_SC(
'(')); valname = Expect(TK_IDENTIFIER);
   971         if(_token == _SC(
',')) {
   973             Lex(); valname = Expect(TK_IDENTIFIER);
   976             idxname = _fs->CreateString(_SC(
"@INDEX@"));
   981         SQInteger stacksize = _fs->GetStackSize();
   984         SQInteger container = _fs->TopTarget();
   986         SQInteger indexpos = _fs->PushLocalVariable(idxname);
   987         _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
   989         SQInteger valuepos = _fs->PushLocalVariable(valname);
   990         _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
   992         SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC(
"@ITERATOR@"))); 
   993         _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
   994         SQInteger jmppos = _fs->GetCurrentPos();
   995         _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
   996         SQInteger foreachpos = _fs->GetCurrentPos();
   997         _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
  1001         _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
  1002         _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
  1003         _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
  1005         CleanStack(stacksize);
  1010         Lex(); Expect(_SC(
'(')); CommaExpr(); Expect(_SC(
')'));
  1012         SQInteger expr = _fs->TopTarget();
  1014         SQInteger tonextcondjmp = -1;
  1015         SQInteger skipcondjmp = -1;
  1016         SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
  1017         _fs->_breaktargets.push_back(0);
  1018         while(_token == TK_CASE) {
  1021                 _fs->AddInstruction(_OP_JMP, 0, 0);
  1022                 skipcondjmp = _fs->GetCurrentPos();
  1023                 _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1027             SQInteger trg = _fs->PopTarget();
  1028             _fs->AddInstruction(_OP_EQ, trg, trg, expr);
  1029             _fs->AddInstruction(_OP_JZ, trg, 0);
  1031             if(skipcondjmp != -1) {
  1032                 _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
  1034             tonextcondjmp = _fs->GetCurrentPos();
  1035             SQInteger stacksize = _fs->GetStackSize();
  1037             _fs->SetStackSize(stacksize);
  1040         if(tonextcondjmp != -1)
  1041             _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1042         if(_token == TK_DEFAULT) {
  1044             Lex(); Expect(_SC(
':'));
  1045             SQInteger stacksize = _fs->GetStackSize();
  1047             _fs->SetStackSize(stacksize);
  1051         __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
  1052         if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
  1053         _fs->_breaktargets.pop_back();
  1059         Lex(); 
id = Expect(TK_IDENTIFIER);
  1061         _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(
id));
  1062         if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1064         while(_token == TK_DOUBLE_COLON) {
  1066             id = Expect(TK_IDENTIFIER);
  1067             _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(
id));
  1068             if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1072         _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1073         EmitDerefOp(_OP_NEWSLOT);
  1079         Lex(); PushExpState();
  1080         _exst._class_or_delete = 
true;
  1081         _exst._funcarg = 
false;
  1087             EmitDerefOp(_OP_NEWSLOT);
  1090         else Error(_SC(
"cannot create a class in a local with the syntax(class <local>)"));
  1097                 val._type = OT_INTEGER;
  1098                 val._unVal.nInteger = _lex._nvalue;
  1101                 val._type = OT_FLOAT;
  1102                 val._unVal.fFloat = _lex._fvalue;
  1104             case TK_STRING_LITERAL:
  1105                 val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
  1112                     val._type = OT_INTEGER;
  1113                     val._unVal.nInteger = -_lex._nvalue;
  1116                     val._type = OT_FLOAT;
  1117                     val._unVal.fFloat = -_lex._fvalue;
  1120                     Error(_SC(
"scalar expected : integer,float"));
  1124             Error(_SC(
"scalar expected : integer,float or string"));
  1133         SQObject 
id = Expect(TK_IDENTIFIER);
  1136         SQObject table = _fs->CreateTable();
  1138         while(_token != _SC(
'}')) {
  1139             SQObject key = Expect(TK_IDENTIFIER);
  1141             if(_token == _SC(
'=')) {
  1143                 val = ExpectScalar();
  1146                 val._type = OT_INTEGER;
  1147                 val._unVal.nInteger = nval++;
  1149             _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
  1150             if(_token == 
',') Lex();
  1152         SQTable *enums = _table(_ss(_vm)->_consts);
  1153         SQObjectPtr strongid = id;
  1159         enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
  1168         _fs->AddInstruction(_OP_PUSHTRAP,0,0);
  1170         if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
  1171         if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
  1172         SQInteger trappos = _fs->GetCurrentPos();
  1175         _fs->AddInstruction(_OP_POPTRAP, 1, 0);
  1176         if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
  1177         if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
  1178         _fs->AddInstruction(_OP_JMP, 0, 0);
  1179         SQInteger jmppos = _fs->GetCurrentPos();
  1180         _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
  1181         Expect(TK_CATCH); Expect(_SC(
'(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(
')'));
  1182         SQInteger stacksize = _fs->GetStackSize();
  1183         SQInteger ex_target = _fs->PushLocalVariable(exid);
  1184         _fs->SetIntructionParam(trappos, 0, ex_target);
  1186         _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
  1187         CleanStack(stacksize);
  1191         Lex(); Expect(_SC(
'('));
  1193         _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
  1197         SQInteger base = -1;
  1198         SQInteger attrs = -1;
  1199         if(_token == TK_EXTENDS) {
  1201             base = _fs->TopTarget();
  1203         if(_token == TK_ATTR_OPEN) {
  1205             _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
  1206             ParseTableOrClass(_SC(
','),TK_ATTR_CLOSE);
  1207             attrs = _fs->TopTarget();
  1210         if(attrs != -1) _fs->PopTarget();
  1211         if(base != -1) _fs->PopTarget();
  1212         _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);
  1213         ParseTableOrClass(_SC(
';'));
  1220         SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget();
  1221         _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);
  1226         Lex(); PushExpState();
  1227         _exst._class_or_delete = 
true;
  1228         _exst._funcarg = 
false;
  1233         else Error(_SC(
"cannot delete a local"));
  1238         Lex(); PushExpState();
  1239         _exst._class_or_delete = 
true;
  1240         _exst._funcarg = 
false;
  1245             SQInteger src = _fs->PopTarget();
  1246             _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
  1252         SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
  1253         funcstate->_name = name;
  1255         funcstate->AddParameter(_fs->CreateString(_SC(
"this")));
  1256         funcstate->_sourcename = _sourcename;
  1257         SQInteger defparams = 0;
  1258         while(_token!=_SC(
')')) {
  1259             if(_token == TK_VARPARAMS) {
  1260                 if(defparams > 0) Error(_SC(
"function with default parameters cannot have variable number of parameters"));
  1261                 funcstate->_varparams = 
true;
  1263                 if(_token != _SC(
')')) Error(_SC(
"expected ')'"));
  1267                 paramname = Expect(TK_IDENTIFIER);
  1268                 funcstate->AddParameter(paramname);
  1269                 if(_token == _SC(
'=')) {
  1272                     funcstate->AddDefaultParam(_fs->TopTarget());
  1276                     if(defparams > 0) Error(_SC(
"expected '='"));
  1278                 if(_token == _SC(
',')) Lex();
  1279                 else if(_token != _SC(
')')) Error(_SC(
"expected ')' or ','"));
  1283         for(SQInteger n = 0; n < defparams; n++) {
  1287         if(_token == _SC(
':')) {
  1288             Lex(); Expect(_SC(
'('));
  1289             while(_token != _SC(
')')) {
  1290                 paramname = Expect(TK_IDENTIFIER);
  1292                 funcstate->AddOuterValue(paramname);
  1293                 if(_token == _SC(
',')) Lex();
  1294                 else if(_token != _SC(
')')) Error(_SC(
"expected ')' or ','"));
  1299         SQFuncState *currchunk = _fs;
  1302         funcstate->AddLineInfos(_lex._prevtoken == _SC(
'\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, 
true);
  1303         funcstate->AddInstruction(_OP_RETURN, -1);
  1304         funcstate->SetStackSize(0);
  1306         SQFunctionProto *func = funcstate->BuildProto();
  1308         funcstate->Dump(func);
  1311         _fs->_functions.push_back(func);
  1312         _fs->PopChildState();
  1316         if(_fs->GetStackSize() != stacksize)
  1317             _fs->SetStackSize(stacksize);
  1321         while(ntoresolve > 0) {
  1322             SQInteger pos = funcstate->_unresolvedbreaks.back();
  1323             funcstate->_unresolvedbreaks.pop_back();
  1325             funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
  1331         while(ntoresolve > 0) {
  1332             SQInteger pos = funcstate->_unresolvedcontinues.back();
  1333             funcstate->_unresolvedcontinues.pop_back();
  1335             funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
  1354 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, 
const SQChar *sourcename, SQObjectPtr &out, 
bool raiseerror, 
bool lineinfo)
  1356     SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
 sqvector< ExpState > ExpStateVec
SQObject Expect(SQInteger tok)
void ParseTableOrClass(SQInteger separator, SQInteger terminator='}')
void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
void PrefixIncDec(SQInteger token)
void MoveIfCurrentTargetIsLocal()
bool IsDerefToken(SQInteger tok)
void EmitDerefOp(SQOpcode op)
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, bool raiseerror, bool lineinfo)
#define BEGIN_BREAKBLE_BLOCK()
void Error(const SQChar *s,...)
#define END_BREAKBLE_BLOCK(continue_target)
static void ThrowError(void *ud, const SQChar *s)
void BIN_EXP(SQOpcode op, void(SQCompiler::*f)(void), SQInteger op3=0)
void CreateFunction(SQObject &name)
void FunctionExp(SQInteger ftype)
bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
ExpState Expression(bool funcarg=false)
void Emit2ArgsOP(SQOpcode op, SQInteger p3=0)
void LocalDeclStatement()
bool Compile(SQObjectPtr &o)
void CleanStack(SQInteger stacksize)
void UnaryOP(SQOpcode op)
void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
void EmitCompoundArith(SQInteger tok, bool deref)