astNodes.cpp 45 KB

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