sqcompiler.cpp 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957
  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->AddInstruction(_OP_SETOUTER, tmp, pos, tmp);
  506. }
  507. break;
  508. }
  509. }
  510. void CommaExpr(bool warningAssign=false)
  511. {
  512. for(Expression(warningAssign);_token == ',';_fs->PopTarget(), Lex(), CommaExpr(warningAssign));
  513. }
  514. void ErrorIfConst(){
  515. SQLocalVarInfo &vsrc = _fs->_vlocals[_fs->TopTarget()];
  516. //printf("%d %d %d %d %s\n", __LINE__, vsrc._scope, vsrc._type, vsrc._pos, vsrc._name._unVal.pString ? _stringval(vsrc._name) : "?");
  517. if(vsrc._type & _VAR_CONST) Error(_SC("can't assign to a const variable"));
  518. }
  519. void Expression(bool warningAssign=false)
  520. {
  521. SQExpState es = _es;
  522. _es.etype = EXPR;
  523. _es.epos = -1;
  524. _es.donot_get = false;
  525. LogicalOrExp();
  526. switch(_token) {
  527. case _SC('='):
  528. case TK_NEWSLOT:
  529. case TK_MINUSEQ:
  530. case TK_PLUSEQ:
  531. case TK_MULEQ:
  532. case TK_DIVEQ:
  533. case TK_MODEQ:{
  534. SQInteger op = _token;
  535. SQInteger ds = _es.etype;
  536. SQInteger pos = _es.epos;
  537. if(ds == EXPR) Error(_SC("can't assign expression"));
  538. else if(ds == BASE) Error(_SC("'base' cannot be modified"));
  539. Lex(); Expression();
  540. switch(op){
  541. case TK_NEWSLOT:
  542. if(ds == OBJECT || ds == BASE)
  543. EmitDerefOp(_OP_NEWSLOT);
  544. else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
  545. Error(_SC("can't 'create' a local slot"));
  546. break;
  547. case _SC('='): //ASSIGN
  548. if(warningAssign) Warning(_SC("WARNING: making assignment at line %d:%d maybe is not what you want\n"),
  549. _lex._currentline, _lex._currentcolumn);
  550. switch(ds) {
  551. case LOCAL:
  552. {
  553. SQInteger src = _fs->PopTarget();
  554. SQInteger dst = _fs->TopTarget();
  555. _fs->AddInstruction(_OP_MOVE, dst, src);
  556. }
  557. break;
  558. case OBJECT:
  559. case BASE:
  560. EmitDerefOp(_OP_SET);
  561. break;
  562. case OUTER:
  563. {
  564. SQInteger src = _fs->PopTarget();
  565. SQInteger dst = _fs->PushTarget();
  566. _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
  567. }
  568. }
  569. break;
  570. case TK_MINUSEQ:
  571. case TK_PLUSEQ:
  572. case TK_MULEQ:
  573. case TK_DIVEQ:
  574. case TK_MODEQ:
  575. EmitCompoundArith(op, ds, pos);
  576. break;
  577. }
  578. }
  579. break;
  580. case _SC('?'): {
  581. Lex();
  582. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  583. SQInteger jzpos = _fs->GetCurrentPos();
  584. SQInteger trg = _fs->PushTarget();
  585. Expression();
  586. SQInteger first_exp = _fs->PopTarget();
  587. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  588. SQInteger endfirstexp = _fs->GetCurrentPos();
  589. _fs->AddInstruction(_OP_JMP, 0, 0);
  590. Expect(_SC(':'));
  591. SQInteger jmppos = _fs->GetCurrentPos();
  592. Expression();
  593. SQInteger second_exp = _fs->PopTarget();
  594. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  595. _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
  596. _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
  597. _fs->SnoozeOpt();
  598. }
  599. break;
  600. }
  601. _es = es;
  602. }
  603. template<typename T> void INVOKE_EXP(T f)
  604. {
  605. SQExpState es = _es;
  606. _es.etype = EXPR;
  607. _es.epos = -1;
  608. _es.donot_get = false;
  609. (this->*f)();
  610. _es = es;
  611. }
  612. template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)
  613. {
  614. Lex();
  615. INVOKE_EXP(f);
  616. SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
  617. _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
  618. }
  619. void LogicalOrExp()
  620. {
  621. LogicalAndExp();
  622. for(;;) if(_token == TK_OR) {
  623. SQInteger first_exp = _fs->PopTarget();
  624. SQInteger trg = _fs->PushTarget();
  625. _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
  626. SQInteger jpos = _fs->GetCurrentPos();
  627. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  628. Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp);
  629. _fs->SnoozeOpt();
  630. SQInteger second_exp = _fs->PopTarget();
  631. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  632. _fs->SnoozeOpt();
  633. _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
  634. break;
  635. }else return;
  636. }
  637. void LogicalAndExp()
  638. {
  639. BitwiseOrExp();
  640. for(;;) switch(_token) {
  641. case TK_AND: {
  642. SQInteger first_exp = _fs->PopTarget();
  643. SQInteger trg = _fs->PushTarget();
  644. _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
  645. SQInteger jpos = _fs->GetCurrentPos();
  646. if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
  647. Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp);
  648. _fs->SnoozeOpt();
  649. SQInteger second_exp = _fs->PopTarget();
  650. if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
  651. _fs->SnoozeOpt();
  652. _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
  653. break;
  654. }
  655. default:
  656. return;
  657. }
  658. }
  659. void BitwiseOrExp()
  660. {
  661. BitwiseXorExp();
  662. for(;;) if(_token == _SC('|'))
  663. {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
  664. }else return;
  665. }
  666. void BitwiseXorExp()
  667. {
  668. BitwiseAndExp();
  669. for(;;) if(_token == _SC('^'))
  670. {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
  671. }else return;
  672. }
  673. void BitwiseAndExp()
  674. {
  675. EqExp();
  676. for(;;) if(_token == _SC('&'))
  677. {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
  678. }else return;
  679. }
  680. void EqExp()
  681. {
  682. CompExp();
  683. for(;;) switch(_token) {
  684. case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
  685. case TK_EQ_IDENTITY :BIN_EXP(_OP_EQI, &SQCompiler::CompExp); break;
  686. case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
  687. case TK_NE_IDENTITY: BIN_EXP(_OP_NEI, &SQCompiler::CompExp); break;
  688. case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
  689. default: return;
  690. }
  691. }
  692. void CompExp()
  693. {
  694. ShiftExp();
  695. for(;;) switch(_token) {
  696. case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
  697. case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
  698. case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
  699. case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
  700. case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;
  701. case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break;
  702. default: return;
  703. }
  704. }
  705. void ShiftExp()
  706. {
  707. PlusExp();
  708. for(;;) switch(_token) {
  709. case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
  710. case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
  711. case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
  712. default: return;
  713. }
  714. }
  715. SQOpcode ChooseArithOpByToken(SQInteger tok)
  716. {
  717. switch(tok) {
  718. case TK_PLUSEQ: case '+': return _OP_ADD;
  719. case TK_MINUSEQ: case '-': return _OP_SUB;
  720. case TK_MULEQ: case '*': return _OP_MUL;
  721. case TK_DIVEQ: case '/': return _OP_DIV;
  722. case TK_MODEQ: case '%': return _OP_MOD;
  723. default: assert(0);
  724. }
  725. return _OP_ADD;
  726. }
  727. SQInteger ChooseCompArithCharByToken(SQInteger tok)
  728. {
  729. SQInteger oper;
  730. switch(tok){
  731. case TK_MINUSEQ: oper = '-'; break;
  732. case TK_PLUSEQ: oper = '+'; break;
  733. case TK_MULEQ: oper = '*'; break;
  734. case TK_DIVEQ: oper = '/'; break;
  735. case TK_MODEQ: oper = '%'; break;
  736. default: oper = 0; //shut up compiler
  737. assert(0); break;
  738. };
  739. return oper;
  740. }
  741. void PlusExp()
  742. {
  743. MultExp();
  744. for(;;) switch(_token) {
  745. case _SC('+'): case _SC('-'):
  746. BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
  747. default: return;
  748. }
  749. }
  750. void MultExp()
  751. {
  752. PrefixedExpr();
  753. for(;;) switch(_token) {
  754. case _SC('*'): case _SC('/'): case _SC('%'):
  755. BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;
  756. default: return;
  757. }
  758. }
  759. //if 'pos' != -1 the previous variable is a local variable
  760. void PrefixedExpr()
  761. {
  762. SQInteger pos = Factor();
  763. for(;;) {
  764. switch(_token) {
  765. case _SC('.'):
  766. pos = -1;
  767. Lex();
  768. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
  769. if(_es.etype==BASE) {
  770. Emit2ArgsOP(_OP_GET);
  771. pos = _fs->TopTarget();
  772. _es.etype = EXPR;
  773. _es.epos = pos;
  774. }
  775. else {
  776. if(NeedGet()) {
  777. Emit2ArgsOP(_OP_GET);
  778. }
  779. _es.etype = OBJECT;
  780. }
  781. break;
  782. case _SC('['):
  783. if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
  784. Lex(); Expression(); Expect(_SC(']'));
  785. pos = -1;
  786. if(_es.etype==BASE) {
  787. Emit2ArgsOP(_OP_GET);
  788. pos = _fs->TopTarget();
  789. _es.etype = EXPR;
  790. _es.epos = pos;
  791. }
  792. else {
  793. if(NeedGet()) {
  794. Emit2ArgsOP(_OP_GET);
  795. }
  796. _es.etype = OBJECT;
  797. }
  798. break;
  799. case TK_MINUSMINUS:
  800. case TK_PLUSPLUS:
  801. {
  802. if(IsEndOfStatement()) return;
  803. SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
  804. Lex();
  805. switch(_es.etype)
  806. {
  807. case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
  808. case OBJECT:
  809. case BASE:
  810. Emit2ArgsOP(_OP_PINC, diff);
  811. break;
  812. case LOCAL: {
  813. SQInteger src = _fs->PopTarget();
  814. _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
  815. }
  816. break;
  817. case OUTER: {
  818. SQInteger tmp1 = _fs->PushTarget();
  819. SQInteger tmp2 = _fs->PushTarget();
  820. _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
  821. _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff);
  822. _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
  823. _fs->PopTarget();
  824. }
  825. }
  826. }
  827. return;
  828. break;
  829. case _SC('('):
  830. switch(_es.etype) {
  831. case OBJECT: {
  832. SQInteger key = _fs->PopTarget(); /* location of the key */
  833. SQInteger table = _fs->PopTarget(); /* location of the object */
  834. SQInteger closure = _fs->PushTarget(); /* location for the closure */
  835. SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
  836. _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
  837. }
  838. break;
  839. case BASE:
  840. //Emit2ArgsOP(_OP_GET);
  841. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  842. break;
  843. case OUTER:
  844. _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
  845. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  846. break;
  847. default:
  848. _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
  849. }
  850. _es.etype = EXPR;
  851. Lex();
  852. FunctionCallArgs();
  853. break;
  854. default: return;
  855. }
  856. }
  857. }
  858. SQInteger Factor()
  859. {
  860. _es.etype = EXPR;
  861. switch(_token)
  862. {
  863. case TK_STRING_LITERAL:
  864. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
  865. Lex();
  866. break;
  867. case TK_BASE:
  868. Lex();
  869. _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
  870. _es.etype = BASE;
  871. _es.epos = _fs->TopTarget();
  872. return (_es.epos);
  873. break;
  874. case TK_IDENTIFIER:
  875. case TK_CONSTRUCTOR:
  876. case TK_DESTRUCTOR:
  877. case TK_THIS:{
  878. SQObject id;
  879. SQObject constant;
  880. switch(_token) {
  881. case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
  882. case TK_THIS: id = _fs->CreateString(_SC("this"), 4); break;
  883. case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"), 11); break;
  884. case TK_DESTRUCTOR: id = _fs->CreateString(_SC("destructor"), 10); break;
  885. }
  886. SQInteger pos = -1;
  887. Lex();
  888. if((pos = _fs->GetLocalVariable(id)) != -1) {
  889. /* Handle a local variable (includes 'this') */
  890. _fs->PushTarget(pos);
  891. _es.etype = LOCAL;
  892. _es.epos = pos;
  893. }
  894. else if((pos = _fs->GetOuterVariable(id)) != -1) {
  895. /* Handle a free var */
  896. if(NeedGet()) {
  897. _es.epos = _fs->PushTarget();
  898. _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);
  899. /* _es.etype = EXPR; already default value */
  900. }
  901. else {
  902. _es.etype = OUTER;
  903. _es.epos = pos;
  904. }
  905. }
  906. else if(IsConstant(id, constant)) {
  907. /* Handle named constant */
  908. SQObjectPtr constval;
  909. SQObject constid;
  910. if(type(constant) == OT_TABLE) {
  911. Expect('.');
  912. constid = Expect(TK_IDENTIFIER);
  913. if(!_table(constant)->Get(constid, constval)) {
  914. constval.Null();
  915. Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
  916. }
  917. }
  918. else {
  919. constval = constant;
  920. }
  921. _es.epos = _fs->PushTarget();
  922. /* generate direct or literal function depending on size */
  923. SQObjectType ctype = type(constval);
  924. switch(ctype) {
  925. case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
  926. case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
  927. default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
  928. }
  929. _es.etype = EXPR;
  930. }
  931. else {
  932. /* Handle a non-local variable, aka a field. Push the 'this' pointer on
  933. * the virtual stack (always found in offset 0, so no instruction needs to
  934. * be generated), and push the key next. Generate an _OP_LOAD instruction
  935. * for the latter. If we are not using the variable as a dref expr, generate
  936. * the _OP_GET instruction.
  937. */
  938. _fs->PushTarget(0);
  939. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  940. if(NeedGet()) {
  941. Emit2ArgsOP(_OP_GET);
  942. }
  943. _es.etype = OBJECT;
  944. }
  945. return _es.epos;
  946. }
  947. break;
  948. case TK_DOUBLE_COLON: // "::"
  949. _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
  950. _es.etype = OBJECT;
  951. _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
  952. _es.epos = -1;
  953. return _es.epos;
  954. break;
  955. case TK_NULL:
  956. _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
  957. Lex();
  958. break;
  959. case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break;
  960. case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;
  961. case TK_TRUE: case TK_FALSE:
  962. _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
  963. Lex();
  964. break;
  965. case _SC('['): {
  966. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
  967. SQInteger apos = _fs->GetCurrentPos(),key = 0;
  968. Lex();
  969. while(_token != _SC(']')) {
  970. Expression();
  971. if(_token == _SC(',')) Lex();
  972. SQInteger val = _fs->PopTarget();
  973. SQInteger array = _fs->TopTarget();
  974. _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);
  975. key++;
  976. }
  977. _fs->SetIntructionParam(apos, 1, key);
  978. Lex();
  979. }
  980. break;
  981. case _SC('{'):
  982. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  983. Lex();ParseTableOrClass(_SC(','),_SC('}'));
  984. break;
  985. case TK_FUNCTION: FunctionExp(_token);break;
  986. case _SC('@'): FunctionExp(_token,true);break;
  987. case TK_CLASS: Lex(); ClassExp();break;
  988. case _SC('-'):
  989. Lex();
  990. switch(_token) {
  991. case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
  992. case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
  993. default: UnaryOP(_OP_NEG);
  994. }
  995. break;
  996. case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
  997. case _SC('~'):
  998. Lex();
  999. if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
  1000. UnaryOP(_OP_BWNOT);
  1001. break;
  1002. case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
  1003. case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
  1004. case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
  1005. case TK_MINUSMINUS :
  1006. case TK_PLUSPLUS :PrefixIncDec(_token); break;
  1007. case TK_DELETE : DeleteExpr(); break;
  1008. case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
  1009. break;
  1010. case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break;
  1011. case TK___FILE__:
  1012. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename));
  1013. Lex();
  1014. break;
  1015. case TK___FUNCTION__:
  1016. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->_name));
  1017. Lex();
  1018. break;
  1019. case TK_IGNORE:
  1020. //Warning("Keyword ignored \"%s\" at line %d:%d\n", _lex.Tok2Str(_token),
  1021. // _lex._currentline, _lex._currentcolumn);
  1022. Lex(); Factor();
  1023. break;
  1024. default: Error(_SC("expression expected"));
  1025. }
  1026. return -1;
  1027. }
  1028. void EmitLoadConstInt(SQInteger value,SQInteger target)
  1029. {
  1030. if(target < 0) {
  1031. target = _fs->PushTarget();
  1032. }
  1033. if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?
  1034. _fs->AddInstruction(_OP_LOADINT, target,value);
  1035. }
  1036. else {
  1037. _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
  1038. }
  1039. }
  1040. void EmitLoadConstFloat(SQFloat value,SQInteger target)
  1041. {
  1042. if(target < 0) {
  1043. target = _fs->PushTarget();
  1044. }
  1045. if(sizeof(SQFloat) == sizeof(SQInt32)) {
  1046. _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
  1047. }
  1048. else {
  1049. _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
  1050. }
  1051. }
  1052. void UnaryOP(SQOpcode op)
  1053. {
  1054. PrefixedExpr();
  1055. SQInteger src = _fs->PopTarget();
  1056. _fs->AddInstruction(op, _fs->PushTarget(), src);
  1057. }
  1058. bool NeedGet()
  1059. {
  1060. switch(_token) {
  1061. case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:
  1062. case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS:
  1063. return false;
  1064. }
  1065. return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
  1066. }
  1067. void FunctionCallArgs()
  1068. {
  1069. SQInteger nargs = 1;//this
  1070. while(_token != _SC(')')) {
  1071. Expression();
  1072. MoveIfCurrentTargetIsLocal();
  1073. nargs++;
  1074. if(_token == _SC(',')){
  1075. Lex();
  1076. if(_token == ')') Error(_SC("expression expected, found ')'"));
  1077. }
  1078. }
  1079. Lex();
  1080. for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
  1081. SQInteger stackbase = _fs->PopTarget();
  1082. SQInteger closure = _fs->PopTarget();
  1083. _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
  1084. }
  1085. void ParseTableOrClass(SQInteger separator,SQInteger terminator)
  1086. {
  1087. SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
  1088. SQObject type_name;
  1089. bool isClass = separator == ';'; //hack recognizes a table/class from the separator
  1090. while(_token != terminator) {
  1091. bool hasattrs = false;
  1092. bool isstatic = false;
  1093. bool isprivate = false;
  1094. //check if is an attribute
  1095. if(isClass) {
  1096. if(_token == TK_ATTR_OPEN) {
  1097. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();
  1098. ParseTableOrClass(',',TK_ATTR_CLOSE);
  1099. hasattrs = true;
  1100. }
  1101. if(_token == TK_STATIC) {
  1102. isstatic = true;
  1103. Lex();
  1104. }
  1105. else if(_token == TK_PUBLIC) {
  1106. Lex();
  1107. }
  1108. else if(_token == TK_PRIVATE) {
  1109. isprivate = true;
  1110. Lex();
  1111. }
  1112. }
  1113. switch(_token) {
  1114. case TK_FUNCTION:
  1115. case TK_CONSTRUCTOR:
  1116. case TK_DESTRUCTOR:{
  1117. SQInteger tk = _token;
  1118. Lex();
  1119. SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) :
  1120. _fs->CreateString(tk == TK_CONSTRUCTOR ? _SC("constructor") : _SC("destructor"));
  1121. Expect(_SC('('));
  1122. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1123. CreateFunction(id);
  1124. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1125. }
  1126. break;
  1127. case _SC('['):
  1128. Lex(); CommaExpr(); Expect(_SC(']'));
  1129. Expect(_SC('=')); Expression();
  1130. break;
  1131. case TK_STRING_LITERAL: //JSON
  1132. case TK_IDENTIFIER: {//JSON
  1133. SQObjectPtr obj = GetTokenObject(_token);
  1134. SQInteger next_token = _SC('=');
  1135. if(_token == _SC(':')){
  1136. if(isClass){
  1137. //class field with type annotation
  1138. Lex();
  1139. type_name = Expect(TK_IDENTIFIER);
  1140. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(obj));
  1141. _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(), 1);
  1142. break;
  1143. }
  1144. else
  1145. {
  1146. next_token = _token;
  1147. }
  1148. }
  1149. Expect(next_token);
  1150. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(obj));
  1151. Expression();
  1152. break;
  1153. }
  1154. default :
  1155. ErrorIfNotToken(TK_IDENTIFIER);
  1156. }
  1157. if(_token == separator) Lex();//optional comma/semicolon
  1158. nkeys++;
  1159. SQInteger val = _fs->PopTarget();
  1160. SQInteger key = _fs->PopTarget();
  1161. SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
  1162. assert((hasattrs && (attrs == key-1)) || !hasattrs);
  1163. unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
  1164. SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
  1165. if(isClass) {
  1166. _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
  1167. }
  1168. else {
  1169. _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
  1170. }
  1171. }
  1172. if(separator == _SC(',')) //hack recognizes a table from the separator
  1173. _fs->SetIntructionParam(tpos, 1, nkeys);
  1174. Lex();
  1175. }
  1176. void LocalDeclStatement()
  1177. {
  1178. SQObject varname;
  1179. bool is_const_declaration = _token == TK_CONST;
  1180. bool is_reference_declaration = false;
  1181. SQInteger declType = _token;
  1182. Lex();
  1183. if( _token == TK_FUNCTION) {
  1184. Lex();
  1185. varname = Expect(TK_IDENTIFIER);
  1186. CheckLocalNameScope(varname, _scope.nested);
  1187. Expect(_SC('('));
  1188. #if 1 //doing this way works but prevents garbage collection when doing multiple reloads on the same vm
  1189. //the following is an attempt to allow local declared functions be called recursivelly
  1190. SQInteger old_pos = _fs->GetCurrentPos(); //save current instructions position
  1191. _fs->PushLocalVariable(varname, _scope.nested, _VAR_CLOSURE); //add function name to find it as outer var if needed
  1192. //-1 to compensate default parameters when relocating
  1193. CreateFunction(varname,false, -1);
  1194. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1195. //rellocate any stack operation (default parameters & _OP_Closure)
  1196. for(int i=old_pos+1, curr_pos = _fs->GetCurrentPos(); i <= curr_pos; ++i){
  1197. SQInstruction & inst = _fs->GetInstruction(i);
  1198. _fs->SetIntructionParam(i, 0, inst._arg0 -1);
  1199. }
  1200. _fs->PopTarget();
  1201. #else
  1202. CreateFunction(varname,false);
  1203. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1204. _fs->PopTarget();
  1205. _fs->PushLocalVariable(varname, _scope.nested, _VAR_CLOSURE);
  1206. #endif
  1207. return;
  1208. }
  1209. do {
  1210. if(_token == _SC('&')){
  1211. is_reference_declaration = true;
  1212. Lex();
  1213. }
  1214. varname = Expect(TK_IDENTIFIER);
  1215. CheckLocalNameScope(varname, _scope.nested);
  1216. if(_token == _SC('=')) {
  1217. Lex(); Expression();
  1218. SQInteger src = _fs->PopTarget();
  1219. SQInteger dest = _fs->PushTarget();
  1220. if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
  1221. declType = _VAR_ANY;
  1222. }
  1223. else if(is_const_declaration || is_reference_declaration)
  1224. Error(_SC("const/reference '%s' need an initializer"), _stringval(varname));
  1225. else{
  1226. SQInteger dest = _fs->PushTarget();
  1227. switch(declType){
  1228. case TK_LOCAL_CHAR_T:
  1229. case TK_LOCAL_WCHAR_T:
  1230. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1231. declType = _VAR_STRING;
  1232. break;
  1233. case TK_LOCAL_BOOL_T:
  1234. //default value false
  1235. _fs->AddInstruction(_OP_LOADBOOL, dest,0);
  1236. declType = _VAR_BOOL;
  1237. break;
  1238. case TK_LOCAL_TABLE_T:
  1239. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1240. declType = _VAR_TABLE;
  1241. break;
  1242. case TK_LOCAL_ARRAY_T:
  1243. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1244. declType = _VAR_ARRAY;
  1245. break;
  1246. case TK_LOCAL_INT8_T:
  1247. case TK_LOCAL_INT16_T:
  1248. case TK_LOCAL_INT32_T:
  1249. case TK_LOCAL_INT64_T:
  1250. case TK_LOCAL_INT_T:
  1251. case TK_LOCAL_UINT8_T:
  1252. case TK_LOCAL_UINT16_T:
  1253. case TK_LOCAL_UINT32_T:
  1254. case TK_LOCAL_UINT64_T:
  1255. case TK_LOCAL_UINT_T:
  1256. //default value 0
  1257. _fs->AddInstruction(_OP_LOADINT, dest,0);
  1258. declType = _VAR_INTEGER;
  1259. break;
  1260. case TK_LOCAL_FLOAT_T:
  1261. case TK_LOCAL_DOUBLE_T:
  1262. case TK_LOCAL_LONG_DOUBLE_T:
  1263. //default value 0.0
  1264. //_OP_LOADFLOAT is only valid when SQFloat size == SQInt32 size
  1265. _fs->AddInstruction(_OP_LOADINT, dest,0);
  1266. declType = _VAR_FLOAT;
  1267. break;
  1268. //case TK_LOCAL:
  1269. default:
  1270. //default value null
  1271. _fs->AddInstruction(_OP_LOADNULLS, dest,1);
  1272. declType = _VAR_ANY;
  1273. }
  1274. }
  1275. _fs->PopTarget();
  1276. _fs->PushLocalVariable(varname, _scope.nested, (is_const_declaration ? _VAR_CONST : declType)
  1277. | (is_reference_declaration ? _VAR_REFERENCE : 0));
  1278. if(_token == _SC(',')) Lex(); else break;
  1279. } while(1);
  1280. }
  1281. void IfStatement()
  1282. {
  1283. SQInteger jmppos;
  1284. bool haselse = false;
  1285. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1286. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  1287. SQInteger jnepos = _fs->GetCurrentPos();
  1288. BEGIN_SCOPE();
  1289. //there is a situation where the if statement has a statement enclosed by {}
  1290. //and after the closing "}" there is no newline or semicolom
  1291. //it's a valid construction but the compiler was complaining about it
  1292. //for now added "&& _token != TK_IDENTIFIER" to the check after "Statement()" call
  1293. /*
  1294. local color = "blue";
  1295. if(color == "yellow"){
  1296. print(color);
  1297. } print("Waht color is it ?");
  1298. */
  1299. Statement();
  1300. //
  1301. if(_token != _SC('}') && _token != TK_ELSE && _token != TK_IDENTIFIER) OptionalSemicolon();
  1302. END_SCOPE();
  1303. SQInteger endifblock = _fs->GetCurrentPos();
  1304. if(_token == TK_ELSE){
  1305. haselse = true;
  1306. BEGIN_SCOPE();
  1307. _fs->AddInstruction(_OP_JMP);
  1308. jmppos = _fs->GetCurrentPos();
  1309. Lex();
  1310. Statement(); if(_token != TK_IDENTIFIER) OptionalSemicolon();
  1311. END_SCOPE();
  1312. _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
  1313. }
  1314. _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
  1315. }
  1316. void WhileStatement()
  1317. {
  1318. SQInteger jzpos, jmppos;
  1319. jmppos = _fs->GetCurrentPos();
  1320. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1321. BEGIN_BREAKBLE_BLOCK();
  1322. _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
  1323. jzpos = _fs->GetCurrentPos();
  1324. BEGIN_SCOPE();
  1325. Statement();
  1326. END_SCOPE();
  1327. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
  1328. _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
  1329. END_BREAKBLE_BLOCK(jmppos);
  1330. }
  1331. void DoWhileStatement()
  1332. {
  1333. Lex();
  1334. SQInteger jmptrg = _fs->GetCurrentPos();
  1335. BEGIN_BREAKBLE_BLOCK()
  1336. BEGIN_SCOPE();
  1337. Statement();
  1338. END_SCOPE();
  1339. //fix proposed by frosch to correct line number info in stack dumps
  1340. _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
  1341. Expect(TK_WHILE);
  1342. SQInteger continuetrg = _fs->GetCurrentPos();
  1343. Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1344. _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
  1345. _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
  1346. END_BREAKBLE_BLOCK(continuetrg);
  1347. }
  1348. void ForStatement()
  1349. {
  1350. Lex();
  1351. BEGIN_SCOPE();
  1352. Expect(_SC('('));
  1353. switch(_token){
  1354. case TK_LOCAL_CHAR_T:
  1355. case TK_LOCAL_WCHAR_T:
  1356. case TK_LOCAL_BOOL_T:
  1357. case TK_LOCAL_TABLE_T:
  1358. case TK_LOCAL_ARRAY_T:
  1359. case TK_LOCAL_INT8_T:
  1360. case TK_LOCAL_INT16_T:
  1361. case TK_LOCAL_INT32_T:
  1362. case TK_LOCAL_INT64_T:
  1363. case TK_LOCAL_INT_T:
  1364. case TK_LOCAL_UINT8_T:
  1365. case TK_LOCAL_UINT16_T:
  1366. case TK_LOCAL_UINT32_T:
  1367. case TK_LOCAL_UINT64_T:
  1368. case TK_LOCAL_UINT_T:
  1369. case TK_LOCAL_FLOAT_T:
  1370. case TK_LOCAL_DOUBLE_T:
  1371. case TK_LOCAL_LONG_DOUBLE_T:
  1372. case TK_LOCAL:
  1373. LocalDeclStatement();
  1374. break;
  1375. default:
  1376. if(_token != _SC(';')){
  1377. CommaExpr();
  1378. _fs->PopTarget();
  1379. }
  1380. }
  1381. Expect(_SC(';'));
  1382. _fs->SnoozeOpt();
  1383. SQInteger jmppos = _fs->GetCurrentPos();
  1384. SQInteger jzpos = -1;
  1385. if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
  1386. Expect(_SC(';'));
  1387. _fs->SnoozeOpt();
  1388. SQInteger expstart = _fs->GetCurrentPos() + 1;
  1389. if(_token != _SC(')')) {
  1390. CommaExpr();
  1391. _fs->PopTarget();
  1392. }
  1393. Expect(_SC(')'));
  1394. _fs->SnoozeOpt();
  1395. SQInteger expend = _fs->GetCurrentPos();
  1396. SQInteger expsize = (expend - expstart) + 1;
  1397. SQInstructionVec exp;
  1398. if(expsize > 0) {
  1399. for(SQInteger i = 0; i < expsize; i++)
  1400. exp.push_back(_fs->GetInstruction(expstart + i));
  1401. _fs->PopInstructions(expsize);
  1402. }
  1403. BEGIN_BREAKBLE_BLOCK()
  1404. Statement();
  1405. SQInteger continuetrg = _fs->GetCurrentPos();
  1406. if(expsize > 0) {
  1407. for(SQInteger i = 0; i < expsize; i++)
  1408. _fs->AddInstruction(exp[i]);
  1409. }
  1410. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
  1411. if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
  1412. END_SCOPE();
  1413. END_BREAKBLE_BLOCK(continuetrg);
  1414. }
  1415. void ForEachStatement()
  1416. {
  1417. SQObject idxname, valname;
  1418. Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
  1419. if(_token == _SC(',')) {
  1420. idxname = valname;
  1421. Lex(); valname = Expect(TK_IDENTIFIER);
  1422. }
  1423. else{
  1424. idxname = _fs->CreateString(_SC("@INDEX@"));
  1425. }
  1426. Expect(TK_IN);
  1427. //save the stack size
  1428. BEGIN_SCOPE();
  1429. //put the table in the stack(evaluate the table expression)
  1430. Expression(); Expect(_SC(')'));
  1431. SQInteger container = _fs->TopTarget();
  1432. //push the index local var
  1433. SQInteger indexpos = _fs->PushLocalVariable(idxname, _scope.nested);
  1434. _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
  1435. //push the value local var
  1436. SQInteger valuepos = _fs->PushLocalVariable(valname, _scope.nested);
  1437. _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
  1438. //push reference index
  1439. SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@")), _scope.nested); //use invalid id to make it inaccessible
  1440. _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
  1441. SQInteger jmppos = _fs->GetCurrentPos();
  1442. _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
  1443. SQInteger foreachpos = _fs->GetCurrentPos();
  1444. _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
  1445. //generate the statement code
  1446. BEGIN_BREAKBLE_BLOCK()
  1447. Statement();
  1448. _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
  1449. _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
  1450. _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
  1451. END_BREAKBLE_BLOCK(foreachpos - 1);
  1452. //restore the local variable stack(remove index,val and ref idx)
  1453. _fs->PopTarget();
  1454. END_SCOPE();
  1455. }
  1456. void SwitchStatement()
  1457. {
  1458. Lex(); Expect(_SC('(')); CommaExpr(true); Expect(_SC(')'));
  1459. Expect(_SC('{'));
  1460. SQInteger expr = _fs->TopTarget();
  1461. bool bfirst = true;
  1462. SQInteger tonextcondjmp = -1;
  1463. SQInteger skipcondjmp = -1;
  1464. SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
  1465. _fs->_breaktargets.push_back(0);
  1466. while(_token == TK_CASE) {
  1467. if(!bfirst) {
  1468. _fs->AddInstruction(_OP_JMP, 0, 0);
  1469. skipcondjmp = _fs->GetCurrentPos();
  1470. _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1471. }
  1472. //condition
  1473. Lex(); ExpressionScalar() /*Expression()*/; Expect(_SC(':'));
  1474. SQInteger trg = _fs->PopTarget();
  1475. SQInteger eqtarget = trg;
  1476. bool local = _fs->IsLocal(trg);
  1477. if(local) {
  1478. eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
  1479. }
  1480. _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
  1481. _fs->AddInstruction(_OP_JZ, eqtarget, 0);
  1482. if(local) {
  1483. _fs->PopTarget();
  1484. }
  1485. //end condition
  1486. if(skipcondjmp != -1) {
  1487. _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
  1488. }
  1489. tonextcondjmp = _fs->GetCurrentPos();
  1490. BEGIN_SCOPE();
  1491. Statements();
  1492. END_SCOPE();
  1493. bfirst = false;
  1494. }
  1495. if(tonextcondjmp != -1)
  1496. _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
  1497. if(_token == TK_DEFAULT) {
  1498. Lex(); Expect(_SC(':'));
  1499. BEGIN_SCOPE();
  1500. Statements();
  1501. END_SCOPE();
  1502. }
  1503. Expect(_SC('}'));
  1504. _fs->PopTarget();
  1505. __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
  1506. if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
  1507. _fs->_breaktargets.pop_back();
  1508. }
  1509. void FunctionStatement()
  1510. {
  1511. SQObject id;
  1512. Lex(); id = Expect(TK_IDENTIFIER);
  1513. _fs->PushTarget(0);
  1514. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1515. if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1516. else CheckGlobalName(id, true);
  1517. while(_token == TK_DOUBLE_COLON) {
  1518. Lex();
  1519. id = Expect(TK_IDENTIFIER);
  1520. //todo check if class function already exists
  1521. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
  1522. if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
  1523. }
  1524. Expect(_SC('('));
  1525. CreateFunction(id);
  1526. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
  1527. EmitDerefOp(_OP_NEWSLOT);
  1528. _fs->PopTarget();
  1529. }
  1530. void ClassStatement()
  1531. {
  1532. SQExpState es;
  1533. Lex();
  1534. if(_token == TK_IDENTIFIER) {
  1535. SQObjectPtr str = SQString::Create(_ss(_vm), _lex._svalue);
  1536. CheckGlobalName(str, true);
  1537. }
  1538. es = _es;
  1539. _es.donot_get = true;
  1540. PrefixedExpr();
  1541. if(_es.etype == EXPR) {
  1542. Error(_SC("invalid class name"));
  1543. }
  1544. else if(_es.etype == OBJECT || _es.etype == BASE) {
  1545. ClassExp();
  1546. EmitDerefOp(_OP_NEWSLOT);
  1547. _fs->PopTarget();
  1548. }
  1549. else {
  1550. Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
  1551. }
  1552. _es = es;
  1553. }
  1554. SQObject ExpectScalar()
  1555. {
  1556. SQObject val;
  1557. val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
  1558. switch(_token) {
  1559. case TK_INTEGER:
  1560. val._type = OT_INTEGER;
  1561. val._unVal.nInteger = _lex._nvalue;
  1562. break;
  1563. case TK_FLOAT:
  1564. val._type = OT_FLOAT;
  1565. val._unVal.fFloat = _lex._fvalue;
  1566. break;
  1567. case TK_STRING_LITERAL:
  1568. val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
  1569. break;
  1570. case TK_TRUE:
  1571. case TK_FALSE:
  1572. val._type = OT_BOOL;
  1573. val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
  1574. break;
  1575. case '-':
  1576. Lex();
  1577. switch(_token)
  1578. {
  1579. case TK_INTEGER:
  1580. val._type = OT_INTEGER;
  1581. val._unVal.nInteger = -_lex._nvalue;
  1582. break;
  1583. case TK_FLOAT:
  1584. val._type = OT_FLOAT;
  1585. val._unVal.fFloat = -_lex._fvalue;
  1586. break;
  1587. default:
  1588. Error(_SC("scalar expected : integer, float"));
  1589. }
  1590. break;
  1591. default:
  1592. Error(_SC("scalar expected : integer, float or string"));
  1593. }
  1594. Lex();
  1595. return val;
  1596. }
  1597. SQInteger ExpressionScalar()
  1598. {
  1599. SQInteger tk_type = _token;
  1600. switch(_token) {
  1601. case TK_INTEGER:
  1602. EmitLoadConstInt(_lex._nvalue,-1);
  1603. break;
  1604. case TK_FLOAT:
  1605. EmitLoadConstFloat(_lex._fvalue,-1);
  1606. break;
  1607. case TK_STRING_LITERAL:
  1608. _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
  1609. break;
  1610. case TK_IDENTIFIER: {
  1611. SQObject id = _fs->CreateString(_lex._svalue);
  1612. Lex();
  1613. ExpressionConstant(id);
  1614. return tk_type;
  1615. }
  1616. break;
  1617. case '-':
  1618. Lex();
  1619. tk_type = _token;
  1620. switch(_token)
  1621. {
  1622. case TK_INTEGER:
  1623. EmitLoadConstInt(-_lex._nvalue,-1);
  1624. break;
  1625. case TK_FLOAT:
  1626. EmitLoadConstFloat(-_lex._fvalue,-1);
  1627. break;
  1628. default:
  1629. Error(_SC("scalar expected : integer, float"));
  1630. }
  1631. break;
  1632. default:
  1633. goto error;
  1634. }
  1635. Lex();
  1636. return tk_type;
  1637. error:
  1638. Error(_SC("constant or scalar expected : integer, float or string"));
  1639. }
  1640. void EnumStatement()
  1641. {
  1642. Lex();
  1643. SQObject id = Expect(TK_IDENTIFIER);
  1644. Expect(_SC('{'));
  1645. //CheckLocalNameScope(id, _scope.nested);
  1646. SQObjectPtr strongid = id;
  1647. CheckLocalNameScope(id, _scope.nested);
  1648. CheckConstsExists(strongid);
  1649. SQObject table = _fs->CreateTable();
  1650. //_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  1651. SQInteger nval = 0;
  1652. while(_token != _SC('}')) {
  1653. SQObject key = Expect(TK_IDENTIFIER);
  1654. SQObject val;
  1655. if(_token == _SC('=')) {
  1656. Lex();
  1657. val = ExpectScalar();
  1658. }
  1659. else {
  1660. val._type = OT_INTEGER;
  1661. val._unVal.nInteger = nval++;
  1662. }
  1663. //SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
  1664. //_fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
  1665. _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
  1666. if(_token == ',') Lex();
  1667. }
  1668. ConstsNewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
  1669. strongid.Null();
  1670. Lex();
  1671. }
  1672. void TryCatchStatement()
  1673. {
  1674. SQObject exid;
  1675. Lex();
  1676. _fs->AddInstruction(_OP_PUSHTRAP,0,0);
  1677. _fs->_traps++;
  1678. if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
  1679. if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
  1680. SQInteger trappos = _fs->GetCurrentPos();
  1681. {
  1682. BEGIN_SCOPE();
  1683. Statement();
  1684. END_SCOPE();
  1685. }
  1686. _fs->_traps--;
  1687. _fs->AddInstruction(_OP_POPTRAP, 1, 0);
  1688. if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
  1689. if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
  1690. _fs->AddInstruction(_OP_JMP, 0, 0);
  1691. SQInteger jmppos = _fs->GetCurrentPos();
  1692. _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
  1693. Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
  1694. {
  1695. BEGIN_SCOPE();
  1696. SQInteger ex_target = _fs->PushLocalVariable(exid, _scope.nested);
  1697. _fs->SetIntructionParam(trappos, 0, ex_target);
  1698. Statement();
  1699. _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
  1700. END_SCOPE();
  1701. }
  1702. }
  1703. void FunctionExp(SQInteger ftype,bool lambda = false)
  1704. {
  1705. Lex(); Expect(_SC('('));
  1706. SQObjectPtr dummy;
  1707. CreateFunction(dummy,lambda);
  1708. _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
  1709. }
  1710. void ClassExp()
  1711. {
  1712. SQInteger base = -1;
  1713. SQInteger attrs = -1;
  1714. if(_token == TK_EXTENDS) {
  1715. Lex(); Expression();
  1716. base = _fs->TopTarget();
  1717. }
  1718. if(_token == TK_ATTR_OPEN) {
  1719. Lex();
  1720. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
  1721. ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
  1722. attrs = _fs->TopTarget();
  1723. }
  1724. Expect(_SC('{'));
  1725. if(attrs != -1) _fs->PopTarget();
  1726. if(base != -1) _fs->PopTarget();
  1727. _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
  1728. ParseTableOrClass(_SC(';'),_SC('}'));
  1729. }
  1730. void DeleteExpr()
  1731. {
  1732. SQExpState es;
  1733. Lex();
  1734. es = _es;
  1735. _es.donot_get = true;
  1736. PrefixedExpr();
  1737. if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
  1738. if(_es.etype==OBJECT || _es.etype==BASE) {
  1739. Emit2ArgsOP(_OP_DELETE);
  1740. }
  1741. else {
  1742. Error(_SC("cannot delete an (outer) local"));
  1743. }
  1744. _es = es;
  1745. }
  1746. void PrefixIncDec(SQInteger token)
  1747. {
  1748. SQExpState es;
  1749. SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
  1750. Lex();
  1751. es = _es;
  1752. _es.donot_get = true;
  1753. PrefixedExpr();
  1754. if(_es.etype==EXPR) {
  1755. Error(_SC("can't '++' or '--' an expression"));
  1756. }
  1757. else if(_es.etype==OBJECT || _es.etype==BASE) {
  1758. Emit2ArgsOP(_OP_INC, diff);
  1759. }
  1760. else if(_es.etype==LOCAL) {
  1761. SQInteger src = _fs->TopTarget();
  1762. _fs->AddInstruction(_OP_INCL, src, src, 0, diff);
  1763. }
  1764. else if(_es.etype==OUTER) {
  1765. SQInteger tmp = _fs->PushTarget();
  1766. _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
  1767. _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff);
  1768. _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
  1769. }
  1770. _es = es;
  1771. }
  1772. void CreateFunction(SQObject &name,bool lambda = false, int stack_offset=0)
  1773. {
  1774. SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
  1775. funcstate->_name = name;
  1776. SQObject paramname, type_name;
  1777. funcstate->AddParameter(_fs->CreateString(_SC("this")), _scope.nested+1);
  1778. funcstate->_sourcename = _sourcename;
  1779. SQInteger defparams = 0;
  1780. SQInteger is_reference = 0;
  1781. while(_token!=_SC(')')) {
  1782. is_reference = 0; //reset is_reference
  1783. if(_token == TK_VARPARAMS) {
  1784. if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
  1785. funcstate->AddParameter(_fs->CreateString(_SC("vargv")), _scope.nested+1);
  1786. funcstate->_varparams = true;
  1787. Lex();
  1788. if(_token != _SC(')')) Error(_SC("expected ')'"));
  1789. break;
  1790. }
  1791. else {
  1792. if(_token == _SC('&')){
  1793. is_reference = 1;
  1794. Lex();
  1795. }
  1796. paramname = Expect(TK_IDENTIFIER);
  1797. funcstate->AddParameter(paramname, _scope.nested+1, is_reference ? _VAR_REFERENCE : _VAR_ANY);
  1798. if(_token == _SC('=')) {
  1799. if(is_reference) Error(_SC("parameter passed by reference can't have default value"));
  1800. Lex();
  1801. if(_token == _SC('[') || _token == _SC('{')) Error(_SC("default parameter with array/table values not supported"));
  1802. Expression();
  1803. //stack_offset to compensate for local functions been relocated to allow recursion
  1804. funcstate->AddDefaultParam(_fs->TopTarget()+stack_offset);
  1805. defparams++;
  1806. }
  1807. else if(_token == _SC(':')){
  1808. //param type specifier like typescript
  1809. Lex();
  1810. type_name = Expect(TK_IDENTIFIER);
  1811. //printf("%d %s\n", __LINE__, _stringval(type_name));
  1812. }
  1813. else {
  1814. if(defparams > 0) Error(_SC("expected '='"));
  1815. }
  1816. if(_token == _SC(',')) Lex();
  1817. else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
  1818. }
  1819. }
  1820. Expect(_SC(')'));
  1821. if(_token == _SC(':')){
  1822. //return type specifier like typescript
  1823. Lex();
  1824. type_name = Expect(TK_IDENTIFIER);
  1825. //printf("%d %s\n", __LINE__, _stringval(type_name));
  1826. }
  1827. for(SQInteger n = 0; n < defparams; n++) {
  1828. _fs->PopTarget();
  1829. }
  1830. SQFuncState *currchunk = _fs;
  1831. _fs = funcstate;
  1832. if(lambda) {
  1833. Expression();
  1834. _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
  1835. else {
  1836. Statement(false);
  1837. }
  1838. funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
  1839. funcstate->AddInstruction(_OP_RETURN, -1);
  1840. funcstate->SetStackSize(0);
  1841. SQFunctionProto *func = funcstate->BuildProto();
  1842. #ifdef _DEBUG_DUMP
  1843. funcstate->Dump(func);
  1844. #endif
  1845. _fs = currchunk;
  1846. _fs->_functions.push_back(func);
  1847. _fs->PopChildState();
  1848. }
  1849. void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
  1850. {
  1851. while(ntoresolve > 0) {
  1852. SQInteger pos = funcstate->_unresolvedbreaks.back();
  1853. funcstate->_unresolvedbreaks.pop_back();
  1854. //set the jmp instruction
  1855. funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
  1856. ntoresolve--;
  1857. }
  1858. }
  1859. void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
  1860. {
  1861. while(ntoresolve > 0) {
  1862. SQInteger pos = funcstate->_unresolvedcontinues.back();
  1863. funcstate->_unresolvedcontinues.pop_back();
  1864. //set the jmp instruction
  1865. funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
  1866. ntoresolve--;
  1867. }
  1868. }
  1869. private:
  1870. SQInteger _token;
  1871. SQFuncState *_fs;
  1872. SQObjectPtr _sourcename;
  1873. SQLexer _lex;
  1874. bool _lineinfo;
  1875. bool _raiseerror;
  1876. bool _show_warnings;
  1877. SQInteger _debugline;
  1878. SQInteger _debugop;
  1879. SQExpState _es;
  1880. SQScope _scope;
  1881. SQChar *_compilererror;
  1882. jmp_buf _errorjmp;
  1883. SQVM *_vm;
  1884. SQObjectPtrVec _scope_consts;
  1885. SQObjectPtr _globals;
  1886. SQChar error_buf[MAX_COMPILER_ERROR_LEN];
  1887. };
  1888. bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out,
  1889. bool raiseerror, bool lineinfo, bool show_warnings)
  1890. {
  1891. SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo, show_warnings);
  1892. return p.Compile(out);
  1893. }
  1894. #endif