ptree.h 30 KB

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