astNodes.cpp 38 KB

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