sqcompiler.cpp 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964
  1. /*
  2. see copyright notice in squirrel.h
  3. */
  4. #include "sqpcheader.h"
  5. #ifndef NO_COMPILER
  6. #include <stdarg.h>
  7. #include <setjmp.h>
  8. #include "sqopcodes.h"
  9. #include "sqstring.h"
  10. #include "sqfuncproto.h"
  11. #include "sqcompiler.h"
  12. #include "sqfuncstate.h"
  13. #include "sqlexer.h"
  14. #include "sqvm.h"
  15. #include "sqtable.h"
  16. #define EXPR 1
  17. #define OBJECT 2
  18. #define BASE 3
  19. #define LOCAL 4
  20. #define OUTER 5
  21. struct SQExpState {
  22. SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */
  23. SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */
  24. bool donot_get; /* signal not to deref the next value */
  25. };
  26. #define MAX_COMPILER_ERROR_LEN 256
  27. struct SQScope {
  28. SQInteger outers;
  29. SQInteger stacksize;
  30. SQInteger nested;
  31. };
  32. #define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
  33. ++_scope.nested; \
  34. _scope.outers = _fs->_outers; \
  35. _scope.stacksize = _fs->GetStackSize();\
  36. _scope_consts.push_back(SQTable::Create(_ss(_vm),0));
  37. #define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \
  38. if(_fs->CountOuters(_scope.stacksize)) { \
  39. _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
  40. } \
  41. }
  42. #define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \
  43. _fs->SetStackSize(_scope.stacksize); \
  44. } \
  45. _scope = __oldscope__; \
  46. _scope_consts.pop_back();\
  47. }
  48. #define END_SCOPE() { SQInteger oldouters = _fs->_outers;\
  49. if(_fs->GetStackSize() != _scope.stacksize) { \
  50. _fs->SetStackSize(_scope.stacksize); \
  51. if(oldouters != _fs->_outers) { \
  52. _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
  53. } \
  54. } \
  55. _scope = __oldscope__; \
  56. }
  57. #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
  58. SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
  59. _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
  60. #define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
  61. __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
  62. if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
  63. if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
  64. _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
  65. class SQCompiler
  66. {
  67. public:
  68. SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename,
  69. bool raiseerror, bool lineinfo, bool show_warnings)
  70. {
  71. _vm=v;
  72. _lex.Init(_ss(v), rg, up,ThrowError,this);
  73. _sourcename = SQString::Create(_ss(v), sourcename);
  74. _lineinfo = lineinfo;_raiseerror = raiseerror;
  75. _show_warnings = show_warnings;
  76. _scope.outers = 0;
  77. _scope.stacksize = 0;
  78. _scope.nested = 0;
  79. _compilererror = NULL;
  80. _globals = SQTable::Create(_ss(_vm),0);
  81. }
  82. ~SQCompiler(){
  83. _table(_globals)->Finalize();
  84. _globals.Null();
  85. }
  86. static void ThrowError(void *ud, const SQChar *s) {
  87. SQCompiler *c = (SQCompiler *)ud;
  88. c->Error(s);
  89. }
  90. void Error(const SQChar *s, ...)
  91. {
  92. va_list vl;
  93. va_start(vl, s);
  94. scvsnprintf(error_buf, sizeof(error_buf), s, vl);
  95. va_end(vl);
  96. _compilererror = error_buf;
  97. longjmp(_errorjmp,1);
  98. }
  99. void Warning(const SQChar *s, ...)
  100. {
  101. if(!_show_warnings) return;
  102. va_list vl;
  103. va_start(vl, s);
  104. scvfprintf(stderr, s, vl);
  105. va_end(vl);
  106. }
  107. void CheckGlobalName(const SQObject &name, bool addIfNotExists=false, bool checkLocals=true){
  108. if(_table(_globals)->Exists(name)){
  109. if(checkLocals) Error(_SC("global '%s' already declared"), _stringval(name));
  110. else Warning(_SC("WARNING: %s:%d:%d global '%s' already declared will be shadowed\n"),
  111. _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
  112. }
  113. else if(checkLocals) CheckLocalNameScope(name, -1, false);
  114. if(addIfNotExists) {
  115. SQObjectPtr oname = name, otrue = true;
  116. _table(_globals)->NewSlot(oname, otrue);
  117. }
  118. }
  119. void CheckLocalNameScope(const SQObject &name, SQInteger scope, bool checkGlobals=true){
  120. SQInteger found = _fs->GetLocalVariable(name);
  121. if(found >= 0){
  122. SQLocalVarInfo &lvi = _fs->_vlocals[found];
  123. if(lvi._scope == scope)
  124. Error(_SC("local '%s' already declared"), _stringval(name));
  125. else
  126. Warning(_SC("WARNING: %s:%d:%d local '%s' already declared will be shadowed\n"),
  127. _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
  128. }
  129. else
  130. {
  131. found = _fs->FindOuterVariable(name);
  132. if(found >= 0) Warning(_SC("WARNING: %s:%d:%d outer variable '%s' already declared will be shadowed\n"),
  133. _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
  134. }
  135. if(checkGlobals) CheckGlobalName(name, false, false);
  136. }
  137. bool IsConstant(const SQObject &name,SQObject &e){
  138. SQObjectPtr val;
  139. for(int i=_scope.nested-1; i >= 0; --i){
  140. if(_table(_scope_consts[i])->Get(name,val)) {
  141. e = val;
  142. return true;
  143. }
  144. }
  145. if(_table(_ss(_vm)->_consts)->Get(name,val)) {
  146. e = val;
  147. return true;
  148. }
  149. return false;
  150. }
  151. SQInteger ExpressionConstant(SQObject id) {
  152. SQObject constant;
  153. SQInteger epos;
  154. if(IsConstant(id, constant)) {
  155. /* Handle named constant */
  156. SQObjectPtr constval;
  157. SQObject constid;
  158. if(type(constant) == OT_TABLE) {
  159. Expect('.');
  160. constid = Expect(TK_IDENTIFIER);
  161. if(!_table(constant)->Get(constid, constval)) {
  162. constval.Null();
  163. Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
  164. }
  165. }
  166. else {
  167. constval = constant;
  168. }
  169. epos = _fs->PushTarget();
  170. /* generate direct or literal function depending on size */
  171. SQObjectType ctype = type(constval);
  172. switch(ctype) {
  173. case OT_INTEGER: EmitLoadConstInt(_integer(constval),epos); break;
  174. case OT_FLOAT: EmitLoadConstFloat(_float(constval),epos); break;
  175. default: _fs->AddInstruction(_OP_LOAD,epos,_fs->GetConstant(constval)); break;
  176. }
  177. } else {
  178. Error(_SC("invalid constant [%s]"), _stringval(id));
  179. }
  180. return epos;
  181. }
  182. void CheckConstsExists(const SQObjectPtr &key){
  183. int found = -1;
  184. for(int i=_scope.nested-1; i >= 0; --i){
  185. if(_table(_scope_consts[i])->Exists(key)) {
  186. found = i+1;
  187. break;
  188. }
  189. }
  190. if(found < 0 && _table(_ss(_vm)->_consts)->Exists(key)) found = 0;
  191. if(found == _scope.nested) {
  192. Error(_SC("constant '%s' already exists\n"), _stringval(key));
  193. }
  194. if(found >= 0) Warning(_SC("WARNING: %s:%d:%d an already defined constant '%s' will be shadowed\n"),
  195. _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(key));
  196. }
  197. bool ConstsGet(const SQObjectPtr &key,SQObjectPtr &val){
  198. for(int i=_scope.nested-1; i >= 0; --i){
  199. if(_table(_scope_consts[i])->Get(key,val)) return true;
  200. }
  201. return _table(_ss(_vm)->_consts)->Get(key,val);
  202. }
  203. bool ConstsNewSlot(const SQObjectPtr &key, const SQObjectPtr &val){
  204. if(_scope.nested) return _table(_scope_consts[_scope.nested-1])->NewSlot(key,val);
  205. return _table(_ss(_vm)->_consts)->NewSlot(key,val);
  206. }
  207. void Lex(){ _token = _lex.Lex();}
  208. SQObjectPtr GetTokenObject(SQInteger tok)
  209. {
  210. SQObjectPtr ret;
  211. switch(tok)
  212. {
  213. case TK_IDENTIFIER:
  214. ret = _fs->CreateString(_lex._svalue);
  215. break;
  216. case TK_STRING_LITERAL:
  217. ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
  218. break;
  219. case TK_INTEGER:
  220. ret = SQObjectPtr(_lex._nvalue);
  221. break;
  222. case TK_FLOAT:
  223. ret = SQObjectPtr(_lex._fvalue);
  224. break;
  225. }
  226. Lex();
  227. return ret;
  228. }
  229. void ErrorIfNotToken(SQInteger tok){
  230. if(_token != tok) {
  231. if(((_token == TK_CONSTRUCTOR) || (_token == TK_DESTRUCTOR)) && tok == TK_IDENTIFIER) {
  232. //do nothing
  233. }
  234. else {
  235. const SQChar *etypename;
  236. if(tok > 255) {
  237. switch(tok)
  238. {
  239. case TK_IDENTIFIER:
  240. etypename = _SC("IDENTIFIER");
  241. break;
  242. case TK_STRING_LITERAL:
  243. etypename = _SC("STRING_LITERAL");
  244. break;
  245. case TK_INTEGER:
  246. etypename = _SC("INTEGER");
  247. break;
  248. case TK_FLOAT:
  249. etypename = _SC("FLOAT");
  250. break;
  251. default:
  252. etypename = _lex.Tok2Str(tok);
  253. }
  254. Error(_SC("expected '%s'"), etypename);
  255. }
  256. Error(_SC("expected '%c'"), tok);
  257. }
  258. }
  259. }
  260. SQObject Expect(SQInteger tok)
  261. {
  262. ErrorIfNotToken(tok);
  263. return GetTokenObject(tok);
  264. }
  265. bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
  266. void OptionalSemicolon()
  267. {
  268. if(_token == _SC(';')) { Lex(); return; }
  269. if(!IsEndOfStatement()) {
  270. Error(_SC("end of statement expected (; or lf) found (%d)"), _token);
  271. }
  272. }
  273. void MoveIfCurrentTargetIsLocal() {
  274. SQInteger trg = _fs->TopTarget();
  275. if(_fs->IsLocal(trg)) {
  276. trg = _fs->PopTarget(); //no pops the target and move it
  277. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
  278. }
  279. }
  280. bool Compile(SQObjectPtr &o)
  281. {
  282. _debugline = 1;
  283. _debugop = 0;
  284. SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
  285. funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
  286. _fs = &funcstate;
  287. _fs->AddParameter(_fs->CreateString(_SC("this")), _scope.nested+1);
  288. _fs->AddParameter(_fs->CreateString(_SC("vargv")), _scope.nested+1);
  289. _fs->_varparams = true;
  290. _fs->_sourcename = _sourcename;
  291. SQInteger stacksize = _fs->GetStackSize();
  292. if(setjmp(_errorjmp) == 0) {
  293. Lex();
  294. while(_token > 0){
  295. Statement();
  296. if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
  297. }
  298. _fs->SetStackSize(stacksize);
  299. _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
  300. _fs->AddInstruction(_OP_RETURN, 0xFF);
  301. _fs->SetStackSize(0);
  302. o =_fs->BuildProto();
  303. #ifdef _DEBUG_DUMP
  304. _fs->Dump(_funcproto(o));
  305. #endif
  306. }
  307. else {
  308. if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
  309. _ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
  310. _lex._currentline, _lex._currentcolumn);
  311. }
  312. _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);
  313. return false;
  314. }
  315. return true;
  316. }
  317. void Statements()
  318. {
  319. while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
  320. Statement();
  321. if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
  322. }
  323. }
  324. void Statement(bool closeframe = true)
  325. {
  326. _fs->AddLineInfos(_lex._currentline, _lineinfo);
  327. switch(_token){
  328. case _SC(';'): Lex(); break;
  329. case TK_IF: IfStatement(); break;
  330. case TK_WHILE: WhileStatement(); break;
  331. case TK_DO: DoWhileStatement(); break;
  332. case TK_FOR: ForStatement(); break;
  333. case TK_FOREACH: ForEachStatement(); break;
  334. case TK_SWITCH: SwitchStatement(); break;
  335. case TK_LOCAL_CHAR_T:
  336. case TK_LOCAL_WCHAR_T:
  337. case TK_LOCAL_BOOL_T:
  338. case TK_LOCAL_TABLE_T:
  339. case TK_LOCAL_ARRAY_T:
  340. case TK_LOCAL_INT8_T:
  341. case TK_LOCAL_INT16_T:
  342. case TK_LOCAL_INT32_T:
  343. case TK_LOCAL_INT64_T:
  344. case TK_LOCAL_INT_T:
  345. case TK_LOCAL_UINT8_T:
  346. case TK_LOCAL_UINT16_T:
  347. case TK_LOCAL_UINT32_T:
  348. case TK_LOCAL_UINT64_T:
  349. case TK_LOCAL_UINT_T:
  350. case TK_LOCAL_FLOAT_T:
  351. case TK_LOCAL_DOUBLE_T:
  352. case TK_LOCAL_LONG_DOUBLE_T:
  353. //case TK_CONST:
  354. case TK_LOCAL: LocalDeclStatement(); break;
  355. case TK_RETURN:
  356. case TK_YIELD: {
  357. SQOpcode op;
  358. if(_token == TK_RETURN) {
  359. op = _OP_RETURN;
  360. }
  361. else {
  362. op = _OP_YIELD;
  363. _fs->_bgenerator = true;
  364. }
  365. Lex();
  366. if(!IsEndOfStatement()) {
  367. SQInteger retexp = _fs->GetCurrentPos()+1;
  368. CommaExpr(true);
  369. if(op == _OP_RETURN && _fs->_traps > 0)
  370. _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
  371. _fs->_returnexp = retexp;
  372. _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());
  373. }
  374. else{
  375. if(op == _OP_RETURN && _fs->_traps > 0)
  376. _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
  377. _fs->_returnexp = -1;
  378. _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
  379. }
  380. break;}
  381. case TK_BREAK:
  382. if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
  383. if(_fs->_breaktargets.top() > 0){
  384. _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
  385. }
  386. RESOLVE_OUTERS();
  387. _fs->AddInstruction(_OP_JMP, 0, -1234);
  388. _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
  389. Lex();
  390. break;
  391. case TK_CONTINUE:
  392. if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
  393. if(_fs->_continuetargets.top() > 0) {
  394. _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
  395. }
  396. RESOLVE_OUTERS();
  397. _fs->AddInstruction(_OP_JMP, 0, -1234);
  398. _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
  399. Lex();
  400. break;
  401. case TK_FUNCTION:
  402. FunctionStatement();
  403. break;
  404. case TK_CLASS:
  405. ClassStatement();
  406. break;
  407. case TK_ENUM:
  408. EnumStatement();
  409. break;
  410. case _SC('{'):{
  411. BEGIN_SCOPE();
  412. Lex();
  413. Statements();
  414. Expect(_SC('}'));
  415. if(closeframe) {
  416. END_SCOPE();
  417. }
  418. else {
  419. END_SCOPE_NO_CLOSE();
  420. }
  421. }
  422. break;
  423. case TK_TRY:
  424. TryCatchStatement();
  425. break;
  426. case TK_THROW:
  427. Lex();
  428. CommaExpr();
  429. _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
  430. break;
  431. case TK_CONST:
  432. {
  433. Lex();
  434. SQObject id = Expect(TK_IDENTIFIER);
  435. Expect('=');
  436. SQObjectPtr strongid = id;
  437. CheckLocalNameScope(id, _scope.nested);
  438. CheckConstsExists(strongid);
  439. SQObject val = ExpectScalar();
  440. OptionalSemicolon();
  441. ConstsNewSlot(strongid,SQObjectPtr(val));
  442. strongid.Null();
  443. }
  444. break;
  445. default:
  446. CommaExpr();
  447. _fs->DiscardTarget();
  448. /*
  449. //Fagiano says that this is not a bug
  450. //and with this modification stack grow by one lement all the time
  451. if(_token == TK_IDENTIFIER){
  452. CommaExpr();
  453. if(_token == TK_IDENTIFIER){
  454. Error(_SC(" '=' expected near '%s'"), _lex._svalue);
  455. }
  456. }
  457. */
  458. //_fs->PopTarget();
  459. break;
  460. }
  461. _fs->SnoozeOpt();
  462. }
  463. void EmitDerefOp(SQOpcode op)
  464. {
  465. SQInteger val = _fs->PopTarget();
  466. SQInteger key = _fs->PopTarget();
  467. SQInteger src = _fs->PopTarget();
  468. _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
  469. }
  470. void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
  471. {
  472. SQInteger p2 = _fs->PopTarget(); //src in OP_GET
  473. SQInteger p1 = _fs->PopTarget(); //key in OP_GET
  474. _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
  475. }
  476. void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)
  477. {
  478. /* Generate code depending on the expression type */
  479. switch(etype) {
  480. case LOCAL:{
  481. SQInteger p2 = _fs->PopTarget(); //src in OP_GET
  482. SQInteger p1 = _fs->PopTarget(); //key in OP_GET
  483. _fs->PushTarget(p1);
  484. //EmitCompArithLocal(tok, p1, p1, p2);
  485. _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);
  486. _fs->SnoozeOpt(); //FIX: stop optimizer in retargeting opcode
  487. }
  488. break;
  489. case OBJECT:
  490. case BASE:
  491. {
  492. SQInteger val = _fs->PopTarget();
  493. SQInteger key = _fs->PopTarget();
  494. SQInteger src = _fs->PopTarget();
  495. /* _OP_COMPARITH mixes dest obj and source val in the arg1 */
  496. _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));
  497. }
  498. break;
  499. case OUTER:
  500. {
  501. SQInteger val = _fs->TopTarget();
  502. SQInteger tmp = _fs->PushTarget();
  503. _fs->AddInstruction(_OP_GETOUTER, tmp, pos);
  504. _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);
  505. _fs->PopTarget();
  506. _fs->PopTarget();
  507. _fs->AddInstruction(_OP_SETOUTER, _fs->PushTarget(), pos, tmp);
  508. }
  509. break;
  510. }
  511. }
  512. void CommaExpr(bool warningAssign=false)
  513. {
  514. for(Expression(warningAssign);_token == ',';_fs->PopTarget(), Lex(), CommaExpr(warningAssign));
  515. }
  516. void ErrorIfConst(){
  517. SQLocalVarInfo &vsrc = _fs->_vlocals[_fs->TopTarget()];
  518. //printf("%d %d %d %d %s\n", __LINE__, vsrc._scope, vsrc._type, vsrc._pos, vsrc._name._unVal.pString ? _stringval(vsrc._name) : "?");
  519. if(vsrc._type & _VAR_CONST) Error(_SC("can't assign to a const variable"));
  520. }
  521. void Expression(bool warningAssign=false)
  522. {
  523. SQExpState es = _es;
  524. _es.etype = EXPR;
  525. _es.epos = -1;
  526. _es.donot_get = false;
  527. LogicalOrExp();
  528. switch(_token) {
  529. case _SC('='):
  530. case TK_NEWSLOT:
  531. case TK_MINUSEQ:
  532. case TK_PLUSEQ:
  533. case TK_MULEQ:
  534. case TK_DIVEQ:
  535. case TK_MODEQ:{
  536. SQInteger op = _token;
  537. SQInteger ds = _es.etype;
  538. SQInteger pos = _es.epos;
  539. if(ds == EXPR) Error(_SC("can't assign expression"));
  540. else if(ds == BASE) Error(_SC("'base' cannot be modified"));
  541. Lex(); Expression();
  542. switch(op){
  543. case TK_NEWSLOT:
  544. if(ds == OBJECT || ds == BASE)
  545. EmitDerefOp(_OP_NEWSLOT);
  546. else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
  547. Error(_SC("can't 'create' a local slot"));
  548. break;
  549. case _SC('='): //ASSIGN
  550. if(warningAssign) Warning(_SC("WARNING: making assignment at line %d:%d maybe is not what you want\n"),
  551. _lex._currentline, _lex._currentcolumn);
  552. switch(ds) {
  553. case LOCAL:
  554. {
  555. SQInteger src = _fs->PopTarget();
  556. SQInteger dst = _fs->TopTarget();
  557. _fs->AddInstruction(_OP_MOVE, dst, src);
  558. }
  559. break;
  560. case OBJECT:
  561. case BASE:
  562. EmitDerefOp(_OP_SET);
  563. break;
  564. case OUTER:
  565. {
  566. SQInteger src = _fs->PopTarget();
  567. SQInteger dst = _fs->PushTarget();
  568. _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
  569. }
  570. }
  571. break;
  572. case TK_MINUSEQ:
  573. case TK_PLUSEQ:
  574. case TK_MULEQ:
  575. case TK_DIVEQ:
  576. case TK_MODEQ:
  577. EmitCompoundArith(op, ds, pos);
  578. break;
  579. }
  580. }
  581. break;
  582. case _SC('?'): {
  583. Lex();
  584. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  585. SQInteger jzpos = _fs->GetCurrentPos();
  586. SQInteger trg = _fs->PushTarget();
  587. Expression();
  588. SQInteger first_exp = _fs->PopTarget();
  589. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  590. SQInteger endfirstexp = _fs->GetCurrentPos();
  591. _fs->AddInstruction(_OP_JMP, 0, 0);
  592. Expect(_SC(':'));
  593. SQInteger jmppos = _fs->GetCurrentPos();
  594. Expression();
  595. SQInteger second_exp = _fs->PopTarget();
  596. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  597. _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
  598. _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
  599. _fs->SnoozeOpt();
  600. }
  601. break;
  602. }
  603. _es = es;
  604. }
  605. template<typename T> void INVOKE_EXP(T f)
  606. {
  607. SQExpState es = _es;
  608. _es.etype = EXPR;
  609. _es.epos = -1;
  610. _es.donot_get = false;
  611. (this->*f)();
  612. _es = es;
  613. }
  614. template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)
  615. {
  616. Lex();
  617. INVOKE_EXP(f);
  618. SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
  619. _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
  620. }
  621. void LogicalOrExp()
  622. {
  623. LogicalAndExp();
  624. for(;;) if(_token == TK_OR) {
  625. SQInteger first_exp = _fs->PopTarget();
  626. SQInteger trg = _fs->PushTarget();
  627. _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
  628. SQInteger jpos = _fs->GetCurrentPos();
  629. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  630. Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp);
  631. _fs->SnoozeOpt();
  632. SQInteger second_exp = _fs->PopTarget();
  633. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  634. _fs->SnoozeOpt();
  635. _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
  636. break;
  637. }else return;
  638. }
  639. void LogicalAndExp()
  640. {
  641. BitwiseOrExp();
  642. for(;;) switch(_token) {
  643. case TK_AND: {
  644. SQInteger first_exp = _fs->PopTarget();
  645. SQInteger trg = _fs->PushTarget();
  646. _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
  647. SQInteger jpos = _fs->GetCurrentPos();
  648. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  649. Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp);
  650. _fs->SnoozeOpt();
  651. SQInteger second_exp = _fs->PopTarget();
  652. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  653. _fs->SnoozeOpt();
  654. _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
  655. break;
  656. }
  657. default:
  658. return;
  659. }
  660. }
  661. void BitwiseOrExp()
  662. {
  663. BitwiseXorExp();
  664. for(;;) if(_token == _SC('|'))
  665. {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
  666. }else return;
  667. }
  668. void BitwiseXorExp()
  669. {
  670. BitwiseAndExp();
  671. for(;;) if(_token == _SC('^'))
  672. {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
  673. }else return;
  674. }
  675. void BitwiseAndExp()
  676. {
  677. EqExp();
  678. for(;;) if(_token == _SC('&'))
  679. {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
  680. }else return;
  681. }
  682. void EqExp()
  683. {
  684. CompExp();
  685. for(;;) switch(_token) {
  686. case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
  687. case TK_EQ_IDENTITY :BIN_EXP(_OP_EQI, &SQCompiler::CompExp); break;
  688. case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
  689. case TK_NE_IDENTITY: BIN_EXP(_OP_NEI, &SQCompiler::CompExp); break;
  690. case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
  691. default: return;
  692. }
  693. }
  694. void CompExp()
  695. {
  696. ShiftExp();
  697. for(;;) switch(_token) {
  698. case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
  699. case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
  700. case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
  701. case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
  702. case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;
  703. case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break;
  704. default: return;
  705. }
  706. }
  707. void ShiftExp()
  708. {
  709. PlusExp();
  710. for(;;) switch(_token) {
  711. case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
  712. case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
  713. case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
  714. default: return;
  715. }
  716. }
  717. SQOpcode ChooseArithOpByToken(SQInteger tok)
  718. {
  719. switch(tok) {
  720. case TK_PLUSEQ: case '+': return _OP_ADD;
  721. case TK_MINUSEQ: case '-': return _OP_SUB;
  722. case TK_MULEQ: case '*': return _OP_MUL;
  723. case TK_DIVEQ: case '/': return _OP_DIV;
  724. case TK_MODEQ: case '%': return _OP_MOD;
  725. default: assert(0);
  726. }
  727. return _OP_ADD;
  728. }
  729. SQInteger ChooseCompArithCharByToken(SQInteger tok)
  730. {
  731. SQInteger oper;
  732. switch(tok){
  733. case TK_MINUSEQ: oper = '-'; break;
  734. case TK_PLUSEQ: oper = '+'; break;
  735. case TK_MULEQ: oper = '*'; break;
  736. case TK_DIVEQ: oper = '/'; break;
  737. case TK_MODEQ: oper = '%'; break;
  738. default: oper = 0; //shut up compiler
  739. assert(0); break;
  740. };
  741. return oper;
  742. }
  743. void PlusExp()
  744. {
  745. MultExp();
  746. for(;;) switch(_token) {
  747. case _SC('+'): case _SC('-'):
  748. BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
  749. default: return;
  750. }
  751. }
  752. void MultExp()
  753. {
  754. PrefixedExpr();
  755. for(;;) switch(_token) {
  756. case _SC('*'): case _SC('/'): case _SC('%'):
  757. BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;
  758. default: return;
  759. }
  760. }
  761. //if 'pos' != -1 the previous variable is a local variable
  762. void PrefixedExpr()
  763. {
  764. SQInteger pos = Factor();
  765. for(;;) {
  766. switch(_token) {
  767. case _SC('.'):
  768. pos = -1;
  769. Lex();
  770. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
  771. if(_es.etype==BASE) {
  772. Emit2ArgsOP(_OP_GET);
  773. pos = _fs->TopTarget();
  774. _es.etype = EXPR;
  775. _es.epos = pos;
  776. }
  777. else {
  778. if(NeedGet()) {
  779. Emit2ArgsOP(_OP_GET);
  780. }
  781. _es.etype = OBJECT;
  782. }
  783. break;
  784. case _SC('['):
  785. if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
  786. Lex(); Expression(); Expect(_SC(']'));
  787. pos = -1;
  788. if(_es.etype==BASE) {
  789. Emit2ArgsOP(_OP_GET);
  790. pos = _fs->TopTarget();
  791. _es.etype = EXPR;
  792. _es.epos = pos;
  793. }
  794. else {
  795. if(NeedGet()) {
  796. Emit2ArgsOP(_OP_GET);
  797. }
  798. _es.etype = OBJECT;
  799. }
  800. break;
  801. case TK_MINUSMINUS:
  802. case TK_PLUSPLUS:
  803. {
  804. if(IsEndOfStatement()) return;
  805. SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
  806. Lex();
  807. switch(_es.etype)
  808. {
  809. case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
  810. case OBJECT:
  811. case BASE:
  812. Emit2ArgsOP(_OP_PINC, diff);
  813. break;
  814. case LOCAL: {
  815. SQInteger src = _fs->PopTarget();
  816. _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
  817. }
  818. break;
  819. case OUTER: {
  820. SQInteger tmp1 = _fs->PushTarget();
  821. SQInteger tmp2 = _fs->PushTarget();
  822. _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
  823. _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff);
  824. _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
  825. _fs->PopTarget();
  826. }
  827. }
  828. }
  829. return;
  830. break;
  831. case _SC('('):
  832. switch(_es.etype) {
  833. case OBJECT: {
  834. SQInteger key = _fs->PopTarget(); /* location of the key */
  835. SQInteger table = _fs->PopTarget(); /* location of the object */
  836. SQInteger closure = _fs->PushTarget(); /* location for the closure */
  837. SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
  838. _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
  839. }
  840. break;
  841. case BASE:
  842. //Emit2ArgsOP(_OP_GET);
  843. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  844. break;
  845. case OUTER:
  846. _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
  847. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  848. break;
  849. default:
  850. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  851. }
  852. _es.etype = EXPR;
  853. Lex();
  854. FunctionCallArgs();
  855. break;
  856. default: return;
  857. }
  858. }
  859. }
  860. SQInteger Factor()
  861. {
  862. _es.etype = EXPR;
  863. switch(_token)
  864. {
  865. case TK_STRING_LITERAL:
  866. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
  867. Lex();
  868. break;
  869. case TK_BASE:
  870. Lex();
  871. _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
  872. _es.etype = BASE;
  873. _es.epos = _fs->TopTarget();
  874. return (_es.epos);
  875. break;
  876. case TK_IDENTIFIER:
  877. case TK_CONSTRUCTOR:
  878. case TK_DESTRUCTOR:
  879. case TK_THIS:{
  880. SQObject id;
  881. SQObject constant;
  882. switch(_token) {
  883. case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
  884. case TK_THIS: id = _fs->CreateString(_SC("this"), 4); break;
  885. case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"), 11); break;
  886. case TK_DESTRUCTOR: id = _fs->CreateString(_SC("destructor"), 10); break;
  887. }
  888. SQInteger pos = -1;
  889. Lex();
  890. if((pos = _fs->GetLocalVariable(id)) != -1) {
  891. /* Handle a local variable (includes 'this') */
  892. _fs->PushTarget(pos);
  893. _es.etype = LOCAL;
  894. _es.epos = pos;
  895. }
  896. else if((pos = _fs->GetOuterVariable(id)) != -1) {
  897. /* Handle a free var */
  898. if(NeedGet()) {
  899. _es.epos = _fs->PushTarget();
  900. _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);
  901. /* _es.etype = EXPR; already default value */
  902. }
  903. else {
  904. _es.etype = OUTER;
  905. _es.epos = pos;
  906. }
  907. }
  908. else if(IsConstant(id, constant)) {
  909. /* Handle named constant */
  910. SQObjectPtr constval;
  911. SQObject constid;
  912. if(type(constant) == OT_TABLE) {
  913. Expect('.');
  914. constid = Expect(TK_IDENTIFIER);
  915. if(!_table(constant)->Get(constid, constval)) {
  916. constval.Null();
  917. Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
  918. }
  919. }
  920. else {
  921. constval = constant;
  922. }
  923. _es.epos = _fs->PushTarget();
  924. /* generate direct or literal function depending on size */
  925. SQObjectType ctype = type(constval);
  926. switch(ctype) {
  927. case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
  928. case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
  929. default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
  930. }
  931. _es.etype = EXPR;
  932. }
  933. else {
  934. /* Handle a non-local variable, aka a field. Push the 'this' pointer on
  935. * the virtual stack (always found in offset 0, so no instruction needs to
  936. * be generated), and push the key next. Generate an _OP_LOAD instruction
  937. * for the latter. If we are not using the variable as a dref expr, generate
  938. * the _OP_GET instruction.
  939. */
  940. _fs->PushTarget(0);
  941. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  942. if(NeedGet()) {
  943. Emit2ArgsOP(_OP_GET);
  944. }
  945. _es.etype = OBJECT;
  946. }
  947. return _es.epos;
  948. }
  949. break;
  950. case TK_DOUBLE_COLON: // "::"
  951. _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
  952. _es.etype = OBJECT;
  953. _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
  954. _es.epos = -1;
  955. return _es.epos;
  956. break;
  957. case TK_NULL:
  958. _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
  959. Lex();
  960. break;
  961. case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break;
  962. case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;
  963. case TK_TRUE: case TK_FALSE:
  964. _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
  965. Lex();
  966. break;
  967. case _SC('['): {
  968. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
  969. SQInteger apos = _fs->GetCurrentPos(),key = 0;
  970. Lex();
  971. while(_token != _SC(']')) {
  972. Expression();
  973. if(_token == _SC(',')) Lex();
  974. SQInteger val = _fs->PopTarget();
  975. SQInteger array = _fs->TopTarget();
  976. _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);
  977. key++;
  978. }
  979. _fs->SetIntructionParam(apos, 1, key);
  980. Lex();
  981. }
  982. break;
  983. case _SC('{'):
  984. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  985. Lex();ParseTableOrClass(_SC(','),_SC('}'));
  986. break;
  987. case TK_FUNCTION: FunctionExp(_token);break;
  988. case _SC('@'): FunctionExp(_token,true);break;
  989. case TK_CLASS: Lex(); ClassExp();break;
  990. case _SC('-'):
  991. Lex();
  992. switch(_token) {
  993. case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
  994. case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
  995. default: UnaryOP(_OP_NEG);
  996. }
  997. break;
  998. case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
  999. case _SC('~'):
  1000. Lex();
  1001. if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
  1002. UnaryOP(_OP_BWNOT);
  1003. break;
  1004. case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
  1005. case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
  1006. case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
  1007. case TK_MINUSMINUS :
  1008. case TK_PLUSPLUS :PrefixIncDec(_token); break;
  1009. case TK_DELETE : DeleteExpr(); break;
  1010. case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
  1011. break;
  1012. case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break;
  1013. case TK___FILE__:
  1014. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename));
  1015. Lex();
  1016. break;
  1017. case TK___FUNCTION__:
  1018. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->_name));
  1019. Lex();
  1020. break;
  1021. case TK_IGNORE:
  1022. //Warning("Keyword ignored \"%s\" at line %d:%d\n", _lex.Tok2Str(_token),
  1023. // _lex._currentline, _lex._currentcolumn);
  1024. Lex(); Factor();
  1025. break;
  1026. default: Error(_SC("expression expected"));
  1027. }
  1028. return -1;
  1029. }
  1030. void EmitLoadConstInt(SQInteger value,SQInteger target)
  1031. {
  1032. if(target < 0) {
  1033. target = _fs->PushTarget();
  1034. }
  1035. if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?
  1036. _fs->AddInstruction(_OP_LOADINT, target,value);
  1037. }
  1038. else {
  1039. _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
  1040. }
  1041. }
  1042. void EmitLoadConstFloat(SQFloat value,SQInteger target)
  1043. {
  1044. if(target < 0) {
  1045. target = _fs->PushTarget();
  1046. }
  1047. if(sizeof(SQFloat) == sizeof(SQInt32)) {
  1048. _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
  1049. }
  1050. else {
  1051. _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
  1052. }
  1053. }
  1054. void UnaryOP(SQOpcode op)
  1055. {
  1056. PrefixedExpr();
  1057. SQInteger src = _fs->PopTarget();
  1058. _fs->AddInstruction(op, _fs->PushTarget(), src);
  1059. }
  1060. bool NeedGet()
  1061. {
  1062. switch(_token) {
  1063. case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:
  1064. case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ:
  1065. return false;
  1066. case TK_PLUSPLUS: case TK_MINUSMINUS:
  1067. if (!IsEndOfStatement()) {
  1068. return false;
  1069. }
  1070. break;
  1071. }
  1072. return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
  1073. }
  1074. void FunctionCallArgs()
  1075. {
  1076. SQInteger nargs = 1;//this
  1077. while(_token != _SC(')')) {
  1078. Expression();
  1079. MoveIfCurrentTargetIsLocal();
  1080. nargs++;
  1081. if(_token == _SC(',')){
  1082. Lex();
  1083. if(_token == ')') Error(_SC("expression expected, found ')'"));
  1084. }
  1085. }
  1086. Lex();
  1087. for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
  1088. SQInteger stackbase = _fs->PopTarget();
  1089. SQInteger closure = _fs->PopTarget();
  1090. _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
  1091. }
  1092. void ParseTableOrClass(SQInteger separator,SQInteger terminator)
  1093. {
  1094. SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
  1095. SQObject type_name;
  1096. bool isClass = separator == ';'; //hack recognizes a table/class from the separator
  1097. while(_token != terminator) {
  1098. bool hasattrs = false;
  1099. bool isstatic = false;
  1100. bool isprivate = false;
  1101. //check if is an attribute
  1102. if(isClass) {
  1103. if(_token == TK_ATTR_OPEN) {
  1104. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();
  1105. ParseTableOrClass(',',TK_ATTR_CLOSE);
  1106. hasattrs = true;
  1107. }
  1108. if(_token == TK_STATIC) {
  1109. isstatic = true;
  1110. Lex();
  1111. }
  1112. else if(_token == TK_PUBLIC) {
  1113. Lex();
  1114. }
  1115. else if(_token == TK_PRIVATE) {
  1116. isprivate = true;
  1117. Lex();
  1118. }
  1119. }
  1120. switch(_token) {
  1121. case TK_FUNCTION:
  1122. case TK_CONSTRUCTOR:
  1123. case TK_DESTRUCTOR:{
  1124. SQInteger tk = _token;
  1125. Lex();
  1126. SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) :
  1127. _fs->CreateString(tk == TK_CONSTRUCTOR ? _SC("constructor") : _SC("destructor"));
  1128. Expect(_SC('('));
  1129. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1130. CreateFunction(id);
  1131. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1132. }
  1133. break;
  1134. case _SC('['):
  1135. Lex(); CommaExpr(); Expect(_SC(']'));
  1136. Expect(_SC('=')); Expression();
  1137. break;
  1138. case TK_STRING_LITERAL: //JSON
  1139. case TK_IDENTIFIER: {//JSON
  1140. SQObjectPtr obj = GetTokenObject(_token);
  1141. SQInteger next_token = _SC('=');
  1142. if(_token == _SC(':')){
  1143. if(isClass){
  1144. //class field with type annotation
  1145. Lex();
  1146. type_name = Expect(TK_IDENTIFIER);
  1147. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(obj));
  1148. _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(), 1);
  1149. break;
  1150. }
  1151. else
  1152. {
  1153. next_token = _token;
  1154. }
  1155. }
  1156. Expect(next_token);
  1157. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(obj));
  1158. Expression();
  1159. break;
  1160. }
  1161. default :
  1162. ErrorIfNotToken(TK_IDENTIFIER);
  1163. }
  1164. if(_token == separator) Lex();//optional comma/semicolon
  1165. nkeys++;
  1166. SQInteger val = _fs->PopTarget();
  1167. SQInteger key = _fs->PopTarget();
  1168. SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
  1169. assert((hasattrs && (attrs == key-1)) || !hasattrs);
  1170. unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
  1171. SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
  1172. if(isClass) {
  1173. _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
  1174. }
  1175. else {
  1176. _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
  1177. }
  1178. }
  1179. if(separator == _SC(',')) //hack recognizes a table from the separator
  1180. _fs->SetIntructionParam(tpos, 1, nkeys);
  1181. Lex();
  1182. }
  1183. void LocalDeclStatement()
  1184. {
  1185. SQObject varname;
  1186. bool is_const_declaration = _token == TK_CONST;
  1187. bool is_reference_declaration = false;
  1188. SQInteger declType = _token;
  1189. Lex();
  1190. if( _token == TK_FUNCTION) {
  1191. Lex();
  1192. varname = Expect(TK_IDENTIFIER);
  1193. CheckLocalNameScope(varname, _scope.nested);
  1194. Expect(_SC('('));
  1195. #if 1 //doing this way works but prevents garbage collection when doing multiple reloads on the same vm
  1196. //the following is an attempt to allow local declared functions be called recursivelly
  1197. SQInteger old_pos = _fs->GetCurrentPos(); //save current instructions position
  1198. _fs->PushLocalVariable(varname, _scope.nested, _VAR_CLOSURE); //add function name to find it as outer var if needed
  1199. //-1 to compensate default parameters when relocating
  1200. CreateFunction(varname,false, -1);
  1201. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1202. //rellocate any stack operation (default parameters & _OP_Closure)
  1203. for(int i=old_pos+1, curr_pos = _fs->GetCurrentPos(); i <= curr_pos; ++i){
  1204. SQInstruction & inst = _fs->GetInstruction(i);
  1205. _fs->SetIntructionParam(i, 0, inst._arg0 -1);
  1206. }
  1207. _fs->PopTarget();
  1208. #else
  1209. CreateFunction(varname,false);
  1210. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1211. _fs->PopTarget();
  1212. _fs->PushLocalVariable(varname, _scope.nested, _VAR_CLOSURE);
  1213. #endif
  1214. return;
  1215. }
  1216. do {
  1217. if(_token == _SC('&')){
  1218. is_reference_declaration = true;
  1219. Lex();
  1220. }
  1221. varname = Expect(TK_IDENTIFIER);
  1222. CheckLocalNameScope(varname, _scope.nested);
  1223. if(_token == _SC('=')) {
  1224. Lex(); Expression();
  1225. SQInteger src = _fs->PopTarget();
  1226. SQInteger dest = _fs->PushTarget();
  1227. if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
  1228. declType = _VAR_ANY;
  1229. }
  1230. else if(is_const_declaration || is_reference_declaration)
  1231. Error(_SC("const/reference '%s' need an initializer"), _stringval(varname));
  1232. else{
  1233. SQInteger dest = _fs->PushTarget();
  1234. switch(declType){
  1235. case TK_LOCAL_CHAR_T:
  1236. case TK_LOCAL_WCHAR_T:
  1237. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1238. declType = _VAR_STRING;
  1239. break;
  1240. case TK_LOCAL_BOOL_T:
  1241. //default value false
  1242. _fs->AddInstruction(_OP_LOADBOOL, dest,0);
  1243. declType = _VAR_BOOL;
  1244. break;
  1245. case TK_LOCAL_TABLE_T:
  1246. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1247. declType = _VAR_TABLE;
  1248. break;
  1249. case TK_LOCAL_ARRAY_T:
  1250. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1251. declType = _VAR_ARRAY;
  1252. break;
  1253. case TK_LOCAL_INT8_T:
  1254. case TK_LOCAL_INT16_T:
  1255. case TK_LOCAL_INT32_T:
  1256. case TK_LOCAL_INT64_T:
  1257. case TK_LOCAL_INT_T:
  1258. case TK_LOCAL_UINT8_T:
  1259. case TK_LOCAL_UINT16_T:
  1260. case TK_LOCAL_UINT32_T:
  1261. case TK_LOCAL_UINT64_T:
  1262. case TK_LOCAL_UINT_T:
  1263. //default value 0
  1264. _fs->AddInstruction(_OP_LOADINT, dest,0);
  1265. declType = _VAR_INTEGER;
  1266. break;
  1267. case TK_LOCAL_FLOAT_T:
  1268. case TK_LOCAL_DOUBLE_T:
  1269. case TK_LOCAL_LONG_DOUBLE_T:
  1270. //default value 0.0
  1271. //_OP_LOADFLOAT is only valid when SQFloat size == SQInt32 size
  1272. _fs->AddInstruction(_OP_LOADINT, dest,0);
  1273. declType = _VAR_FLOAT;
  1274. break;
  1275. //case TK_LOCAL:
  1276. default:
  1277. //default value null
  1278. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1279. declType = _VAR_ANY;
  1280. }
  1281. }
  1282. _fs->PopTarget();
  1283. _fs->PushLocalVariable(varname, _scope.nested, (is_const_declaration ? _VAR_CONST : declType)
  1284. | (is_reference_declaration ? _VAR_REFERENCE : 0));
  1285. if(_token == _SC(',')) Lex(); else break;
  1286. } while(1);
  1287. }
  1288. void IfStatement()
  1289. {
  1290. SQInteger jmppos;
  1291. bool haselse = false;
  1292. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1293. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  1294. SQInteger jnepos = _fs->GetCurrentPos();
  1295. BEGIN_SCOPE();
  1296. //there is a situation where the if statement has a statement enclosed by {}
  1297. //and after the closing "}" there is no newline or semicolom
  1298. //it's a valid construction but the compiler was complaining about it
  1299. //for now added "&& _token != TK_IDENTIFIER" to the check after "Statement()" call
  1300. /*
  1301. local color = "blue";
  1302. if(color == "yellow"){
  1303. print(color);
  1304. } print("Waht color is it ?");
  1305. */
  1306. Statement();
  1307. //
  1308. if(_token != _SC('}') && _token != TK_ELSE && _token != TK_IDENTIFIER) OptionalSemicolon();
  1309. END_SCOPE();
  1310. SQInteger endifblock = _fs->GetCurrentPos();
  1311. if(_token == TK_ELSE){
  1312. haselse = true;
  1313. BEGIN_SCOPE();
  1314. _fs->AddInstruction(_OP_JMP);
  1315. jmppos = _fs->GetCurrentPos();
  1316. Lex();
  1317. Statement(); if(_token != TK_IDENTIFIER) OptionalSemicolon();
  1318. END_SCOPE();
  1319. _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
  1320. }
  1321. _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
  1322. }
  1323. void WhileStatement()
  1324. {
  1325. SQInteger jzpos, jmppos;
  1326. jmppos = _fs->GetCurrentPos();
  1327. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1328. BEGIN_BREAKBLE_BLOCK();
  1329. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  1330. jzpos = _fs->GetCurrentPos();
  1331. BEGIN_SCOPE();
  1332. Statement();
  1333. END_SCOPE();
  1334. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
  1335. _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
  1336. END_BREAKBLE_BLOCK(jmppos);
  1337. }
  1338. void DoWhileStatement()
  1339. {
  1340. Lex();
  1341. SQInteger jmptrg = _fs->GetCurrentPos();
  1342. BEGIN_BREAKBLE_BLOCK()
  1343. BEGIN_SCOPE();
  1344. Statement();
  1345. END_SCOPE();
  1346. //fix proposed by frosch to correct line number info in stack dumps
  1347. _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
  1348. Expect(TK_WHILE);
  1349. SQInteger continuetrg = _fs->GetCurrentPos();
  1350. Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1351. _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
  1352. _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
  1353. END_BREAKBLE_BLOCK(continuetrg);
  1354. }
  1355. void ForStatement()
  1356. {
  1357. Lex();
  1358. BEGIN_SCOPE();
  1359. Expect(_SC('('));
  1360. switch(_token){
  1361. case TK_LOCAL_CHAR_T:
  1362. case TK_LOCAL_WCHAR_T:
  1363. case TK_LOCAL_BOOL_T:
  1364. case TK_LOCAL_TABLE_T:
  1365. case TK_LOCAL_ARRAY_T:
  1366. case TK_LOCAL_INT8_T:
  1367. case TK_LOCAL_INT16_T:
  1368. case TK_LOCAL_INT32_T:
  1369. case TK_LOCAL_INT64_T:
  1370. case TK_LOCAL_INT_T:
  1371. case TK_LOCAL_UINT8_T:
  1372. case TK_LOCAL_UINT16_T:
  1373. case TK_LOCAL_UINT32_T:
  1374. case TK_LOCAL_UINT64_T:
  1375. case TK_LOCAL_UINT_T:
  1376. case TK_LOCAL_FLOAT_T:
  1377. case TK_LOCAL_DOUBLE_T:
  1378. case TK_LOCAL_LONG_DOUBLE_T:
  1379. case TK_LOCAL:
  1380. LocalDeclStatement();
  1381. break;
  1382. default:
  1383. if(_token != _SC(';')){
  1384. CommaExpr();
  1385. _fs->PopTarget();
  1386. }
  1387. }
  1388. Expect(_SC(';'));
  1389. _fs->SnoozeOpt();
  1390. SQInteger jmppos = _fs->GetCurrentPos();
  1391. SQInteger jzpos = -1;
  1392. if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
  1393. Expect(_SC(';'));
  1394. _fs->SnoozeOpt();
  1395. SQInteger expstart = _fs->GetCurrentPos() + 1;
  1396. if(_token != _SC(')')) {
  1397. CommaExpr();
  1398. _fs->PopTarget();
  1399. }
  1400. Expect(_SC(')'));
  1401. _fs->SnoozeOpt();
  1402. SQInteger expend = _fs->GetCurrentPos();
  1403. SQInteger expsize = (expend - expstart) + 1;
  1404. SQInstructionVec exp;
  1405. if(expsize > 0) {
  1406. for(SQInteger i = 0; i < expsize; i++)
  1407. exp.push_back(_fs->GetInstruction(expstart + i));
  1408. _fs->PopInstructions(expsize);
  1409. }
  1410. BEGIN_BREAKBLE_BLOCK()
  1411. Statement();
  1412. SQInteger continuetrg = _fs->GetCurrentPos();
  1413. if(expsize > 0) {
  1414. for(SQInteger i = 0; i < expsize; i++)
  1415. _fs->AddInstruction(exp[i]);
  1416. }
  1417. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
  1418. if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
  1419. END_SCOPE();
  1420. END_BREAKBLE_BLOCK(continuetrg);
  1421. }
  1422. void ForEachStatement()
  1423. {
  1424. SQObject idxname, valname;
  1425. Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
  1426. if(_token == _SC(',')) {
  1427. idxname = valname;
  1428. Lex(); valname = Expect(TK_IDENTIFIER);
  1429. }
  1430. else{
  1431. idxname = _fs->CreateString(_SC("@INDEX@"));
  1432. }
  1433. Expect(TK_IN);
  1434. //save the stack size
  1435. BEGIN_SCOPE();
  1436. //put the table in the stack(evaluate the table expression)
  1437. Expression(); Expect(_SC(')'));
  1438. SQInteger container = _fs->TopTarget();
  1439. //push the index local var
  1440. SQInteger indexpos = _fs->PushLocalVariable(idxname, _scope.nested);
  1441. _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
  1442. //push the value local var
  1443. SQInteger valuepos = _fs->PushLocalVariable(valname, _scope.nested);
  1444. _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
  1445. //push reference index
  1446. SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@")), _scope.nested); //use invalid id to make it inaccessible
  1447. _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
  1448. SQInteger jmppos = _fs->GetCurrentPos();
  1449. _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
  1450. SQInteger foreachpos = _fs->GetCurrentPos();
  1451. _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
  1452. //generate the statement code
  1453. BEGIN_BREAKBLE_BLOCK()
  1454. Statement();
  1455. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
  1456. _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
  1457. _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
  1458. END_BREAKBLE_BLOCK(foreachpos - 1);
  1459. //restore the local variable stack(remove index,val and ref idx)
  1460. _fs->PopTarget();
  1461. END_SCOPE();
  1462. }
  1463. void SwitchStatement()
  1464. {
  1465. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1466. Expect(_SC('{'));
  1467. SQInteger expr = _fs->TopTarget();
  1468. bool bfirst = true;
  1469. SQInteger tonextcondjmp = -1;
  1470. SQInteger skipcondjmp = -1;
  1471. SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
  1472. _fs->_breaktargets.push_back(0);
  1473. while(_token == TK_CASE) {
  1474. if(!bfirst) {
  1475. _fs->AddInstruction(_OP_JMP, 0, 0);
  1476. skipcondjmp = _fs->GetCurrentPos();
  1477. _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1478. }
  1479. //condition
  1480. Lex(); ExpressionScalar() /*Expression()*/; Expect(_SC(':'));
  1481. SQInteger trg = _fs->PopTarget();
  1482. SQInteger eqtarget = trg;
  1483. bool local = _fs->IsLocal(trg);
  1484. if(local) {
  1485. eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
  1486. }
  1487. _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
  1488. _fs->AddInstruction(_OP_JZ, eqtarget, 0);
  1489. if(local) {
  1490. _fs->PopTarget();
  1491. }
  1492. //end condition
  1493. if(skipcondjmp != -1) {
  1494. _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
  1495. }
  1496. tonextcondjmp = _fs->GetCurrentPos();
  1497. BEGIN_SCOPE();
  1498. Statements();
  1499. END_SCOPE();
  1500. bfirst = false;
  1501. }
  1502. if(tonextcondjmp != -1)
  1503. _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1504. if(_token == TK_DEFAULT) {
  1505. Lex(); Expect(_SC(':'));
  1506. BEGIN_SCOPE();
  1507. Statements();
  1508. END_SCOPE();
  1509. }
  1510. Expect(_SC('}'));
  1511. _fs->PopTarget();
  1512. __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
  1513. if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
  1514. _fs->_breaktargets.pop_back();
  1515. }
  1516. void FunctionStatement()
  1517. {
  1518. SQObject id;
  1519. Lex(); id = Expect(TK_IDENTIFIER);
  1520. _fs->PushTarget(0);
  1521. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1522. if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1523. else CheckGlobalName(id, true);
  1524. while(_token == TK_DOUBLE_COLON) {
  1525. Lex();
  1526. id = Expect(TK_IDENTIFIER);
  1527. //todo check if class function already exists
  1528. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1529. if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1530. }
  1531. Expect(_SC('('));
  1532. CreateFunction(id);
  1533. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1534. EmitDerefOp(_OP_NEWSLOT);
  1535. _fs->PopTarget();
  1536. }
  1537. void ClassStatement()
  1538. {
  1539. SQExpState es;
  1540. Lex();
  1541. if(_token == TK_IDENTIFIER) {
  1542. SQObjectPtr str = SQString::Create(_ss(_vm), _lex._svalue);
  1543. CheckGlobalName(str, true);
  1544. }
  1545. es = _es;
  1546. _es.donot_get = true;
  1547. PrefixedExpr();
  1548. if(_es.etype == EXPR) {
  1549. Error(_SC("invalid class name"));
  1550. }
  1551. else if(_es.etype == OBJECT || _es.etype == BASE) {
  1552. ClassExp();
  1553. EmitDerefOp(_OP_NEWSLOT);
  1554. _fs->PopTarget();
  1555. }
  1556. else {
  1557. Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
  1558. }
  1559. _es = es;
  1560. }
  1561. SQObject ExpectScalar()
  1562. {
  1563. SQObject val;
  1564. val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
  1565. switch(_token) {
  1566. case TK_INTEGER:
  1567. val._type = OT_INTEGER;
  1568. val._unVal.nInteger = _lex._nvalue;
  1569. break;
  1570. case TK_FLOAT:
  1571. val._type = OT_FLOAT;
  1572. val._unVal.fFloat = _lex._fvalue;
  1573. break;
  1574. case TK_STRING_LITERAL:
  1575. val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
  1576. break;
  1577. case TK_TRUE:
  1578. case TK_FALSE:
  1579. val._type = OT_BOOL;
  1580. val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
  1581. break;
  1582. case '-':
  1583. Lex();
  1584. switch(_token)
  1585. {
  1586. case TK_INTEGER:
  1587. val._type = OT_INTEGER;
  1588. val._unVal.nInteger = -_lex._nvalue;
  1589. break;
  1590. case TK_FLOAT:
  1591. val._type = OT_FLOAT;
  1592. val._unVal.fFloat = -_lex._fvalue;
  1593. break;
  1594. default:
  1595. Error(_SC("scalar expected : integer, float"));
  1596. }
  1597. break;
  1598. default:
  1599. Error(_SC("scalar expected : integer, float or string"));
  1600. }
  1601. Lex();
  1602. return val;
  1603. }
  1604. SQInteger ExpressionScalar()
  1605. {
  1606. SQInteger tk_type = _token;
  1607. switch(_token) {
  1608. case TK_INTEGER:
  1609. EmitLoadConstInt(_lex._nvalue,-1);
  1610. break;
  1611. case TK_FLOAT:
  1612. EmitLoadConstFloat(_lex._fvalue,-1);
  1613. break;
  1614. case TK_STRING_LITERAL:
  1615. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
  1616. break;
  1617. case TK_IDENTIFIER: {
  1618. SQObject id = _fs->CreateString(_lex._svalue);
  1619. Lex();
  1620. ExpressionConstant(id);
  1621. return tk_type;
  1622. }
  1623. break;
  1624. case '-':
  1625. Lex();
  1626. tk_type = _token;
  1627. switch(_token)
  1628. {
  1629. case TK_INTEGER:
  1630. EmitLoadConstInt(-_lex._nvalue,-1);
  1631. break;
  1632. case TK_FLOAT:
  1633. EmitLoadConstFloat(-_lex._fvalue,-1);
  1634. break;
  1635. default:
  1636. Error(_SC("scalar expected : integer, float"));
  1637. }
  1638. break;
  1639. default:
  1640. goto error;
  1641. }
  1642. Lex();
  1643. return tk_type;
  1644. error:
  1645. Error(_SC("constant or scalar expected : integer, float or string"));
  1646. }
  1647. void EnumStatement()
  1648. {
  1649. Lex();
  1650. SQObject id = Expect(TK_IDENTIFIER);
  1651. Expect(_SC('{'));
  1652. //CheckLocalNameScope(id, _scope.nested);
  1653. SQObjectPtr strongid = id;
  1654. CheckLocalNameScope(id, _scope.nested);
  1655. CheckConstsExists(strongid);
  1656. SQObject table = _fs->CreateTable();
  1657. //_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  1658. SQInteger nval = 0;
  1659. while(_token != _SC('}')) {
  1660. SQObject key = Expect(TK_IDENTIFIER);
  1661. SQObject val;
  1662. if(_token == _SC('=')) {
  1663. Lex();
  1664. val = ExpectScalar();
  1665. }
  1666. else {
  1667. val._type = OT_INTEGER;
  1668. val._unVal.nInteger = nval++;
  1669. }
  1670. //SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
  1671. //_fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
  1672. _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
  1673. if(_token == ',') Lex();
  1674. }
  1675. ConstsNewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
  1676. strongid.Null();
  1677. Lex();
  1678. }
  1679. void TryCatchStatement()
  1680. {
  1681. SQObject exid;
  1682. Lex();
  1683. _fs->AddInstruction(_OP_PUSHTRAP,0,0);
  1684. _fs->_traps++;
  1685. if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
  1686. if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
  1687. SQInteger trappos = _fs->GetCurrentPos();
  1688. {
  1689. BEGIN_SCOPE();
  1690. Statement();
  1691. END_SCOPE();
  1692. }
  1693. _fs->_traps--;
  1694. _fs->AddInstruction(_OP_POPTRAP, 1, 0);
  1695. if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
  1696. if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
  1697. _fs->AddInstruction(_OP_JMP, 0, 0);
  1698. SQInteger jmppos = _fs->GetCurrentPos();
  1699. _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
  1700. Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
  1701. {
  1702. BEGIN_SCOPE();
  1703. SQInteger ex_target = _fs->PushLocalVariable(exid, _scope.nested);
  1704. _fs->SetIntructionParam(trappos, 0, ex_target);
  1705. Statement();
  1706. _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
  1707. END_SCOPE();
  1708. }
  1709. }
  1710. void FunctionExp(SQInteger ftype,bool lambda = false)
  1711. {
  1712. Lex(); Expect(_SC('('));
  1713. SQObjectPtr dummy;
  1714. CreateFunction(dummy,lambda);
  1715. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
  1716. }
  1717. void ClassExp()
  1718. {
  1719. SQInteger base = -1;
  1720. SQInteger attrs = -1;
  1721. if(_token == TK_EXTENDS) {
  1722. Lex(); Expression();
  1723. base = _fs->TopTarget();
  1724. }
  1725. if(_token == TK_ATTR_OPEN) {
  1726. Lex();
  1727. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  1728. ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
  1729. attrs = _fs->TopTarget();
  1730. }
  1731. Expect(_SC('{'));
  1732. if(attrs != -1) _fs->PopTarget();
  1733. if(base != -1) _fs->PopTarget();
  1734. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
  1735. ParseTableOrClass(_SC(';'),_SC('}'));
  1736. }
  1737. void DeleteExpr()
  1738. {
  1739. SQExpState es;
  1740. Lex();
  1741. es = _es;
  1742. _es.donot_get = true;
  1743. PrefixedExpr();
  1744. if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
  1745. if(_es.etype==OBJECT || _es.etype==BASE) {
  1746. Emit2ArgsOP(_OP_DELETE);
  1747. }
  1748. else {
  1749. Error(_SC("cannot delete an (outer) local"));
  1750. }
  1751. _es = es;
  1752. }
  1753. void PrefixIncDec(SQInteger token)
  1754. {
  1755. SQExpState es;
  1756. SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
  1757. Lex();
  1758. es = _es;
  1759. _es.donot_get = true;
  1760. PrefixedExpr();
  1761. if(_es.etype==EXPR) {
  1762. Error(_SC("can't '++' or '--' an expression"));
  1763. }
  1764. else if(_es.etype==OBJECT || _es.etype==BASE) {
  1765. Emit2ArgsOP(_OP_INC, diff);
  1766. }
  1767. else if(_es.etype==LOCAL) {
  1768. SQInteger src = _fs->TopTarget();
  1769. _fs->AddInstruction(_OP_INCL, src, src, 0, diff);
  1770. }
  1771. else if(_es.etype==OUTER) {
  1772. SQInteger tmp = _fs->PushTarget();
  1773. _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
  1774. _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff);
  1775. _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
  1776. }
  1777. _es = es;
  1778. }
  1779. void CreateFunction(SQObject &name,bool lambda = false, int stack_offset=0)
  1780. {
  1781. SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
  1782. funcstate->_name = name;
  1783. SQObject paramname, type_name;
  1784. funcstate->AddParameter(_fs->CreateString(_SC("this")), _scope.nested+1);
  1785. funcstate->_sourcename = _sourcename;
  1786. SQInteger defparams = 0;
  1787. SQInteger is_reference = 0;
  1788. while(_token!=_SC(')')) {
  1789. is_reference = 0; //reset is_reference
  1790. if(_token == TK_VARPARAMS) {
  1791. if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
  1792. funcstate->AddParameter(_fs->CreateString(_SC("vargv")), _scope.nested+1);
  1793. funcstate->_varparams = true;
  1794. Lex();
  1795. if(_token != _SC(')')) Error(_SC("expected ')'"));
  1796. break;
  1797. }
  1798. else {
  1799. if(_token == _SC('&')){
  1800. is_reference = 1;
  1801. Lex();
  1802. }
  1803. paramname = Expect(TK_IDENTIFIER);
  1804. funcstate->AddParameter(paramname, _scope.nested+1, is_reference ? _VAR_REFERENCE : _VAR_ANY);
  1805. if(_token == _SC('=')) {
  1806. if(is_reference) Error(_SC("parameter passed by reference can't have default value"));
  1807. Lex();
  1808. if(_token == _SC('[') || _token == _SC('{')) Error(_SC("default parameter with array/table values not supported"));
  1809. Expression();
  1810. //stack_offset to compensate for local functions been relocated to allow recursion
  1811. funcstate->AddDefaultParam(_fs->TopTarget()+stack_offset);
  1812. defparams++;
  1813. }
  1814. else if(_token == _SC(':')){
  1815. //param type specifier like typescript
  1816. Lex();
  1817. type_name = Expect(TK_IDENTIFIER);
  1818. //printf("%d %s\n", __LINE__, _stringval(type_name));
  1819. }
  1820. else {
  1821. if(defparams > 0) Error(_SC("expected '='"));
  1822. }
  1823. if(_token == _SC(',')) Lex();
  1824. else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
  1825. }
  1826. }
  1827. Expect(_SC(')'));
  1828. if(_token == _SC(':')){
  1829. //return type specifier like typescript
  1830. Lex();
  1831. type_name = Expect(TK_IDENTIFIER);
  1832. //printf("%d %s\n", __LINE__, _stringval(type_name));
  1833. }
  1834. for(SQInteger n = 0; n < defparams; n++) {
  1835. _fs->PopTarget();
  1836. }
  1837. SQFuncState *currchunk = _fs;
  1838. _fs = funcstate;
  1839. if(lambda) {
  1840. Expression();
  1841. _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
  1842. else {
  1843. Statement(false);
  1844. }
  1845. funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
  1846. funcstate->AddInstruction(_OP_RETURN, -1);
  1847. funcstate->SetStackSize(0);
  1848. SQFunctionProto *func = funcstate->BuildProto();
  1849. #ifdef _DEBUG_DUMP
  1850. funcstate->Dump(func);
  1851. #endif
  1852. _fs = currchunk;
  1853. _fs->_functions.push_back(func);
  1854. _fs->PopChildState();
  1855. }
  1856. void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
  1857. {
  1858. while(ntoresolve > 0) {
  1859. SQInteger pos = funcstate->_unresolvedbreaks.back();
  1860. funcstate->_unresolvedbreaks.pop_back();
  1861. //set the jmp instruction
  1862. funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
  1863. ntoresolve--;
  1864. }
  1865. }
  1866. void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
  1867. {
  1868. while(ntoresolve > 0) {
  1869. SQInteger pos = funcstate->_unresolvedcontinues.back();
  1870. funcstate->_unresolvedcontinues.pop_back();
  1871. //set the jmp instruction
  1872. funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
  1873. ntoresolve--;
  1874. }
  1875. }
  1876. private:
  1877. SQInteger _token;
  1878. SQFuncState *_fs;
  1879. SQObjectPtr _sourcename;
  1880. SQLexer _lex;
  1881. bool _lineinfo;
  1882. bool _raiseerror;
  1883. bool _show_warnings;
  1884. SQInteger _debugline;
  1885. SQInteger _debugop;
  1886. SQExpState _es;
  1887. SQScope _scope;
  1888. SQChar *_compilererror;
  1889. jmp_buf _errorjmp;
  1890. SQVM *_vm;
  1891. SQObjectPtrVec _scope_consts;
  1892. SQObjectPtr _globals;
  1893. SQChar error_buf[MAX_COMPILER_ERROR_LEN];
  1894. };
  1895. bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out,
  1896. bool raiseerror, bool lineinfo, bool show_warnings)
  1897. {
  1898. SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo, show_warnings);
  1899. return p.Compile(out);
  1900. }
  1901. #endif