ptree.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  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. kFunctionHasDestructuringPattern = 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 pnodeArgs;
  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 SetHasDestructuringPattern(bool set = true) { SetFlags(kFunctionHasDestructuringPattern, set); }
  244. void SetHasHeapArguments(bool set = true) { SetFlags(kFunctionHasHeapArguments, 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 HasDestructuringPattern() const { return HasFlags(kFunctionHasDestructuringPattern); }
  275. bool HasHeapArguments() const { return true; /* HasFlags(kFunctionHasHeapArguments); Disabling stack arguments. Always return HeapArguments as True */ }
  276. bool HasOnlyThisStmts() const { return !HasFlags(kFunctionHasNonThisStmt); }
  277. bool HasReferenceableBuiltInArguments() const { return HasFlags(kFunctionHasReferenceableBuiltInArguments); }
  278. bool HasSuperReference() const { return HasFlags(kFunctionHasSuperReference); }
  279. bool HasDirectSuper() const { return HasFlags(kFunctionHasDirectSuper); }
  280. bool HasNewTargetReference() const { return HasFlags(kFunctionHasNewTargetReference); }
  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. bool IsSimpleParameterList() const { return !HasDefaultArguments() && !HasDestructuringPattern() && pnodeRest == nullptr; }
  299. size_t LengthInBytes()
  300. {
  301. return cbLim - cbMin;
  302. }
  303. Symbol *GetFuncSymbol();
  304. void SetFuncSymbol(Symbol *sym);
  305. ParseNodePtr GetParamScope() const;
  306. ParseNodePtr *GetParamScopeRef() const;
  307. ParseNodePtr GetBodyScope() const;
  308. ParseNodePtr *GetBodyScopeRef() const;
  309. ParseNodePtr GetTopLevelScope() const
  310. {
  311. // Top level scope will be the same for knopProg and knopFncDecl.
  312. return GetParamScope();
  313. }
  314. template<typename Fn>
  315. void MapContainerScopes(Fn fn)
  316. {
  317. fn(this->pnodeScopes->sxBlock.pnodeScopes);
  318. if (this->pnodeBodyScope != nullptr)
  319. {
  320. fn(this->pnodeBodyScope->sxBlock.pnodeScopes);
  321. }
  322. }
  323. };
  324. struct PnClass
  325. {
  326. ParseNodePtr pnodeName;
  327. ParseNodePtr pnodeDeclName;
  328. ParseNodePtr pnodeBlock;
  329. ParseNodePtr pnodeConstructor;
  330. ParseNodePtr pnodeMembers;
  331. ParseNodePtr pnodeStaticMembers;
  332. ParseNodePtr pnodeExtends;
  333. };
  334. struct PnStrTemplate
  335. {
  336. ParseNodePtr pnodeStringLiterals;
  337. ParseNodePtr pnodeStringRawLiterals;
  338. ParseNodePtr pnodeSubstitutionExpressions;
  339. uint16 countStringLiterals;
  340. BYTE isTaggedTemplate:1;
  341. };
  342. struct PnProg : PnFnc
  343. {
  344. ParseNodePtr pnodeLastValStmt;
  345. bool m_UsesArgumentsAtGlobal;
  346. };
  347. struct PnCall
  348. {
  349. ParseNodePtr pnodeNext;
  350. ParseNodePtr pnodeTarget;
  351. ParseNodePtr pnodeArgs;
  352. uint16 argCount;
  353. uint16 spreadArgCount;
  354. BYTE callOfConstants : 1;
  355. BYTE isApplyCall : 1;
  356. BYTE isEvalCall : 1;
  357. };
  358. struct PnStmt
  359. {
  360. ParseNodePtr pnodeOuter;
  361. // Set by parsing code, used by code gen.
  362. uint grfnop;
  363. // Needed for byte code gen.
  364. Js::ByteCodeLabel breakLabel;
  365. Js::ByteCodeLabel continueLabel;
  366. };
  367. struct PnBlock : PnStmt
  368. {
  369. ParseNodePtr pnodeStmt;
  370. ParseNodePtr pnodeLastValStmt;
  371. ParseNodePtr pnodeLexVars;
  372. ParseNodePtr pnodeScopes;
  373. ParseNodePtr pnodeNext;
  374. Scope *scope;
  375. ParseNodePtr enclosingBlock;
  376. int blockId;
  377. PnodeBlockType blockType:2;
  378. BYTE callsEval:1;
  379. BYTE childCallsEval:1;
  380. void SetCallsEval(bool does) { callsEval = does; }
  381. bool GetCallsEval() const { return callsEval; }
  382. void SetChildCallsEval(bool does) { childCallsEval = does; }
  383. bool GetChildCallsEval() const { return childCallsEval; }
  384. void SetEnclosingBlock(ParseNodePtr pnode) { enclosingBlock = pnode; }
  385. ParseNodePtr GetEnclosingBlock() const { return enclosingBlock; }
  386. bool HasBlockScopedContent() const;
  387. };
  388. struct PnJump : PnStmt
  389. {
  390. ParseNodePtr pnodeTarget;
  391. bool hasExplicitTarget;
  392. };
  393. struct PnLoop : PnStmt
  394. {
  395. // Needed for byte code gen
  396. uint loopId;
  397. };
  398. struct PnWhile : PnLoop
  399. {
  400. ParseNodePtr pnodeCond;
  401. ParseNodePtr pnodeBody;
  402. };
  403. struct PnWith : PnStmt
  404. {
  405. ParseNodePtr pnodeObj;
  406. ParseNodePtr pnodeBody;
  407. ParseNodePtr pnodeScopes;
  408. ParseNodePtr pnodeNext;
  409. Scope *scope;
  410. };
  411. struct PnParamPattern
  412. {
  413. ParseNodePtr pnodeNext;
  414. Js::RegSlot location;
  415. ParseNodePtr pnode1;
  416. };
  417. struct PnIf : PnStmt
  418. {
  419. ParseNodePtr pnodeCond;
  420. ParseNodePtr pnodeTrue;
  421. ParseNodePtr pnodeFalse;
  422. };
  423. struct PnHelperCall2 {
  424. ParseNodePtr pnodeArg1;
  425. ParseNodePtr pnodeArg2;
  426. int helperId;
  427. };
  428. struct PnForInOrForOf : PnLoop
  429. {
  430. ParseNodePtr pnodeObj;
  431. ParseNodePtr pnodeBody;
  432. ParseNodePtr pnodeLval;
  433. ParseNodePtr pnodeBlock;
  434. Js::RegSlot itemLocation;
  435. };
  436. struct PnFor : PnLoop
  437. {
  438. ParseNodePtr pnodeCond;
  439. ParseNodePtr pnodeBody;
  440. ParseNodePtr pnodeInit;
  441. ParseNodePtr pnodeIncr;
  442. ParseNodePtr pnodeBlock;
  443. ParseNodePtr pnodeInverted;
  444. };
  445. struct PnSwitch : PnStmt
  446. {
  447. ParseNodePtr pnodeVal;
  448. ParseNodePtr pnodeCases;
  449. ParseNodePtr pnodeDefault;
  450. ParseNodePtr pnodeBlock;
  451. };
  452. struct PnCase : PnStmt
  453. {
  454. ParseNodePtr pnodeNext;
  455. ParseNodePtr pnodeExpr; // nullptr for default
  456. ParseNodePtr pnodeBody;
  457. Js::ByteCodeLabel labelCase;
  458. };
  459. struct PnReturn : PnStmt
  460. {
  461. ParseNodePtr pnodeExpr;
  462. };
  463. struct PnTryFinally : PnStmt
  464. {
  465. ParseNodePtr pnodeTry;
  466. ParseNodePtr pnodeFinally;
  467. };
  468. struct PnTryCatch : PnStmt
  469. {
  470. ParseNodePtr pnodeTry;
  471. ParseNodePtr pnodeCatch;
  472. };
  473. struct PnTry : PnStmt
  474. {
  475. ParseNodePtr pnodeBody;
  476. };
  477. struct PnCatch : PnStmt
  478. {
  479. ParseNodePtr pnodeNext;
  480. ParseNodePtr pnodeParam;
  481. ParseNodePtr pnodeBody;
  482. ParseNodePtr pnodeScopes;
  483. Scope *scope;
  484. };
  485. struct PnFinally : PnStmt
  486. {
  487. ParseNodePtr pnodeBody;
  488. };
  489. struct ParseNode
  490. {
  491. OpCode nop;
  492. ushort grfpn;
  493. charcount_t ichMin; // start offset into the original source buffer
  494. charcount_t ichLim; // end offset into the original source buffer
  495. Js::RegSlot location;
  496. bool isUsed; // indicates whether an expression such as x++ is used
  497. bool emitLabels;
  498. bool notEscapedUse; // Use by byte code generator. Currently, only used by child of knopComma
  499. bool isInList;
  500. bool isCallApplyTargetLoad;
  501. #ifdef EDIT_AND_CONTINUE
  502. ParseNodePtr parent;
  503. #endif
  504. union
  505. {
  506. PnArrLit sxArrLit; // Array literal
  507. PnBin sxBin; // binary operators
  508. PnBlock sxBlock; // block { }
  509. PnCall sxCall; // function call
  510. PnCase sxCase; // switch case
  511. PnCatch sxCatch; // { catch(e : expr) {body} }
  512. PnClass sxClass; // class declaration
  513. PnFinally sxFinally; // finally
  514. PnFlt sxFlt; // double constant
  515. PnFnc sxFnc; // function declaration
  516. PnFor sxFor; // for loop
  517. PnForInOrForOf sxForInOrForOf; // for-in loop
  518. PnHelperCall2 sxHelperCall2; // call to helper
  519. PnIf sxIf; // if
  520. PnInt sxInt; // integer constant
  521. PnJump sxJump; // break and continue
  522. PnLabel sxLabel; // label nodes
  523. PnLoop sxLoop; // base for loop nodes
  524. PnPid sxPid; // identifier or string
  525. PnProg sxProg; // global program
  526. PnReturn sxReturn; // return [expr]
  527. PnStmt sxStmt; // base for statement nodes
  528. PnStrTemplate sxStrTemplate; // string template declaration
  529. PnSwitch sxSwitch; // switch
  530. PnTri sxTri; // ternary operator
  531. PnTry sxTry; // try-catch
  532. PnTryCatch sxTryCatch; // try-catch
  533. PnTryFinally sxTryFinally; // try-catch-finally
  534. PnUni sxUni; // unary operators
  535. PnVar sxVar; // variable declaration
  536. PnWhile sxWhile; // while and do-while loops
  537. PnWith sxWith; // with
  538. PnParamPattern sxParamPattern; // Destructure pattern for function/catch parameter
  539. };
  540. IdentPtr name()
  541. {
  542. if (this->nop == knopName || this->nop == knopStr)
  543. {
  544. return this->sxPid.pid;
  545. }
  546. else if (this->nop == knopVarDecl)
  547. {
  548. return this->sxVar.pid;
  549. }
  550. else if (this->nop == knopConstDecl)
  551. {
  552. return this->sxVar.pid;
  553. }
  554. return nullptr;
  555. }
  556. static const uint mpnopgrfnop[knopLim];
  557. static uint Grfnop(int nop)
  558. {
  559. Assert(nop < knopLim);
  560. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  561. }
  562. BOOL IsStatement()
  563. {
  564. return (nop >= knopList && nop != knopLabel) || ((Grfnop(nop) & fnopAsg) != 0);
  565. }
  566. uint Grfnop(void)
  567. {
  568. Assert(nop < knopLim);
  569. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  570. }
  571. charcount_t LengthInCodepoints() const
  572. {
  573. return (this->ichLim - this->ichMin);
  574. }
  575. // This node is a function decl node and function has a var declaration named 'arguments',
  576. bool HasVarArguments() const
  577. {
  578. return ((nop == knopFncDecl) && (grfpn & PNodeFlags::fpnArguments_varDeclaration));
  579. }
  580. bool CapturesSyms() const
  581. {
  582. return (grfpn & PNodeFlags::fpnCapturesSyms) != 0;
  583. }
  584. void SetCapturesSyms()
  585. {
  586. grfpn |= PNodeFlags::fpnCapturesSyms;
  587. }
  588. bool IsInList() const { return this->isInList; }
  589. void SetIsInList() { this->isInList = true; }
  590. bool IsNotEscapedUse() const { return this->notEscapedUse; }
  591. void SetNotEscapedUse() { this->notEscapedUse = true; }
  592. bool CanFlattenConcatExpr() const { return !!(this->grfpn & PNodeFlags::fpnCanFlattenConcatExpr); }
  593. bool IsCallApplyTargetLoad() { return isCallApplyTargetLoad; }
  594. void SetIsCallApplyTargetLoad() { isCallApplyTargetLoad = true; }
  595. bool IsVarLetOrConst() const
  596. {
  597. return this->nop == knopVarDecl || this->nop == knopLetDecl || this->nop == knopConstDecl;
  598. }
  599. ParseNodePtr GetFormalNext()
  600. {
  601. ParseNodePtr pnodeNext = nullptr;
  602. if (nop == knopParamPattern)
  603. {
  604. pnodeNext = this->sxParamPattern.pnodeNext;
  605. }
  606. else
  607. {
  608. Assert(IsVarLetOrConst());
  609. pnodeNext = this->sxVar.pnodeNext;
  610. }
  611. return pnodeNext;
  612. }
  613. bool IsPattern() const
  614. {
  615. return nop == knopObjectPattern || nop == knopArrayPattern;
  616. }
  617. #if DBG_DUMP
  618. void Dump();
  619. #endif
  620. };
  621. const int kcbPnNone = offsetof(ParseNode, sxUni);
  622. const int kcbPnArrLit = kcbPnNone + sizeof(PnArrLit);
  623. const int kcbPnBin = kcbPnNone + sizeof(PnBin);
  624. const int kcbPnBlock = kcbPnNone + sizeof(PnBlock);
  625. const int kcbPnCall = kcbPnNone + sizeof(PnCall);
  626. const int kcbPnCase = kcbPnNone + sizeof(PnCase);
  627. const int kcbPnCatch = kcbPnNone + sizeof(PnCatch);
  628. const int kcbPnClass = kcbPnNone + sizeof(PnClass);
  629. const int kcbPnFinally = kcbPnNone + sizeof(PnFinally);
  630. const int kcbPnFlt = kcbPnNone + sizeof(PnFlt);
  631. const int kcbPnFnc = kcbPnNone + sizeof(PnFnc);
  632. const int kcbPnFor = kcbPnNone + sizeof(PnFor);
  633. const int kcbPnForIn = kcbPnNone + sizeof(PnForInOrForOf);
  634. const int kcbPnForOf = kcbPnNone + sizeof(PnForInOrForOf);
  635. const int kcbPnHelperCall3 = kcbPnNone + sizeof(PnHelperCall2);
  636. const int kcbPnIf = kcbPnNone + sizeof(PnIf);
  637. const int kcbPnInt = kcbPnNone + sizeof(PnInt);
  638. const int kcbPnJump = kcbPnNone + sizeof(PnJump);
  639. const int kcbPnLabel = kcbPnNone + sizeof(PnLabel);
  640. const int kcbPnPid = kcbPnNone + sizeof(PnPid);
  641. const int kcbPnProg = kcbPnNone + sizeof(PnProg);
  642. const int kcbPnReturn = kcbPnNone + sizeof(PnReturn);
  643. const int kcbPnSlot = kcbPnNone + sizeof(PnSlot);
  644. const int kcbPnStrTemplate = kcbPnNone + sizeof(PnStrTemplate);
  645. const int kcbPnSwitch = kcbPnNone + sizeof(PnSwitch);
  646. const int kcbPnTri = kcbPnNone + sizeof(PnTri);
  647. const int kcbPnTry = kcbPnNone + sizeof(PnTry);
  648. const int kcbPnTryCatch = kcbPnNone + sizeof(PnTryCatch);
  649. const int kcbPnTryFinally = kcbPnNone + sizeof(PnTryFinally);
  650. const int kcbPnUni = kcbPnNone + sizeof(PnUni);
  651. const int kcbPnUniSlot = kcbPnNone + sizeof(PnUniSlot);
  652. const int kcbPnVar = kcbPnNone + sizeof(PnVar);
  653. const int kcbPnWhile = kcbPnNone + sizeof(PnWhile);
  654. const int kcbPnWith = kcbPnNone + sizeof(PnWith);
  655. const int kcbPnParamPattern = kcbPnNone + sizeof(PnParamPattern);
  656. #define AssertNodeMem(pnode) AssertPvCb(pnode, kcbPnNone)
  657. #define AssertNodeMemN(pnode) AssertPvCbN(pnode, kcbPnNone)