ast.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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. #ifndef _AST_H_
  23. #define _AST_H_
  24. class ExprEvalState;
  25. class Namespace;
  26. class SimObject;
  27. class SimGroup;
  28. class CodeStream;
  29. /// Enable this #define if you are seeing the message "precompile size mismatch" in the console.
  30. /// This will help track down which node type is causing the error. It could be
  31. /// due to incorrect compiler optimization.
  32. //#define DEBUG_AST_NODES
  33. enum TypeReq
  34. {
  35. TypeReqNone,
  36. TypeReqUInt,
  37. TypeReqFloat,
  38. TypeReqString
  39. };
  40. enum ExprNodeName
  41. {
  42. NameExprNode,
  43. NameFloatNode,
  44. NameIntNode,
  45. NameVarNode
  46. };
  47. /// Representation of a node for the scripting language parser.
  48. ///
  49. /// When the scripting language is evaluated, it is turned from a string representation,
  50. /// into a parse tree, thence into byte code, which is ultimately interpreted by the VM.
  51. ///
  52. /// This is the base class for the nodes in the parse tree. There are a great many subclasses,
  53. /// each representing a different language construct.
  54. struct StmtNode
  55. {
  56. StmtNode* next; ///< Next entry in parse tree.
  57. StmtNode();
  58. virtual ~StmtNode() {}
  59. /// @name next Accessors
  60. /// @{
  61. ///
  62. void append(StmtNode* next);
  63. StmtNode* getNext() const { return next; }
  64. /// @}
  65. /// @name Debug Info
  66. /// @{
  67. StringTableEntry dbgFileName; ///< Name of file this node is associated with.
  68. S32 dbgLineNumber; ///< Line number this node is associated with.
  69. #ifdef DEBUG_AST_NODES
  70. virtual String dbgStmtType() const = 0;
  71. #endif
  72. /// @}
  73. /// @name Breaking
  74. /// @{
  75. void addBreakLine(CodeStream& codeStream);
  76. /// @}
  77. /// @name Compilation
  78. /// @{
  79. virtual U32 compileStmt(CodeStream& codeStream, U32 ip) = 0;
  80. virtual void setPackage(StringTableEntry packageName);
  81. /// @}
  82. };
  83. /// Helper macro
  84. #ifndef DEBUG_AST_NODES
  85. # define DBG_STMT_TYPE(s) virtual const char* dbgStmtType() const { return "#s"; }
  86. #else
  87. # define DBG_STMT_TYPE(s)
  88. #endif
  89. struct BreakStmtNode : StmtNode
  90. {
  91. static BreakStmtNode* alloc(S32 lineNumber);
  92. U32 compileStmt(CodeStream& codeStream, U32 ip);
  93. DBG_STMT_TYPE(BreakStmtNode);
  94. };
  95. struct ContinueStmtNode : StmtNode
  96. {
  97. static ContinueStmtNode* alloc(S32 lineNumber);
  98. U32 compileStmt(CodeStream& codeStream, U32 ip);
  99. DBG_STMT_TYPE(ContinueStmtNode);
  100. };
  101. /// A mathematical expression.
  102. struct ExprNode : StmtNode
  103. {
  104. ExprNode* optimizedNode;
  105. U32 compileStmt(CodeStream& codeStream, U32 ip);
  106. virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type) = 0;
  107. virtual TypeReq getPreferredType() = 0;
  108. virtual ExprNodeName getExprNodeNameEnum() const { return NameExprNode; }
  109. };
  110. struct ReturnStmtNode : StmtNode
  111. {
  112. ExprNode* expr;
  113. static ReturnStmtNode* alloc(S32 lineNumber, ExprNode* expr);
  114. U32 compileStmt(CodeStream& codeStream, U32 ip);
  115. DBG_STMT_TYPE(ReturnStmtNode);
  116. };
  117. struct IfStmtNode : StmtNode
  118. {
  119. ExprNode* testExpr;
  120. StmtNode* ifBlock, * elseBlock;
  121. U32 endifOffset;
  122. U32 elseOffset;
  123. bool integer;
  124. bool propagate;
  125. static IfStmtNode* alloc(S32 lineNumber, ExprNode* testExpr, StmtNode* ifBlock, StmtNode* elseBlock, bool propagateThrough);
  126. void propagateSwitchExpr(ExprNode* left, bool string);
  127. ExprNode* getSwitchOR(ExprNode* left, ExprNode* list, bool string);
  128. U32 compileStmt(CodeStream& codeStream, U32 ip);
  129. DBG_STMT_TYPE(IfStmtNode);
  130. };
  131. struct LoopStmtNode : StmtNode
  132. {
  133. ExprNode* testExpr;
  134. ExprNode* initExpr;
  135. ExprNode* endLoopExpr;
  136. StmtNode* loopBlock;
  137. bool isDoLoop;
  138. U32 breakOffset;
  139. U32 continueOffset;
  140. U32 loopBlockStartOffset;
  141. bool integer;
  142. static LoopStmtNode* alloc(S32 lineNumber, ExprNode* testExpr, ExprNode* initExpr, ExprNode* endLoopExpr, StmtNode* loopBlock, bool isDoLoop);
  143. U32 compileStmt(CodeStream& codeStream, U32 ip);
  144. DBG_STMT_TYPE(LoopStmtNode);
  145. };
  146. /// A "foreach" statement.
  147. struct IterStmtNode : StmtNode
  148. {
  149. /// Local variable name to use for the container element.
  150. StringTableEntry varName;
  151. /// Expression evaluating to a SimSet object.
  152. ExprNode* containerExpr;
  153. /// The statement body.
  154. StmtNode* body;
  155. /// If true, this is a 'foreach$'.
  156. bool isStringIter;
  157. /// Bytecode size of body statement. Set by precompileStmt.
  158. U32 bodySize;
  159. static IterStmtNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter);
  160. U32 compileStmt(CodeStream& codeStream, U32 ip);
  161. };
  162. /// A binary mathematical expression (ie, left op right).
  163. struct BinaryExprNode : ExprNode
  164. {
  165. S32 op;
  166. ExprNode* left;
  167. ExprNode* right;
  168. };
  169. struct FloatBinaryExprNode : BinaryExprNode
  170. {
  171. static FloatBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right);
  172. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  173. bool optimize();
  174. TypeReq getPreferredType();
  175. DBG_STMT_TYPE(FloatBinaryExprNode);
  176. };
  177. struct ConditionalExprNode : ExprNode
  178. {
  179. ExprNode* testExpr;
  180. ExprNode* trueExpr;
  181. ExprNode* falseExpr;
  182. bool integer;
  183. static ConditionalExprNode* alloc(S32 lineNumber, ExprNode* testExpr, ExprNode* trueExpr, ExprNode* falseExpr);
  184. virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  185. virtual TypeReq getPreferredType();
  186. DBG_STMT_TYPE(ConditionalExprNode);
  187. };
  188. struct IntBinaryExprNode : BinaryExprNode
  189. {
  190. TypeReq subType;
  191. U32 operand;
  192. static IntBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right);
  193. void getSubTypeOperand();
  194. bool optimize();
  195. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  196. TypeReq getPreferredType();
  197. DBG_STMT_TYPE(IntBinaryExprNode);
  198. };
  199. struct StreqExprNode : BinaryExprNode
  200. {
  201. bool eq;
  202. static StreqExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right, bool eq);
  203. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  204. TypeReq getPreferredType();
  205. DBG_STMT_TYPE(StreqExprNode);
  206. };
  207. struct StrcatExprNode : BinaryExprNode
  208. {
  209. S32 appendChar;
  210. static StrcatExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right, S32 appendChar);
  211. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  212. TypeReq getPreferredType();
  213. DBG_STMT_TYPE(StrcatExprNode);
  214. };
  215. struct CommaCatExprNode : BinaryExprNode
  216. {
  217. static CommaCatExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right);
  218. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  219. TypeReq getPreferredType();
  220. DBG_STMT_TYPE(CommaCatExprNode);
  221. };
  222. struct IntUnaryExprNode : ExprNode
  223. {
  224. S32 op;
  225. ExprNode* expr;
  226. bool integer;
  227. static IntUnaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* expr);
  228. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  229. TypeReq getPreferredType();
  230. DBG_STMT_TYPE(IntUnaryExprNode);
  231. };
  232. struct FloatUnaryExprNode : ExprNode
  233. {
  234. S32 op;
  235. ExprNode* expr;
  236. static FloatUnaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* expr);
  237. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  238. TypeReq getPreferredType();
  239. DBG_STMT_TYPE(FloatUnaryExprNode);
  240. };
  241. struct VarNode : ExprNode
  242. {
  243. StringTableEntry varName;
  244. ExprNode* arrayIndex;
  245. static VarNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex);
  246. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  247. TypeReq getPreferredType();
  248. virtual ExprNodeName getExprNodeNameEnum() const { return NameVarNode; }
  249. DBG_STMT_TYPE(VarNode);
  250. };
  251. struct IntNode : ExprNode
  252. {
  253. S32 value;
  254. U32 index; // if it's converted to float/string
  255. static IntNode* alloc(S32 lineNumber, S32 value);
  256. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  257. TypeReq getPreferredType();
  258. virtual ExprNodeName getExprNodeNameEnum() const { return NameIntNode; }
  259. DBG_STMT_TYPE(IntNode);
  260. };
  261. struct FloatNode : ExprNode
  262. {
  263. F64 value;
  264. U32 index;
  265. static FloatNode* alloc(S32 lineNumber, F64 value);
  266. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  267. TypeReq getPreferredType();
  268. virtual ExprNodeName getExprNodeNameEnum() const { return NameFloatNode; }
  269. DBG_STMT_TYPE(FloatNode);
  270. };
  271. struct StrConstNode : ExprNode
  272. {
  273. char* str;
  274. F64 fVal;
  275. U32 index;
  276. bool tag;
  277. bool doc; // Specifies that this string is a documentation block.
  278. static StrConstNode* alloc(S32 lineNumber, char* str, bool tag, bool doc = false);
  279. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  280. TypeReq getPreferredType();
  281. DBG_STMT_TYPE(StrConstNode);
  282. };
  283. struct ConstantNode : ExprNode
  284. {
  285. StringTableEntry value;
  286. F64 fVal;
  287. U32 index;
  288. static ConstantNode* alloc(S32 lineNumber, StringTableEntry value);
  289. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  290. TypeReq getPreferredType();
  291. DBG_STMT_TYPE(ConstantNode);
  292. };
  293. struct AssignExprNode : ExprNode
  294. {
  295. StringTableEntry varName;
  296. ExprNode* expr;
  297. ExprNode* arrayIndex;
  298. TypeReq subType;
  299. static AssignExprNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr);
  300. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  301. TypeReq getPreferredType();
  302. DBG_STMT_TYPE(AssignExprNode);
  303. };
  304. struct AssignDecl
  305. {
  306. S32 lineNumber;
  307. S32 token;
  308. ExprNode* expr;
  309. bool integer;
  310. };
  311. struct AssignOpExprNode : ExprNode
  312. {
  313. StringTableEntry varName;
  314. ExprNode* expr;
  315. ExprNode* arrayIndex;
  316. S32 op;
  317. U32 operand;
  318. TypeReq subType;
  319. static AssignOpExprNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr, S32 op);
  320. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  321. TypeReq getPreferredType();
  322. DBG_STMT_TYPE(AssignOpExprNode);
  323. };
  324. struct TTagSetStmtNode : StmtNode
  325. {
  326. StringTableEntry tag;
  327. ExprNode* valueExpr;
  328. ExprNode* stringExpr;
  329. static TTagSetStmtNode* alloc(S32 lineNumber, StringTableEntry tag, ExprNode* valueExpr, ExprNode* stringExpr);
  330. U32 compileStmt(CodeStream& codeStream, U32 ip);
  331. DBG_STMT_TYPE(TTagSetStmtNode);
  332. };
  333. struct TTagDerefNode : ExprNode
  334. {
  335. ExprNode* expr;
  336. static TTagDerefNode* alloc(S32 lineNumber, ExprNode* expr);
  337. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  338. TypeReq getPreferredType();
  339. DBG_STMT_TYPE(TTagDerefNode);
  340. };
  341. struct TTagExprNode : ExprNode
  342. {
  343. StringTableEntry tag;
  344. static TTagExprNode* alloc(S32 lineNumber, StringTableEntry tag);
  345. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  346. TypeReq getPreferredType();
  347. DBG_STMT_TYPE(TTagExprNode);
  348. };
  349. struct FuncCallExprNode : ExprNode
  350. {
  351. StringTableEntry funcName;
  352. StringTableEntry nameSpace;
  353. ExprNode* args;
  354. U32 callType;
  355. enum {
  356. FunctionCall,
  357. StaticCall,
  358. MethodCall,
  359. ParentCall
  360. };
  361. static FuncCallExprNode* alloc(S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode* args, bool dot);
  362. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  363. TypeReq getPreferredType();
  364. DBG_STMT_TYPE(FuncCallExprNode);
  365. };
  366. struct AssertCallExprNode : ExprNode
  367. {
  368. ExprNode* testExpr;
  369. const char* message;
  370. U32 messageIndex;
  371. static AssertCallExprNode* alloc(S32 lineNumber, ExprNode* testExpr, const char* message);
  372. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  373. TypeReq getPreferredType();
  374. DBG_STMT_TYPE(AssertCallExprNode);
  375. };
  376. struct SlotDecl
  377. {
  378. S32 lineNumber;
  379. ExprNode* object;
  380. StringTableEntry slotName;
  381. ExprNode* array;
  382. };
  383. struct SlotAccessNode : ExprNode
  384. {
  385. ExprNode* objectExpr, * arrayExpr;
  386. StringTableEntry slotName;
  387. static SlotAccessNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName);
  388. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  389. TypeReq getPreferredType();
  390. DBG_STMT_TYPE(SlotAccessNode);
  391. };
  392. struct InternalSlotDecl
  393. {
  394. S32 lineNumber;
  395. ExprNode* object;
  396. ExprNode* slotExpr;
  397. bool recurse;
  398. };
  399. struct InternalSlotAccessNode : ExprNode
  400. {
  401. ExprNode* objectExpr, * slotExpr;
  402. bool recurse;
  403. static InternalSlotAccessNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* slotExpr, bool recurse);
  404. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  405. TypeReq getPreferredType();
  406. DBG_STMT_TYPE(InternalSlotAccessNode);
  407. };
  408. struct SlotAssignNode : ExprNode
  409. {
  410. ExprNode* objectExpr, * arrayExpr;
  411. StringTableEntry slotName;
  412. ExprNode* valueExpr;
  413. U32 typeID;
  414. static SlotAssignNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName, ExprNode* valueExpr, U32 typeID = -1);
  415. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  416. TypeReq getPreferredType();
  417. DBG_STMT_TYPE(SlotAssignNode);
  418. };
  419. struct SlotAssignOpNode : ExprNode
  420. {
  421. ExprNode* objectExpr, * arrayExpr;
  422. StringTableEntry slotName;
  423. S32 op;
  424. ExprNode* valueExpr;
  425. U32 operand;
  426. TypeReq subType;
  427. static SlotAssignOpNode* alloc(S32 lineNumber, ExprNode* objectExpr, StringTableEntry slotName, ExprNode* arrayExpr, S32 op, ExprNode* valueExpr);
  428. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  429. TypeReq getPreferredType();
  430. DBG_STMT_TYPE(SlotAssignOpNode);
  431. };
  432. struct ObjectDeclNode : ExprNode
  433. {
  434. ExprNode* classNameExpr;
  435. StringTableEntry parentObject;
  436. ExprNode* objectNameExpr;
  437. ExprNode* argList;
  438. SlotAssignNode* slotDecls;
  439. ObjectDeclNode* subObjects;
  440. bool isDatablock;
  441. U32 failOffset;
  442. bool isClassNameInternal;
  443. bool isSingleton;
  444. static ObjectDeclNode* alloc(S32 lineNumber, ExprNode* classNameExpr, ExprNode* objectNameExpr, ExprNode* argList, StringTableEntry parentObject, SlotAssignNode* slotDecls, ObjectDeclNode* subObjects, bool isDatablock, bool classNameInternal, bool isSingleton);
  445. U32 precompileSubObject(bool);
  446. U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
  447. U32 compileSubObject(CodeStream& codeStream, U32 ip, bool);
  448. TypeReq getPreferredType();
  449. DBG_STMT_TYPE(ObjectDeclNode);
  450. };
  451. struct ObjectBlockDecl
  452. {
  453. SlotAssignNode* slots;
  454. ObjectDeclNode* decls;
  455. };
  456. struct FunctionDeclStmtNode : StmtNode
  457. {
  458. StringTableEntry fnName;
  459. VarNode* args;
  460. StmtNode* stmts;
  461. StringTableEntry nameSpace;
  462. StringTableEntry package;
  463. U32 endOffset;
  464. U32 argc;
  465. static FunctionDeclStmtNode* alloc(S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode* args, StmtNode* stmts);
  466. U32 compileStmt(CodeStream& codeStream, U32 ip);
  467. void setPackage(StringTableEntry packageName);
  468. DBG_STMT_TYPE(FunctionDeclStmtNode);
  469. };
  470. extern StmtNode* gStatementList;
  471. extern ExprEvalState gEvalState;
  472. #endif