astNodes.cpp 39 KB

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