astNodes.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "console/console.h"
  24. #include "console/telnetDebugger.h"
  25. #include "console/ast.h"
  26. #include "core/tAlgorithm.h"
  27. #include "core/strings/findMatch.h"
  28. #include "console/consoleInternal.h"
  29. #include "core/stream/fileStream.h"
  30. #include "console/compiler.h"
  31. #include "console/simBase.h"
  32. template< typename T >
  33. struct Token
  34. {
  35. T value;
  36. S32 lineNumber;
  37. };
  38. #include "console/cmdgram.h"
  39. namespace Compiler
  40. {
  41. U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip)
  42. {
  43. for(StmtNode *walk = block; walk; walk = walk->getNext())
  44. ip = walk->compileStmt(codeStream, ip);
  45. return codeStream.tell();
  46. }
  47. }
  48. using namespace Compiler;
  49. //-----------------------------------------------------------------------------
  50. void StmtNode::addBreakLine(CodeStream &code)
  51. {
  52. code.addBreakLine(dbgLineNumber, code.tell());
  53. }
  54. //------------------------------------------------------------
  55. StmtNode::StmtNode()
  56. {
  57. next = NULL;
  58. dbgFileName = CodeBlock::smCurrentParser->getCurrentFile();
  59. }
  60. void StmtNode::setPackage(StringTableEntry)
  61. {
  62. }
  63. void StmtNode::append(StmtNode *next)
  64. {
  65. StmtNode *walk = this;
  66. while(walk->next)
  67. walk = walk->next;
  68. walk->next = next;
  69. }
  70. void FunctionDeclStmtNode::setPackage(StringTableEntry packageName)
  71. {
  72. package = packageName;
  73. }
  74. //------------------------------------------------------------
  75. //
  76. // Console language compilers
  77. //
  78. //------------------------------------------------------------
  79. static U32 conversionOp(TypeReq src, TypeReq dst)
  80. {
  81. if(src == TypeReqString)
  82. {
  83. switch(dst)
  84. {
  85. case TypeReqUInt:
  86. return OP_STR_TO_UINT;
  87. case TypeReqFloat:
  88. return OP_STR_TO_FLT;
  89. case TypeReqNone:
  90. return OP_STR_TO_NONE;
  91. case TypeReqVar:
  92. return OP_SAVEVAR_STR;
  93. default:
  94. break;
  95. }
  96. }
  97. else if(src == TypeReqFloat)
  98. {
  99. switch(dst)
  100. {
  101. case TypeReqUInt:
  102. return OP_FLT_TO_UINT;
  103. case TypeReqString:
  104. return OP_FLT_TO_STR;
  105. case TypeReqNone:
  106. return OP_FLT_TO_NONE;
  107. case TypeReqVar:
  108. return OP_SAVEVAR_FLT;
  109. default:
  110. break;
  111. }
  112. }
  113. else if(src == TypeReqUInt)
  114. {
  115. switch(dst)
  116. {
  117. case TypeReqFloat:
  118. return OP_UINT_TO_FLT;
  119. case TypeReqString:
  120. return OP_UINT_TO_STR;
  121. case TypeReqNone:
  122. return OP_UINT_TO_NONE;
  123. case TypeReqVar:
  124. return OP_SAVEVAR_UINT;
  125. default:
  126. break;
  127. }
  128. }
  129. else if(src == TypeReqVar)
  130. {
  131. switch(dst)
  132. {
  133. case TypeReqUInt:
  134. return OP_LOADVAR_UINT;
  135. case TypeReqFloat:
  136. return OP_LOADVAR_FLT;
  137. case TypeReqString:
  138. return OP_LOADVAR_STR;
  139. case TypeReqNone:
  140. return OP_COPYVAR_TO_NONE;
  141. default:
  142. break;
  143. }
  144. }
  145. return OP_INVALID;
  146. }
  147. //------------------------------------------------------------
  148. U32 BreakStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  149. {
  150. if(codeStream.inLoop())
  151. {
  152. addBreakLine(codeStream);
  153. codeStream.emit(OP_JMP);
  154. codeStream.emitFix(CodeStream::FIXTYPE_BREAK);
  155. }
  156. else
  157. {
  158. Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber);
  159. }
  160. return codeStream.tell();
  161. }
  162. //------------------------------------------------------------
  163. U32 ContinueStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  164. {
  165. if(codeStream.inLoop())
  166. {
  167. addBreakLine(codeStream);
  168. codeStream.emit(OP_JMP);
  169. codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE);
  170. }
  171. else
  172. {
  173. Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber);
  174. }
  175. return codeStream.tell();
  176. }
  177. //------------------------------------------------------------
  178. U32 ExprNode::compileStmt(CodeStream &codeStream, U32 ip)
  179. {
  180. addBreakLine(codeStream);
  181. return compile(codeStream, ip, TypeReqNone);
  182. }
  183. //------------------------------------------------------------
  184. U32 ReturnStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  185. {
  186. addBreakLine(codeStream);
  187. if(!expr)
  188. codeStream.emit(OP_RETURN_VOID);
  189. else
  190. {
  191. TypeReq walkType = expr->getPreferredType();
  192. if (walkType == TypeReqNone) walkType = TypeReqString;
  193. ip = expr->compile(codeStream, ip, walkType);
  194. // Return the correct type
  195. switch (walkType) {
  196. case TypeReqUInt:
  197. codeStream.emit(OP_RETURN_UINT);
  198. break;
  199. case TypeReqFloat:
  200. codeStream.emit(OP_RETURN_FLT);
  201. break;
  202. default:
  203. codeStream.emit(OP_RETURN);
  204. break;
  205. }
  206. }
  207. return codeStream.tell();
  208. }
  209. //------------------------------------------------------------
  210. ExprNode *IfStmtNode::getSwitchOR(ExprNode *left, ExprNode *list, bool string)
  211. {
  212. ExprNode *nextExpr = (ExprNode *) list->getNext();
  213. ExprNode *test;
  214. if(string)
  215. test = StreqExprNode::alloc( left->dbgLineNumber, left, list, true );
  216. else
  217. test = IntBinaryExprNode::alloc( left->dbgLineNumber, opEQ, left, list );
  218. if(!nextExpr)
  219. return test;
  220. return IntBinaryExprNode::alloc( test->dbgLineNumber, opOR, test, getSwitchOR( left, nextExpr, string ) );
  221. }
  222. void IfStmtNode::propagateSwitchExpr(ExprNode *left, bool string)
  223. {
  224. testExpr = getSwitchOR(left, testExpr, string);
  225. if(propagate && elseBlock)
  226. ((IfStmtNode *) elseBlock)->propagateSwitchExpr(left, string);
  227. }
  228. U32 IfStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  229. {
  230. U32 endifIp, elseIp;
  231. addBreakLine(codeStream);
  232. if(testExpr->getPreferredType() == TypeReqUInt)
  233. {
  234. integer = true;
  235. }
  236. else
  237. {
  238. integer = false;
  239. }
  240. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  241. codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT);
  242. if(elseBlock)
  243. {
  244. elseIp = codeStream.emit(0);
  245. elseOffset = compileBlock(ifBlock, codeStream, ip) + 2;
  246. codeStream.emit(OP_JMP);
  247. endifIp = codeStream.emit(0);
  248. endifOffset = compileBlock(elseBlock, codeStream, ip);
  249. codeStream.patch(endifIp, endifOffset);
  250. codeStream.patch(elseIp, elseOffset);
  251. }
  252. else
  253. {
  254. endifIp = codeStream.emit(0);
  255. endifOffset = compileBlock(ifBlock, codeStream, ip);
  256. codeStream.patch(endifIp, endifOffset);
  257. }
  258. // Resolve fixes
  259. return codeStream.tell();
  260. }
  261. //------------------------------------------------------------
  262. U32 LoopStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  263. {
  264. if(testExpr->getPreferredType() == TypeReqUInt)
  265. {
  266. integer = true;
  267. }
  268. else
  269. {
  270. integer = false;
  271. }
  272. // if it's a for loop or a while loop it goes:
  273. // initExpr
  274. // testExpr
  275. // OP_JMPIFNOT to break point
  276. // loopStartPoint:
  277. // loopBlock
  278. // continuePoint:
  279. // endLoopExpr
  280. // testExpr
  281. // OP_JMPIF loopStartPoint
  282. // breakPoint:
  283. // otherwise if it's a do ... while() it goes:
  284. // initExpr
  285. // loopStartPoint:
  286. // loopBlock
  287. // continuePoint:
  288. // endLoopExpr
  289. // testExpr
  290. // OP_JMPIF loopStartPoint
  291. // breakPoint:
  292. // loopBlockStart == start of loop block
  293. // continue == skip to end
  294. // break == exit loop
  295. addBreakLine(codeStream);
  296. codeStream.pushFixScope(true);
  297. if(initExpr)
  298. ip = initExpr->compile(codeStream, ip, TypeReqNone);
  299. if(!isDoLoop)
  300. {
  301. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  302. codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT);
  303. codeStream.emitFix(CodeStream::FIXTYPE_BREAK);
  304. }
  305. // Compile internals of loop.
  306. loopBlockStartOffset = codeStream.tell();
  307. continueOffset = compileBlock(loopBlock, codeStream, ip);
  308. if(endLoopExpr)
  309. ip = endLoopExpr->compile(codeStream, ip, TypeReqNone);
  310. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  311. codeStream.emit(integer ? OP_JMPIF : OP_JMPIFF);
  312. codeStream.emitFix(CodeStream::FIXTYPE_LOOPBLOCKSTART);
  313. breakOffset = codeStream.tell(); // exit loop
  314. codeStream.fixLoop(loopBlockStartOffset, breakOffset, continueOffset);
  315. codeStream.popFixScope();
  316. return codeStream.tell();
  317. }
  318. //------------------------------------------------------------
  319. U32 IterStmtNode::compileStmt( CodeStream &codeStream, U32 ip )
  320. {
  321. // Instruction sequence:
  322. //
  323. // containerExpr
  324. // OP_ITER_BEGIN varName .fail
  325. // .continue:
  326. // OP_ITER .break
  327. // body
  328. // OP_JMP .continue
  329. // .break:
  330. // OP_ITER_END
  331. // .fail:
  332. addBreakLine(codeStream);
  333. codeStream.pushFixScope(true);
  334. const U32 startIp = ip;
  335. containerExpr->compile( codeStream, startIp, TypeReqString );
  336. codeStream.emit(isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN);
  337. codeStream.emitSTE( varName );
  338. const U32 finalFix = codeStream.emit(0);
  339. const U32 continueIp = codeStream.emit(OP_ITER);
  340. codeStream.emitFix(CodeStream::FIXTYPE_BREAK);
  341. const U32 bodyIp = codeStream.tell();
  342. const U32 jmpIp = compileBlock( body, codeStream, bodyIp);
  343. const U32 breakIp = jmpIp + 2;
  344. const U32 finalIp = breakIp + 1;
  345. codeStream.emit(OP_JMP);
  346. codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE);
  347. codeStream.emit(OP_ITER_END);
  348. codeStream.patch(finalFix, finalIp);
  349. codeStream.fixLoop(bodyIp, breakIp, continueIp);
  350. codeStream.popFixScope();
  351. return codeStream.tell();
  352. }
  353. //------------------------------------------------------------
  354. U32 ConditionalExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  355. {
  356. // code is testExpr
  357. // JMPIFNOT falseStart
  358. // trueExpr
  359. // JMP end
  360. // falseExpr
  361. if(testExpr->getPreferredType() == TypeReqUInt)
  362. {
  363. integer = true;
  364. }
  365. else
  366. {
  367. integer = false;
  368. }
  369. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  370. codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT);
  371. U32 jumpElseIp = codeStream.emit(0);
  372. ip = trueExpr->compile(codeStream, ip, type);
  373. codeStream.emit(OP_JMP);
  374. U32 jumpEndIp = codeStream.emit(0);
  375. codeStream.patch(jumpElseIp, codeStream.tell());
  376. ip = falseExpr->compile(codeStream, ip, type);
  377. codeStream.patch(jumpEndIp, codeStream.tell());
  378. return codeStream.tell();
  379. }
  380. TypeReq ConditionalExprNode::getPreferredType()
  381. {
  382. return trueExpr->getPreferredType();
  383. }
  384. //------------------------------------------------------------
  385. U32 FloatBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  386. {
  387. ip = right->compile(codeStream, ip, TypeReqFloat);
  388. ip = left->compile(codeStream, ip, TypeReqFloat);
  389. U32 operand = OP_INVALID;
  390. switch(op)
  391. {
  392. case '+':
  393. operand = OP_ADD;
  394. break;
  395. case '-':
  396. operand = OP_SUB;
  397. break;
  398. case '/':
  399. operand = OP_DIV;
  400. break;
  401. case '*':
  402. operand = OP_MUL;
  403. break;
  404. }
  405. codeStream.emit(operand);
  406. if(type != TypeReqFloat)
  407. codeStream.emit(conversionOp(TypeReqFloat, type));
  408. return codeStream.tell();
  409. }
  410. TypeReq FloatBinaryExprNode::getPreferredType()
  411. {
  412. return TypeReqFloat;
  413. }
  414. //------------------------------------------------------------
  415. void IntBinaryExprNode::getSubTypeOperand()
  416. {
  417. subType = TypeReqUInt;
  418. switch(op)
  419. {
  420. case '^':
  421. operand = OP_XOR;
  422. break;
  423. case '%':
  424. operand = OP_MOD;
  425. break;
  426. case '&':
  427. operand = OP_BITAND;
  428. break;
  429. case '|':
  430. operand = OP_BITOR;
  431. break;
  432. case '<':
  433. operand = OP_CMPLT;
  434. subType = TypeReqFloat;
  435. break;
  436. case '>':
  437. operand = OP_CMPGR;
  438. subType = TypeReqFloat;
  439. break;
  440. case opGE:
  441. operand = OP_CMPGE;
  442. subType = TypeReqFloat;
  443. break;
  444. case opLE:
  445. operand = OP_CMPLE;
  446. subType = TypeReqFloat;
  447. break;
  448. case opEQ:
  449. operand = OP_CMPEQ;
  450. subType = TypeReqFloat;
  451. break;
  452. case opNE:
  453. operand = OP_CMPNE;
  454. subType = TypeReqFloat;
  455. break;
  456. case opOR:
  457. operand = OP_OR;
  458. break;
  459. case opAND:
  460. operand = OP_AND;
  461. break;
  462. case opSHR:
  463. operand = OP_SHR;
  464. break;
  465. case opSHL:
  466. operand = OP_SHL;
  467. break;
  468. }
  469. }
  470. U32 IntBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  471. {
  472. getSubTypeOperand();
  473. if(operand == OP_OR || operand == OP_AND)
  474. {
  475. ip = left->compile(codeStream, ip, subType);
  476. codeStream.emit(operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP);
  477. U32 jmpIp = codeStream.emit(0);
  478. ip = right->compile(codeStream, ip, subType);
  479. codeStream.patch(jmpIp, ip);
  480. }
  481. else
  482. {
  483. ip = right->compile(codeStream, ip, subType);
  484. ip = left->compile(codeStream, ip, subType);
  485. codeStream.emit(operand);
  486. }
  487. if(type != TypeReqUInt)
  488. codeStream.emit(conversionOp(TypeReqUInt, type));
  489. return codeStream.tell();
  490. }
  491. TypeReq IntBinaryExprNode::getPreferredType()
  492. {
  493. return TypeReqUInt;
  494. }
  495. //------------------------------------------------------------
  496. U32 StreqExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  497. {
  498. // eval str left
  499. // OP_ADVANCE_STR_NUL
  500. // eval str right
  501. // OP_COMPARE_STR
  502. // optional conversion
  503. ip = left->compile(codeStream, ip, TypeReqString);
  504. codeStream.emit(OP_ADVANCE_STR_NUL);
  505. ip = right->compile(codeStream, ip, TypeReqString);
  506. codeStream.emit(OP_COMPARE_STR);
  507. if(!eq)
  508. codeStream.emit(OP_NOT);
  509. if(type != TypeReqUInt)
  510. codeStream.emit(conversionOp(TypeReqUInt, type));
  511. return codeStream.tell();
  512. }
  513. TypeReq StreqExprNode::getPreferredType()
  514. {
  515. return TypeReqUInt;
  516. }
  517. //------------------------------------------------------------
  518. U32 StrcatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  519. {
  520. ip = left->compile(codeStream, ip, TypeReqString);
  521. if(!appendChar)
  522. codeStream.emit(OP_ADVANCE_STR);
  523. else
  524. {
  525. codeStream.emit(OP_ADVANCE_STR_APPENDCHAR);
  526. codeStream.emit(appendChar);
  527. }
  528. ip = right->compile(codeStream, ip, TypeReqString);
  529. codeStream.emit(OP_REWIND_STR);
  530. if(type == TypeReqUInt)
  531. codeStream.emit(OP_STR_TO_UINT);
  532. else if(type == TypeReqFloat)
  533. codeStream.emit(OP_STR_TO_FLT);
  534. return codeStream.tell();
  535. }
  536. TypeReq StrcatExprNode::getPreferredType()
  537. {
  538. return TypeReqString;
  539. }
  540. //------------------------------------------------------------
  541. U32 CommaCatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  542. {
  543. ip = left->compile(codeStream, ip, TypeReqString);
  544. codeStream.emit(OP_ADVANCE_STR_COMMA);
  545. ip = right->compile(codeStream, ip, TypeReqString);
  546. codeStream.emit(OP_REWIND_STR);
  547. // At this point the stack has the concatenated string.
  548. // But we're paranoid, so accept (but whine) if we get an oddity...
  549. if(type == TypeReqUInt || type == TypeReqFloat)
  550. Con::warnf(ConsoleLogEntry::General, "%s (%d): converting comma string to a number... probably wrong.", dbgFileName, dbgLineNumber);
  551. if(type == TypeReqUInt)
  552. codeStream.emit(OP_STR_TO_UINT);
  553. else if(type == TypeReqFloat)
  554. codeStream.emit(OP_STR_TO_FLT);
  555. return codeStream.tell();
  556. }
  557. TypeReq CommaCatExprNode::getPreferredType()
  558. {
  559. return TypeReqString;
  560. }
  561. //------------------------------------------------------------
  562. U32 IntUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  563. {
  564. integer = true;
  565. TypeReq prefType = expr->getPreferredType();
  566. if(op == '!' && (prefType == TypeReqFloat || prefType == TypeReqString))
  567. integer = false;
  568. ip = expr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  569. if(op == '!')
  570. codeStream.emit(integer ? OP_NOT : OP_NOTF);
  571. else if(op == '~')
  572. codeStream.emit(OP_ONESCOMPLEMENT);
  573. if(type != TypeReqUInt)
  574. codeStream.emit(conversionOp(TypeReqUInt, type));
  575. return codeStream.tell();
  576. }
  577. TypeReq IntUnaryExprNode::getPreferredType()
  578. {
  579. return TypeReqUInt;
  580. }
  581. //------------------------------------------------------------
  582. U32 FloatUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  583. {
  584. ip = expr->compile(codeStream, ip, TypeReqFloat);
  585. codeStream.emit(OP_NEG);
  586. if(type != TypeReqFloat)
  587. codeStream.emit(conversionOp(TypeReqFloat, type));
  588. return codeStream.tell();
  589. }
  590. TypeReq FloatUnaryExprNode::getPreferredType()
  591. {
  592. return TypeReqFloat;
  593. }
  594. //------------------------------------------------------------
  595. U32 VarNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  596. {
  597. // if this has an arrayIndex...
  598. // OP_LOADIMMED_IDENT
  599. // varName
  600. // OP_ADVANCE_STR
  601. // evaluate arrayIndex TypeReqString
  602. // OP_REWIND_STR
  603. // OP_SETCURVAR_ARRAY
  604. // OP_LOADVAR (type)
  605. // else
  606. // OP_SETCURVAR
  607. // varName
  608. // OP_LOADVAR (type)
  609. if(type == TypeReqNone)
  610. return codeStream.tell();
  611. precompileIdent(varName);
  612. codeStream.emit(arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR);
  613. codeStream.emitSTE(varName);
  614. if(arrayIndex)
  615. {
  616. codeStream.emit(OP_ADVANCE_STR);
  617. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  618. codeStream.emit(OP_REWIND_STR);
  619. codeStream.emit(OP_SETCURVAR_ARRAY);
  620. }
  621. switch(type)
  622. {
  623. case TypeReqUInt:
  624. codeStream.emit(OP_LOADVAR_UINT);
  625. break;
  626. case TypeReqFloat:
  627. codeStream.emit(OP_LOADVAR_FLT);
  628. break;
  629. case TypeReqString:
  630. codeStream.emit(OP_LOADVAR_STR);
  631. break;
  632. case TypeReqVar:
  633. codeStream.emit(OP_LOADVAR_VAR);
  634. break;
  635. case TypeReqNone:
  636. break;
  637. default:
  638. break;
  639. }
  640. return codeStream.tell();
  641. }
  642. TypeReq VarNode::getPreferredType()
  643. {
  644. return TypeReqNone; // no preferred type
  645. }
  646. //------------------------------------------------------------
  647. U32 IntNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  648. {
  649. if(type == TypeReqString)
  650. index = getCurrentStringTable()->addIntString(value);
  651. else if(type == TypeReqFloat)
  652. index = getCurrentFloatTable()->add(value);
  653. switch(type)
  654. {
  655. case TypeReqUInt:
  656. codeStream.emit(OP_LOADIMMED_UINT);
  657. codeStream.emit(value);
  658. break;
  659. case TypeReqString:
  660. codeStream.emit(OP_LOADIMMED_STR);
  661. codeStream.emit(index);
  662. break;
  663. case TypeReqFloat:
  664. codeStream.emit(OP_LOADIMMED_FLT);
  665. codeStream.emit(index);
  666. break;
  667. case TypeReqNone:
  668. break;
  669. }
  670. return codeStream.tell();
  671. }
  672. TypeReq IntNode::getPreferredType()
  673. {
  674. return TypeReqUInt;
  675. }
  676. //------------------------------------------------------------
  677. U32 FloatNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  678. {
  679. if(type == TypeReqString)
  680. index = getCurrentStringTable()->addFloatString(value);
  681. else if(type == TypeReqFloat)
  682. index = getCurrentFloatTable()->add(value);
  683. switch(type)
  684. {
  685. case TypeReqUInt:
  686. codeStream.emit(OP_LOADIMMED_UINT);
  687. codeStream.emit(U32(value));
  688. break;
  689. case TypeReqString:
  690. codeStream.emit(OP_LOADIMMED_STR);
  691. codeStream.emit(index);
  692. break;
  693. case TypeReqFloat:
  694. codeStream.emit(OP_LOADIMMED_FLT);
  695. codeStream.emit(index);
  696. break;
  697. case TypeReqNone:
  698. break;
  699. }
  700. return codeStream.tell();
  701. }
  702. TypeReq FloatNode::getPreferredType()
  703. {
  704. return TypeReqFloat;
  705. }
  706. //------------------------------------------------------------
  707. U32 StrConstNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  708. {
  709. // Early out for documentation block.
  710. if( doc )
  711. {
  712. index = getCurrentStringTable()->add(str, true, tag);
  713. }
  714. else if(type == TypeReqString)
  715. {
  716. index = getCurrentStringTable()->add(str, true, tag);
  717. }
  718. else if (type != TypeReqNone)
  719. {
  720. fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber);
  721. if(type == TypeReqFloat)
  722. {
  723. index = getCurrentFloatTable()->add(fVal);
  724. }
  725. }
  726. // If this is a DOCBLOCK, then process w/ appropriate op...
  727. if( doc )
  728. {
  729. codeStream.emit(OP_DOCBLOCK_STR);
  730. codeStream.emit(index);
  731. return ip;
  732. }
  733. // Otherwise, deal with it normally as a string literal case.
  734. switch(type)
  735. {
  736. case TypeReqString:
  737. codeStream.emit(tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR);
  738. codeStream.emit(index);
  739. break;
  740. case TypeReqUInt:
  741. codeStream.emit(OP_LOADIMMED_UINT);
  742. codeStream.emit(U32(fVal));
  743. break;
  744. case TypeReqFloat:
  745. codeStream.emit(OP_LOADIMMED_FLT);
  746. codeStream.emit(index);
  747. break;
  748. case TypeReqNone:
  749. break;
  750. }
  751. return codeStream.tell();
  752. }
  753. TypeReq StrConstNode::getPreferredType()
  754. {
  755. return TypeReqString;
  756. }
  757. //------------------------------------------------------------
  758. U32 ConstantNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  759. {
  760. if(type == TypeReqString)
  761. {
  762. precompileIdent(value);
  763. }
  764. else if (type != TypeReqNone)
  765. {
  766. fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber);
  767. if(type == TypeReqFloat)
  768. index = getCurrentFloatTable()->add(fVal);
  769. }
  770. switch(type)
  771. {
  772. case TypeReqString:
  773. codeStream.emit(OP_LOADIMMED_IDENT);
  774. codeStream.emitSTE(value);
  775. break;
  776. case TypeReqUInt:
  777. codeStream.emit(OP_LOADIMMED_UINT);
  778. codeStream.emit(U32(fVal));
  779. break;
  780. case TypeReqFloat:
  781. codeStream.emit(OP_LOADIMMED_FLT);
  782. codeStream.emit(index);
  783. break;
  784. case TypeReqNone:
  785. break;
  786. }
  787. return ip;
  788. }
  789. TypeReq ConstantNode::getPreferredType()
  790. {
  791. return TypeReqString;
  792. }
  793. //------------------------------------------------------------
  794. U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  795. {
  796. subType = expr->getPreferredType();
  797. if(subType == TypeReqNone)
  798. subType = type;
  799. if(subType == TypeReqNone)
  800. {
  801. // What we need to do in this case is turn it into a VarNode reference.
  802. // Unfortunately other nodes such as field access (SlotAccessNode)
  803. // cannot be optimized in the same manner as all fields are exposed
  804. // and set as strings.
  805. if (dynamic_cast<VarNode*>(expr) != NULL)
  806. {
  807. subType = TypeReqVar;
  808. }
  809. else
  810. {
  811. subType = TypeReqString;
  812. }
  813. }
  814. // if it's an array expr, the formula is:
  815. // eval expr
  816. // (push and pop if it's TypeReqString) OP_ADVANCE_STR
  817. // OP_LOADIMMED_IDENT
  818. // varName
  819. // OP_ADVANCE_STR
  820. // eval array
  821. // OP_REWIND_STR
  822. // OP_SETCURVAR_ARRAY_CREATE
  823. // OP_TERMINATE_REWIND_STR
  824. // OP_SAVEVAR
  825. //else
  826. // eval expr
  827. // OP_SETCURVAR_CREATE
  828. // varname
  829. // OP_SAVEVAR
  830. precompileIdent(varName);
  831. ip = expr->compile(codeStream, ip, subType);
  832. if(arrayIndex)
  833. {
  834. if(subType == TypeReqString)
  835. codeStream.emit(OP_ADVANCE_STR);
  836. codeStream.emit(OP_LOADIMMED_IDENT);
  837. codeStream.emitSTE(varName);
  838. codeStream.emit(OP_ADVANCE_STR);
  839. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  840. codeStream.emit(OP_REWIND_STR);
  841. codeStream.emit(OP_SETCURVAR_ARRAY_CREATE);
  842. if(subType == TypeReqString)
  843. codeStream.emit(OP_TERMINATE_REWIND_STR);
  844. }
  845. else
  846. {
  847. codeStream.emit(OP_SETCURVAR_CREATE);
  848. codeStream.emitSTE(varName);
  849. }
  850. switch(subType)
  851. {
  852. case TypeReqString:
  853. codeStream.emit(OP_SAVEVAR_STR);
  854. break;
  855. case TypeReqUInt:
  856. codeStream.emit(OP_SAVEVAR_UINT);
  857. break;
  858. case TypeReqFloat:
  859. codeStream.emit(OP_SAVEVAR_FLT);
  860. break;
  861. case TypeReqVar:
  862. codeStream.emit(OP_SAVEVAR_VAR);
  863. break;
  864. case TypeReqNone:
  865. break;
  866. }
  867. if(type != subType)
  868. codeStream.emit(conversionOp(subType, type));
  869. return ip;
  870. }
  871. TypeReq AssignExprNode::getPreferredType()
  872. {
  873. return expr->getPreferredType();
  874. }
  875. //------------------------------------------------------------
  876. static void getAssignOpTypeOp(S32 op, TypeReq &type, U32 &operand)
  877. {
  878. switch(op)
  879. {
  880. case '+':
  881. type = TypeReqFloat;
  882. operand = OP_ADD;
  883. break;
  884. case '-':
  885. type = TypeReqFloat;
  886. operand = OP_SUB;
  887. break;
  888. case '*':
  889. type = TypeReqFloat;
  890. operand = OP_MUL;
  891. break;
  892. case '/':
  893. type = TypeReqFloat;
  894. operand = OP_DIV;
  895. break;
  896. case '%':
  897. type = TypeReqUInt;
  898. operand = OP_MOD;
  899. break;
  900. case '&':
  901. type = TypeReqUInt;
  902. operand = OP_BITAND;
  903. break;
  904. case '^':
  905. type = TypeReqUInt;
  906. operand = OP_XOR;
  907. break;
  908. case '|':
  909. type = TypeReqUInt;
  910. operand = OP_BITOR;
  911. break;
  912. case opSHL:
  913. type = TypeReqUInt;
  914. operand = OP_SHL;
  915. break;
  916. case opSHR:
  917. type = TypeReqUInt;
  918. operand = OP_SHR;
  919. break;
  920. }
  921. }
  922. U32 AssignOpExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  923. {
  924. // goes like this...
  925. // eval expr as float or int
  926. // if there's an arrayIndex
  927. // OP_LOADIMMED_IDENT
  928. // varName
  929. // OP_ADVANCE_STR
  930. // eval arrayIndex stringwise
  931. // OP_REWIND_STR
  932. // OP_SETCURVAR_ARRAY_CREATE
  933. // else
  934. // OP_SETCURVAR_CREATE
  935. // varName
  936. // OP_LOADVAR_FLT or UINT
  937. // operand
  938. // OP_SAVEVAR_FLT or UINT
  939. // conversion OP if necessary.
  940. getAssignOpTypeOp(op, subType, operand);
  941. precompileIdent(varName);
  942. ip = expr->compile(codeStream, ip, subType);
  943. if(!arrayIndex)
  944. {
  945. codeStream.emit(OP_SETCURVAR_CREATE);
  946. codeStream.emitSTE(varName);
  947. }
  948. else
  949. {
  950. codeStream.emit(OP_LOADIMMED_IDENT);
  951. codeStream.emitSTE(varName);
  952. codeStream.emit(OP_ADVANCE_STR);
  953. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  954. codeStream.emit(OP_REWIND_STR);
  955. codeStream.emit(OP_SETCURVAR_ARRAY_CREATE);
  956. }
  957. codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT);
  958. codeStream.emit(operand);
  959. codeStream.emit((subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT);
  960. if(subType != type)
  961. codeStream.emit(conversionOp(subType, type));
  962. return codeStream.tell();
  963. }
  964. TypeReq AssignOpExprNode::getPreferredType()
  965. {
  966. getAssignOpTypeOp(op, subType, operand);
  967. return subType;
  968. }
  969. //------------------------------------------------------------
  970. U32 TTagSetStmtNode::compileStmt(CodeStream&, U32 ip)
  971. {
  972. return ip;
  973. }
  974. //------------------------------------------------------------
  975. U32 TTagDerefNode::compile(CodeStream&, U32 ip, TypeReq)
  976. {
  977. return ip;
  978. }
  979. TypeReq TTagDerefNode::getPreferredType()
  980. {
  981. return TypeReqNone;
  982. }
  983. //------------------------------------------------------------
  984. U32 TTagExprNode::compile(CodeStream&, U32 ip, TypeReq)
  985. {
  986. return ip;
  987. }
  988. TypeReq TTagExprNode::getPreferredType()
  989. {
  990. return TypeReqNone;
  991. }
  992. //------------------------------------------------------------
  993. U32 FuncCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  994. {
  995. // OP_PUSH_FRAME
  996. // arg OP_PUSH arg OP_PUSH arg OP_PUSH
  997. // eval all the args, then call the function.
  998. // OP_CALLFUNC
  999. // function
  1000. // namespace
  1001. // isDot
  1002. precompileIdent(funcName);
  1003. precompileIdent(nameSpace);
  1004. codeStream.emit(OP_PUSH_FRAME);
  1005. for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext())
  1006. {
  1007. TypeReq walkType = walk->getPreferredType();
  1008. if (walkType == TypeReqNone) walkType = TypeReqString;
  1009. ip = walk->compile(codeStream, ip, walkType);
  1010. switch (walk->getPreferredType())
  1011. {
  1012. case TypeReqFloat:
  1013. codeStream.emit(OP_PUSH_FLT);
  1014. break;
  1015. case TypeReqUInt:
  1016. codeStream.emit(OP_PUSH_UINT);
  1017. break;
  1018. default:
  1019. codeStream.emit(OP_PUSH);
  1020. break;
  1021. }
  1022. }
  1023. if(callType == MethodCall || callType == ParentCall)
  1024. codeStream.emit(OP_CALLFUNC);
  1025. else
  1026. codeStream.emit(OP_CALLFUNC_RESOLVE);
  1027. codeStream.emitSTE(funcName);
  1028. codeStream.emitSTE(nameSpace);
  1029. codeStream.emit(callType);
  1030. if(type != TypeReqString)
  1031. codeStream.emit(conversionOp(TypeReqString, type));
  1032. return codeStream.tell();
  1033. }
  1034. TypeReq FuncCallExprNode::getPreferredType()
  1035. {
  1036. return TypeReqString;
  1037. }
  1038. //------------------------------------------------------------
  1039. U32 AssertCallExprNode::compile( CodeStream &codeStream, U32 ip, TypeReq type )
  1040. {
  1041. #ifdef TORQUE_ENABLE_SCRIPTASSERTS
  1042. messageIndex = getCurrentStringTable()->add( message, true, false );
  1043. ip = testExpr->compile( codeStream, ip, TypeReqUInt );
  1044. codeStream.emit(OP_ASSERT);
  1045. codeStream.emit(messageIndex);
  1046. #endif
  1047. return codeStream.tell();
  1048. }
  1049. TypeReq AssertCallExprNode::getPreferredType()
  1050. {
  1051. return TypeReqNone;
  1052. }
  1053. //------------------------------------------------------------
  1054. U32 SlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  1055. {
  1056. if(type == TypeReqNone)
  1057. return ip;
  1058. precompileIdent(slotName);
  1059. if(arrayExpr)
  1060. {
  1061. // eval array
  1062. // OP_ADVANCE_STR
  1063. // evaluate object expression sub (OP_SETCURFIELD)
  1064. // OP_TERMINATE_REWIND_STR
  1065. // OP_SETCURFIELDARRAY
  1066. // total add of 4 + array precomp
  1067. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1068. codeStream.emit(OP_ADVANCE_STR);
  1069. }
  1070. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1071. codeStream.emit(OP_SETCUROBJECT);
  1072. codeStream.emit(OP_SETCURFIELD);
  1073. codeStream.emitSTE(slotName);
  1074. if(arrayExpr)
  1075. {
  1076. codeStream.emit(OP_TERMINATE_REWIND_STR);
  1077. codeStream.emit(OP_SETCURFIELD_ARRAY);
  1078. }
  1079. switch(type)
  1080. {
  1081. case TypeReqUInt:
  1082. codeStream.emit(OP_LOADFIELD_UINT);
  1083. break;
  1084. case TypeReqFloat:
  1085. codeStream.emit(OP_LOADFIELD_FLT);
  1086. break;
  1087. case TypeReqString:
  1088. codeStream.emit(OP_LOADFIELD_STR);
  1089. break;
  1090. case TypeReqNone:
  1091. break;
  1092. }
  1093. return codeStream.tell();
  1094. }
  1095. TypeReq SlotAccessNode::getPreferredType()
  1096. {
  1097. return TypeReqNone;
  1098. }
  1099. //-----------------------------------------------------------------------------
  1100. U32 InternalSlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  1101. {
  1102. if(type == TypeReqNone)
  1103. return ip;
  1104. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1105. codeStream.emit(OP_SETCUROBJECT);
  1106. ip = slotExpr->compile(codeStream, ip, TypeReqString);
  1107. codeStream.emit(OP_SETCUROBJECT_INTERNAL);
  1108. codeStream.emit(recurse);
  1109. if(type != TypeReqUInt)
  1110. codeStream.emit(conversionOp(TypeReqUInt, type));
  1111. return codeStream.tell();
  1112. }
  1113. TypeReq InternalSlotAccessNode::getPreferredType()
  1114. {
  1115. return TypeReqUInt;
  1116. }
  1117. //-----------------------------------------------------------------------------
  1118. U32 SlotAssignNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  1119. {
  1120. // first eval the expression TypeReqString
  1121. // if it's an array:
  1122. // if OP_ADVANCE_STR 1
  1123. // eval array
  1124. // OP_ADVANCE_STR 1
  1125. // evaluate object expr
  1126. // OP_SETCUROBJECT 1
  1127. // OP_SETCURFIELD 1
  1128. // fieldName 1
  1129. // OP_TERMINATE_REWIND_STR 1
  1130. // OP_SETCURFIELDARRAY 1
  1131. // OP_TERMINATE_REWIND_STR 1
  1132. // else
  1133. // OP_ADVANCE_STR
  1134. // evaluate object expr
  1135. // OP_SETCUROBJECT
  1136. // OP_SETCURFIELD
  1137. // fieldName
  1138. // OP_TERMINATE_REWIND_STR
  1139. // OP_SAVEFIELD
  1140. // convert to return type if necessary.
  1141. precompileIdent(slotName);
  1142. ip = valueExpr->compile(codeStream, ip, TypeReqString);
  1143. codeStream.emit(OP_ADVANCE_STR);
  1144. if(arrayExpr)
  1145. {
  1146. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1147. codeStream.emit(OP_ADVANCE_STR);
  1148. }
  1149. if(objectExpr)
  1150. {
  1151. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1152. codeStream.emit(OP_SETCUROBJECT);
  1153. }
  1154. else
  1155. codeStream.emit(OP_SETCUROBJECT_NEW);
  1156. codeStream.emit(OP_SETCURFIELD);
  1157. codeStream.emitSTE(slotName);
  1158. if(arrayExpr)
  1159. {
  1160. codeStream.emit(OP_TERMINATE_REWIND_STR);
  1161. codeStream.emit(OP_SETCURFIELD_ARRAY);
  1162. }
  1163. codeStream.emit(OP_TERMINATE_REWIND_STR);
  1164. codeStream.emit(OP_SAVEFIELD_STR);
  1165. if(typeID != -1)
  1166. {
  1167. codeStream.emit(OP_SETCURFIELD_TYPE);
  1168. codeStream.emit(typeID);
  1169. }
  1170. if(type != TypeReqString)
  1171. codeStream.emit(conversionOp(TypeReqString, type));
  1172. return codeStream.tell();
  1173. }
  1174. TypeReq SlotAssignNode::getPreferredType()
  1175. {
  1176. return TypeReqString;
  1177. }
  1178. //------------------------------------------------------------
  1179. U32 SlotAssignOpNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  1180. {
  1181. // first eval the expression as its type
  1182. // if it's an array:
  1183. // eval array
  1184. // OP_ADVANCE_STR
  1185. // evaluate object expr
  1186. // OP_SETCUROBJECT
  1187. // OP_SETCURFIELD
  1188. // fieldName
  1189. // OP_TERMINATE_REWIND_STR
  1190. // OP_SETCURFIELDARRAY
  1191. // else
  1192. // evaluate object expr
  1193. // OP_SETCUROBJECT
  1194. // OP_SETCURFIELD
  1195. // fieldName
  1196. // OP_LOADFIELD of appropriate type
  1197. // operand
  1198. // OP_SAVEFIELD of appropriate type
  1199. // convert to return type if necessary.
  1200. getAssignOpTypeOp(op, subType, operand);
  1201. precompileIdent(slotName);
  1202. ip = valueExpr->compile(codeStream, ip, subType);
  1203. if(arrayExpr)
  1204. {
  1205. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1206. codeStream.emit(OP_ADVANCE_STR);
  1207. }
  1208. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1209. codeStream.emit(OP_SETCUROBJECT);
  1210. codeStream.emit(OP_SETCURFIELD);
  1211. codeStream.emitSTE(slotName);
  1212. if(arrayExpr)
  1213. {
  1214. codeStream.emit(OP_TERMINATE_REWIND_STR);
  1215. codeStream.emit(OP_SETCURFIELD_ARRAY);
  1216. }
  1217. codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT);
  1218. codeStream.emit(operand);
  1219. codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT);
  1220. if(subType != type)
  1221. codeStream.emit(conversionOp(subType, type));
  1222. return codeStream.tell();
  1223. }
  1224. TypeReq SlotAssignOpNode::getPreferredType()
  1225. {
  1226. getAssignOpTypeOp(op, subType, operand);
  1227. return subType;
  1228. }
  1229. //------------------------------------------------------------
  1230. U32 ObjectDeclNode::compileSubObject(CodeStream &codeStream, U32 ip, bool root)
  1231. {
  1232. // goes
  1233. // OP_PUSHFRAME 1
  1234. // name expr
  1235. // OP_PUSH 1
  1236. // args... PUSH
  1237. // OP_CREATE_OBJECT 1
  1238. // parentObject 1
  1239. // isDatablock 1
  1240. // internalName 1
  1241. // isSingleton 1
  1242. // lineNumber 1
  1243. // fail point 1
  1244. // for each field, eval
  1245. // OP_ADD_OBJECT (to UINT[0]) 1
  1246. // root? 1
  1247. // add all the sub objects.
  1248. // OP_END_OBJECT 1
  1249. // root? 1
  1250. // To fix the stack issue [7/9/2007 Black]
  1251. // OP_FINISH_OBJECT <-- fail point jumps to this opcode
  1252. codeStream.emit(OP_PUSH_FRAME);
  1253. ip = classNameExpr->compile(codeStream, ip, TypeReqString);
  1254. codeStream.emit(OP_PUSH);
  1255. ip = objectNameExpr->compile(codeStream, ip, TypeReqString);
  1256. codeStream.emit(OP_PUSH);
  1257. for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext())
  1258. {
  1259. TypeReq walkType = exprWalk->getPreferredType();
  1260. if (walkType == TypeReqNone) walkType = TypeReqString;
  1261. ip = exprWalk->compile(codeStream, ip, walkType);
  1262. switch (exprWalk->getPreferredType())
  1263. {
  1264. case TypeReqFloat:
  1265. codeStream.emit(OP_PUSH_FLT);
  1266. break;
  1267. case TypeReqUInt:
  1268. codeStream.emit(OP_PUSH_UINT);
  1269. break;
  1270. default:
  1271. codeStream.emit(OP_PUSH);
  1272. break;
  1273. }
  1274. }
  1275. codeStream.emit(OP_CREATE_OBJECT);
  1276. codeStream.emitSTE(parentObject);
  1277. codeStream.emit(isDatablock);
  1278. codeStream.emit(isClassNameInternal);
  1279. codeStream.emit(isSingleton);
  1280. codeStream.emit(dbgLineNumber);
  1281. const U32 failIp = codeStream.emit(0);
  1282. for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext())
  1283. ip = slotWalk->compile(codeStream, ip, TypeReqNone);
  1284. codeStream.emit(OP_ADD_OBJECT);
  1285. codeStream.emit(root);
  1286. for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext())
  1287. ip = objectWalk->compileSubObject(codeStream, ip, false);
  1288. codeStream.emit(OP_END_OBJECT);
  1289. codeStream.emit(root || isDatablock);
  1290. // Added to fix the object creation issue [7/9/2007 Black]
  1291. failOffset = codeStream.emit(OP_FINISH_OBJECT);
  1292. codeStream.patch(failIp, failOffset);
  1293. return codeStream.tell();
  1294. }
  1295. U32 ObjectDeclNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
  1296. {
  1297. // root object decl does:
  1298. // push 0 onto the UINT stack OP_LOADIMMED_UINT
  1299. // precompiles the subObject(true)
  1300. // UINT stack now has object id
  1301. // type conv to type
  1302. codeStream.emit(OP_LOADIMMED_UINT);
  1303. codeStream.emit(0);
  1304. ip = compileSubObject(codeStream, ip, true);
  1305. if(type != TypeReqUInt)
  1306. codeStream.emit(conversionOp(TypeReqUInt, type));
  1307. return codeStream.tell();
  1308. }
  1309. TypeReq ObjectDeclNode::getPreferredType()
  1310. {
  1311. return TypeReqUInt;
  1312. }
  1313. //------------------------------------------------------------
  1314. U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
  1315. {
  1316. // OP_FUNC_DECL
  1317. // func name
  1318. // namespace
  1319. // package
  1320. // hasBody?
  1321. // func end ip
  1322. // argc
  1323. // ident array[argc]
  1324. // code
  1325. // OP_RETURN_VOID
  1326. setCurrentStringTable(&getFunctionStringTable());
  1327. setCurrentFloatTable(&getFunctionFloatTable());
  1328. argc = 0;
  1329. for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext())
  1330. {
  1331. precompileIdent(walk->varName);
  1332. argc++;
  1333. }
  1334. CodeBlock::smInFunction = true;
  1335. precompileIdent(fnName);
  1336. precompileIdent(nameSpace);
  1337. precompileIdent(package);
  1338. CodeBlock::smInFunction = false;
  1339. codeStream.emit(OP_FUNC_DECL);
  1340. codeStream.emitSTE(fnName);
  1341. codeStream.emitSTE(nameSpace);
  1342. codeStream.emitSTE(package);
  1343. codeStream.emit(U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 ));
  1344. const U32 endIp = codeStream.emit(0);
  1345. codeStream.emit(argc);
  1346. for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext())
  1347. {
  1348. codeStream.emitSTE(walk->varName);
  1349. }
  1350. CodeBlock::smInFunction = true;
  1351. ip = compileBlock(stmts, codeStream, ip);
  1352. // Add break so breakpoint can be set at closing brace or
  1353. // in empty function.
  1354. addBreakLine(codeStream);
  1355. CodeBlock::smInFunction = false;
  1356. codeStream.emit(OP_RETURN_VOID);
  1357. codeStream.patch(endIp, codeStream.tell());
  1358. setCurrentStringTable(&getGlobalStringTable());
  1359. setCurrentFloatTable(&getGlobalFloatTable());
  1360. return ip;
  1361. }