astNodes.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934
  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 "platform/event.h"
  26. #include "console/ast.h"
  27. #include "core/tAlgorithm.h"
  28. #include "core/strings/findMatch.h"
  29. #include "console/consoleInternal.h"
  30. #include "core/stream/fileStream.h"
  31. #include "console/compiler.h"
  32. #include "console/simBase.h"
  33. template< typename T >
  34. struct Token
  35. {
  36. T value;
  37. S32 lineNumber;
  38. };
  39. #include "console/cmdgram.h"
  40. namespace Compiler
  41. {
  42. U32 precompileBlock(StmtNode *block, U32 loopCount)
  43. {
  44. U32 sum = 0;
  45. for(StmtNode *walk = block; walk; walk = walk->getNext())
  46. {
  47. const U32 temp = walk->precompileStmt(loopCount);
  48. #ifdef DEBUG_AST_NODES
  49. if(temp > 1000)
  50. Con::printf("suspect %s '%s' line %d", walk->dbgStmtType().c_str(), walk->dbgFileName, walk->dbgLineNumber);
  51. #endif
  52. sum += temp;
  53. }
  54. return sum;
  55. }
  56. U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint)
  57. {
  58. for(StmtNode *walk = block; walk; walk = walk->getNext())
  59. ip = walk->compileStmt(codeStream, ip, continuePoint, breakPoint);
  60. return ip;
  61. }
  62. }
  63. using namespace Compiler;
  64. //-----------------------------------------------------------------------------
  65. void StmtNode::addBreakCount()
  66. {
  67. CodeBlock::smBreakLineCount++;
  68. }
  69. void StmtNode::addBreakLine(U32 ip)
  70. {
  71. U32 line = CodeBlock::smBreakLineCount * 2;
  72. CodeBlock::smBreakLineCount++;
  73. if(getBreakCodeBlock()->lineBreakPairs)
  74. {
  75. getBreakCodeBlock()->lineBreakPairs[line] = dbgLineNumber;
  76. getBreakCodeBlock()->lineBreakPairs[line+1] = ip;
  77. }
  78. }
  79. //------------------------------------------------------------
  80. StmtNode::StmtNode()
  81. {
  82. next = NULL;
  83. dbgFileName = CodeBlock::smCurrentParser->getCurrentFile();
  84. }
  85. void StmtNode::setPackage(StringTableEntry)
  86. {
  87. }
  88. void StmtNode::append(StmtNode *next)
  89. {
  90. StmtNode *walk = this;
  91. while(walk->next)
  92. walk = walk->next;
  93. walk->next = next;
  94. }
  95. void FunctionDeclStmtNode::setPackage(StringTableEntry packageName)
  96. {
  97. package = packageName;
  98. }
  99. //------------------------------------------------------------
  100. //
  101. // Console language compilers
  102. //
  103. //------------------------------------------------------------
  104. static U32 conversionOp(TypeReq src, TypeReq dst)
  105. {
  106. if(src == TypeReqString)
  107. {
  108. switch(dst)
  109. {
  110. case TypeReqUInt:
  111. return OP_STR_TO_UINT;
  112. case TypeReqFloat:
  113. return OP_STR_TO_FLT;
  114. case TypeReqNone:
  115. return OP_STR_TO_NONE;
  116. default:
  117. break;
  118. }
  119. }
  120. else if(src == TypeReqFloat)
  121. {
  122. switch(dst)
  123. {
  124. case TypeReqUInt:
  125. return OP_FLT_TO_UINT;
  126. case TypeReqString:
  127. return OP_FLT_TO_STR;
  128. case TypeReqNone:
  129. return OP_FLT_TO_NONE;
  130. default:
  131. break;
  132. }
  133. }
  134. else if(src == TypeReqUInt)
  135. {
  136. switch(dst)
  137. {
  138. case TypeReqFloat:
  139. return OP_UINT_TO_FLT;
  140. case TypeReqString:
  141. return OP_UINT_TO_STR;
  142. case TypeReqNone:
  143. return OP_UINT_TO_NONE;
  144. default:
  145. break;
  146. }
  147. }
  148. return OP_INVALID;
  149. }
  150. //------------------------------------------------------------
  151. U32 BreakStmtNode::precompileStmt(U32 loopCount)
  152. {
  153. if(loopCount)
  154. {
  155. addBreakCount();
  156. return 2;
  157. }
  158. Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber);
  159. return 0;
  160. }
  161. U32 BreakStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32 breakPoint)
  162. {
  163. if(breakPoint)
  164. {
  165. addBreakLine(ip);
  166. codeStream[ip++] = OP_JMP;
  167. codeStream[ip++] = breakPoint;
  168. }
  169. return ip;
  170. }
  171. //------------------------------------------------------------
  172. U32 ContinueStmtNode::precompileStmt(U32 loopCount)
  173. {
  174. if(loopCount)
  175. {
  176. addBreakCount();
  177. return 2;
  178. }
  179. Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber);
  180. return 0;
  181. }
  182. U32 ContinueStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32)
  183. {
  184. if(continuePoint)
  185. {
  186. addBreakLine(ip);
  187. codeStream[ip++] = OP_JMP;
  188. codeStream[ip++] = continuePoint;
  189. }
  190. return ip;
  191. }
  192. //------------------------------------------------------------
  193. U32 ExprNode::precompileStmt(U32)
  194. {
  195. addBreakCount();
  196. return precompile(TypeReqNone);
  197. }
  198. U32 ExprNode::compileStmt(U32 *codeStream, U32 ip, U32, U32)
  199. {
  200. addBreakLine(ip);
  201. return compile(codeStream, ip, TypeReqNone);
  202. }
  203. //------------------------------------------------------------
  204. U32 ReturnStmtNode::precompileStmt(U32)
  205. {
  206. addBreakCount();
  207. U32 size = 0;
  208. if (expr) {
  209. TypeReq walkType = expr->getPreferredType();
  210. if (walkType == TypeReqNone) walkType = TypeReqString;
  211. size = expr->precompile(walkType);
  212. }
  213. return 1 + size;
  214. }
  215. U32 ReturnStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32)
  216. {
  217. addBreakLine(ip);
  218. if(!expr)
  219. codeStream[ip++] = OP_RETURN_VOID;
  220. else
  221. {
  222. TypeReq walkType = expr->getPreferredType();
  223. if (walkType == TypeReqNone) walkType = TypeReqString;
  224. ip = expr->compile(codeStream, ip, walkType);
  225. // Return the correct type
  226. switch (walkType) {
  227. case TypeReqUInt:
  228. codeStream[ip++] = OP_RETURN_UINT;
  229. break;
  230. case TypeReqFloat:
  231. codeStream[ip++] = OP_RETURN_FLT;
  232. break;
  233. default:
  234. codeStream[ip++] = OP_RETURN;
  235. break;
  236. }
  237. }
  238. return ip;
  239. }
  240. //------------------------------------------------------------
  241. ExprNode *IfStmtNode::getSwitchOR(ExprNode *left, ExprNode *list, bool string)
  242. {
  243. ExprNode *nextExpr = (ExprNode *) list->getNext();
  244. ExprNode *test;
  245. if(string)
  246. test = StreqExprNode::alloc( left->dbgLineNumber, left, list, true );
  247. else
  248. test = IntBinaryExprNode::alloc( left->dbgLineNumber, opEQ, left, list );
  249. if(!nextExpr)
  250. return test;
  251. return IntBinaryExprNode::alloc( test->dbgLineNumber, opOR, test, getSwitchOR( left, nextExpr, string ) );
  252. }
  253. void IfStmtNode::propagateSwitchExpr(ExprNode *left, bool string)
  254. {
  255. testExpr = getSwitchOR(left, testExpr, string);
  256. if(propagate && elseBlock)
  257. ((IfStmtNode *) elseBlock)->propagateSwitchExpr(left, string);
  258. }
  259. U32 IfStmtNode::precompileStmt(U32 loopCount)
  260. {
  261. U32 exprSize;
  262. addBreakCount();
  263. if(testExpr->getPreferredType() == TypeReqUInt)
  264. {
  265. exprSize = testExpr->precompile(TypeReqUInt);
  266. integer = true;
  267. }
  268. else
  269. {
  270. exprSize = testExpr->precompile(TypeReqFloat);
  271. integer = false;
  272. }
  273. // next is the JMPIFNOT or JMPIFFNOT - size of 2
  274. U32 ifSize = precompileBlock(ifBlock, loopCount);
  275. if(!elseBlock)
  276. endifOffset = ifSize + 2 + exprSize;
  277. else
  278. {
  279. elseOffset = exprSize + 2 + ifSize + 2;
  280. U32 elseSize = precompileBlock(elseBlock, loopCount);
  281. endifOffset = elseOffset + elseSize;
  282. }
  283. return endifOffset;
  284. }
  285. U32 IfStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint)
  286. {
  287. U32 start = ip;
  288. addBreakLine(ip);
  289. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  290. codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT;
  291. if(elseBlock)
  292. {
  293. codeStream[ip++] = start + elseOffset;
  294. ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint);
  295. codeStream[ip++] = OP_JMP;
  296. codeStream[ip++] = start + endifOffset;
  297. ip = compileBlock(elseBlock, codeStream, ip, continuePoint, breakPoint);
  298. }
  299. else
  300. {
  301. codeStream[ip++] = start + endifOffset;
  302. ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint);
  303. }
  304. return ip;
  305. }
  306. //------------------------------------------------------------
  307. U32 LoopStmtNode::precompileStmt(U32 loopCount)
  308. {
  309. U32 initSize = 0;
  310. addBreakCount();
  311. if(initExpr)
  312. initSize = initExpr->precompile(TypeReqNone);
  313. U32 testSize;
  314. if(testExpr->getPreferredType() == TypeReqUInt)
  315. {
  316. integer = true;
  317. testSize = testExpr->precompile(TypeReqUInt);
  318. }
  319. else
  320. {
  321. integer = false;
  322. testSize = testExpr->precompile(TypeReqFloat);
  323. }
  324. U32 blockSize = precompileBlock(loopBlock, loopCount + 1);
  325. U32 endLoopSize = 0;
  326. if(endLoopExpr)
  327. endLoopSize = endLoopExpr->precompile(TypeReqNone);
  328. // if it's a for loop or a while loop it goes:
  329. // initExpr
  330. // testExpr
  331. // OP_JMPIFNOT to break point
  332. // loopStartPoint:
  333. // loopBlock
  334. // continuePoint:
  335. // endLoopExpr
  336. // testExpr
  337. // OP_JMPIF loopStartPoint
  338. // breakPoint:
  339. // otherwise if it's a do ... while() it goes:
  340. // initExpr
  341. // loopStartPoint:
  342. // loopBlock
  343. // continuePoint:
  344. // endLoopExpr
  345. // testExpr
  346. // OP_JMPIF loopStartPoint
  347. // breakPoint:
  348. if(!isDoLoop)
  349. {
  350. loopBlockStartOffset = initSize + testSize + 2;
  351. continueOffset = loopBlockStartOffset + blockSize;
  352. breakOffset = continueOffset + endLoopSize + testSize + 2;
  353. }
  354. else
  355. {
  356. loopBlockStartOffset = initSize;
  357. continueOffset = initSize + blockSize;
  358. breakOffset = continueOffset + endLoopSize + testSize + 2;
  359. }
  360. return breakOffset;
  361. }
  362. U32 LoopStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32)
  363. {
  364. addBreakLine(ip);
  365. U32 start = ip;
  366. if(initExpr)
  367. ip = initExpr->compile(codeStream, ip, TypeReqNone);
  368. if(!isDoLoop)
  369. {
  370. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  371. codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT;
  372. codeStream[ip++] = start + breakOffset;
  373. }
  374. // Compile internals of loop.
  375. ip = compileBlock(loopBlock, codeStream, ip, start + continueOffset, start + breakOffset);
  376. if(endLoopExpr)
  377. ip = endLoopExpr->compile(codeStream, ip, TypeReqNone);
  378. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  379. codeStream[ip++] = integer ? OP_JMPIF : OP_JMPIFF;
  380. codeStream[ip++] = start + loopBlockStartOffset;
  381. return ip;
  382. }
  383. //------------------------------------------------------------
  384. U32 IterStmtNode::precompileStmt( U32 loopCount )
  385. {
  386. addBreakCount();
  387. // Instruction sequence:
  388. //
  389. // containerExpr
  390. // OP_ITER_BEGIN varName .fail
  391. // .continue:
  392. // OP_ITER .break
  393. // body
  394. // OP_JMP .continue
  395. // .break:
  396. // OP_ITER_END
  397. // .fail:
  398. U32 exprSize = containerExpr->precompile( TypeReqString );
  399. bodySize = precompileBlock( body, loopCount + 1 );
  400. return
  401. exprSize
  402. + 3 // OP_ITER_BEGIN
  403. + 2 // OP_ITER
  404. + bodySize
  405. + 2 // OP_JMP
  406. + 1 // OP_ITER_END
  407. ;
  408. }
  409. U32 IterStmtNode::compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint )
  410. {
  411. addBreakLine( ip );
  412. const U32 startIp = ip;
  413. const U32 iterBeginIp = containerExpr->compile( codeStream, startIp, TypeReqString );
  414. const U32 continueIp = iterBeginIp + 3;
  415. const U32 bodyIp = continueIp + 2;
  416. const U32 jmpIp = bodyIp + bodySize;
  417. const U32 breakIp = jmpIp + 2;
  418. const U32 finalIp = breakIp + 1;
  419. codeStream[ iterBeginIp ] = isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN;
  420. codeStream[ iterBeginIp + 1 ] = STEtoU32( varName, iterBeginIp + 1 );
  421. codeStream[ iterBeginIp + 2 ] = finalIp;
  422. codeStream[ continueIp ] = OP_ITER;
  423. codeStream[ continueIp + 1 ] = breakIp;
  424. compileBlock( body, codeStream, bodyIp, continueIp, breakIp );
  425. codeStream[ jmpIp ] = OP_JMP;
  426. codeStream[ jmpIp + 1 ] = continueIp;
  427. codeStream[ breakIp ] = OP_ITER_END;
  428. return finalIp;
  429. }
  430. //------------------------------------------------------------
  431. U32 ConditionalExprNode::precompile(TypeReq type)
  432. {
  433. // code is testExpr
  434. // JMPIFNOT falseStart
  435. // trueExpr
  436. // JMP end
  437. // falseExpr
  438. U32 exprSize;
  439. if(testExpr->getPreferredType() == TypeReqUInt)
  440. {
  441. exprSize = testExpr->precompile(TypeReqUInt);
  442. integer = true;
  443. }
  444. else
  445. {
  446. exprSize = testExpr->precompile(TypeReqFloat);
  447. integer = false;
  448. }
  449. return exprSize +
  450. trueExpr->precompile(type) +
  451. falseExpr->precompile(type) + 4;
  452. }
  453. U32 ConditionalExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  454. {
  455. ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  456. codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT;
  457. U32 jumpElseIp = ip++;
  458. ip = trueExpr->compile(codeStream, ip, type);
  459. codeStream[ip++] = OP_JMP;
  460. U32 jumpEndIp = ip++;
  461. codeStream[jumpElseIp] = ip;
  462. ip = falseExpr->compile(codeStream, ip, type);
  463. codeStream[jumpEndIp] = ip;
  464. return ip;
  465. }
  466. TypeReq ConditionalExprNode::getPreferredType()
  467. {
  468. return trueExpr->getPreferredType();
  469. }
  470. //------------------------------------------------------------
  471. U32 FloatBinaryExprNode::precompile(TypeReq type)
  472. {
  473. U32 addSize = left->precompile(TypeReqFloat) + right->precompile(TypeReqFloat) + 1;
  474. if(type != TypeReqFloat)
  475. addSize++;
  476. return addSize;
  477. }
  478. U32 FloatBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  479. {
  480. ip = right->compile(codeStream, ip, TypeReqFloat);
  481. ip = left->compile(codeStream, ip, TypeReqFloat);
  482. U32 operand = OP_INVALID;
  483. switch(op)
  484. {
  485. case '+':
  486. operand = OP_ADD;
  487. break;
  488. case '-':
  489. operand = OP_SUB;
  490. break;
  491. case '/':
  492. operand = OP_DIV;
  493. break;
  494. case '*':
  495. operand = OP_MUL;
  496. break;
  497. }
  498. codeStream[ip++] = operand;
  499. if(type != TypeReqFloat)
  500. codeStream[ip++] =conversionOp(TypeReqFloat, type);
  501. return ip;
  502. }
  503. TypeReq FloatBinaryExprNode::getPreferredType()
  504. {
  505. return TypeReqFloat;
  506. }
  507. //------------------------------------------------------------
  508. void IntBinaryExprNode::getSubTypeOperand()
  509. {
  510. subType = TypeReqUInt;
  511. switch(op)
  512. {
  513. case '^':
  514. operand = OP_XOR;
  515. break;
  516. case '%':
  517. operand = OP_MOD;
  518. break;
  519. case '&':
  520. operand = OP_BITAND;
  521. break;
  522. case '|':
  523. operand = OP_BITOR;
  524. break;
  525. case '<':
  526. operand = OP_CMPLT;
  527. subType = TypeReqFloat;
  528. break;
  529. case '>':
  530. operand = OP_CMPGR;
  531. subType = TypeReqFloat;
  532. break;
  533. case opGE:
  534. operand = OP_CMPGE;
  535. subType = TypeReqFloat;
  536. break;
  537. case opLE:
  538. operand = OP_CMPLE;
  539. subType = TypeReqFloat;
  540. break;
  541. case opEQ:
  542. operand = OP_CMPEQ;
  543. subType = TypeReqFloat;
  544. break;
  545. case opNE:
  546. operand = OP_CMPNE;
  547. subType = TypeReqFloat;
  548. break;
  549. case opOR:
  550. operand = OP_OR;
  551. break;
  552. case opAND:
  553. operand = OP_AND;
  554. break;
  555. case opSHR:
  556. operand = OP_SHR;
  557. break;
  558. case opSHL:
  559. operand = OP_SHL;
  560. break;
  561. }
  562. }
  563. U32 IntBinaryExprNode::precompile(TypeReq type)
  564. {
  565. getSubTypeOperand();
  566. U32 addSize = left->precompile(subType) + right->precompile(subType) + 1;
  567. if(operand == OP_OR || operand == OP_AND)
  568. addSize++;
  569. if(type != TypeReqUInt)
  570. addSize++;
  571. return addSize;
  572. }
  573. U32 IntBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  574. {
  575. if(operand == OP_OR || operand == OP_AND)
  576. {
  577. ip = left->compile(codeStream, ip, subType);
  578. codeStream[ip++] = operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP;
  579. U32 jmpIp = ip++;
  580. ip = right->compile(codeStream, ip, subType);
  581. codeStream[jmpIp] = ip;
  582. }
  583. else
  584. {
  585. ip = right->compile(codeStream, ip, subType);
  586. ip = left->compile(codeStream, ip, subType);
  587. codeStream[ip++] = operand;
  588. }
  589. if(type != TypeReqUInt)
  590. codeStream[ip++] =conversionOp(TypeReqUInt, type);
  591. return ip;
  592. }
  593. TypeReq IntBinaryExprNode::getPreferredType()
  594. {
  595. return TypeReqUInt;
  596. }
  597. //------------------------------------------------------------
  598. U32 StreqExprNode::precompile(TypeReq type)
  599. {
  600. // eval str left
  601. // OP_ADVANCE_STR_NUL
  602. // eval str right
  603. // OP_COMPARE_STR
  604. // optional conversion
  605. U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2;
  606. if(!eq)
  607. addSize ++;
  608. if(type != TypeReqUInt)
  609. addSize ++;
  610. return addSize;
  611. }
  612. U32 StreqExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  613. {
  614. ip = left->compile(codeStream, ip, TypeReqString);
  615. codeStream[ip++] = OP_ADVANCE_STR_NUL;
  616. ip = right->compile(codeStream, ip, TypeReqString);
  617. codeStream[ip++] = OP_COMPARE_STR;
  618. if(!eq)
  619. codeStream[ip++] = OP_NOT;
  620. if(type != TypeReqUInt)
  621. codeStream[ip++] = conversionOp(TypeReqUInt, type);
  622. return ip;
  623. }
  624. TypeReq StreqExprNode::getPreferredType()
  625. {
  626. return TypeReqUInt;
  627. }
  628. //------------------------------------------------------------
  629. U32 StrcatExprNode::precompile(TypeReq type)
  630. {
  631. U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2;
  632. if(appendChar)
  633. addSize++;
  634. if(type != TypeReqString)
  635. addSize ++;
  636. return addSize;
  637. }
  638. U32 StrcatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  639. {
  640. ip = left->compile(codeStream, ip, TypeReqString);
  641. if(!appendChar)
  642. codeStream[ip++] = OP_ADVANCE_STR;
  643. else
  644. {
  645. codeStream[ip++] = OP_ADVANCE_STR_APPENDCHAR;
  646. codeStream[ip++] = appendChar;
  647. }
  648. ip = right->compile(codeStream, ip, TypeReqString);
  649. codeStream[ip++] = OP_REWIND_STR;
  650. if(type == TypeReqUInt)
  651. codeStream[ip++] = OP_STR_TO_UINT;
  652. else if(type == TypeReqFloat)
  653. codeStream[ip++] = OP_STR_TO_FLT;
  654. return ip;
  655. }
  656. TypeReq StrcatExprNode::getPreferredType()
  657. {
  658. return TypeReqString;
  659. }
  660. //------------------------------------------------------------
  661. U32 CommaCatExprNode::precompile(TypeReq type)
  662. {
  663. U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2;
  664. if(type != TypeReqString)
  665. addSize ++;
  666. return addSize;
  667. }
  668. U32 CommaCatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  669. {
  670. ip = left->compile(codeStream, ip, TypeReqString);
  671. codeStream[ip++] = OP_ADVANCE_STR_COMMA;
  672. ip = right->compile(codeStream, ip, TypeReqString);
  673. codeStream[ip++] = OP_REWIND_STR;
  674. // At this point the stack has the concatenated string.
  675. // But we're paranoid, so accept (but whine) if we get an oddity...
  676. if(type == TypeReqUInt || type == TypeReqFloat)
  677. Con::warnf(ConsoleLogEntry::General, "%s (%d): converting comma string to a number... probably wrong.", dbgFileName, dbgLineNumber);
  678. if(type == TypeReqUInt)
  679. codeStream[ip++] = OP_STR_TO_UINT;
  680. else if(type == TypeReqFloat)
  681. codeStream[ip++] = OP_STR_TO_FLT;
  682. return ip;
  683. }
  684. TypeReq CommaCatExprNode::getPreferredType()
  685. {
  686. return TypeReqString;
  687. }
  688. //------------------------------------------------------------
  689. U32 IntUnaryExprNode::precompile(TypeReq type)
  690. {
  691. integer = true;
  692. TypeReq prefType = expr->getPreferredType();
  693. if(op == '!' && (prefType == TypeReqFloat || prefType == TypeReqString))
  694. integer = false;
  695. U32 exprSize = expr->precompile(integer ? TypeReqUInt : TypeReqFloat);
  696. if(type != TypeReqUInt)
  697. return exprSize + 2;
  698. else
  699. return exprSize + 1;
  700. }
  701. U32 IntUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  702. {
  703. ip = expr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat);
  704. if(op == '!')
  705. codeStream[ip++] = integer ? OP_NOT : OP_NOTF;
  706. else if(op == '~')
  707. codeStream[ip++] = OP_ONESCOMPLEMENT;
  708. if(type != TypeReqUInt)
  709. codeStream[ip++] =conversionOp(TypeReqUInt, type);
  710. return ip;
  711. }
  712. TypeReq IntUnaryExprNode::getPreferredType()
  713. {
  714. return TypeReqUInt;
  715. }
  716. //------------------------------------------------------------
  717. U32 FloatUnaryExprNode::precompile(TypeReq type)
  718. {
  719. U32 exprSize = expr->precompile(TypeReqFloat);
  720. if(type != TypeReqFloat)
  721. return exprSize + 2;
  722. else
  723. return exprSize + 1;
  724. }
  725. U32 FloatUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  726. {
  727. ip = expr->compile(codeStream, ip, TypeReqFloat);
  728. codeStream[ip++] = OP_NEG;
  729. if(type != TypeReqFloat)
  730. codeStream[ip++] =conversionOp(TypeReqFloat, type);
  731. return ip;
  732. }
  733. TypeReq FloatUnaryExprNode::getPreferredType()
  734. {
  735. return TypeReqFloat;
  736. }
  737. //------------------------------------------------------------
  738. U32 VarNode::precompile(TypeReq type)
  739. {
  740. // if this has an arrayIndex...
  741. // OP_LOADIMMED_IDENT
  742. // varName
  743. // OP_ADVANCE_STR
  744. // evaluate arrayIndex TypeReqString
  745. // OP_REWIND_STR
  746. // OP_SETCURVAR_ARRAY
  747. // OP_LOADVAR (type)
  748. // else
  749. // OP_SETCURVAR
  750. // varName
  751. // OP_LOADVAR (type)
  752. if(type == TypeReqNone)
  753. return 0;
  754. precompileIdent(varName);
  755. return (arrayIndex ? arrayIndex->precompile(TypeReqString) + 6 : 3);
  756. }
  757. U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  758. {
  759. if(type == TypeReqNone)
  760. return ip;
  761. codeStream[ip++] = arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR;
  762. codeStream[ip] = STEtoU32(varName, ip);
  763. ip++;
  764. if(arrayIndex)
  765. {
  766. codeStream[ip++] = OP_ADVANCE_STR;
  767. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  768. codeStream[ip++] = OP_REWIND_STR;
  769. codeStream[ip++] = OP_SETCURVAR_ARRAY;
  770. }
  771. switch(type)
  772. {
  773. case TypeReqUInt:
  774. codeStream[ip++] = OP_LOADVAR_UINT;
  775. break;
  776. case TypeReqFloat:
  777. codeStream[ip++] = OP_LOADVAR_FLT;
  778. break;
  779. case TypeReqString:
  780. codeStream[ip++] = OP_LOADVAR_STR;
  781. break;
  782. case TypeReqNone:
  783. break;
  784. }
  785. return ip;
  786. }
  787. TypeReq VarNode::getPreferredType()
  788. {
  789. return TypeReqNone; // no preferred type
  790. }
  791. //------------------------------------------------------------
  792. U32 IntNode::precompile(TypeReq type)
  793. {
  794. if(type == TypeReqNone)
  795. return 0;
  796. if(type == TypeReqString)
  797. index = getCurrentStringTable()->addIntString(value);
  798. else if(type == TypeReqFloat)
  799. index = getCurrentFloatTable()->add(value);
  800. return 2;
  801. }
  802. U32 IntNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  803. {
  804. switch(type)
  805. {
  806. case TypeReqUInt:
  807. codeStream[ip++] = OP_LOADIMMED_UINT;
  808. codeStream[ip++] = value;
  809. break;
  810. case TypeReqString:
  811. codeStream[ip++] = OP_LOADIMMED_STR;
  812. codeStream[ip++] = index;
  813. break;
  814. case TypeReqFloat:
  815. codeStream[ip++] = OP_LOADIMMED_FLT;
  816. codeStream[ip++] = index;
  817. break;
  818. case TypeReqNone:
  819. break;
  820. }
  821. return ip;
  822. }
  823. TypeReq IntNode::getPreferredType()
  824. {
  825. return TypeReqUInt;
  826. }
  827. //------------------------------------------------------------
  828. U32 FloatNode::precompile(TypeReq type)
  829. {
  830. if(type == TypeReqNone)
  831. return 0;
  832. if(type == TypeReqString)
  833. index = getCurrentStringTable()->addFloatString(value);
  834. else if(type == TypeReqFloat)
  835. index = getCurrentFloatTable()->add(value);
  836. return 2;
  837. }
  838. U32 FloatNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  839. {
  840. switch(type)
  841. {
  842. case TypeReqUInt:
  843. codeStream[ip++] = OP_LOADIMMED_UINT;
  844. codeStream[ip++] = U32(value);
  845. break;
  846. case TypeReqString:
  847. codeStream[ip++] = OP_LOADIMMED_STR;
  848. codeStream[ip++] = index;
  849. break;
  850. case TypeReqFloat:
  851. codeStream[ip++] = OP_LOADIMMED_FLT;
  852. codeStream[ip++] = index;
  853. break;
  854. case TypeReqNone:
  855. break;
  856. }
  857. return ip;
  858. }
  859. TypeReq FloatNode::getPreferredType()
  860. {
  861. return TypeReqFloat;
  862. }
  863. //------------------------------------------------------------
  864. U32 StrConstNode::precompile(TypeReq type)
  865. {
  866. // Early out for documentation block.
  867. if( doc )
  868. {
  869. index = getCurrentStringTable()->add(str, true, tag);
  870. return 2;
  871. }
  872. if(type == TypeReqString)
  873. {
  874. index = getCurrentStringTable()->add(str, true, tag);
  875. return 2;
  876. }
  877. else if(type == TypeReqNone)
  878. {
  879. return 0;
  880. }
  881. fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber);
  882. if(type == TypeReqFloat)
  883. index = getCurrentFloatTable()->add(fVal);
  884. return 2;
  885. }
  886. U32 StrConstNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  887. {
  888. // If this is a DOCBLOCK, then process w/ appropriate op...
  889. if( doc )
  890. {
  891. codeStream[ip++] = OP_DOCBLOCK_STR;
  892. codeStream[ip++] = index;
  893. return ip;
  894. }
  895. // Otherwise, deal with it normally as a string literal case.
  896. switch(type)
  897. {
  898. case TypeReqString:
  899. codeStream[ip++] = tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR;
  900. codeStream[ip++] = index;
  901. break;
  902. case TypeReqUInt:
  903. codeStream[ip++] = OP_LOADIMMED_UINT;
  904. codeStream[ip++] = U32(fVal);
  905. break;
  906. case TypeReqFloat:
  907. codeStream[ip++] = OP_LOADIMMED_FLT;
  908. codeStream[ip++] = index;
  909. break;
  910. case TypeReqNone:
  911. break;
  912. }
  913. return ip;
  914. }
  915. TypeReq StrConstNode::getPreferredType()
  916. {
  917. return TypeReqString;
  918. }
  919. //------------------------------------------------------------
  920. U32 ConstantNode::precompile(TypeReq type)
  921. {
  922. if(type == TypeReqString)
  923. {
  924. precompileIdent(value);
  925. return 2;
  926. }
  927. else if(type == TypeReqNone)
  928. return 0;
  929. fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber);
  930. if(type == TypeReqFloat)
  931. index = getCurrentFloatTable()->add(fVal);
  932. return 2;
  933. }
  934. U32 ConstantNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  935. {
  936. switch(type)
  937. {
  938. case TypeReqString:
  939. codeStream[ip++] = OP_LOADIMMED_IDENT;
  940. codeStream[ip] = STEtoU32(value, ip);
  941. ip++;
  942. break;
  943. case TypeReqUInt:
  944. codeStream[ip++] = OP_LOADIMMED_UINT;
  945. codeStream[ip++] = U32(fVal);
  946. break;
  947. case TypeReqFloat:
  948. codeStream[ip++] = OP_LOADIMMED_FLT;
  949. codeStream[ip++] = index;
  950. break;
  951. case TypeReqNone:
  952. break;
  953. }
  954. return ip;
  955. }
  956. TypeReq ConstantNode::getPreferredType()
  957. {
  958. return TypeReqString;
  959. }
  960. //------------------------------------------------------------
  961. U32 AssignExprNode::precompile(TypeReq type)
  962. {
  963. subType = expr->getPreferredType();
  964. if(subType == TypeReqNone)
  965. subType = type;
  966. if(subType == TypeReqNone)
  967. subType = TypeReqString;
  968. // if it's an array expr, the formula is:
  969. // eval expr
  970. // (push and pop if it's TypeReqString) OP_ADVANCE_STR
  971. // OP_LOADIMMED_IDENT
  972. // varName
  973. // OP_ADVANCE_STR
  974. // eval array
  975. // OP_REWIND_STR
  976. // OP_SETCURVAR_ARRAY_CREATE
  977. // OP_TERMINATE_REWIND_STR
  978. // OP_SAVEVAR
  979. //else
  980. // eval expr
  981. // OP_SETCURVAR_CREATE
  982. // varname
  983. // OP_SAVEVAR
  984. const U32 addSize = (type != subType ? 1 : 0);
  985. const U32 retSize = expr->precompile(subType);
  986. #ifdef DEBUG_AST_NODES
  987. if(retSize > 1000)
  988. Con::printf("Bad expr %s", expr->dbgStmtType().c_str());
  989. #endif
  990. precompileIdent(varName);
  991. return retSize + addSize + (arrayIndex ? arrayIndex->precompile(TypeReqString) + (subType == TypeReqString ? 8 : 6 ) : 3);
  992. }
  993. U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  994. {
  995. ip = expr->compile(codeStream, ip, subType);
  996. if(arrayIndex)
  997. {
  998. if(subType == TypeReqString)
  999. codeStream[ip++] = OP_ADVANCE_STR;
  1000. codeStream[ip++] = OP_LOADIMMED_IDENT;
  1001. codeStream[ip] = STEtoU32(varName, ip);
  1002. ip++;
  1003. codeStream[ip++] = OP_ADVANCE_STR;
  1004. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  1005. codeStream[ip++] = OP_REWIND_STR;
  1006. codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE;
  1007. if(subType == TypeReqString)
  1008. codeStream[ip++] = OP_TERMINATE_REWIND_STR;
  1009. }
  1010. else
  1011. {
  1012. codeStream[ip++] = OP_SETCURVAR_CREATE;
  1013. codeStream[ip] = STEtoU32(varName, ip);
  1014. ip++;
  1015. }
  1016. switch(subType)
  1017. {
  1018. case TypeReqString:
  1019. codeStream[ip++] = OP_SAVEVAR_STR;
  1020. break;
  1021. case TypeReqUInt:
  1022. codeStream[ip++] = OP_SAVEVAR_UINT;
  1023. break;
  1024. case TypeReqFloat:
  1025. codeStream[ip++] = OP_SAVEVAR_FLT;
  1026. break;
  1027. case TypeReqNone:
  1028. break;
  1029. }
  1030. if(type != subType)
  1031. codeStream[ip++] = conversionOp(subType, type);
  1032. return ip;
  1033. }
  1034. TypeReq AssignExprNode::getPreferredType()
  1035. {
  1036. return expr->getPreferredType();
  1037. }
  1038. //------------------------------------------------------------
  1039. static void getAssignOpTypeOp(S32 op, TypeReq &type, U32 &operand)
  1040. {
  1041. switch(op)
  1042. {
  1043. case '+':
  1044. type = TypeReqFloat;
  1045. operand = OP_ADD;
  1046. break;
  1047. case '-':
  1048. type = TypeReqFloat;
  1049. operand = OP_SUB;
  1050. break;
  1051. case '*':
  1052. type = TypeReqFloat;
  1053. operand = OP_MUL;
  1054. break;
  1055. case '/':
  1056. type = TypeReqFloat;
  1057. operand = OP_DIV;
  1058. break;
  1059. case '%':
  1060. type = TypeReqUInt;
  1061. operand = OP_MOD;
  1062. break;
  1063. case '&':
  1064. type = TypeReqUInt;
  1065. operand = OP_BITAND;
  1066. break;
  1067. case '^':
  1068. type = TypeReqUInt;
  1069. operand = OP_XOR;
  1070. break;
  1071. case '|':
  1072. type = TypeReqUInt;
  1073. operand = OP_BITOR;
  1074. break;
  1075. case opSHL:
  1076. type = TypeReqUInt;
  1077. operand = OP_SHL;
  1078. break;
  1079. case opSHR:
  1080. type = TypeReqUInt;
  1081. operand = OP_SHR;
  1082. break;
  1083. }
  1084. }
  1085. U32 AssignOpExprNode::precompile(TypeReq type)
  1086. {
  1087. // goes like this...
  1088. // eval expr as float or int
  1089. // if there's an arrayIndex
  1090. // OP_LOADIMMED_IDENT
  1091. // varName
  1092. // OP_ADVANCE_STR
  1093. // eval arrayIndex stringwise
  1094. // OP_REWIND_STR
  1095. // OP_SETCURVAR_ARRAY_CREATE
  1096. // else
  1097. // OP_SETCURVAR_CREATE
  1098. // varName
  1099. // OP_LOADVAR_FLT or UINT
  1100. // operand
  1101. // OP_SAVEVAR_FLT or UINT
  1102. // conversion OP if necessary.
  1103. getAssignOpTypeOp(op, subType, operand);
  1104. precompileIdent(varName);
  1105. U32 size = expr->precompile(subType);
  1106. if(type != subType)
  1107. size++;
  1108. if(!arrayIndex)
  1109. return size + 5;
  1110. else
  1111. {
  1112. size += arrayIndex->precompile(TypeReqString);
  1113. return size + 8;
  1114. }
  1115. }
  1116. U32 AssignOpExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1117. {
  1118. ip = expr->compile(codeStream, ip, subType);
  1119. if(!arrayIndex)
  1120. {
  1121. codeStream[ip++] = OP_SETCURVAR_CREATE;
  1122. codeStream[ip] = STEtoU32(varName, ip);
  1123. ip++;
  1124. }
  1125. else
  1126. {
  1127. codeStream[ip++] = OP_LOADIMMED_IDENT;
  1128. codeStream[ip] = STEtoU32(varName, ip);
  1129. ip++;
  1130. codeStream[ip++] = OP_ADVANCE_STR;
  1131. ip = arrayIndex->compile(codeStream, ip, TypeReqString);
  1132. codeStream[ip++] = OP_REWIND_STR;
  1133. codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE;
  1134. }
  1135. codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT;
  1136. codeStream[ip++] = operand;
  1137. codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT;
  1138. if(subType != type)
  1139. codeStream[ip++] = conversionOp(subType, type);
  1140. return ip;
  1141. }
  1142. TypeReq AssignOpExprNode::getPreferredType()
  1143. {
  1144. getAssignOpTypeOp(op, subType, operand);
  1145. return subType;
  1146. }
  1147. //------------------------------------------------------------
  1148. U32 TTagSetStmtNode::precompileStmt(U32 loopCount)
  1149. {
  1150. TORQUE_UNUSED(loopCount);
  1151. return 0;
  1152. }
  1153. U32 TTagSetStmtNode::compileStmt(U32*, U32 ip, U32, U32)
  1154. {
  1155. return ip;
  1156. }
  1157. //------------------------------------------------------------
  1158. U32 TTagDerefNode::precompile(TypeReq)
  1159. {
  1160. return 0;
  1161. }
  1162. U32 TTagDerefNode::compile(U32*, U32 ip, TypeReq)
  1163. {
  1164. return ip;
  1165. }
  1166. TypeReq TTagDerefNode::getPreferredType()
  1167. {
  1168. return TypeReqNone;
  1169. }
  1170. //------------------------------------------------------------
  1171. U32 TTagExprNode::precompile(TypeReq)
  1172. {
  1173. return 0;
  1174. }
  1175. U32 TTagExprNode::compile(U32*, U32 ip, TypeReq)
  1176. {
  1177. return ip;
  1178. }
  1179. TypeReq TTagExprNode::getPreferredType()
  1180. {
  1181. return TypeReqNone;
  1182. }
  1183. //------------------------------------------------------------
  1184. U32 FuncCallExprNode::precompile(TypeReq type)
  1185. {
  1186. // OP_PUSH_FRAME
  1187. // arg OP_PUSH arg OP_PUSH arg OP_PUSH
  1188. // eval all the args, then call the function.
  1189. // OP_CALLFUNC
  1190. // function
  1191. // namespace
  1192. // isDot
  1193. U32 size = 0;
  1194. if(type != TypeReqString)
  1195. size++;
  1196. precompileIdent(funcName);
  1197. precompileIdent(nameSpace);
  1198. for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext()) {
  1199. TypeReq walkType = walk->getPreferredType();
  1200. if (walkType == TypeReqNone) walkType = TypeReqString;
  1201. size += walk->precompile(walkType) + 1;
  1202. }
  1203. return size + 5;
  1204. }
  1205. U32 FuncCallExprNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1206. {
  1207. codeStream[ip++] = OP_PUSH_FRAME;
  1208. for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext())
  1209. {
  1210. TypeReq walkType = walk->getPreferredType();
  1211. if (walkType == TypeReqNone) walkType = TypeReqString;
  1212. ip = walk->compile(codeStream, ip, walkType);
  1213. switch (walk->getPreferredType()) {
  1214. case TypeReqFloat:
  1215. codeStream[ip++] = OP_PUSH_FLT;
  1216. break;
  1217. case TypeReqUInt:
  1218. codeStream[ip++] = OP_PUSH_UINT;
  1219. break;
  1220. default:
  1221. codeStream[ip++] = OP_PUSH;
  1222. break;
  1223. }
  1224. }
  1225. if(callType == MethodCall || callType == ParentCall)
  1226. codeStream[ip++] = OP_CALLFUNC;
  1227. else
  1228. codeStream[ip++] = OP_CALLFUNC_RESOLVE;
  1229. codeStream[ip] = STEtoU32(funcName, ip);
  1230. ip++;
  1231. codeStream[ip] = STEtoU32(nameSpace, ip);
  1232. ip++;
  1233. codeStream[ip++] = callType;
  1234. if(type != TypeReqString)
  1235. codeStream[ip++] = conversionOp(TypeReqString, type);
  1236. return ip;
  1237. }
  1238. TypeReq FuncCallExprNode::getPreferredType()
  1239. {
  1240. return TypeReqString;
  1241. }
  1242. //------------------------------------------------------------
  1243. U32 AssertCallExprNode::precompile( TypeReq type )
  1244. {
  1245. #ifdef TORQUE_ENABLE_SCRIPTASSERTS
  1246. messageIndex = getCurrentStringTable()->add( message, true, false );
  1247. U32 exprSize = testExpr->precompile(TypeReqUInt);
  1248. return exprSize + 2;
  1249. #else
  1250. return 0;
  1251. #endif
  1252. }
  1253. U32 AssertCallExprNode::compile( U32 *codeStream, U32 ip, TypeReq type )
  1254. {
  1255. #ifdef TORQUE_ENABLE_SCRIPTASSERTS
  1256. ip = testExpr->compile( codeStream, ip, TypeReqUInt );
  1257. codeStream[ip++] = OP_ASSERT;
  1258. codeStream[ip++] = messageIndex;
  1259. #endif
  1260. return ip;
  1261. }
  1262. TypeReq AssertCallExprNode::getPreferredType()
  1263. {
  1264. return TypeReqNone;
  1265. }
  1266. //------------------------------------------------------------
  1267. U32 SlotAccessNode::precompile(TypeReq type)
  1268. {
  1269. if(type == TypeReqNone)
  1270. return 0;
  1271. U32 size = 0;
  1272. precompileIdent(slotName);
  1273. if(arrayExpr)
  1274. {
  1275. // eval array
  1276. // OP_ADVANCE_STR
  1277. // evaluate object expression sub (OP_SETCURFIELD)
  1278. // OP_TERMINATE_REWIND_STR
  1279. // OP_SETCURFIELDARRAY
  1280. // total add of 4 + array precomp
  1281. size += 3 + arrayExpr->precompile(TypeReqString);
  1282. }
  1283. // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT)
  1284. size += objectExpr->precompile(TypeReqString) + 3;
  1285. // get field in desired type:
  1286. return size + 1;
  1287. }
  1288. U32 SlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1289. {
  1290. if(type == TypeReqNone)
  1291. return ip;
  1292. if(arrayExpr)
  1293. {
  1294. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1295. codeStream[ip++] = OP_ADVANCE_STR;
  1296. }
  1297. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1298. codeStream[ip++] = OP_SETCUROBJECT;
  1299. codeStream[ip++] = OP_SETCURFIELD;
  1300. codeStream[ip] = STEtoU32(slotName, ip);
  1301. ip++;
  1302. if(arrayExpr)
  1303. {
  1304. codeStream[ip++] = OP_TERMINATE_REWIND_STR;
  1305. codeStream[ip++] = OP_SETCURFIELD_ARRAY;
  1306. }
  1307. switch(type)
  1308. {
  1309. case TypeReqUInt:
  1310. codeStream[ip++] = OP_LOADFIELD_UINT;
  1311. break;
  1312. case TypeReqFloat:
  1313. codeStream[ip++] = OP_LOADFIELD_FLT;
  1314. break;
  1315. case TypeReqString:
  1316. codeStream[ip++] = OP_LOADFIELD_STR;
  1317. break;
  1318. case TypeReqNone:
  1319. break;
  1320. }
  1321. return ip;
  1322. }
  1323. TypeReq SlotAccessNode::getPreferredType()
  1324. {
  1325. return TypeReqNone;
  1326. }
  1327. //-----------------------------------------------------------------------------
  1328. U32 InternalSlotAccessNode::precompile(TypeReq type)
  1329. {
  1330. if(type == TypeReqNone)
  1331. return 0;
  1332. U32 size = 3;
  1333. // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT)
  1334. size += objectExpr->precompile(TypeReqString);
  1335. size += slotExpr->precompile(TypeReqString);
  1336. if(type != TypeReqUInt)
  1337. size++;
  1338. // get field in desired type:
  1339. return size;
  1340. }
  1341. U32 InternalSlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1342. {
  1343. if(type == TypeReqNone)
  1344. return ip;
  1345. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1346. codeStream[ip++] = OP_SETCUROBJECT;
  1347. ip = slotExpr->compile(codeStream, ip, TypeReqString);
  1348. codeStream[ip++] = OP_SETCUROBJECT_INTERNAL;
  1349. codeStream[ip++] = recurse;
  1350. if(type != TypeReqUInt)
  1351. codeStream[ip++] = conversionOp(TypeReqUInt, type);
  1352. return ip;
  1353. }
  1354. TypeReq InternalSlotAccessNode::getPreferredType()
  1355. {
  1356. return TypeReqUInt;
  1357. }
  1358. //-----------------------------------------------------------------------------
  1359. //------------------------------------------------------------
  1360. U32 SlotAssignNode::precompile(TypeReq type)
  1361. {
  1362. // first eval the expression TypeReqString
  1363. // if it's an array:
  1364. // if OP_ADVANCE_STR 1
  1365. // eval array
  1366. // OP_ADVANCE_STR 1
  1367. // evaluate object expr
  1368. // OP_SETCUROBJECT 1
  1369. // OP_SETCURFIELD 1
  1370. // fieldName 1
  1371. // OP_TERMINATE_REWIND_STR 1
  1372. // OP_SETCURFIELDARRAY 1
  1373. // OP_TERMINATE_REWIND_STR 1
  1374. // else
  1375. // OP_ADVANCE_STR
  1376. // evaluate object expr
  1377. // OP_SETCUROBJECT
  1378. // OP_SETCURFIELD
  1379. // fieldName
  1380. // OP_TERMINATE_REWIND_STR
  1381. // OP_SAVEFIELD
  1382. // convert to return type if necessary.
  1383. U32 size = 0;
  1384. if(type != TypeReqString)
  1385. size++;
  1386. precompileIdent(slotName);
  1387. size += valueExpr->precompile(TypeReqString);
  1388. if(objectExpr)
  1389. size += objectExpr->precompile(TypeReqString) + 5;
  1390. else
  1391. size += 5;
  1392. if(arrayExpr)
  1393. size += arrayExpr->precompile(TypeReqString) + 3;
  1394. if(typeID != -1)
  1395. size += 2;
  1396. return size + 1;
  1397. }
  1398. U32 SlotAssignNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1399. {
  1400. ip = valueExpr->compile(codeStream, ip, TypeReqString);
  1401. codeStream[ip++] = OP_ADVANCE_STR;
  1402. if(arrayExpr)
  1403. {
  1404. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1405. codeStream[ip++] = OP_ADVANCE_STR;
  1406. }
  1407. if(objectExpr)
  1408. {
  1409. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1410. codeStream[ip++] = OP_SETCUROBJECT;
  1411. }
  1412. else
  1413. codeStream[ip++] = OP_SETCUROBJECT_NEW;
  1414. codeStream[ip++] = OP_SETCURFIELD;
  1415. codeStream[ip] = STEtoU32(slotName, ip);
  1416. ip++;
  1417. if(arrayExpr)
  1418. {
  1419. codeStream[ip++] = OP_TERMINATE_REWIND_STR;
  1420. codeStream[ip++] = OP_SETCURFIELD_ARRAY;
  1421. }
  1422. codeStream[ip++] = OP_TERMINATE_REWIND_STR;
  1423. codeStream[ip++] = OP_SAVEFIELD_STR;
  1424. if(typeID != -1)
  1425. {
  1426. codeStream[ip++] = OP_SETCURFIELD_TYPE;
  1427. codeStream[ip++] = typeID;
  1428. }
  1429. if(type != TypeReqString)
  1430. codeStream[ip++] = conversionOp(TypeReqString, type);
  1431. return ip;
  1432. }
  1433. TypeReq SlotAssignNode::getPreferredType()
  1434. {
  1435. return TypeReqString;
  1436. }
  1437. //------------------------------------------------------------
  1438. U32 SlotAssignOpNode::precompile(TypeReq type)
  1439. {
  1440. // first eval the expression as its type
  1441. // if it's an array:
  1442. // eval array
  1443. // OP_ADVANCE_STR
  1444. // evaluate object expr
  1445. // OP_SETCUROBJECT
  1446. // OP_SETCURFIELD
  1447. // fieldName
  1448. // OP_TERMINATE_REWIND_STR
  1449. // OP_SETCURFIELDARRAY
  1450. // else
  1451. // evaluate object expr
  1452. // OP_SETCUROBJECT
  1453. // OP_SETCURFIELD
  1454. // fieldName
  1455. // OP_LOADFIELD of appropriate type
  1456. // operand
  1457. // OP_SAVEFIELD of appropriate type
  1458. // convert to return type if necessary.
  1459. getAssignOpTypeOp(op, subType, operand);
  1460. precompileIdent(slotName);
  1461. U32 size = valueExpr->precompile(subType);
  1462. if(type != subType)
  1463. size++;
  1464. if(arrayExpr)
  1465. return size + 9 + arrayExpr->precompile(TypeReqString) + objectExpr->precompile(TypeReqString);
  1466. else
  1467. return size + 6 + objectExpr->precompile(TypeReqString);
  1468. }
  1469. U32 SlotAssignOpNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1470. {
  1471. ip = valueExpr->compile(codeStream, ip, subType);
  1472. if(arrayExpr)
  1473. {
  1474. ip = arrayExpr->compile(codeStream, ip, TypeReqString);
  1475. codeStream[ip++] = OP_ADVANCE_STR;
  1476. }
  1477. ip = objectExpr->compile(codeStream, ip, TypeReqString);
  1478. codeStream[ip++] = OP_SETCUROBJECT;
  1479. codeStream[ip++] = OP_SETCURFIELD;
  1480. codeStream[ip] = STEtoU32(slotName, ip);
  1481. ip++;
  1482. if(arrayExpr)
  1483. {
  1484. codeStream[ip++] = OP_TERMINATE_REWIND_STR;
  1485. codeStream[ip++] = OP_SETCURFIELD_ARRAY;
  1486. }
  1487. codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT;
  1488. codeStream[ip++] = operand;
  1489. codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT;
  1490. if(subType != type)
  1491. codeStream[ip++] = conversionOp(subType, type);
  1492. return ip;
  1493. }
  1494. TypeReq SlotAssignOpNode::getPreferredType()
  1495. {
  1496. getAssignOpTypeOp(op, subType, operand);
  1497. return subType;
  1498. }
  1499. //------------------------------------------------------------
  1500. U32 ObjectDeclNode::precompileSubObject(bool)
  1501. {
  1502. // goes
  1503. // OP_PUSHFRAME 1
  1504. // name expr
  1505. // OP_PUSH 1
  1506. // args... PUSH
  1507. // OP_CREATE_OBJECT 1
  1508. // parentObject 1
  1509. // isDatablock 1
  1510. // internalName 1
  1511. // isSingleton 1
  1512. // lineNumber 1
  1513. // fail point 1
  1514. // for each field, eval
  1515. // OP_ADD_OBJECT (to UINT[0]) 1
  1516. // root? 1
  1517. // add all the sub objects.
  1518. // OP_END_OBJECT 1
  1519. // root? 1
  1520. // To fix the stack issue [7/9/2007 Black]
  1521. // OP_FINISH_OBJECT <-- fail point jumps to this opcode
  1522. U32 argSize = 0;
  1523. precompileIdent(parentObject);
  1524. for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext()) {
  1525. TypeReq walkType = exprWalk->getPreferredType();
  1526. if (walkType == TypeReqNone) walkType = TypeReqString;
  1527. argSize += exprWalk->precompile(walkType) + 1;
  1528. }
  1529. argSize += classNameExpr->precompile(TypeReqString) + 1;
  1530. U32 nameSize = objectNameExpr->precompile(TypeReqString) + 1;
  1531. U32 slotSize = 0;
  1532. for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext())
  1533. slotSize += slotWalk->precompile(TypeReqNone);
  1534. // OP_ADD_OBJECT
  1535. U32 subObjSize = 0;
  1536. for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext())
  1537. subObjSize += objectWalk->precompileSubObject(false);
  1538. failOffset = 12 + nameSize + argSize + slotSize + subObjSize;
  1539. // +1 because the failOffset should jump to OP_FINISH_OBJECT [7/9/2007 Black]
  1540. return failOffset + 1;
  1541. }
  1542. U32 ObjectDeclNode::precompile(TypeReq type)
  1543. {
  1544. // root object decl does:
  1545. // push 0 onto the UINT stack OP_LOADIMMED_UINT
  1546. // precompiles the subObject(true)
  1547. // UINT stack now has object id
  1548. // type conv to type
  1549. U32 ret = 2 + precompileSubObject(true);
  1550. if(type != TypeReqUInt)
  1551. return ret + 1;
  1552. return ret;
  1553. }
  1554. U32 ObjectDeclNode::compileSubObject(U32 *codeStream, U32 ip, bool root)
  1555. {
  1556. U32 start = ip;
  1557. codeStream[ip++] = OP_PUSH_FRAME;
  1558. ip = classNameExpr->compile(codeStream, ip, TypeReqString);
  1559. codeStream[ip++] = OP_PUSH;
  1560. ip = objectNameExpr->compile(codeStream, ip, TypeReqString);
  1561. codeStream[ip++] = OP_PUSH;
  1562. for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext())
  1563. {
  1564. TypeReq walkType = exprWalk->getPreferredType();
  1565. if (walkType == TypeReqNone) walkType = TypeReqString;
  1566. ip = exprWalk->compile(codeStream, ip, walkType);
  1567. switch (exprWalk->getPreferredType()) {
  1568. case TypeReqFloat:
  1569. codeStream[ip++] = OP_PUSH_FLT;
  1570. break;
  1571. case TypeReqUInt:
  1572. codeStream[ip++] = OP_PUSH_UINT;
  1573. break;
  1574. default:
  1575. codeStream[ip++] = OP_PUSH;
  1576. break;
  1577. }
  1578. }
  1579. codeStream[ip++] = OP_CREATE_OBJECT;
  1580. codeStream[ip] = STEtoU32(parentObject, ip);
  1581. ip++;
  1582. codeStream[ip++] = isDatablock;
  1583. codeStream[ip++] = isClassNameInternal;
  1584. codeStream[ip++] = isSingleton;
  1585. codeStream[ip++] = dbgLineNumber;
  1586. codeStream[ip++] = start + failOffset;
  1587. for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext())
  1588. ip = slotWalk->compile(codeStream, ip, TypeReqNone);
  1589. codeStream[ip++] = OP_ADD_OBJECT;
  1590. codeStream[ip++] = root;
  1591. for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext())
  1592. ip = objectWalk->compileSubObject(codeStream, ip, false);
  1593. codeStream[ip++] = OP_END_OBJECT;
  1594. codeStream[ip++] = root || isDatablock;
  1595. // Added to fix the object creation issue [7/9/2007 Black]
  1596. codeStream[ip++] = OP_FINISH_OBJECT;
  1597. return ip;
  1598. }
  1599. U32 ObjectDeclNode::compile(U32 *codeStream, U32 ip, TypeReq type)
  1600. {
  1601. codeStream[ip++] = OP_LOADIMMED_UINT;
  1602. codeStream[ip++] = 0;
  1603. ip = compileSubObject(codeStream, ip, true);
  1604. if(type != TypeReqUInt)
  1605. codeStream[ip++] = conversionOp(TypeReqUInt, type);
  1606. return ip;
  1607. }
  1608. TypeReq ObjectDeclNode::getPreferredType()
  1609. {
  1610. return TypeReqUInt;
  1611. }
  1612. //------------------------------------------------------------
  1613. U32 FunctionDeclStmtNode::precompileStmt(U32)
  1614. {
  1615. // OP_FUNC_DECL
  1616. // func name
  1617. // namespace
  1618. // package
  1619. // hasBody?
  1620. // func end ip
  1621. // argc
  1622. // ident array[argc]
  1623. // code
  1624. // OP_RETURN_VOID
  1625. setCurrentStringTable(&getFunctionStringTable());
  1626. setCurrentFloatTable(&getFunctionFloatTable());
  1627. argc = 0;
  1628. for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext())
  1629. argc++;
  1630. CodeBlock::smInFunction = true;
  1631. precompileIdent(fnName);
  1632. precompileIdent(nameSpace);
  1633. precompileIdent(package);
  1634. U32 subSize = precompileBlock(stmts, 0);
  1635. CodeBlock::smInFunction = false;
  1636. addBreakCount();
  1637. setCurrentStringTable(&getGlobalStringTable());
  1638. setCurrentFloatTable(&getGlobalFloatTable());
  1639. endOffset = argc + subSize + 8;
  1640. return endOffset;
  1641. }
  1642. U32 FunctionDeclStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32)
  1643. {
  1644. U32 start = ip;
  1645. codeStream[ip++] = OP_FUNC_DECL;
  1646. codeStream[ip] = STEtoU32(fnName, ip);
  1647. ip++;
  1648. codeStream[ip] = STEtoU32(nameSpace, ip);
  1649. ip++;
  1650. codeStream[ip] = STEtoU32(package, ip);
  1651. ip++;
  1652. codeStream[ip++] = U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 );
  1653. codeStream[ip++] = start + endOffset;
  1654. codeStream[ip++] = argc;
  1655. for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext())
  1656. {
  1657. codeStream[ip] = STEtoU32(walk->varName, ip);
  1658. ip++;
  1659. }
  1660. CodeBlock::smInFunction = true;
  1661. ip = compileBlock(stmts, codeStream, ip, 0, 0);
  1662. // Add break so breakpoint can be set at closing brace or
  1663. // in empty function.
  1664. addBreakLine( ip );
  1665. CodeBlock::smInFunction = false;
  1666. codeStream[ip++] = OP_RETURN_VOID;
  1667. return ip;
  1668. }