node_stack.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_
  5. #define CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_
  6. #include <type_traits>
  7. #include "common/vlog.h"
  8. #include "llvm/ADT/SmallVector.h"
  9. #include "toolchain/parse/node_ids.h"
  10. #include "toolchain/parse/node_kind.h"
  11. #include "toolchain/parse/tree.h"
  12. #include "toolchain/parse/typed_nodes.h"
  13. #include "toolchain/sem_ir/ids.h"
  14. namespace Carbon::Check {
  15. // A non-discriminated union of ID types.
  16. template <typename... IdTypes>
  17. class IdUnion {
  18. public:
  19. // The default constructor forms an invalid ID.
  20. explicit constexpr IdUnion() : index(IdBase::InvalidIndex) {}
  21. template <typename IdT>
  22. requires(std::same_as<IdT, IdTypes> || ...)
  23. explicit constexpr IdUnion(IdT id) : index(id.index) {}
  24. static constexpr std::size_t NumValidKinds = sizeof...(IdTypes);
  25. // A numbering for the associated ID types.
  26. enum class Kind : int8_t {
  27. // The first `sizeof...(IdTypes)` indexes correspond to the types in
  28. // `IdTypes`.
  29. // An explicit invalid state.
  30. Invalid = NumValidKinds,
  31. // No active union element.
  32. None,
  33. };
  34. // Returns the ID given its type.
  35. template <typename IdT>
  36. requires(std::same_as<IdT, IdTypes> || ...)
  37. constexpr auto As() const -> IdT {
  38. return IdT(index);
  39. }
  40. // Returns the ID given its kind.
  41. template <Kind K>
  42. requires(static_cast<size_t>(K) < sizeof...(IdTypes))
  43. constexpr auto As() const {
  44. using IdT = __type_pack_element<static_cast<size_t>(K), IdTypes...>;
  45. return As<IdT>();
  46. }
  47. // Translates an ID type to the enum ID kind. Returns Invalid if `IdT` isn't
  48. // a type that can be stored in this union.
  49. template <typename IdT>
  50. static constexpr auto KindFor() -> Kind {
  51. // A bool for each type saying whether it matches. The result is the index
  52. // of the first `true` in this list. If none matches, then the result is the
  53. // length of the list, which is mapped to `Invalid`.
  54. constexpr bool TypeMatches[] = {std::same_as<IdT, IdTypes>...};
  55. constexpr int Index =
  56. std::find(TypeMatches, TypeMatches + sizeof...(IdTypes), true) -
  57. TypeMatches;
  58. return static_cast<Kind>(Index);
  59. }
  60. private:
  61. decltype(IdBase::index) index;
  62. };
  63. // The stack of parse nodes representing the current state of a Check::Context.
  64. // Each parse node can have an associated id of some kind (instruction,
  65. // instruction block, function, class, ...).
  66. //
  67. // All pushes and pops will be vlogged.
  68. //
  69. // Pop APIs will run basic verification:
  70. //
  71. // - If receiving a Parse::NodeKind, verify that the parse_node being popped has
  72. // that kind. Similarly, if receiving a Parse::NodeCategory, make sure the
  73. // of the popped parse_node overlaps that category.
  74. // - Validates the kind of id data in the node based on the kind or category of
  75. // the parse_node.
  76. //
  77. // These should be assumed API constraints unless otherwise mentioned on a
  78. // method. The main exception is PopAndIgnore, which doesn't do verification.
  79. class NodeStack {
  80. public:
  81. explicit NodeStack(const Parse::Tree& parse_tree,
  82. llvm::raw_ostream* vlog_stream)
  83. : parse_tree_(&parse_tree), vlog_stream_(vlog_stream) {}
  84. // Pushes a solo parse tree node onto the stack. Used when there is no
  85. // IR generated by the node.
  86. auto Push(Parse::NodeId parse_node) -> void {
  87. auto kind = parse_tree_->node_kind(parse_node);
  88. CARBON_CHECK(ParseNodeKindToIdKind(kind) == Id::Kind::None)
  89. << "Parse kind expects an Id: " << kind;
  90. CARBON_VLOG() << "Node Push " << stack_.size() << ": " << kind
  91. << " -> <none>\n";
  92. CARBON_CHECK(stack_.size() < (1 << 20))
  93. << "Excessive stack size: likely infinite loop";
  94. stack_.push_back(Entry{parse_node, Id()});
  95. }
  96. // Pushes a parse tree node onto the stack with an ID.
  97. template <typename IdT>
  98. auto Push(Parse::NodeId parse_node, IdT id) -> void {
  99. auto kind = parse_tree_->node_kind(parse_node);
  100. CARBON_CHECK(ParseNodeKindToIdKind(kind) == Id::KindFor<IdT>())
  101. << "Parse kind expected a different IdT: " << kind << " -> " << id
  102. << "\n";
  103. CARBON_CHECK(id.is_valid()) << "Push called with invalid id: "
  104. << parse_tree_->node_kind(parse_node);
  105. CARBON_VLOG() << "Node Push " << stack_.size() << ": " << kind << " -> "
  106. << id << "\n";
  107. CARBON_CHECK(stack_.size() < (1 << 20))
  108. << "Excessive stack size: likely infinite loop";
  109. stack_.push_back(Entry{parse_node, Id(id)});
  110. }
  111. // Returns whether there is a node of the specified kind on top of the stack.
  112. auto PeekIs(Parse::NodeKind kind) const -> bool {
  113. return !stack_.empty() && PeekParseNodeKind() == kind;
  114. }
  115. // Returns whether there is a node of the specified kind on top of the stack.
  116. // Templated for consistency with other functions taking a parse node kind.
  117. template <const Parse::NodeKind& RequiredParseKind>
  118. auto PeekIs() const -> bool {
  119. return PeekIs(RequiredParseKind);
  120. }
  121. // Returns whether the node on the top of the stack has an overlapping
  122. // category.
  123. auto PeekIs(Parse::NodeCategory category) const -> bool {
  124. return !stack_.empty() && !!(PeekParseNodeKind().category() & category);
  125. }
  126. // Returns whether the node on the top of the stack has an overlapping
  127. // category. Templated for consistency with other functions taking a parse
  128. // node category.
  129. template <Parse::NodeCategory RequiredParseCategory>
  130. auto PeekIs() const -> bool {
  131. return PeekIs(RequiredParseCategory);
  132. }
  133. // Returns whether there is a name on top of the stack.
  134. auto PeekIsName() const -> bool {
  135. return !stack_.empty() && ParseNodeKindToIdKind(PeekParseNodeKind()) ==
  136. Id::KindFor<SemIR::NameId>();
  137. }
  138. // Returns whether the *next* node on the stack is a given kind. This doesn't
  139. // have the breadth of support versus other Peek functions because it's
  140. // expected to be used in narrow circumstances when determining how to treat
  141. // the *current* top of the stack.
  142. template <const Parse::NodeKind& RequiredParseKind>
  143. auto PeekNextIs() const -> bool {
  144. CARBON_CHECK(stack_.size() >= 2);
  145. return parse_tree_->node_kind(stack_[stack_.size() - 2].parse_node) ==
  146. RequiredParseKind;
  147. }
  148. // Pops the top of the stack without any verification.
  149. auto PopAndIgnore() -> void {
  150. Entry back = stack_.pop_back_val();
  151. CARBON_VLOG() << "Node Pop " << stack_.size() << ": "
  152. << parse_tree_->node_kind(back.parse_node)
  153. << " -> <ignored>\n";
  154. }
  155. // Pops the top of the stack and returns the parse_node.
  156. template <const Parse::NodeKind& RequiredParseKind>
  157. auto PopForSoloParseNode() -> Parse::NodeIdForKind<RequiredParseKind> {
  158. Entry back = PopEntry<SemIR::InstId>();
  159. RequireIdKind(RequiredParseKind, Id::Kind::None);
  160. RequireParseKind<RequiredParseKind>(back.parse_node);
  161. return Parse::NodeIdForKind<RequiredParseKind>(back.parse_node);
  162. }
  163. // Pops the top of the stack if it is the given kind, and returns the
  164. // parse_node. Otherwise, returns std::nullopt.
  165. template <const Parse::NodeKind& RequiredParseKind>
  166. auto PopForSoloParseNodeIf()
  167. -> std::optional<Parse::NodeIdForKind<RequiredParseKind>> {
  168. if (PeekIs<RequiredParseKind>()) {
  169. return PopForSoloParseNode<RequiredParseKind>();
  170. }
  171. return std::nullopt;
  172. }
  173. // Pops the top of the stack.
  174. template <const Parse::NodeKind& RequiredParseKind>
  175. auto PopAndDiscardSoloParseNode() -> void {
  176. PopForSoloParseNode<RequiredParseKind>();
  177. }
  178. // Pops the top of the stack if it is the given kind. Returns `true` if a node
  179. // was popped.
  180. template <const Parse::NodeKind& RequiredParseKind>
  181. auto PopAndDiscardSoloParseNodeIf() -> bool {
  182. if (!PeekIs<RequiredParseKind>()) {
  183. return false;
  184. }
  185. PopForSoloParseNode<RequiredParseKind>();
  186. return true;
  187. }
  188. // Pops an expression from the top of the stack and returns the parse_node and
  189. // the ID.
  190. auto PopExprWithParseNode() -> std::pair<Parse::AnyExprId, SemIR::InstId>;
  191. // Pops a pattern from the top of the stack and returns the parse_node and
  192. // the ID.
  193. auto PopPatternWithParseNode() -> std::pair<Parse::NodeId, SemIR::InstId> {
  194. return PopWithParseNode<SemIR::InstId>();
  195. }
  196. // Pops a name from the top of the stack and returns the parse_node and
  197. // the ID.
  198. auto PopNameWithParseNode() -> std::pair<Parse::NodeId, SemIR::NameId> {
  199. return PopWithParseNode<SemIR::NameId>();
  200. }
  201. // Pops the top of the stack and returns the parse_node and the ID.
  202. template <const Parse::NodeKind& RequiredParseKind>
  203. auto PopWithParseNode() -> auto {
  204. auto id = Peek<RequiredParseKind>();
  205. Parse::NodeIdForKind<RequiredParseKind> parse_node(
  206. stack_.pop_back_val().parse_node);
  207. return std::make_pair(parse_node, id);
  208. }
  209. // Pops the top of the stack and returns the parse_node and the ID.
  210. template <Parse::NodeCategory RequiredParseCategory>
  211. auto PopWithParseNode() -> auto {
  212. auto id = Peek<RequiredParseCategory>();
  213. Parse::NodeIdInCategory<RequiredParseCategory> parse_node(
  214. stack_.pop_back_val().parse_node);
  215. return std::make_pair(parse_node, id);
  216. }
  217. // Pops an expression from the top of the stack and returns the ID.
  218. // Expressions always map Parse::NodeCategory::Expr nodes to SemIR::InstId.
  219. auto PopExpr() -> SemIR::InstId { return PopExprWithParseNode().second; }
  220. // Pops a pattern from the top of the stack and returns the ID.
  221. // Patterns map multiple Parse::NodeKinds to SemIR::InstId always.
  222. auto PopPattern() -> SemIR::InstId {
  223. return PopPatternWithParseNode().second;
  224. }
  225. // Pops a name from the top of the stack and returns the ID.
  226. auto PopName() -> SemIR::NameId { return PopNameWithParseNode().second; }
  227. // Pops the top of the stack and returns the ID.
  228. template <const Parse::NodeKind& RequiredParseKind>
  229. auto Pop() -> auto {
  230. return PopWithParseNode<RequiredParseKind>().second;
  231. }
  232. // Pops the top of the stack and returns the ID.
  233. template <Parse::NodeCategory RequiredParseCategory>
  234. auto Pop() -> auto {
  235. return PopWithParseNode<RequiredParseCategory>().second;
  236. }
  237. // Pops the top of the stack and returns the ID.
  238. template <typename IdT>
  239. auto Pop() -> IdT {
  240. return PopWithParseNode<IdT>().second;
  241. }
  242. // Pops the top of the stack if it has the given kind, and returns the ID.
  243. // Otherwise returns std::nullopt.
  244. template <const Parse::NodeKind& RequiredParseKind>
  245. auto PopIf() -> std::optional<decltype(Pop<RequiredParseKind>())> {
  246. if (PeekIs<RequiredParseKind>()) {
  247. return Pop<RequiredParseKind>();
  248. }
  249. return std::nullopt;
  250. }
  251. // Pops the top of the stack if it has the given category, and returns the ID.
  252. // Otherwise returns std::nullopt.
  253. template <Parse::NodeCategory RequiredParseCategory>
  254. auto PopIf() -> std::optional<decltype(Pop<RequiredParseCategory>())> {
  255. if (PeekIs<RequiredParseCategory>()) {
  256. return Pop<RequiredParseCategory>();
  257. }
  258. return std::nullopt;
  259. }
  260. // Pops the top of the stack and returns the parse_node and the ID if it is
  261. // of the specified kind.
  262. template <const Parse::NodeKind& RequiredParseKind>
  263. auto PopWithParseNodeIf()
  264. -> std::pair<Parse::NodeIdForKind<RequiredParseKind>,
  265. decltype(PopIf<RequiredParseKind>())> {
  266. if (!PeekIs<RequiredParseKind>()) {
  267. return {Parse::NodeId::Invalid, std::nullopt};
  268. }
  269. return PopWithParseNode<RequiredParseKind>();
  270. }
  271. // Pops the top of the stack and returns the parse_node and the ID if it is
  272. // of the specified category.
  273. template <Parse::NodeCategory RequiredParseCategory>
  274. auto PopWithParseNodeIf()
  275. -> std::pair<Parse::NodeIdInCategory<RequiredParseCategory>,
  276. decltype(PopIf<RequiredParseCategory>())> {
  277. if (!PeekIs<RequiredParseCategory>()) {
  278. return {Parse::NodeId::Invalid, std::nullopt};
  279. }
  280. return PopWithParseNode<RequiredParseCategory>();
  281. }
  282. // Peeks at the parse node of the top of the node stack.
  283. auto PeekParseNode() const -> Parse::NodeId {
  284. return stack_.back().parse_node;
  285. }
  286. // Peeks at the kind of the parse node of the top of the node stack.
  287. auto PeekParseNodeKind() const -> Parse::NodeKind {
  288. return parse_tree_->node_kind(PeekParseNode());
  289. }
  290. // Peeks at the ID associated with the top of the name stack.
  291. template <const Parse::NodeKind& RequiredParseKind>
  292. auto Peek() const -> auto {
  293. Entry back = stack_.back();
  294. RequireParseKind<RequiredParseKind>(back.parse_node);
  295. constexpr Id::Kind RequiredIdKind =
  296. ParseNodeKindToIdKind(RequiredParseKind);
  297. return Peek<RequiredIdKind>();
  298. }
  299. // Peeks at the ID associated with the top of the name stack.
  300. template <Parse::NodeCategory RequiredParseCategory>
  301. auto Peek() const -> auto {
  302. Entry back = stack_.back();
  303. RequireParseCategory<RequiredParseCategory>(back.parse_node);
  304. constexpr std::optional<Id::Kind> RequiredIdKind =
  305. ParseNodeCategoryToIdKind(RequiredParseCategory, false);
  306. static_assert(RequiredIdKind.has_value());
  307. return Peek<*RequiredIdKind>();
  308. }
  309. // Prints the stack for a stack dump.
  310. auto PrintForStackDump(llvm::raw_ostream& output) const -> void;
  311. auto empty() const -> bool { return stack_.empty(); }
  312. auto size() const -> size_t { return stack_.size(); }
  313. protected:
  314. // An ID that can be associated with a parse node.
  315. //
  316. // Each parse node kind has a corresponding Id::Kind indicating which kind of
  317. // ID is stored, computed by ParseNodeKindToIdKind. Id::Kind::None indicates
  318. // that the parse node has no associated ID, in which case the *SoloParseNode
  319. // functions should be used to push and pop it. Id::Kind::Invalid indicates
  320. // that the parse node should not appear in the node stack at all.
  321. using Id = IdUnion<SemIR::InstId, SemIR::InstBlockId, SemIR::FunctionId,
  322. SemIR::ClassId, SemIR::InterfaceId, SemIR::ImplId,
  323. SemIR::NameId, SemIR::TypeId>;
  324. // An entry in stack_.
  325. struct Entry {
  326. // The parse node associated with the stack entry.
  327. Parse::NodeId parse_node;
  328. // The ID associated with this parse node. The kind of ID is determined by
  329. // the kind of the parse node, so a separate discriminiator is not needed.
  330. Id id;
  331. };
  332. static_assert(sizeof(Entry) == 8, "Unexpected Entry size");
  333. // Translate a parse node category to the enum ID kind it should always
  334. // provide, if it is consistent.
  335. static constexpr auto ParseNodeCategoryToIdKind(Parse::NodeCategory category,
  336. bool for_node_kind)
  337. -> std::optional<Id::Kind> {
  338. std::optional<Id::Kind> result;
  339. auto set_id_if_category_is = [&](Parse::NodeCategory cat, Id::Kind kind) {
  340. if (!!(category & cat)) {
  341. // Check for no consistent Id::Kind due to category with multiple bits
  342. // set. When computing the Id::Kind for a node kind, a partial category
  343. // match is OK, so long as we don't match two inconsistent categories.
  344. // When computing the Id::Kind for a category query, the query can't
  345. // have any extra bits set or we could be popping a node that is not in
  346. // this category.
  347. if (for_node_kind ? result.has_value() : !!(category & ~cat)) {
  348. result = Id::Kind::Invalid;
  349. } else {
  350. result = kind;
  351. }
  352. }
  353. };
  354. // TODO: Patterns should also produce an `InstId`, but currently
  355. // `TuplePattern` produces an `InstBlockId`.
  356. set_id_if_category_is(Parse::NodeCategory::Expr,
  357. Id::KindFor<SemIR::InstId>());
  358. set_id_if_category_is(Parse::NodeCategory::MemberName,
  359. Id::KindFor<SemIR::NameId>());
  360. set_id_if_category_is(Parse::NodeCategory::ImplAs,
  361. Id::KindFor<SemIR::TypeId>());
  362. set_id_if_category_is(Parse::NodeCategory::Decl |
  363. Parse::NodeCategory::Statement |
  364. Parse::NodeCategory::Modifier,
  365. Id::Kind::None);
  366. return result;
  367. }
  368. using IdKindTableType = std::array<Id::Kind, Parse::NodeKind::ValidCount>;
  369. // Lookup table to implement `ParseNodeKindToIdKind`. Initialized to the
  370. // return value of `ComputeIdKindTable()`.
  371. static const IdKindTableType IdKindTable;
  372. static constexpr auto ComputeIdKindTable() -> IdKindTableType {
  373. IdKindTableType table = {};
  374. auto to_id_kind =
  375. [](const Parse::NodeKind::Definition& node_kind) -> Id::Kind {
  376. if (auto from_category =
  377. ParseNodeCategoryToIdKind(node_kind.category(), true)) {
  378. return *from_category;
  379. }
  380. switch (node_kind) {
  381. case Parse::NodeKind::Addr:
  382. case Parse::NodeKind::BindingPattern:
  383. case Parse::NodeKind::CallExprStart:
  384. case Parse::NodeKind::CompileTimeBindingPattern:
  385. case Parse::NodeKind::IfExprThen:
  386. case Parse::NodeKind::ReturnType:
  387. case Parse::NodeKind::ShortCircuitOperandAnd:
  388. case Parse::NodeKind::ShortCircuitOperandOr:
  389. case Parse::NodeKind::StructFieldValue:
  390. case Parse::NodeKind::StructFieldType:
  391. return Id::KindFor<SemIR::InstId>();
  392. case Parse::NodeKind::IfCondition:
  393. case Parse::NodeKind::IfExprIf:
  394. case Parse::NodeKind::ImplForall:
  395. case Parse::NodeKind::ImplicitParamList:
  396. case Parse::NodeKind::TuplePattern:
  397. case Parse::NodeKind::WhileCondition:
  398. case Parse::NodeKind::WhileConditionStart:
  399. return Id::KindFor<SemIR::InstBlockId>();
  400. case Parse::NodeKind::FunctionDefinitionStart:
  401. return Id::KindFor<SemIR::FunctionId>();
  402. case Parse::NodeKind::ClassDefinitionStart:
  403. return Id::KindFor<SemIR::ClassId>();
  404. case Parse::NodeKind::InterfaceDefinitionStart:
  405. return Id::KindFor<SemIR::InterfaceId>();
  406. case Parse::NodeKind::ImplDefinitionStart:
  407. return Id::KindFor<SemIR::ImplId>();
  408. case Parse::NodeKind::SelfValueName:
  409. return Id::KindFor<SemIR::NameId>();
  410. case Parse::NodeKind::ArrayExprSemi:
  411. case Parse::NodeKind::ClassIntroducer:
  412. case Parse::NodeKind::CodeBlockStart:
  413. case Parse::NodeKind::ExprOpenParen:
  414. case Parse::NodeKind::FunctionIntroducer:
  415. case Parse::NodeKind::IfStatementElse:
  416. case Parse::NodeKind::ImplicitParamListStart:
  417. case Parse::NodeKind::ImplIntroducer:
  418. case Parse::NodeKind::InterfaceIntroducer:
  419. case Parse::NodeKind::LetInitializer:
  420. case Parse::NodeKind::LetIntroducer:
  421. case Parse::NodeKind::QualifiedName:
  422. case Parse::NodeKind::ReturnedModifier:
  423. case Parse::NodeKind::ReturnStatementStart:
  424. case Parse::NodeKind::ReturnVarModifier:
  425. case Parse::NodeKind::StructLiteralOrStructTypeLiteralStart:
  426. case Parse::NodeKind::TuplePatternStart:
  427. case Parse::NodeKind::VariableInitializer:
  428. case Parse::NodeKind::VariableIntroducer:
  429. return Id::Kind::None;
  430. default:
  431. return Id::Kind::Invalid;
  432. }
  433. };
  434. #define CARBON_PARSE_NODE_KIND(Name) \
  435. table[Parse::Name::Kind.AsInt()] = to_id_kind(Parse::Name::Kind);
  436. #include "toolchain/parse/node_kind.def"
  437. return table;
  438. }
  439. // Translate a parse node kind to the enum ID kind it should always provide.
  440. static constexpr auto ParseNodeKindToIdKind(Parse::NodeKind kind)
  441. -> Id::Kind {
  442. return IdKindTable[kind.AsInt()];
  443. }
  444. // Peeks at the ID associated with the top of the name stack.
  445. template <Id::Kind RequiredIdKind>
  446. auto Peek() const -> auto {
  447. Id id = stack_.back().id;
  448. return id.As<RequiredIdKind>();
  449. }
  450. // Pops an entry.
  451. template <typename IdT>
  452. auto PopEntry() -> Entry {
  453. Entry back = stack_.pop_back_val();
  454. CARBON_VLOG() << "Node Pop " << stack_.size() << ": "
  455. << parse_tree_->node_kind(back.parse_node) << " -> "
  456. << back.id.template As<IdT>() << "\n";
  457. return back;
  458. }
  459. // Pops the top of the stack and returns the parse_node and the ID.
  460. template <typename IdT>
  461. auto PopWithParseNode() -> std::pair<Parse::NodeId, IdT> {
  462. Entry back = PopEntry<IdT>();
  463. RequireIdKind(parse_tree_->node_kind(back.parse_node), Id::KindFor<IdT>());
  464. return {back.parse_node, back.id.template As<IdT>()};
  465. }
  466. // Require a Parse::NodeKind be mapped to a particular Id::Kind.
  467. auto RequireIdKind(Parse::NodeKind parse_kind, Id::Kind id_kind) const
  468. -> void {
  469. CARBON_CHECK(ParseNodeKindToIdKind(parse_kind) == id_kind)
  470. << "Unexpected Id::Kind mapping for " << parse_kind;
  471. }
  472. // Require an entry to have the given Parse::NodeKind.
  473. template <const Parse::NodeKind& RequiredParseKind>
  474. auto RequireParseKind(Parse::NodeId parse_node) const -> void {
  475. auto actual_kind = parse_tree_->node_kind(parse_node);
  476. CARBON_CHECK(RequiredParseKind == actual_kind)
  477. << "Expected " << RequiredParseKind << ", found " << actual_kind;
  478. }
  479. // Require an entry to have the given Parse::NodeCategory.
  480. template <Parse::NodeCategory RequiredParseCategory>
  481. auto RequireParseCategory(Parse::NodeId parse_node) const -> void {
  482. auto kind = parse_tree_->node_kind(parse_node);
  483. CARBON_CHECK(!!(RequiredParseCategory & kind.category()))
  484. << "Expected " << RequiredParseCategory << ", found " << kind
  485. << " with category " << kind.category();
  486. }
  487. // The file's parse tree.
  488. const Parse::Tree* parse_tree_;
  489. // Whether to print verbose output.
  490. llvm::raw_ostream* vlog_stream_;
  491. // The actual stack.
  492. // PushEntry and PopEntry control modification in order to centralize
  493. // vlogging.
  494. llvm::SmallVector<Entry> stack_;
  495. };
  496. constexpr NodeStack::IdKindTableType NodeStack::IdKindTable =
  497. ComputeIdKindTable();
  498. inline auto NodeStack::PopExprWithParseNode()
  499. -> std::pair<Parse::AnyExprId, SemIR::InstId> {
  500. return PopWithParseNode<Parse::NodeCategory::Expr>();
  501. }
  502. } // namespace Carbon::Check
  503. #endif // CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_