pnodewalk.h 21 KB

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