ptree.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. struct Ident;
  7. typedef Ident *IdentPtr;
  8. class Scope;
  9. /***************************************************************************
  10. Flags for classifying node operators.
  11. ***************************************************************************/
  12. const uint fnopNone = 0x0000;
  13. const uint fnopConst = 0x0001; // constant
  14. const uint fnopLeaf = 0x0002; // leaf
  15. const uint fnopUni = 0x0004; // unary
  16. const uint fnopBin = 0x0008; // binary
  17. const uint fnopRel = 0x0010; // relational
  18. const uint fnopAsg = 0x0020; // assignment
  19. const uint fnopBreak = 0x0040; // break can be used within this statement
  20. const uint fnopContinue = 0x0080; // continue can be used within this statement
  21. const uint fnopCleanup = 0x0100; // requires cleanup (eg, with or for-in).
  22. const uint fnopJump = 0x0200;
  23. const uint fnopNotExprStmt = 0x0400;
  24. const uint fnopBinList = 0x0800;
  25. const uint fnopExprMask = (fnopLeaf|fnopUni|fnopBin);
  26. /***************************************************************************
  27. Flags for classifying parse nodes.
  28. ***************************************************************************/
  29. enum PNodeFlags : ushort
  30. {
  31. fpnNone = 0x0000,
  32. // knopFncDecl nodes.
  33. fpnArguments_overriddenByDecl = 0x0001, // function has a parameter, let/const decl, class or nested function named 'arguments', which overrides the built-in arguments object
  34. fpnArguments_varDeclaration = 0x0002, // function has a var declaration named 'arguments', which may change the way an 'arguments' identifier is resolved
  35. // knopVarDecl nodes.
  36. fpnArguments = 0x0004,
  37. fpnHidden = 0x0008,
  38. // Statement nodes.
  39. fpnExplicitSemicolon = 0x0010, // statement terminated by an explicit semicolon
  40. fpnAutomaticSemicolon = 0x0020, // statement terminated by an automatic semicolon
  41. fpnMissingSemicolon = 0x0040, // statement missing terminating semicolon, and is not applicable for automatic semicolon insertion
  42. fpnDclList = 0x0080, // statement is a declaration list
  43. fpnSyntheticNode = 0x0100, // node is added by the parser or does it represent user code
  44. fpnIndexOperator = 0x0200, // dot operator is an optimization of an index operator
  45. fpnJumbStatement = 0x0400, // break or continue that was removed by error recovery
  46. // Unary/Binary nodes
  47. fpnCanFlattenConcatExpr = 0x0800, // the result of the binary operation can participate in concat N
  48. // Potentially overlapping traversal flags
  49. // These flags are set and cleared during a single node traversal and their values can be used in other node traversals.
  50. fpnMemberReference = 0x1000, // The node is a member reference symbol
  51. fpnCapturesSyms = 0x2000, // The node is a statement (or contains a sub-statement)
  52. // that captures symbols.
  53. };
  54. /***************************************************************************
  55. Data structs for ParseNodes. ParseNode includes a union of these.
  56. ***************************************************************************/
  57. struct PnUni
  58. {
  59. ParseNodePtr pnode1;
  60. };
  61. struct PnBin
  62. {
  63. ParseNodePtr pnodeNext;
  64. ParseNodePtr pnode1;
  65. ParseNodePtr pnode2;
  66. };
  67. struct PnTri
  68. {
  69. ParseNodePtr pnodeNext;
  70. ParseNodePtr pnode1;
  71. ParseNodePtr pnode2;
  72. ParseNodePtr pnode3;
  73. };
  74. struct PnSlot
  75. {
  76. uint slotIndex;
  77. };
  78. struct PnUniSlot : PnUni
  79. {
  80. uint slotIndex;
  81. uint staticFuncId;
  82. };
  83. struct PnInt
  84. {
  85. long lw;
  86. };
  87. struct PnFlt
  88. {
  89. double dbl;
  90. bool maybeInt : 1;
  91. };
  92. class Symbol;
  93. struct PidRefStack;
  94. struct PnPid
  95. {
  96. IdentPtr pid;
  97. Symbol **symRef;
  98. Symbol *sym;
  99. UnifiedRegex::RegexPattern* regexPattern;
  100. uint regexPatternIndex;
  101. void SetSymRef(PidRefStack *ref);
  102. Symbol **GetSymRef() const { return symRef; }
  103. Js::PropertyId PropertyIdFromNameNode() const;
  104. };
  105. struct PnVar
  106. {
  107. ParseNodePtr pnodeNext;
  108. IdentPtr pid;
  109. Symbol *sym;
  110. Symbol **symRef;
  111. ParseNodePtr pnodeInit;
  112. BOOLEAN isSwitchStmtDecl;
  113. BOOLEAN isBlockScopeFncDeclVar;
  114. void InitDeclNode(IdentPtr name, ParseNodePtr initExpr)
  115. {
  116. this->pid = name;
  117. this->pnodeInit = initExpr;
  118. this->pnodeNext = nullptr;
  119. this->sym = nullptr;
  120. this->symRef = nullptr;
  121. this->isSwitchStmtDecl = false;
  122. this->isBlockScopeFncDeclVar = false;
  123. }
  124. };
  125. struct PnLabel
  126. {
  127. IdentPtr pid;
  128. ParseNodePtr pnodeNext;
  129. };
  130. struct PnArrLit : PnUni
  131. {
  132. uint count;
  133. uint spreadCount;
  134. BYTE arrayOfTaggedInts:1; // indicates that array initializer nodes are all tagged ints
  135. BYTE arrayOfInts:1; // indicates that array initializer nodes are all ints
  136. BYTE arrayOfNumbers:1; // indicates that array initializer nodes are all numbers
  137. BYTE hasMissingValues:1;
  138. };
  139. class FuncInfo;
  140. enum PnodeBlockType : unsigned
  141. {
  142. Global,
  143. Function,
  144. Regular,
  145. Parameter
  146. };
  147. enum FncFlags
  148. {
  149. kFunctionNone = 0,
  150. kFunctionNested = 1 << 0, // True if function is nested in another.
  151. kFunctionDeclaration = 1 << 1, // is this a declaration or an expression?
  152. kFunctionCallsEval = 1 << 2, // function uses eval
  153. kFunctionUsesArguments = 1 << 3, // function uses arguments
  154. kFunctionHasHeapArguments = 1 << 4, // function's "arguments" escape the scope
  155. kFunctionHasReferenceableBuiltInArguments = 1 << 5, // the built-in 'arguments' object is referenceable in the function
  156. kFunctionIsAccessor = 1 << 6, // function is a property getter or setter
  157. kFunctionHasNonThisStmt = 1 << 7,
  158. kFunctionStrictMode = 1 << 8,
  159. kFunctionDoesNotEscape = 1 << 9, // function is known not to escape its declaring scope
  160. kFunctionSubsumed = 1 << 10, // function expression is a parameter in a call that has no closing paren and should be treated as a global declaration (only occurs during error correction)
  161. kFunctionHasThisStmt = 1 << 11, // function has at least one this.assignment and might be a constructor
  162. kFunctionHasWithStmt = 1 << 12, // function (or child) uses with
  163. kFunctionIsLambda = 1 << 13,
  164. kFunctionChildCallsEval = 1 << 14,
  165. kFunctionHasNonSimpleParameterList = 1 << 15,
  166. kFunctionHasSuperReference = 1 << 16,
  167. kFunctionIsMethod = 1 << 17,
  168. kFunctionIsClassConstructor = 1 << 18, // function is a class constructor
  169. kFunctionIsBaseClassConstructor = 1 << 19, // function is a base class constructor
  170. kFunctionIsClassMember = 1 << 20, // function is a class member
  171. kFunctionNameIsHidden = 1 << 21, // True if a named function expression has its name hidden from nested functions
  172. kFunctionIsGeneratedDefault = 1 << 22, // Is the function generated by us as a default (e.g. default class constructor)
  173. kFunctionHasDefaultArguments = 1 << 23, // Function has one or more ES6 default arguments
  174. kFunctionIsStaticMember = 1 << 24,
  175. kFunctionIsGenerator = 1 << 25, // Function is an ES6 generator function
  176. kFunctionAsmjsMode = 1 << 26,
  177. kFunctionHasNewTargetReference = 1 << 27, // function has a reference to new.target
  178. kFunctionIsAsync = 1 << 28, // function is async
  179. kFunctionHasDirectSuper = 1 << 29, // super()
  180. };
  181. struct RestorePoint;
  182. struct DeferredFunctionStub;
  183. struct PnFnc
  184. {
  185. ParseNodePtr pnodeNext;
  186. ParseNodePtr pnodeName;
  187. IdentPtr pid;
  188. LPCOLESTR hint;
  189. ulong hintLength;
  190. ulong hintOffset;
  191. bool isNameIdentifierRef;
  192. ParseNodePtr pnodeScopes;
  193. ParseNodePtr pnodeBodyScope;
  194. ParseNodePtr pnodeParams;
  195. ParseNodePtr pnodeVars;
  196. ParseNodePtr pnodeBody;
  197. ParseNodePtr pnodeRest;
  198. FuncInfo *funcInfo; // function information gathered during byte code generation
  199. Scope *scope;
  200. uint nestedCount; // Nested function count (valid until children have been processed)
  201. uint nestedIndex; // Index within the parent function
  202. uint16 firstDefaultArg; // Position of the first default argument, if any
  203. unsigned int fncFlags;
  204. long astSize;
  205. size_t cbMin; // Min an Lim UTF8 offsets.
  206. size_t cbLim;
  207. ULONG lineNumber; // Line number relative to the current source buffer of the function declaration.
  208. ULONG columnNumber; // Column number of the declaration.
  209. Js::LocalFunctionId functionId;
  210. #if DBG
  211. Js::LocalFunctionId deferredParseNextFunctionId;
  212. #endif
  213. RestorePoint *pRestorePoint;
  214. DeferredFunctionStub *deferredStub;
  215. static const long MaxStackClosureAST = 800000;
  216. private:
  217. void SetFlags(uint flags, bool set)
  218. {
  219. if (set)
  220. {
  221. fncFlags |= flags;
  222. }
  223. else
  224. {
  225. fncFlags &= ~flags;
  226. }
  227. }
  228. bool HasFlags(uint flags) const
  229. {
  230. return (fncFlags & flags) == flags;
  231. }
  232. public:
  233. void ClearFlags()
  234. {
  235. fncFlags = kFunctionNone;
  236. }
  237. void SetAsmjsMode(bool set = true) { SetFlags(kFunctionAsmjsMode, set); }
  238. void SetCallsEval(bool set = true) { SetFlags(kFunctionCallsEval, set); }
  239. void SetChildCallsEval(bool set = true) { SetFlags(kFunctionChildCallsEval, set); }
  240. void SetDeclaration(bool set = true) { SetFlags(kFunctionDeclaration, set); }
  241. void SetDoesNotEscape(bool set = true) { SetFlags(kFunctionDoesNotEscape, set); }
  242. void SetHasDefaultArguments(bool set = true) { SetFlags(kFunctionHasDefaultArguments, set); }
  243. void SetHasHeapArguments(bool set = true) { SetFlags(kFunctionHasHeapArguments, set); }
  244. void SetHasNonSimpleParameterList(bool set = true) { SetFlags(kFunctionHasNonSimpleParameterList, set); }
  245. void SetHasNonThisStmt(bool set = true) { SetFlags(kFunctionHasNonThisStmt, set); }
  246. void SetHasReferenceableBuiltInArguments(bool set = true) { SetFlags(kFunctionHasReferenceableBuiltInArguments, set); }
  247. void SetHasSuperReference(bool set = true) { SetFlags(kFunctionHasSuperReference, set); }
  248. void SetHasDirectSuper(bool set = true) { SetFlags(kFunctionHasDirectSuper, set); }
  249. void SetHasNewTargetReference(bool set = true) { SetFlags(kFunctionHasNewTargetReference, set); }
  250. void SetHasThisStmt(bool set = true) { SetFlags(kFunctionHasThisStmt, set); }
  251. void SetHasWithStmt(bool set = true) { SetFlags(kFunctionHasWithStmt, set); }
  252. void SetIsAccessor(bool set = true) { SetFlags(kFunctionIsAccessor, set); }
  253. void SetIsAsync(bool set = true) { SetFlags(kFunctionIsAsync, set); }
  254. void SetIsClassConstructor(bool set = true) { SetFlags(kFunctionIsClassConstructor, set); }
  255. void SetIsBaseClassConstructor(bool set = true) { SetFlags(kFunctionIsBaseClassConstructor, set); }
  256. void SetIsClassMember(bool set = true) { SetFlags(kFunctionIsClassMember, set); }
  257. void SetIsGeneratedDefault(bool set = true) { SetFlags(kFunctionIsGeneratedDefault, set); }
  258. void SetIsGenerator(bool set = true) { SetFlags(kFunctionIsGenerator, set); }
  259. void SetIsLambda(bool set = true) { SetFlags(kFunctionIsLambda, set); }
  260. void SetIsMethod(bool set = true) { SetFlags(kFunctionIsMethod, set); }
  261. void SetIsStaticMember(bool set = true) { SetFlags(kFunctionIsStaticMember, set); }
  262. void SetNameIsHidden(bool set = true) { SetFlags(kFunctionNameIsHidden, set); }
  263. void SetNested(bool set = true) { SetFlags(kFunctionNested, set); }
  264. void SetStrictMode(bool set = true) { SetFlags(kFunctionStrictMode, set); }
  265. void SetSubsumed(bool set = true) { SetFlags(kFunctionSubsumed, set); }
  266. void SetUsesArguments(bool set = true) { SetFlags(kFunctionUsesArguments, set); }
  267. bool CallsEval() const { return HasFlags(kFunctionCallsEval); }
  268. bool ChildCallsEval() const { return HasFlags(kFunctionChildCallsEval); }
  269. bool DoesNotEscape() const { return HasFlags(kFunctionDoesNotEscape); }
  270. bool GetArgumentsObjectEscapes() const { return HasFlags(kFunctionHasHeapArguments); }
  271. bool GetAsmjsMode() const { return HasFlags(kFunctionAsmjsMode); }
  272. bool GetStrictMode() const { return HasFlags(kFunctionStrictMode); }
  273. bool HasDefaultArguments() const { return HasFlags(kFunctionHasDefaultArguments); }
  274. bool HasHeapArguments() const { return true; /* HasFlags(kFunctionHasHeapArguments); Disabling stack arguments. Always return HeapArguments as True */ }
  275. bool HasOnlyThisStmts() const { return !HasFlags(kFunctionHasNonThisStmt); }
  276. bool HasReferenceableBuiltInArguments() const { return HasFlags(kFunctionHasReferenceableBuiltInArguments); }
  277. bool HasSuperReference() const { return HasFlags(kFunctionHasSuperReference); }
  278. bool HasDirectSuper() const { return HasFlags(kFunctionHasDirectSuper); }
  279. bool HasNewTargetReference() const { return HasFlags(kFunctionHasNewTargetReference); }
  280. bool HasNonSimpleParameterList() { return HasFlags(kFunctionHasNonSimpleParameterList); }
  281. bool HasThisStmt() const { return HasFlags(kFunctionHasThisStmt); }
  282. bool HasWithStmt() const { return HasFlags(kFunctionHasWithStmt); }
  283. bool IsAccessor() const { return HasFlags(kFunctionIsAccessor); }
  284. bool IsAsync() const { return HasFlags(kFunctionIsAsync); }
  285. bool IsClassConstructor() const { return HasFlags(kFunctionIsClassConstructor); }
  286. bool IsBaseClassConstructor() const { return HasFlags(kFunctionIsBaseClassConstructor); }
  287. bool IsClassMember() const { return HasFlags(kFunctionIsClassMember); }
  288. bool IsDeclaration() const { return HasFlags(kFunctionDeclaration); }
  289. bool IsGeneratedDefault() const { return HasFlags(kFunctionIsGeneratedDefault); }
  290. bool IsGenerator() const { return HasFlags(kFunctionIsGenerator); }
  291. bool IsLambda() const { return HasFlags(kFunctionIsLambda); }
  292. bool IsMethod() const { return HasFlags(kFunctionIsMethod); }
  293. bool IsNested() const { return HasFlags(kFunctionNested); }
  294. bool IsStaticMember() const { return HasFlags(kFunctionIsStaticMember); }
  295. bool IsSubsumed() const { return HasFlags(kFunctionSubsumed); }
  296. bool NameIsHidden() const { return HasFlags(kFunctionNameIsHidden); }
  297. bool UsesArguments() const { return HasFlags(kFunctionUsesArguments); }
  298. size_t LengthInBytes()
  299. {
  300. return cbLim - cbMin;
  301. }
  302. Symbol *GetFuncSymbol();
  303. void SetFuncSymbol(Symbol *sym);
  304. ParseNodePtr GetParamScope() const;
  305. ParseNodePtr GetBodyScope() const;
  306. ParseNodePtr GetTopLevelScope() const
  307. {
  308. // Top level scope will be the same for knopProg and knopFncDecl.
  309. return GetParamScope();
  310. }
  311. template<typename Fn>
  312. void MapContainerScopes(Fn fn)
  313. {
  314. fn(this->pnodeScopes->sxBlock.pnodeScopes);
  315. if (this->pnodeBodyScope != nullptr)
  316. {
  317. fn(this->pnodeBodyScope->sxBlock.pnodeScopes);
  318. }
  319. }
  320. };
  321. struct PnClass
  322. {
  323. ParseNodePtr pnodeName;
  324. ParseNodePtr pnodeDeclName;
  325. ParseNodePtr pnodeBlock;
  326. ParseNodePtr pnodeConstructor;
  327. ParseNodePtr pnodeMembers;
  328. ParseNodePtr pnodeStaticMembers;
  329. ParseNodePtr pnodeExtends;
  330. };
  331. struct PnStrTemplate
  332. {
  333. ParseNodePtr pnodeStringLiterals;
  334. ParseNodePtr pnodeStringRawLiterals;
  335. ParseNodePtr pnodeSubstitutionExpressions;
  336. uint16 countStringLiterals;
  337. BYTE isTaggedTemplate:1;
  338. };
  339. struct PnProg : PnFnc
  340. {
  341. ParseNodePtr pnodeLastValStmt;
  342. bool m_UsesArgumentsAtGlobal;
  343. };
  344. struct PnModule : PnProg
  345. {
  346. ModuleExportEntryList* localExportEntries;
  347. ModuleExportEntryList* indirectExportEntries;
  348. ModuleExportEntryList* starExportEntries;
  349. ModuleImportEntryList* importEntries;
  350. IdentPtrList* requestedModules;
  351. };
  352. struct PnCall
  353. {
  354. ParseNodePtr pnodeNext;
  355. ParseNodePtr pnodeTarget;
  356. ParseNodePtr pnodeArgs;
  357. uint16 argCount;
  358. uint16 spreadArgCount;
  359. BYTE callOfConstants : 1;
  360. BYTE isApplyCall : 1;
  361. BYTE isEvalCall : 1;
  362. };
  363. struct PnStmt
  364. {
  365. ParseNodePtr pnodeOuter;
  366. // Set by parsing code, used by code gen.
  367. uint grfnop;
  368. // Needed for byte code gen.
  369. Js::ByteCodeLabel breakLabel;
  370. Js::ByteCodeLabel continueLabel;
  371. };
  372. struct PnBlock : PnStmt
  373. {
  374. ParseNodePtr pnodeStmt;
  375. ParseNodePtr pnodeLastValStmt;
  376. ParseNodePtr pnodeLexVars;
  377. ParseNodePtr pnodeScopes;
  378. ParseNodePtr pnodeNext;
  379. Scope *scope;
  380. ParseNodePtr enclosingBlock;
  381. int blockId;
  382. PnodeBlockType blockType:2;
  383. BYTE callsEval:1;
  384. BYTE childCallsEval:1;
  385. void SetCallsEval(bool does) { callsEval = does; }
  386. bool GetCallsEval() const { return callsEval; }
  387. void SetChildCallsEval(bool does) { childCallsEval = does; }
  388. bool GetChildCallsEval() const { return childCallsEval; }
  389. void SetEnclosingBlock(ParseNodePtr pnode) { enclosingBlock = pnode; }
  390. ParseNodePtr GetEnclosingBlock() const { return enclosingBlock; }
  391. bool HasBlockScopedContent() const;
  392. };
  393. struct PnJump : PnStmt
  394. {
  395. ParseNodePtr pnodeTarget;
  396. bool hasExplicitTarget;
  397. };
  398. struct PnLoop : PnStmt
  399. {
  400. // Needed for byte code gen
  401. uint loopId;
  402. };
  403. struct PnWhile : PnLoop
  404. {
  405. ParseNodePtr pnodeCond;
  406. ParseNodePtr pnodeBody;
  407. };
  408. struct PnWith : PnStmt
  409. {
  410. ParseNodePtr pnodeObj;
  411. ParseNodePtr pnodeBody;
  412. ParseNodePtr pnodeScopes;
  413. ParseNodePtr pnodeNext;
  414. Scope *scope;
  415. };
  416. struct PnParamPattern
  417. {
  418. ParseNodePtr pnodeNext;
  419. Js::RegSlot location;
  420. ParseNodePtr pnode1;
  421. };
  422. struct PnIf : PnStmt
  423. {
  424. ParseNodePtr pnodeCond;
  425. ParseNodePtr pnodeTrue;
  426. ParseNodePtr pnodeFalse;
  427. };
  428. struct PnHelperCall2 {
  429. ParseNodePtr pnodeArg1;
  430. ParseNodePtr pnodeArg2;
  431. int helperId;
  432. };
  433. struct PnForInOrForOf : PnLoop
  434. {
  435. ParseNodePtr pnodeObj;
  436. ParseNodePtr pnodeBody;
  437. ParseNodePtr pnodeLval;
  438. ParseNodePtr pnodeBlock;
  439. Js::RegSlot itemLocation;
  440. };
  441. struct PnFor : PnLoop
  442. {
  443. ParseNodePtr pnodeCond;
  444. ParseNodePtr pnodeBody;
  445. ParseNodePtr pnodeInit;
  446. ParseNodePtr pnodeIncr;
  447. ParseNodePtr pnodeBlock;
  448. ParseNodePtr pnodeInverted;
  449. };
  450. struct PnSwitch : PnStmt
  451. {
  452. ParseNodePtr pnodeVal;
  453. ParseNodePtr pnodeCases;
  454. ParseNodePtr pnodeDefault;
  455. ParseNodePtr pnodeBlock;
  456. };
  457. struct PnCase : PnStmt
  458. {
  459. ParseNodePtr pnodeNext;
  460. ParseNodePtr pnodeExpr; // nullptr for default
  461. ParseNodePtr pnodeBody;
  462. Js::ByteCodeLabel labelCase;
  463. };
  464. struct PnReturn : PnStmt
  465. {
  466. ParseNodePtr pnodeExpr;
  467. };
  468. struct PnTryFinally : PnStmt
  469. {
  470. ParseNodePtr pnodeTry;
  471. ParseNodePtr pnodeFinally;
  472. };
  473. struct PnTryCatch : PnStmt
  474. {
  475. ParseNodePtr pnodeTry;
  476. ParseNodePtr pnodeCatch;
  477. };
  478. struct PnTry : PnStmt
  479. {
  480. ParseNodePtr pnodeBody;
  481. };
  482. struct PnCatch : PnStmt
  483. {
  484. ParseNodePtr pnodeNext;
  485. ParseNodePtr pnodeParam;
  486. ParseNodePtr pnodeBody;
  487. ParseNodePtr pnodeScopes;
  488. Scope *scope;
  489. };
  490. struct PnFinally : PnStmt
  491. {
  492. ParseNodePtr pnodeBody;
  493. };
  494. struct ParseNode
  495. {
  496. OpCode nop;
  497. ushort grfpn;
  498. charcount_t ichMin; // start offset into the original source buffer
  499. charcount_t ichLim; // end offset into the original source buffer
  500. Js::RegSlot location;
  501. bool isUsed; // indicates whether an expression such as x++ is used
  502. bool emitLabels;
  503. bool notEscapedUse; // Use by byte code generator. Currently, only used by child of knopComma
  504. bool isInList;
  505. bool isCallApplyTargetLoad;
  506. #ifdef EDIT_AND_CONTINUE
  507. ParseNodePtr parent;
  508. #endif
  509. union
  510. {
  511. PnArrLit sxArrLit; // Array literal
  512. PnBin sxBin; // binary operators
  513. PnBlock sxBlock; // block { }
  514. PnCall sxCall; // function call
  515. PnCase sxCase; // switch case
  516. PnCatch sxCatch; // { catch(e : expr) {body} }
  517. PnClass sxClass; // class declaration
  518. PnFinally sxFinally; // finally
  519. PnFlt sxFlt; // double constant
  520. PnFnc sxFnc; // function declaration
  521. PnFor sxFor; // for loop
  522. PnForInOrForOf sxForInOrForOf; // for-in loop
  523. PnHelperCall2 sxHelperCall2; // call to helper
  524. PnIf sxIf; // if
  525. PnInt sxInt; // integer constant
  526. PnJump sxJump; // break and continue
  527. PnLabel sxLabel; // label nodes
  528. PnLoop sxLoop; // base for loop nodes
  529. PnModule sxModule; // global module
  530. PnPid sxPid; // identifier or string
  531. PnProg sxProg; // global program
  532. PnReturn sxReturn; // return [expr]
  533. PnStmt sxStmt; // base for statement nodes
  534. PnStrTemplate sxStrTemplate; // string template declaration
  535. PnSwitch sxSwitch; // switch
  536. PnTri sxTri; // ternary operator
  537. PnTry sxTry; // try-catch
  538. PnTryCatch sxTryCatch; // try-catch
  539. PnTryFinally sxTryFinally; // try-catch-finally
  540. PnUni sxUni; // unary operators
  541. PnVar sxVar; // variable declaration
  542. PnWhile sxWhile; // while and do-while loops
  543. PnWith sxWith; // with
  544. PnParamPattern sxParamPattern; // Destructure pattern for function/catch parameter
  545. };
  546. IdentPtr name()
  547. {
  548. if (this->nop == knopName || this->nop == knopStr)
  549. {
  550. return this->sxPid.pid;
  551. }
  552. else if (this->nop == knopVarDecl)
  553. {
  554. return this->sxVar.pid;
  555. }
  556. else if (this->nop == knopConstDecl)
  557. {
  558. return this->sxVar.pid;
  559. }
  560. return nullptr;
  561. }
  562. static const uint mpnopgrfnop[knopLim];
  563. static uint Grfnop(int nop)
  564. {
  565. Assert(nop < knopLim);
  566. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  567. }
  568. BOOL IsStatement()
  569. {
  570. return (nop >= knopList && nop != knopLabel) || ((Grfnop(nop) & fnopAsg) != 0);
  571. }
  572. uint Grfnop(void)
  573. {
  574. Assert(nop < knopLim);
  575. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  576. }
  577. charcount_t LengthInCodepoints() const
  578. {
  579. return (this->ichLim - this->ichMin);
  580. }
  581. // This node is a function decl node and function has a var declaration named 'arguments',
  582. bool HasVarArguments() const
  583. {
  584. return ((nop == knopFncDecl) && (grfpn & PNodeFlags::fpnArguments_varDeclaration));
  585. }
  586. bool CapturesSyms() const
  587. {
  588. return (grfpn & PNodeFlags::fpnCapturesSyms) != 0;
  589. }
  590. void SetCapturesSyms()
  591. {
  592. grfpn |= PNodeFlags::fpnCapturesSyms;
  593. }
  594. bool IsInList() const { return this->isInList; }
  595. void SetIsInList() { this->isInList = true; }
  596. bool IsNotEscapedUse() const { return this->notEscapedUse; }
  597. void SetNotEscapedUse() { this->notEscapedUse = true; }
  598. bool CanFlattenConcatExpr() const { return !!(this->grfpn & PNodeFlags::fpnCanFlattenConcatExpr); }
  599. bool IsCallApplyTargetLoad() { return isCallApplyTargetLoad; }
  600. void SetIsCallApplyTargetLoad() { isCallApplyTargetLoad = true; }
  601. bool IsVarLetOrConst() const
  602. {
  603. return this->nop == knopVarDecl || this->nop == knopLetDecl || this->nop == knopConstDecl;
  604. }
  605. ParseNodePtr GetFormalNext()
  606. {
  607. ParseNodePtr pnodeNext = nullptr;
  608. if (nop == knopParamPattern)
  609. {
  610. pnodeNext = this->sxParamPattern.pnodeNext;
  611. }
  612. else
  613. {
  614. Assert(IsVarLetOrConst());
  615. pnodeNext = this->sxVar.pnodeNext;
  616. }
  617. return pnodeNext;
  618. }
  619. bool IsPattern() const
  620. {
  621. return nop == knopObjectPattern || nop == knopArrayPattern;
  622. }
  623. #if DBG_DUMP
  624. void Dump();
  625. #endif
  626. };
  627. const int kcbPnNone = offsetof(ParseNode, sxUni);
  628. const int kcbPnArrLit = kcbPnNone + sizeof(PnArrLit);
  629. const int kcbPnBin = kcbPnNone + sizeof(PnBin);
  630. const int kcbPnBlock = kcbPnNone + sizeof(PnBlock);
  631. const int kcbPnCall = kcbPnNone + sizeof(PnCall);
  632. const int kcbPnCase = kcbPnNone + sizeof(PnCase);
  633. const int kcbPnCatch = kcbPnNone + sizeof(PnCatch);
  634. const int kcbPnClass = kcbPnNone + sizeof(PnClass);
  635. const int kcbPnFinally = kcbPnNone + sizeof(PnFinally);
  636. const int kcbPnFlt = kcbPnNone + sizeof(PnFlt);
  637. const int kcbPnFnc = kcbPnNone + sizeof(PnFnc);
  638. const int kcbPnFor = kcbPnNone + sizeof(PnFor);
  639. const int kcbPnForIn = kcbPnNone + sizeof(PnForInOrForOf);
  640. const int kcbPnForOf = kcbPnNone + sizeof(PnForInOrForOf);
  641. const int kcbPnHelperCall3 = kcbPnNone + sizeof(PnHelperCall2);
  642. const int kcbPnIf = kcbPnNone + sizeof(PnIf);
  643. const int kcbPnInt = kcbPnNone + sizeof(PnInt);
  644. const int kcbPnJump = kcbPnNone + sizeof(PnJump);
  645. const int kcbPnLabel = kcbPnNone + sizeof(PnLabel);
  646. const int kcbPnModule = kcbPnNone + sizeof(PnModule);
  647. const int kcbPnPid = kcbPnNone + sizeof(PnPid);
  648. const int kcbPnProg = kcbPnNone + sizeof(PnProg);
  649. const int kcbPnReturn = kcbPnNone + sizeof(PnReturn);
  650. const int kcbPnSlot = kcbPnNone + sizeof(PnSlot);
  651. const int kcbPnStrTemplate = kcbPnNone + sizeof(PnStrTemplate);
  652. const int kcbPnSwitch = kcbPnNone + sizeof(PnSwitch);
  653. const int kcbPnTri = kcbPnNone + sizeof(PnTri);
  654. const int kcbPnTry = kcbPnNone + sizeof(PnTry);
  655. const int kcbPnTryCatch = kcbPnNone + sizeof(PnTryCatch);
  656. const int kcbPnTryFinally = kcbPnNone + sizeof(PnTryFinally);
  657. const int kcbPnUni = kcbPnNone + sizeof(PnUni);
  658. const int kcbPnUniSlot = kcbPnNone + sizeof(PnUniSlot);
  659. const int kcbPnVar = kcbPnNone + sizeof(PnVar);
  660. const int kcbPnWhile = kcbPnNone + sizeof(PnWhile);
  661. const int kcbPnWith = kcbPnNone + sizeof(PnWith);
  662. const int kcbPnParamPattern = kcbPnNone + sizeof(PnParamPattern);
  663. #define AssertNodeMem(pnode) AssertPvCb(pnode, kcbPnNone)
  664. #define AssertNodeMemN(pnode) AssertPvCbN(pnode, kcbPnNone)