pnodewalk.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. #pragma once
  7. template <class _ResultType, class _Context>
  8. struct WalkerPolicyBase
  9. {
  10. using ResultType = _ResultType ;
  11. using Context = _Context ;
  12. inline bool ContinueWalk(ResultType) { return true; }
  13. inline ResultType DefaultResult() { return ResultType(); }
  14. inline ResultType WalkNode(ParseNode *pnode, Context context) { return DefaultResult(); }
  15. inline ResultType WalkListNode(ParseNode *pnode, Context context) { return DefaultResult(); }
  16. virtual ResultType WalkChild(ParseNode *pnode, Context context) { return DefaultResult(); }
  17. inline ResultType WalkFirstChild(ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  18. inline ResultType WalkSecondChild(ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  19. inline ResultType WalkNthChild(ParseNode *pparentnode, ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  20. inline void WalkReference(ParseNode **ppnode, Context context) { }
  21. };
  22. template <class _Context>
  23. struct WalkerPolicyBase<bool, _Context>
  24. {
  25. typedef bool ResultType;
  26. using Context = _Context ;
  27. inline bool ContinueWalk(ResultType) { return true; }
  28. inline bool DefaultResult() { return true; }
  29. inline ResultType WalkNode(ParseNode *pnode, Context context) { return DefaultResult(); }
  30. inline ResultType WalkListNode(ParseNode *pnode, Context context) { return DefaultResult(); }
  31. virtual ResultType WalkChild(ParseNode *pnode, Context context) { return DefaultResult(); }
  32. inline ResultType WalkFirstChild(ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  33. inline ResultType WalkSecondChild(ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  34. inline ResultType WalkNthChild(ParseNode *pparentnode, ParseNode *pnode, Context context) { return WalkChild(pnode, context); }
  35. inline void WalkReference(ParseNode **ppnode, Context context) { }
  36. };
  37. template <typename WalkerPolicy>
  38. class ParseNodeWalker : public WalkerPolicy
  39. {
  40. using WalkerPolicy::ContinueWalk;
  41. using WalkerPolicy::DefaultResult;
  42. using WalkerPolicy::WalkNode;
  43. using WalkerPolicy::WalkListNode;
  44. using WalkerPolicy::WalkFirstChild;
  45. using WalkerPolicy::WalkSecondChild;
  46. using WalkerPolicy::WalkNthChild;
  47. using WalkerPolicy::WalkReference;
  48. public:
  49. typedef typename WalkerPolicy::Context Context;
  50. protected:
  51. typedef typename WalkerPolicy::ResultType ResultType;
  52. private:
  53. ResultType WalkList(ParseNode *pnodeparent, ParseNode *&pnode, Context context)
  54. {
  55. ResultType result = DefaultResult();
  56. bool first = true;
  57. if (pnode)
  58. {
  59. result = WalkListNode(pnode, context);
  60. if (!ContinueWalk(result)) return result;
  61. ParseNodePtr current = pnode;
  62. ParseNodePtr *ppnode = &pnode;
  63. // Skip list nodes and nested VarDeclList nodes
  64. while ((current->nop == knopList && (current->grfpn & PNodeFlags::fpnDclList) == 0) ||
  65. (current->nop == pnode->nop && (current->grfpn & pnode->grfpn & PNodeFlags::fpnDclList)))
  66. {
  67. WalkReference(&current->AsParseNodeBin()->pnode1, context);
  68. result = first ? WalkFirstChild(current->AsParseNodeBin()->pnode1, context) : WalkNthChild(pnodeparent, current->AsParseNodeBin()->pnode1, context);
  69. first = false;
  70. if (!ContinueWalk(result)) return result;
  71. ppnode = &current->AsParseNodeBin()->pnode2;
  72. current = *ppnode;
  73. }
  74. WalkReference(ppnode, context);
  75. result = first ? WalkFirstChild(*ppnode, context) : WalkNthChild(pnodeparent, *ppnode, context);
  76. }
  77. // Reset the reference back.
  78. WalkReference(nullptr, context);
  79. return result;
  80. }
  81. ResultType WalkLeaf(ParseNode *pnode, Context context)
  82. {
  83. return WalkNode(pnode, context);
  84. }
  85. ResultType WalkPreUnary(ParseNodeUni *pnode, Context context)
  86. {
  87. ResultType result = WalkNode(pnode, context);
  88. if (ContinueWalk(result) && pnode->pnode1) result = WalkFirstChild(pnode->pnode1, context);
  89. return result;
  90. }
  91. ResultType WalkPostUnary(ParseNodeUni *pnode, Context context)
  92. {
  93. ResultType result = WalkFirstChild(pnode->pnode1, context);
  94. if (ContinueWalk(result)) result = WalkNode(pnode, context);
  95. return result;
  96. }
  97. ResultType WalkBinary(ParseNodeBin *pnode, Context context)
  98. {
  99. ResultType result = WalkFirstChild(pnode->pnode1, context);
  100. if (ContinueWalk(result))
  101. {
  102. result = WalkNode(pnode, context);
  103. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnode2, context);
  104. }
  105. return result;
  106. }
  107. ResultType WalkTernary(ParseNodeTri *pnode, Context context)
  108. {
  109. ResultType result = WalkFirstChild(pnode->pnode1, context);
  110. if (ContinueWalk(result))
  111. {
  112. result = WalkNode(pnode, context);
  113. if (ContinueWalk(result))
  114. {
  115. result = WalkSecondChild(pnode->pnode2, context);
  116. if (ContinueWalk(result)) result = WalkNthChild(pnode, pnode->pnode3, context);
  117. }
  118. }
  119. return result;
  120. }
  121. ResultType WalkCall(ParseNodeCall *pnode, Context context)
  122. {
  123. ResultType result = WalkFirstChild(pnode->pnodeTarget, context);
  124. if (ContinueWalk(result))
  125. {
  126. result = WalkNode(pnode, context);
  127. if (ContinueWalk(result)) result = WalkList(pnode, pnode->pnodeArgs, context);
  128. }
  129. return result;
  130. }
  131. ResultType WalkStringTemplate(ParseNodeStrTemplate *pnode, Context context)
  132. {
  133. ResultType result;
  134. if (!pnode->isTaggedTemplate)
  135. {
  136. if (pnode->pnodeSubstitutionExpressions == nullptr)
  137. {
  138. // If we don't have any substitution expressions, then we should only have one string literal and not a list
  139. result = WalkNode(pnode->pnodeStringLiterals, context);
  140. }
  141. else
  142. {
  143. result = WalkList(pnode, pnode->pnodeSubstitutionExpressions, context);
  144. if (ContinueWalk(result))
  145. {
  146. result = WalkList(pnode, pnode->pnodeStringLiterals, context);
  147. }
  148. }
  149. }
  150. else
  151. {
  152. result = WalkList(pnode, pnode->pnodeStringLiterals, context);
  153. }
  154. return result;
  155. }
  156. ResultType WalkVar(ParseNodeVar *pnode, Context context)
  157. {
  158. ResultType result = WalkNode(pnode, context);
  159. if (ContinueWalk(result) && pnode->pnodeInit) result = WalkFirstChild(pnode->pnodeInit, context);
  160. return result;
  161. }
  162. ResultType WalkFnc(ParseNodeFnc *pnode, Context context)
  163. {
  164. ResultType result;
  165. // For ordering, arguments are considered prior to the function and the body after.
  166. ParseNodePtr argNode = pnode->pnodeParams;
  167. while (argNode)
  168. {
  169. result = argNode == pnode->pnodeParams ? WalkFirstChild(argNode, context) : WalkNthChild(pnode, argNode, context);
  170. if (!ContinueWalk(result)) return result;
  171. if (argNode->nop == knopParamPattern)
  172. {
  173. argNode = argNode->AsParseNodeParamPattern()->pnodeNext;
  174. }
  175. else
  176. {
  177. argNode = argNode->AsParseNodeVar()->pnodeNext;
  178. }
  179. }
  180. if (pnode->pnodeRest != nullptr)
  181. {
  182. result = WalkSecondChild(pnode->pnodeRest, context);
  183. if (!ContinueWalk(result)) return result;
  184. }
  185. result = WalkNode(pnode, context);
  186. if (ContinueWalk(result)) result = WalkNthChild(pnode, pnode->pnodeBody, context);
  187. return result;
  188. }
  189. ResultType WalkProg(ParseNodeProg *pnode, Context context)
  190. {
  191. ResultType result = WalkNode(pnode, context);
  192. if (ContinueWalk(result)) result = WalkList(pnode, pnode->pnodeBody, context);
  193. return result;
  194. }
  195. ResultType WalkFor(ParseNodeFor *pnode, Context context)
  196. {
  197. ResultType result = WalkFirstChild(pnode->pnodeInit, context);
  198. if (ContinueWalk(result))
  199. {
  200. result = WalkNthChild(pnode, pnode->pnodeCond, context);
  201. if (ContinueWalk(result))
  202. {
  203. result = WalkNthChild(pnode, pnode->pnodeIncr, context);
  204. if (ContinueWalk(result))
  205. {
  206. result = WalkNode(pnode, context);
  207. if (ContinueWalk(result))
  208. {
  209. result = WalkSecondChild(pnode->pnodeBody, context);
  210. }
  211. }
  212. }
  213. }
  214. return result;
  215. }
  216. ResultType WalkIf(ParseNodeIf *pnode, Context context)
  217. {
  218. ResultType result = WalkFirstChild(pnode->pnodeCond, context);
  219. if (ContinueWalk(result))
  220. {
  221. result = WalkNode(pnode, context);
  222. if (ContinueWalk(result))
  223. {
  224. result = WalkSecondChild(pnode->pnodeTrue, context);
  225. if (ContinueWalk(result) && pnode->pnodeFalse)
  226. result = WalkNthChild(pnode, pnode->pnodeFalse, context);
  227. }
  228. }
  229. return result;
  230. }
  231. ResultType WalkWhile(ParseNodeWhile *pnode, Context context)
  232. {
  233. ResultType result = WalkFirstChild(pnode->pnodeCond, context);
  234. if (ContinueWalk(result))
  235. {
  236. result = WalkNode(pnode, context);
  237. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeBody, context);
  238. }
  239. return result;
  240. }
  241. ResultType WalkDoWhile(ParseNodeWhile *pnode, Context context)
  242. {
  243. ResultType result = WalkFirstChild(pnode->pnodeBody, context);
  244. if (ContinueWalk(result))
  245. {
  246. result = WalkNode(pnode, context);
  247. if (ContinueWalk(result))
  248. {
  249. result = WalkSecondChild(pnode->pnodeCond, context);
  250. }
  251. }
  252. return result;
  253. }
  254. ResultType WalkForInOrForOf(ParseNodeForInOrForOf *pnode, Context context)
  255. {
  256. ResultType result = WalkFirstChild(pnode->pnodeLval, context);
  257. if (ContinueWalk(result))
  258. {
  259. result = WalkNthChild(pnode, pnode->pnodeObj, context);
  260. if (ContinueWalk(result))
  261. {
  262. result = WalkNode(pnode, context);
  263. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeBody, context);
  264. }
  265. }
  266. return result;
  267. }
  268. ResultType WalkReturn(ParseNodeReturn *pnode, Context context)
  269. {
  270. ResultType result = WalkNode(pnode, context);
  271. if (ContinueWalk(result) && pnode->pnodeExpr) result = WalkFirstChild(pnode->pnodeExpr, context);
  272. return result;
  273. }
  274. ResultType WalkBlock(ParseNodeBlock *pnode, Context context)
  275. {
  276. ResultType result = WalkNode(pnode, context);
  277. if (ContinueWalk(result) && pnode->pnodeStmt)
  278. result = WalkList(pnode, pnode->pnodeStmt, context);
  279. return result;
  280. }
  281. ResultType WalkWith(ParseNodeWith *pnode, Context context)
  282. {
  283. ResultType result = WalkFirstChild(pnode->pnodeObj, context);
  284. if (ContinueWalk(result))
  285. {
  286. result = WalkNode(pnode, context);
  287. if (ContinueWalk(result))
  288. {
  289. result = WalkSecondChild(pnode->pnodeBody, context);
  290. }
  291. }
  292. return result;
  293. }
  294. ResultType WalkSwitch(ParseNodeSwitch *pnode, Context context)
  295. {
  296. ResultType result = WalkFirstChild(pnode->pnodeVal, context);
  297. if (ContinueWalk(result))
  298. {
  299. for (ParseNodeCase** caseNode = &(pnode->pnodeCases); *caseNode != nullptr; caseNode = &((*caseNode)->pnodeNext))
  300. {
  301. result = *caseNode == pnode->pnodeCases ? WalkFirstChild(*caseNode, context) : WalkNthChild(pnode, *caseNode, context);
  302. if (!ContinueWalk(result)) return result;
  303. }
  304. result = WalkNode(pnode, context);
  305. }
  306. return result;
  307. }
  308. ResultType WalkCase(ParseNodeCase *pnode, Context context)
  309. {
  310. ResultType result = WalkFirstChild(pnode->pnodeExpr, context);
  311. if (ContinueWalk(result))
  312. {
  313. result = WalkNode(pnode, context);
  314. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeBody, context);
  315. }
  316. return result;
  317. }
  318. ResultType WalkTryFinally(ParseNodeTryFinally *pnode, Context context)
  319. {
  320. ResultType result = WalkFirstChild(pnode->pnodeTry, context);
  321. if (ContinueWalk(result))
  322. {
  323. result = WalkNode(pnode, context);
  324. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeFinally, context);
  325. }
  326. return result;
  327. }
  328. ResultType WalkFinally(ParseNodeFinally *pnode, Context context)
  329. {
  330. ResultType result = WalkNode(pnode, context);
  331. if (ContinueWalk(result)) result = WalkFirstChild(pnode->pnodeBody, context);
  332. return result;
  333. }
  334. ResultType WalkCatch(ParseNodeCatch *pnode, Context context)
  335. {
  336. ResultType result = WalkFirstChild(pnode->GetParam(), context);
  337. if (ContinueWalk(result))
  338. {
  339. result = WalkNode(pnode, context);
  340. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeBody, context);
  341. }
  342. return result;
  343. }
  344. ResultType WalkTryCatch(ParseNodeTryCatch *pnode, Context context)
  345. {
  346. ResultType result = WalkFirstChild(pnode->pnodeTry, context);
  347. if (ContinueWalk(result))
  348. {
  349. result = WalkNode(pnode, context);
  350. if (ContinueWalk(result)) result = WalkSecondChild(pnode->pnodeCatch, context);
  351. }
  352. return result;
  353. }
  354. ResultType WalkTry(ParseNodeTry *pnode, Context context)
  355. {
  356. ResultType result = WalkNode(pnode, context);
  357. if (ContinueWalk(result)) result = WalkFirstChild(pnode->pnodeBody, context);
  358. return result;
  359. }
  360. ResultType WalkClass(ParseNodeClass *pnode, Context context)
  361. {
  362. // First walk the class node itself
  363. ResultType result = WalkNode(pnode, context);
  364. if (!ContinueWalk(result)) return result;
  365. // Walk extends expr
  366. result = WalkFirstChild(pnode->pnodeExtends, context);
  367. if (!ContinueWalk(result)) return result;
  368. // Walk the constructor
  369. result = WalkNthChild(pnode, pnode->pnodeConstructor, context);
  370. if (!ContinueWalk(result)) return result;
  371. // Walk all non-static members
  372. result = WalkList(pnode, pnode->pnodeMembers, context);
  373. return result;
  374. }
  375. public:
  376. ResultType Walk(ParseNode *pnode, Context context)
  377. {
  378. if (!pnode) return DefaultResult();
  379. switch (pnode->nop) {
  380. // Handle all special cases first.
  381. // Post-fix unary operators.
  382. //PTNODE(knopIncPost , "++ post" ,Inc ,Uni ,fnopUni|fnopAsg)
  383. //PTNODE(knopDecPost , "-- post" ,Dec ,Uni ,fnopUni|fnopAsg)
  384. case knopIncPost:
  385. case knopDecPost:
  386. return WalkPostUnary(pnode->AsParseNodeUni(), context);
  387. // Call and call like
  388. //PTNODE(knopCall , "()" ,None ,Bin ,fnopBin)
  389. //PTNODE(knopNew , "new" ,None ,Bin ,fnopBin)
  390. case knopCall:
  391. case knopNew:
  392. return WalkCall(pnode->AsParseNodeCall(), context);
  393. // Ternary operator
  394. //PTNODE(knopQmark , "?" ,None ,Tri ,fnopBin)
  395. case knopQmark:
  396. return WalkTernary(pnode->AsParseNodeTri(), context);
  397. // General nodes.
  398. //PTNODE(knopList , "<list>" ,None ,Bin ,fnopNone)
  399. case knopList:
  400. return WalkList(NULL, pnode, context);
  401. //PTNODE(knopVarDecl , "varDcl" ,None ,Var ,fnopNone)
  402. case knopVarDecl:
  403. case knopConstDecl:
  404. case knopLetDecl:
  405. case knopTemp:
  406. return WalkVar(pnode->AsParseNodeVar(), context);
  407. //PTNODE(knopFncDecl , "fncDcl" ,None ,Fnc ,fnopLeaf)
  408. case knopFncDecl:
  409. return WalkFnc(pnode->AsParseNodeFnc(), context);
  410. //PTNODE(knopProg , "program" ,None ,Fnc ,fnopNone)
  411. case knopProg:
  412. return WalkProg(pnode->AsParseNodeProg(), context);
  413. //PTNODE(knopFor , "for" ,None ,For ,fnopBreak|fnopContinue)
  414. case knopFor:
  415. return WalkFor(pnode->AsParseNodeFor(), context);
  416. //PTNODE(knopIf , "if" ,None ,If ,fnopNone)
  417. case knopIf:
  418. return WalkIf(pnode->AsParseNodeIf(), context);
  419. //PTNODE(knopWhile , "while" ,None ,While,fnopBreak|fnopContinue)
  420. case knopWhile:
  421. return WalkWhile(pnode->AsParseNodeWhile(), context);
  422. //PTNODE(knopDoWhile , "do-while" ,None ,While,fnopBreak|fnopContinue)
  423. case knopDoWhile:
  424. return WalkDoWhile(pnode->AsParseNodeWhile(), context);
  425. //PTNODE(knopForIn , "for in" ,None ,ForIn,fnopBreak|fnopContinue|fnopCleanup)
  426. case knopForIn:
  427. return WalkForInOrForOf(pnode->AsParseNodeForInOrForOf(), context);
  428. case knopForOf:
  429. return WalkForInOrForOf(pnode->AsParseNodeForInOrForOf(), context);
  430. case knopForAwaitOf:
  431. return WalkForInOrForOf(pnode->AsParseNodeForInOrForOf(), context);
  432. //PTNODE(knopReturn , "return" ,None ,Uni ,fnopNone)
  433. case knopReturn:
  434. return WalkReturn(pnode->AsParseNodeReturn(), context);
  435. //PTNODE(knopBlock , "{}" ,None ,Block,fnopNone)
  436. case knopBlock:
  437. return WalkBlock(pnode->AsParseNodeBlock(), context);
  438. //PTNODE(knopWith , "with" ,None ,With ,fnopCleanup)
  439. case knopWith:
  440. return WalkWith(pnode->AsParseNodeWith(), context);
  441. //PTNODE(knopSwitch , "switch" ,None ,Switch,fnopBreak)
  442. case knopSwitch:
  443. return WalkSwitch(pnode->AsParseNodeSwitch(), context);
  444. //PTNODE(knopCase , "case" ,None ,Case ,fnopNone)
  445. case knopCase:
  446. return WalkCase(pnode->AsParseNodeCase(), context);
  447. //PTNODE(knopTryFinally,"try-finally",None,TryFinally,fnopCleanup)
  448. case knopTryFinally:
  449. return WalkTryFinally(pnode->AsParseNodeTryFinally(), context);
  450. case knopFinally:
  451. return WalkFinally(pnode->AsParseNodeFinally(), context);
  452. //PTNODE(knopCatch , "catch" ,None ,Catch,fnopNone)
  453. case knopCatch:
  454. return WalkCatch(pnode->AsParseNodeCatch(), context);
  455. //PTNODE(knopTryCatch , "try-catch" ,None ,TryCatch ,fnopCleanup)
  456. case knopTryCatch:
  457. return WalkTryCatch(pnode->AsParseNodeTryCatch(), context);
  458. //PTNODE(knopTry , "try" ,None ,Try ,fnopCleanup)
  459. case knopTry:
  460. return WalkTry(pnode->AsParseNodeTry(), context);
  461. //PTNODE(knopThrow , "throw" ,None ,Uni ,fnopNone)
  462. case knopThrow:
  463. return WalkPostUnary(pnode->AsParseNodeUni(), context);
  464. case knopStrTemplate:
  465. return WalkStringTemplate(pnode->AsParseNodeStrTemplate(), context);
  466. //PTNODE(knopClassDecl , "classDecl" ,None ,Class ,fnopLeaf)
  467. case knopClassDecl:
  468. return WalkClass(pnode->AsParseNodeClass(), context);
  469. case knopExportDefault:
  470. return Walk(pnode->AsParseNodeExportDefault()->pnodeExpr, context);
  471. default:
  472. {
  473. uint fnop = ParseNode::Grfnop(pnode->nop);
  474. if (fnop & fnopLeaf || fnop & fnopNone)
  475. {
  476. return WalkLeaf(pnode, context);
  477. }
  478. else if (fnop & fnopBin)
  479. {
  480. return WalkBinary(pnode->AsParseNodeBin(), context);
  481. }
  482. else if (fnop & fnopUni)
  483. {
  484. // Prefix unary operators.
  485. return WalkPreUnary(pnode->AsParseNodeUni(), context);
  486. }
  487. // Some node types are both fnopNotExprStmt and something else. Try the above cases first and fall back to this one.
  488. if (fnop & fnopNotExprStmt)
  489. {
  490. return WalkLeaf(pnode, context);
  491. }
  492. Assert(false);
  493. __assume(false);
  494. }
  495. }
  496. }
  497. };