2 see copyright notice in squirrel.h
\r
4 #include "sqpcheader.h"
\r
7 #include "sqopcodes.h"
\r
8 #include "sqstring.h"
\r
9 #include "sqfuncproto.h"
\r
10 #include "sqcompiler.h"
\r
11 #include "sqfuncstate.h"
\r
12 #include "sqlexer.h"
\r
14 #include "sqtable.h"
\r
16 #define DEREF_NO_DEREF -1
\r
17 #define DEREF_FIELD -2
\r
23 _deref = DEREF_NO_DEREF;
\r
25 _class_or_delete = false;
\r
28 bool _class_or_delete;
\r
34 typedef sqvector<ExpState> ExpStateVec;
\r
36 #define _exst (_expstates.top())
\r
38 #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
\r
39 SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
\r
40 _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
\r
42 #define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
\r
43 __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
\r
44 if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
\r
45 if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
\r
46 _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
\r
51 SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
\r
54 _lex.Init(_ss(v), rg, up,ThrowError,this);
\r
55 _sourcename = SQString::Create(_ss(v), sourcename);
\r
56 _lineinfo = lineinfo;_raiseerror = raiseerror;
\r
57 compilererror = NULL;
\r
59 static void ThrowError(void *ud, const SQChar *s) {
\r
60 SQCompiler *c = (SQCompiler *)ud;
\r
63 void Error(const SQChar *s, ...)
\r
65 static SQChar temp[256];
\r
68 scvsprintf(temp, s, vl);
\r
70 compilererror = temp;
\r
71 longjmp(_errorjmp,1);
\r
73 void Lex(){ _token = _lex.Lex();}
\r
74 void PushExpState(){ _expstates.push_back(ExpState()); }
\r
75 bool IsDerefToken(SQInteger tok)
\r
78 case _SC('='): case _SC('('): case TK_NEWSLOT:
\r
79 case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;
\r
83 ExpState PopExpState()
\r
85 ExpState ret = _expstates.top();
\r
86 _expstates.pop_back();
\r
89 SQObject Expect(SQInteger tok)
\r
93 if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
\r
94 //ret = SQString::Create(_ss(_vm),_SC("constructor"));
\r
98 const SQChar *etypename;
\r
102 case TK_IDENTIFIER:
\r
103 etypename = _SC("IDENTIFIER");
\r
105 case TK_STRING_LITERAL:
\r
106 etypename = _SC("STRING_LITERAL");
\r
109 etypename = _SC("INTEGER");
\r
112 etypename = _SC("FLOAT");
\r
115 etypename = _lex.Tok2Str(tok);
\r
117 Error(_SC("expected '%s'"), etypename);
\r
119 Error(_SC("expected '%c'"), tok);
\r
125 case TK_IDENTIFIER:
\r
126 ret = _fs->CreateString(_lex._svalue);
\r
128 case TK_STRING_LITERAL:
\r
129 ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
\r
132 ret = SQObjectPtr(_lex._nvalue);
\r
135 ret = SQObjectPtr(_lex._fvalue);
\r
141 bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
\r
142 void OptionalSemicolon()
\r
144 if(_token == _SC(';')) { Lex(); return; }
\r
145 if(!IsEndOfStatement()) {
\r
146 Error(_SC("end of statement expected (; or lf)"));
\r
149 void MoveIfCurrentTargetIsLocal() {
\r
150 SQInteger trg = _fs->TopTarget();
\r
151 if(_fs->IsLocal(trg)) {
\r
152 trg = _fs->PopTarget(); //no pops the target and move it
\r
153 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
\r
156 bool Compile(SQObjectPtr &o)
\r
161 SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
\r
162 funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
\r
164 _fs->AddParameter(_fs->CreateString(_SC("this")));
\r
165 _fs->_sourcename = _sourcename;
\r
166 SQInteger stacksize = _fs->GetStackSize();
\r
167 if(setjmp(_errorjmp) == 0) {
\r
171 if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
\r
173 CleanStack(stacksize);
\r
174 _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
\r
175 _fs->AddInstruction(_OP_RETURN, 0xFF);
\r
176 _fs->SetStackSize(0);
\r
177 o =_fs->BuildProto();
\r
179 _fs->Dump(_funcproto(o));
\r
183 if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
\r
184 _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
\r
185 _lex._currentline, _lex._currentcolumn);
\r
187 _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
\r
194 while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
\r
196 if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
\r
201 _fs->AddLineInfos(_lex._currentline, _lineinfo);
\r
203 case _SC(';'): Lex(); break;
\r
204 case TK_IF: IfStatement(); break;
\r
205 case TK_WHILE: WhileStatement(); break;
\r
206 case TK_DO: DoWhileStatement(); break;
\r
207 case TK_FOR: ForStatement(); break;
\r
208 case TK_FOREACH: ForEachStatement(); break;
\r
209 case TK_SWITCH: SwitchStatement(); break;
\r
210 case TK_LOCAL: LocalDeclStatement(); break;
\r
214 if(_token == TK_RETURN) {
\r
220 _fs->_bgenerator = true;
\r
223 if(!IsEndOfStatement()) {
\r
224 SQInteger retexp = _fs->GetCurrentPos()+1;
\r
226 if(op == _OP_RETURN && _fs->_traps > 0)
\r
227 _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
\r
228 _fs->_returnexp = retexp;
\r
229 _fs->AddInstruction(op, 1, _fs->PopTarget());
\r
232 if(op == _OP_RETURN && _fs->_traps > 0)
\r
233 _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
\r
234 _fs->_returnexp = -1;
\r
235 _fs->AddInstruction(op, 0xFF);
\r
239 if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
\r
240 if(_fs->_breaktargets.top() > 0){
\r
241 _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
\r
243 _fs->AddInstruction(_OP_JMP, 0, -1234);
\r
244 _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
\r
248 if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
\r
249 if(_fs->_continuetargets.top() > 0) {
\r
250 _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
\r
252 _fs->AddInstruction(_OP_JMP, 0, -1234);
\r
253 _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
\r
257 FunctionStatement();
\r
266 SQInteger stacksize = _fs->GetStackSize();
\r
270 _fs->SetStackSize(stacksize);
\r
274 TryCatchStatement();
\r
279 _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
\r
284 SQObject id = Expect(TK_IDENTIFIER);
\r
286 SQObject val = ExpectScalar();
\r
287 OptionalSemicolon();
\r
288 SQTable *enums = _table(_ss(_vm)->_consts);
\r
289 SQObjectPtr strongid = id;
\r
290 enums->NewSlot(strongid,SQObjectPtr(val));
\r
301 void EmitDerefOp(SQOpcode op)
\r
303 SQInteger val = _fs->PopTarget();
\r
304 SQInteger key = _fs->PopTarget();
\r
305 SQInteger src = _fs->PopTarget();
\r
306 _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
\r
308 void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
\r
310 SQInteger p2 = _fs->PopTarget(); //src in OP_GET
\r
311 SQInteger p1 = _fs->PopTarget(); //key in OP_GET
\r
312 _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
\r
314 void EmitCompoundArith(SQInteger tok,bool deref)
\r
318 case TK_MINUSEQ: oper = '-'; break;
\r
319 case TK_PLUSEQ: oper = '+'; break;
\r
320 case TK_MULEQ: oper = '*'; break;
\r
321 case TK_DIVEQ: oper = '/'; break;
\r
322 case TK_MODEQ: oper = '%'; break;
\r
323 default: oper = 0; //shut up compiler
\r
327 SQInteger val = _fs->PopTarget();
\r
328 SQInteger key = _fs->PopTarget();
\r
329 SQInteger src = _fs->PopTarget();
\r
330 //mixes dest obj and source val in the arg1(hack?)
\r
331 _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);
\r
334 Emit2ArgsOP(_OP_COMPARITHL, oper);
\r
339 for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
\r
341 ExpState Expression(bool funcarg = false)
\r
344 _exst._class_or_delete = false;
\r
345 _exst._funcarg = funcarg;
\r
356 SQInteger op = _token;
\r
357 SQInteger ds = _exst._deref;
\r
358 bool freevar = _exst._freevar;
\r
359 if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));
\r
360 Lex(); Expression();
\r
364 if(freevar) Error(_SC("free variables cannot be modified"));
\r
365 if(ds == DEREF_FIELD)
\r
366 EmitDerefOp(_OP_NEWSLOT);
\r
367 else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
\r
368 Error(_SC("can't 'create' a local slot"));
\r
370 case _SC('='): //ASSIGN
\r
371 if(freevar) Error(_SC("free variables cannot be modified"));
\r
372 if(ds == DEREF_FIELD)
\r
373 EmitDerefOp(_OP_SET);
\r
374 else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
\r
375 SQInteger p2 = _fs->PopTarget(); //src in OP_GET
\r
376 SQInteger p1 = _fs->TopTarget(); //key in OP_GET
\r
377 _fs->AddInstruction(_OP_MOVE, p1, p2);
\r
385 EmitCompoundArith(op,ds == DEREF_FIELD);
\r
392 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
\r
393 SQInteger jzpos = _fs->GetCurrentPos();
\r
394 SQInteger trg = _fs->PushTarget();
\r
396 SQInteger first_exp = _fs->PopTarget();
\r
397 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
\r
398 SQInteger endfirstexp = _fs->GetCurrentPos();
\r
399 _fs->AddInstruction(_OP_JMP, 0, 0);
\r
401 SQInteger jmppos = _fs->GetCurrentPos();
\r
403 SQInteger second_exp = _fs->PopTarget();
\r
404 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
\r
405 _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
\r
406 _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
\r
411 return PopExpState();
\r
413 void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0)
\r
415 Lex(); (this->*f)();
\r
416 SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
\r
417 _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
\r
419 void LogicalOrExp()
\r
422 for(;;) if(_token == TK_OR) {
\r
423 SQInteger first_exp = _fs->PopTarget();
\r
424 SQInteger trg = _fs->PushTarget();
\r
425 _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
\r
426 SQInteger jpos = _fs->GetCurrentPos();
\r
427 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
\r
428 Lex(); LogicalOrExp();
\r
430 SQInteger second_exp = _fs->PopTarget();
\r
431 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
\r
433 _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
\r
437 void LogicalAndExp()
\r
440 for(;;) switch(_token) {
\r
442 SQInteger first_exp = _fs->PopTarget();
\r
443 SQInteger trg = _fs->PushTarget();
\r
444 _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
\r
445 SQInteger jpos = _fs->GetCurrentPos();
\r
446 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
\r
447 Lex(); LogicalAndExp();
\r
449 SQInteger second_exp = _fs->PopTarget();
\r
450 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
\r
452 _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
\r
455 case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;
\r
456 case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;
\r
461 void BitwiseOrExp()
\r
464 for(;;) if(_token == _SC('|'))
\r
465 {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
\r
468 void BitwiseXorExp()
\r
471 for(;;) if(_token == _SC('^'))
\r
472 {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
\r
475 void BitwiseAndExp()
\r
478 for(;;) if(_token == _SC('&'))
\r
479 {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);
\r
485 for(;;) switch(_token) {
\r
486 case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;
\r
487 case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
\r
488 case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
\r
489 case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
\r
490 case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
\r
491 case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;
\r
498 for(;;) switch(_token) {
\r
499 case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
\r
500 case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
\r
501 case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
\r
508 for(;;) switch(_token) {
\r
509 case _SC('+'): case _SC('-'):
\r
510 BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;
\r
518 for(;;) switch(_token) {
\r
519 case _SC('*'): case _SC('/'): case _SC('%'):
\r
520 BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;
\r
524 //if 'pos' != -1 the previous variable is a local variable
\r
525 void PrefixedExpr()
\r
527 SQInteger pos = Factor();
\r
534 if(_token == TK_PARENT) {
\r
537 Error(_SC("parent cannot be set"));
\r
538 SQInteger src = _fs->PopTarget();
\r
539 _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
\r
542 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
\r
543 if(NeedGet()) Emit2ArgsOP(_OP_GET);
\r
545 _exst._deref = DEREF_FIELD;
\r
546 _exst._freevar = false;
\r
550 if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
\r
551 Lex(); Expression(); Expect(_SC(']'));
\r
553 if(NeedGet()) Emit2ArgsOP(_OP_GET);
\r
554 _exst._deref = DEREF_FIELD;
\r
555 _exst._freevar = false;
\r
557 case TK_MINUSMINUS:
\r
559 if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
\r
560 SQInteger tok = _token; Lex();
\r
562 Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
\r
563 else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
\r
564 SQInteger src = _fs->PopTarget();
\r
565 _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
\r
573 if(_exst._deref != DEREF_NO_DEREF) {
\r
575 SQInteger key = _fs->PopTarget(); //key
\r
576 SQInteger table = _fs->PopTarget(); //table etc...
\r
577 SQInteger closure = _fs->PushTarget();
\r
578 SQInteger ttarget = _fs->PushTarget();
\r
579 _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
\r
582 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
\r
586 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
\r
587 _exst._deref = DEREF_NO_DEREF;
\r
589 FunctionCallArgs();
\r
598 _exst._deref = DEREF_NO_DEREF;
\r
601 case TK_STRING_LITERAL: {
\r
602 //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
\r
603 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
\r
607 case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
\r
608 case TK_VARGV: { Lex();
\r
612 SQInteger src = _fs->PopTarget();
\r
613 _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);
\r
616 case TK_IDENTIFIER:
\r
617 case TK_CONSTRUCTOR:
\r
619 _exst._freevar = false;
\r
623 case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
\r
624 case TK_THIS: id = _fs->CreateString(_SC("this")); break;
\r
625 case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;
\r
627 SQInteger pos = -1;
\r
629 if((pos = _fs->GetLocalVariable(id)) == -1) {
\r
630 //checks if is a free variable
\r
631 if((pos = _fs->GetOuterVariable(id)) != -1) {
\r
632 _exst._deref = _fs->PushTarget();
\r
633 _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
\r
634 _exst._freevar = true;
\r
636 else if(_fs->IsConstant(id,constant)) { //line 634
\r
637 SQObjectPtr constval;
\r
639 if(type(constant) == OT_TABLE) {
\r
640 Expect('.'); constid = Expect(TK_IDENTIFIER);
\r
641 if(!_table(constant)->Get(constid,constval)) {
\r
643 Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid));
\r
647 constval = constant;
\r
649 _exst._deref = _fs->PushTarget();
\r
650 SQObjectType ctype = type(constval);
\r
651 if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {
\r
652 _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));
\r
654 else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {
\r
655 SQFloat f = _float(constval);
\r
656 _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));
\r
659 _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));
\r
662 _exst._freevar = true;
\r
665 _fs->PushTarget(0);
\r
666 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
\r
667 if(NeedGet()) Emit2ArgsOP(_OP_GET);
\r
668 _exst._deref = DEREF_FIELD;
\r
673 _fs->PushTarget(pos);
\r
674 _exst._deref = pos;
\r
676 return _exst._deref;
\r
679 case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;
\r
680 case TK_DOUBLE_COLON: // "::"
\r
681 _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());
\r
682 _exst._deref = DEREF_FIELD;
\r
683 _token = _SC('.'); //hack
\r
687 _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
\r
691 if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?
\r
692 _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);
\r
695 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));
\r
701 if(sizeof(SQFloat) == sizeof(SQInt32)) {
\r
702 _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));
\r
705 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
\r
709 case TK_TRUE: case TK_FALSE:
\r
710 _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
\r
714 _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());
\r
715 SQInteger apos = _fs->GetCurrentPos(),key = 0;
\r
717 while(_token != _SC(']')) {
\r
719 if(_token == _SC(',')) Lex();
\r
720 SQInteger val = _fs->PopTarget();
\r
721 SQInteger array = _fs->TopTarget();
\r
722 _fs->AddInstruction(_OP_APPENDARRAY, array, val);
\r
725 _fs->SetIntructionParam(apos, 1, key);
\r
730 _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
\r
731 Lex();ParseTableOrClass(_SC(','));
\r
734 case TK_FUNCTION: FunctionExp(_token);break;
\r
735 case TK_CLASS: Lex(); ClassExp();break;
\r
736 case _SC('-'): UnaryOP(_OP_NEG); break;
\r
737 case _SC('!'): UnaryOP(_OP_NOT); break;
\r
738 case _SC('~'): UnaryOP(_OP_BWNOT); break;
\r
739 case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;
\r
740 case TK_RESUME : UnaryOP(_OP_RESUME); break;
\r
741 case TK_CLONE : UnaryOP(_OP_CLONE); break;
\r
742 case TK_MINUSMINUS :
\r
743 case TK_PLUSPLUS :PrefixIncDec(_token); break;
\r
744 case TK_DELETE : DeleteExpr(); break;
\r
745 case TK_DELEGATE : DelegateExpr(); break;
\r
746 case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
\r
748 default: Error(_SC("expression expected"));
\r
752 void UnaryOP(SQOpcode op)
\r
754 Lex(); PrefixedExpr();
\r
755 SQInteger src = _fs->PopTarget();
\r
756 _fs->AddInstruction(op, _fs->PushTarget(), src);
\r
761 case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:
\r
762 case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:
\r
765 return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));
\r
768 void FunctionCallArgs()
\r
770 SQInteger nargs = 1;//this
\r
771 while(_token != _SC(')')) {
\r
773 MoveIfCurrentTargetIsLocal();
\r
775 if(_token == _SC(',')){
\r
777 if(_token == ')') Error(_SC("expression expected, found ')'"));
\r
781 for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
\r
782 SQInteger stackbase = _fs->PopTarget();
\r
783 SQInteger closure = _fs->PopTarget();
\r
784 _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
\r
786 void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')
\r
788 SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
\r
790 while(_token != terminator) {
\r
791 bool hasattrs = false;
\r
792 bool isstatic = false;
\r
793 //check if is an attribute
\r
794 if(separator == ';') {
\r
795 if(_token == TK_ATTR_OPEN) {
\r
796 _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();
\r
797 ParseTableOrClass(',',TK_ATTR_CLOSE);
\r
800 if(_token == TK_STATIC) {
\r
807 case TK_CONSTRUCTOR:{
\r
808 SQInteger tk = _token;
\r
810 SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
\r
812 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
\r
813 CreateFunction(id);
\r
814 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
\r
818 Lex(); CommaExpr(); Expect(_SC(']'));
\r
819 Expect(_SC('=')); Expression();
\r
822 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
\r
823 Expect(_SC('=')); Expression();
\r
826 if(_token == separator) Lex();//optional comma/semicolon
\r
828 SQInteger val = _fs->PopTarget();
\r
829 SQInteger key = _fs->PopTarget();
\r
830 SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
\r
831 assert(hasattrs && attrs == key-1 || !hasattrs);
\r
832 unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
\r
833 SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
\r
834 _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);
\r
835 //_fs->PopTarget();
\r
837 if(separator == _SC(',')) //hack recognizes a table from the separator
\r
838 _fs->SetIntructionParam(tpos, 1, nkeys);
\r
841 void LocalDeclStatement()
\r
845 Lex(); varname = Expect(TK_IDENTIFIER);
\r
846 if(_token == _SC('=')) {
\r
847 Lex(); Expression();
\r
848 SQInteger src = _fs->PopTarget();
\r
849 SQInteger dest = _fs->PushTarget();
\r
850 if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
\r
853 _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
\r
856 _fs->PushLocalVariable(varname);
\r
858 } while(_token == _SC(','));
\r
863 bool haselse = false;
\r
864 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
\r
865 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
\r
866 SQInteger jnepos = _fs->GetCurrentPos();
\r
867 SQInteger stacksize = _fs->GetStackSize();
\r
871 if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
\r
873 CleanStack(stacksize);
\r
874 SQInteger endifblock = _fs->GetCurrentPos();
\r
875 if(_token == TK_ELSE){
\r
877 stacksize = _fs->GetStackSize();
\r
878 _fs->AddInstruction(_OP_JMP);
\r
879 jmppos = _fs->GetCurrentPos();
\r
881 Statement(); OptionalSemicolon();
\r
882 CleanStack(stacksize);
\r
883 _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
\r
885 _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
\r
887 void WhileStatement()
\r
889 SQInteger jzpos, jmppos;
\r
890 SQInteger stacksize = _fs->GetStackSize();
\r
891 jmppos = _fs->GetCurrentPos();
\r
892 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
\r
894 BEGIN_BREAKBLE_BLOCK();
\r
895 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
\r
896 jzpos = _fs->GetCurrentPos();
\r
897 stacksize = _fs->GetStackSize();
\r
901 CleanStack(stacksize);
\r
902 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
\r
903 _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
\r
905 END_BREAKBLE_BLOCK(jmppos);
\r
907 void DoWhileStatement()
\r
910 SQInteger jzpos = _fs->GetCurrentPos();
\r
911 SQInteger stacksize = _fs->GetStackSize();
\r
912 BEGIN_BREAKBLE_BLOCK()
\r
914 CleanStack(stacksize);
\r
916 SQInteger continuetrg = _fs->GetCurrentPos();
\r
917 Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
\r
918 _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);
\r
919 END_BREAKBLE_BLOCK(continuetrg);
\r
921 void ForStatement()
\r
924 SQInteger stacksize = _fs->GetStackSize();
\r
926 if(_token == TK_LOCAL) LocalDeclStatement();
\r
927 else if(_token != _SC(';')){
\r
933 SQInteger jmppos = _fs->GetCurrentPos();
\r
934 SQInteger jzpos = -1;
\r
935 if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
\r
938 SQInteger expstart = _fs->GetCurrentPos() + 1;
\r
939 if(_token != _SC(')')) {
\r
945 SQInteger expend = _fs->GetCurrentPos();
\r
946 SQInteger expsize = (expend - expstart) + 1;
\r
947 SQInstructionVec exp;
\r
949 for(SQInteger i = 0; i < expsize; i++)
\r
950 exp.push_back(_fs->GetInstruction(expstart + i));
\r
951 _fs->PopInstructions(expsize);
\r
953 BEGIN_BREAKBLE_BLOCK()
\r
955 SQInteger continuetrg = _fs->GetCurrentPos();
\r
957 for(SQInteger i = 0; i < expsize; i++)
\r
958 _fs->AddInstruction(exp[i]);
\r
960 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
\r
961 if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
\r
962 CleanStack(stacksize);
\r
964 END_BREAKBLE_BLOCK(continuetrg);
\r
966 void ForEachStatement()
\r
968 SQObject idxname, valname;
\r
969 Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
\r
970 if(_token == _SC(',')) {
\r
972 Lex(); valname = Expect(TK_IDENTIFIER);
\r
975 idxname = _fs->CreateString(_SC("@INDEX@"));
\r
979 //save the stack size
\r
980 SQInteger stacksize = _fs->GetStackSize();
\r
981 //put the table in the stack(evaluate the table expression)
\r
982 Expression(); Expect(_SC(')'));
\r
983 SQInteger container = _fs->TopTarget();
\r
984 //push the index local var
\r
985 SQInteger indexpos = _fs->PushLocalVariable(idxname);
\r
986 _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
\r
987 //push the value local var
\r
988 SQInteger valuepos = _fs->PushLocalVariable(valname);
\r
989 _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
\r
990 //push reference index
\r
991 SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
\r
992 _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
\r
993 SQInteger jmppos = _fs->GetCurrentPos();
\r
994 _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
\r
995 SQInteger foreachpos = _fs->GetCurrentPos();
\r
996 _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
\r
997 //generate the statement code
\r
998 BEGIN_BREAKBLE_BLOCK()
\r
1000 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
\r
1001 _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
\r
1002 _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
\r
1003 //restore the local variable stack(remove index,val and ref idx)
\r
1004 CleanStack(stacksize);
\r
1005 END_BREAKBLE_BLOCK(foreachpos - 1);
\r
1007 void SwitchStatement()
\r
1009 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
\r
1011 SQInteger expr = _fs->TopTarget();
\r
1012 bool bfirst = true;
\r
1013 SQInteger tonextcondjmp = -1;
\r
1014 SQInteger skipcondjmp = -1;
\r
1015 SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
\r
1016 _fs->_breaktargets.push_back(0);
\r
1017 while(_token == TK_CASE) {
\r
1018 //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one
\r
1020 _fs->AddInstruction(_OP_JMP, 0, 0);
\r
1021 skipcondjmp = _fs->GetCurrentPos();
\r
1022 _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
\r
1025 Lex(); Expression(); Expect(_SC(':'));
\r
1026 SQInteger trg = _fs->PopTarget();
\r
1027 _fs->AddInstruction(_OP_EQ, trg, trg, expr);
\r
1028 _fs->AddInstruction(_OP_JZ, trg, 0);
\r
1030 if(skipcondjmp != -1) {
\r
1031 _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
\r
1033 tonextcondjmp = _fs->GetCurrentPos();
\r
1034 SQInteger stacksize = _fs->GetStackSize();
\r
1036 _fs->SetStackSize(stacksize);
\r
1039 if(tonextcondjmp != -1)
\r
1040 _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
\r
1041 if(_token == TK_DEFAULT) {
\r
1042 // _fs->AddLineInfos(_lex._currentline, _lineinfo);
\r
1043 Lex(); Expect(_SC(':'));
\r
1044 SQInteger stacksize = _fs->GetStackSize();
\r
1046 _fs->SetStackSize(stacksize);
\r
1050 __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
\r
1051 if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
\r
1052 _fs->_breaktargets.pop_back();
\r
1055 void FunctionStatement()
\r
1058 Lex(); id = Expect(TK_IDENTIFIER);
\r
1059 _fs->PushTarget(0);
\r
1060 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
\r
1061 if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
\r
1063 while(_token == TK_DOUBLE_COLON) {
\r
1065 id = Expect(TK_IDENTIFIER);
\r
1066 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
\r
1067 if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
\r
1070 CreateFunction(id);
\r
1071 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
\r
1072 EmitDerefOp(_OP_NEWSLOT);
\r
1075 void ClassStatement()
\r
1078 Lex(); PushExpState();
\r
1079 _exst._class_or_delete = true;
\r
1080 _exst._funcarg = false;
\r
1082 es = PopExpState();
\r
1083 if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));
\r
1084 if(es._deref == DEREF_FIELD) {
\r
1086 EmitDerefOp(_OP_NEWSLOT);
\r
1089 else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
\r
1091 SQObject ExpectScalar()
\r
1096 val._type = OT_INTEGER;
\r
1097 val._unVal.nInteger = _lex._nvalue;
\r
1100 val._type = OT_FLOAT;
\r
1101 val._unVal.fFloat = _lex._fvalue;
\r
1103 case TK_STRING_LITERAL:
\r
1104 val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
\r
1111 val._type = OT_INTEGER;
\r
1112 val._unVal.nInteger = -_lex._nvalue;
\r
1115 val._type = OT_FLOAT;
\r
1116 val._unVal.fFloat = -_lex._fvalue;
\r
1119 Error(_SC("scalar expected : integer,float"));
\r
1123 Error(_SC("scalar expected : integer,float or string"));
\r
1128 void EnumStatement()
\r
1132 SQObject id = Expect(TK_IDENTIFIER);
\r
1135 SQObject table = _fs->CreateTable();
\r
1136 SQInteger nval = 0;
\r
1137 while(_token != _SC('}')) {
\r
1138 SQObject key = Expect(TK_IDENTIFIER);
\r
1140 if(_token == _SC('=')) {
\r
1142 val = ExpectScalar();
\r
1145 val._type = OT_INTEGER;
\r
1146 val._unVal.nInteger = nval++;
\r
1148 _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
\r
1149 if(_token == ',') Lex();
\r
1151 SQTable *enums = _table(_ss(_vm)->_consts);
\r
1152 SQObjectPtr strongid = id;
\r
1153 /*SQObjectPtr dummy;
\r
1154 if(enums->Get(strongid,dummy)) {
\r
1155 dummy.Null(); strongid.Null();
\r
1156 Error(_SC("enumeration already exists"));
\r
1158 enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
\r
1163 void TryCatchStatement()
\r
1167 _fs->AddInstruction(_OP_PUSHTRAP,0,0);
\r
1169 if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
\r
1170 if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
\r
1171 SQInteger trappos = _fs->GetCurrentPos();
\r
1174 _fs->AddInstruction(_OP_POPTRAP, 1, 0);
\r
1175 if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
\r
1176 if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
\r
1177 _fs->AddInstruction(_OP_JMP, 0, 0);
\r
1178 SQInteger jmppos = _fs->GetCurrentPos();
\r
1179 _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
\r
1180 Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
\r
1181 SQInteger stacksize = _fs->GetStackSize();
\r
1182 SQInteger ex_target = _fs->PushLocalVariable(exid);
\r
1183 _fs->SetIntructionParam(trappos, 0, ex_target);
\r
1185 _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
\r
1186 CleanStack(stacksize);
\r
1188 void FunctionExp(SQInteger ftype)
\r
1190 Lex(); Expect(_SC('('));
\r
1191 CreateFunction(_null_);
\r
1192 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
\r
1196 SQInteger base = -1;
\r
1197 SQInteger attrs = -1;
\r
1198 if(_token == TK_EXTENDS) {
\r
1199 Lex(); Expression();
\r
1200 base = _fs->TopTarget();
\r
1202 if(_token == TK_ATTR_OPEN) {
\r
1204 _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
\r
1205 ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
\r
1206 attrs = _fs->TopTarget();
\r
1209 if(attrs != -1) _fs->PopTarget();
\r
1210 if(base != -1) _fs->PopTarget();
\r
1211 _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);
\r
1212 ParseTableOrClass(_SC(';'));
\r
1214 void DelegateExpr()
\r
1216 Lex(); CommaExpr();
\r
1219 SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget();
\r
1220 _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);
\r
1225 Lex(); PushExpState();
\r
1226 _exst._class_or_delete = true;
\r
1227 _exst._funcarg = false;
\r
1229 es = PopExpState();
\r
1230 if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));
\r
1231 if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);
\r
1232 else Error(_SC("cannot delete a local"));
\r
1234 void PrefixIncDec(SQInteger token)
\r
1237 Lex(); PushExpState();
\r
1238 _exst._class_or_delete = true;
\r
1239 _exst._funcarg = false;
\r
1241 es = PopExpState();
\r
1242 if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);
\r
1244 SQInteger src = _fs->PopTarget();
\r
1245 _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
\r
1248 void CreateFunction(SQObject &name)
\r
1251 SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
\r
1252 funcstate->_name = name;
\r
1253 SQObject paramname;
\r
1254 funcstate->AddParameter(_fs->CreateString(_SC("this")));
\r
1255 funcstate->_sourcename = _sourcename;
\r
1256 SQInteger defparams = 0;
\r
1257 while(_token!=_SC(')')) {
\r
1258 if(_token == TK_VARPARAMS) {
\r
1259 if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
\r
1260 funcstate->_varparams = true;
\r
1262 if(_token != _SC(')')) Error(_SC("expected ')'"));
\r
1266 paramname = Expect(TK_IDENTIFIER);
\r
1267 funcstate->AddParameter(paramname);
\r
1268 if(_token == _SC('=')) {
\r
1271 funcstate->AddDefaultParam(_fs->TopTarget());
\r
1275 if(defparams > 0) Error(_SC("expected '='"));
\r
1277 if(_token == _SC(',')) Lex();
\r
1278 else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
\r
1282 for(SQInteger n = 0; n < defparams; n++) {
\r
1286 if(_token == _SC(':')) {
\r
1287 Lex(); Expect(_SC('('));
\r
1288 while(_token != _SC(')')) {
\r
1289 paramname = Expect(TK_IDENTIFIER);
\r
1290 //outers are treated as implicit local variables
\r
1291 funcstate->AddOuterValue(paramname);
\r
1292 if(_token == _SC(',')) Lex();
\r
1293 else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
\r
1298 SQFuncState *currchunk = _fs;
\r
1301 funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
\r
1302 funcstate->AddInstruction(_OP_RETURN, -1);
\r
1303 funcstate->SetStackSize(0);
\r
1304 //_fs->->_stacksize = _fs->_stacksize;
\r
1305 SQFunctionProto *func = funcstate->BuildProto();
\r
1306 #ifdef _DEBUG_DUMP
\r
1307 funcstate->Dump(func);
\r
1310 _fs->_functions.push_back(func);
\r
1311 _fs->PopChildState();
\r
1313 void CleanStack(SQInteger stacksize)
\r
1315 if(_fs->GetStackSize() != stacksize)
\r
1316 _fs->SetStackSize(stacksize);
\r
1318 void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
\r
1320 while(ntoresolve > 0) {
\r
1321 SQInteger pos = funcstate->_unresolvedbreaks.back();
\r
1322 funcstate->_unresolvedbreaks.pop_back();
\r
1323 //set the jmp instruction
\r
1324 funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
\r
1328 void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
\r
1330 while(ntoresolve > 0) {
\r
1331 SQInteger pos = funcstate->_unresolvedcontinues.back();
\r
1332 funcstate->_unresolvedcontinues.pop_back();
\r
1333 //set the jmp instruction
\r
1334 funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
\r
1341 SQObjectPtr _sourcename;
\r
1345 SQInteger _debugline;
\r
1346 SQInteger _debugop;
\r
1347 ExpStateVec _expstates;
\r
1348 SQChar *compilererror;
\r
1349 jmp_buf _errorjmp;
\r
1353 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
\r
1355 SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
\r
1356 return p.Compile(out);
\r