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)