node_stack.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  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 "common/vlog.h"
  7. #include "llvm/ADT/SmallVector.h"
  8. #include "toolchain/parse/node_ids.h"
  9. #include "toolchain/parse/node_kind.h"
  10. #include "toolchain/parse/tree.h"
  11. #include "toolchain/parse/typed_nodes.h"
  12. #include "toolchain/sem_ir/id_kind.h"
  13. #include "toolchain/sem_ir/ids.h"
  14. namespace Carbon::Check {
  15. // A non-discriminated union of ID types.
  16. class IdUnion {
  17. public:
  18. // The default constructor forms a `None` ID.
  19. explicit constexpr IdUnion() : index(AnyIdBase::NoneIndex) {}
  20. template <typename IdT>
  21. requires SemIR::IdKind::Contains<IdT>
  22. explicit constexpr IdUnion(IdT id) : index(id.index) {}
  23. using Kind = SemIR::IdKind::RawEnumType;
  24. // Returns the ID given its type.
  25. template <typename IdT>
  26. requires SemIR::IdKind::Contains<IdT>
  27. constexpr auto As() const -> IdT {
  28. return IdT(index);
  29. }
  30. // Returns the ID given its kind.
  31. template <SemIR::IdKind::RawEnumType K>
  32. constexpr auto As() const -> SemIR::IdKind::TypeFor<K> {
  33. return As<SemIR::IdKind::TypeFor<K>>();
  34. }
  35. // Translates an ID type to the enum ID kind. Returns `None` if `IdT` isn't
  36. // a type that can be stored in this union.
  37. template <typename IdT>
  38. static constexpr auto KindFor() -> Kind {
  39. return SemIR::IdKind::For<IdT>;
  40. }
  41. private:
  42. decltype(AnyIdBase::index) index;
  43. };
  44. // The stack of parse nodes representing the current state of a Check::Context.
  45. // Each parse node can have an associated id of some kind (instruction,
  46. // instruction block, function, class, ...).
  47. //
  48. // All pushes and pops will be vlogged.
  49. //
  50. // Pop APIs will run basic verification:
  51. //
  52. // - If receiving a Parse::NodeKind, verify that the node_id being popped has
  53. // that kind. Similarly, if receiving a Parse::NodeCategory, make sure the
  54. // of the popped node_id overlaps that category.
  55. // - Validates the kind of id data in the node based on the kind or category of
  56. // the node_id.
  57. //
  58. // These should be assumed API constraints unless otherwise mentioned on a
  59. // method. The main exception is PopAndIgnore, which doesn't do verification.
  60. class NodeStack {
  61. public:
  62. explicit NodeStack(const Parse::Tree& parse_tree,
  63. llvm::raw_ostream* vlog_stream)
  64. : parse_tree_(&parse_tree), vlog_stream_(vlog_stream) {}
  65. // Pushes a solo parse tree node onto the stack. Used when there is no
  66. // IR generated by the node.
  67. auto Push(Parse::NodeId node_id) -> void {
  68. auto kind = parse_tree_->node_kind(node_id);
  69. CARBON_CHECK(NodeKindToIdKind(kind) == Id::Kind::None,
  70. "Parse kind expects an Id: {0}", kind);
  71. CARBON_VLOG("Node Push {0}: {1} -> <none>\n", stack_.size(), kind);
  72. CARBON_CHECK(stack_.size() < (1 << 20),
  73. "Excessive stack size: likely infinite loop");
  74. stack_.push_back({.node_id = node_id, .id = Id()});
  75. }
  76. // Pushes a parse tree node onto the stack with an ID.
  77. template <typename IdT>
  78. auto Push(Parse::NodeId node_id, IdT id) -> void {
  79. auto kind = parse_tree_->node_kind(node_id);
  80. CARBON_CHECK(NodeKindToIdKind(kind) == Id::KindFor<IdT>(),
  81. "Parse kind expected a different IdT: {0} -> {1}\n", kind, id);
  82. CARBON_CHECK(id.has_value(), "Push called with `None` id: {0}",
  83. parse_tree_->node_kind(node_id));
  84. CARBON_VLOG("Node Push {0}: {1} -> {2}\n", stack_.size(), kind, id);
  85. CARBON_CHECK(stack_.size() < (1 << 20),
  86. "Excessive stack size: likely infinite loop");
  87. stack_.push_back({.node_id = node_id, .id = Id(id)});
  88. }
  89. // TODO: Most parse nodes don't know about TypeInstId, so downgrade TypeInstId
  90. // to InstId to match expectations. We should teach parse nodes that will
  91. // receive a TypeInstId to expect it, and this function can go away.
  92. auto Push(Parse::NodeId node_id, SemIR::TypeInstId id) -> void {
  93. auto kind = parse_tree_->node_kind(node_id);
  94. if (NodeKindToIdKind(kind) == Id::KindFor<SemIR::InstId>()) {
  95. Push<SemIR::InstId>(node_id, id);
  96. } else {
  97. Push<SemIR::TypeInstId>(node_id, id);
  98. }
  99. }
  100. // Returns whether there is a node of the specified kind on top of the stack.
  101. auto PeekIs(Parse::NodeKind kind) const -> bool {
  102. return !stack_.empty() && PeekNodeKind() == kind;
  103. }
  104. // Returns whether the node on the top of the stack has an overlapping
  105. // category.
  106. auto PeekIs(Parse::NodeCategory category) const -> bool {
  107. return !stack_.empty() && PeekNodeKind().category().HasAnyOf(category);
  108. }
  109. // Returns whether there is a node with the corresponding ID on top of the
  110. // stack.
  111. template <typename IdT>
  112. auto PeekIs() const -> bool {
  113. return !stack_.empty() &&
  114. NodeKindToIdKind(PeekNodeKind()) == Id::KindFor<IdT>();
  115. }
  116. // Returns whether the *next* node on the stack is a given kind. This doesn't
  117. // have the breadth of support versus other Peek functions because it's
  118. // expected to be used in narrow circumstances when determining how to treat
  119. // the *current* top of the stack.
  120. auto PeekNextIs(Parse::NodeKind kind) const -> bool {
  121. CARBON_CHECK(stack_.size() >= 2);
  122. return parse_tree_->node_kind(stack_[stack_.size() - 2].node_id) == kind;
  123. }
  124. // Pops the top of the stack without any verification.
  125. auto PopAndIgnore() -> void {
  126. Entry back = stack_.pop_back_val();
  127. CARBON_VLOG("Node Pop {0}: {1} -> <ignored>\n", stack_.size(),
  128. parse_tree_->node_kind(back.node_id));
  129. }
  130. // Pops the top of the stack and returns the node_id.
  131. template <const Parse::NodeKind& RequiredParseKind>
  132. auto PopForSoloNodeId() -> Parse::NodeIdForKind<RequiredParseKind> {
  133. Entry back = PopEntry<SemIR::InstId>();
  134. RequireIdKind(RequiredParseKind, Id::Kind::None);
  135. return parse_tree_->As<Parse::NodeIdForKind<RequiredParseKind>>(
  136. back.node_id);
  137. }
  138. // Pops the top of the stack if it is the given kind, and returns the
  139. // node_id. Otherwise, returns std::nullopt.
  140. template <const Parse::NodeKind& RequiredParseKind>
  141. auto PopForSoloNodeIdIf()
  142. -> std::optional<Parse::NodeIdForKind<RequiredParseKind>> {
  143. if (PeekIs(RequiredParseKind)) {
  144. return PopForSoloNodeId<RequiredParseKind>();
  145. }
  146. return std::nullopt;
  147. }
  148. // Pops the top of the stack.
  149. template <const Parse::NodeKind& RequiredParseKind>
  150. auto PopAndDiscardSoloNodeId() -> void {
  151. PopForSoloNodeId<RequiredParseKind>();
  152. }
  153. // Pops the top of the stack if it is the given kind. Returns `true` if a node
  154. // was popped.
  155. template <const Parse::NodeKind& RequiredParseKind>
  156. auto PopAndDiscardSoloNodeIdIf() -> bool {
  157. if (!PeekIs(RequiredParseKind)) {
  158. return false;
  159. }
  160. PopForSoloNodeId<RequiredParseKind>();
  161. return true;
  162. }
  163. // Pops an expression from the top of the stack and returns the node_id and
  164. // the ID.
  165. auto PopExprWithNodeId() -> std::pair<Parse::AnyExprId, SemIR::InstId>;
  166. // Pops a pattern from the top of the stack and returns the node_id and
  167. // the ID.
  168. auto PopPatternWithNodeId() -> std::pair<Parse::NodeId, SemIR::InstId> {
  169. return PopWithNodeId<SemIR::InstId>();
  170. }
  171. // Pops a name from the top of the stack and returns the node_id and
  172. // the ID.
  173. auto PopNameWithNodeId() -> std::pair<Parse::NodeId, SemIR::NameId> {
  174. return PopWithNodeId<SemIR::NameId>();
  175. }
  176. // Pops the top of the stack and returns the node_id and the ID.
  177. template <const Parse::NodeKind& RequiredParseKind>
  178. auto PopWithNodeId() -> auto {
  179. auto id = Peek<RequiredParseKind>();
  180. auto node_id = parse_tree_->As<Parse::NodeIdForKind<RequiredParseKind>>(
  181. stack_.pop_back_val().node_id);
  182. return std::make_pair(node_id, id);
  183. }
  184. // Pops the top of the stack and returns the node_id and the ID.
  185. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  186. auto PopWithNodeId() -> auto {
  187. auto id = Peek<RequiredParseCategory>();
  188. auto node_id =
  189. parse_tree_->As<Parse::NodeIdInCategory<RequiredParseCategory>>(
  190. stack_.pop_back_val().node_id);
  191. return std::make_pair(node_id, id);
  192. }
  193. // Pops an expression from the top of the stack and returns the ID.
  194. // Expressions always map Parse::NodeCategory::Expr nodes to SemIR::InstId.
  195. auto PopExpr() -> SemIR::InstId { return PopExprWithNodeId().second; }
  196. // Pops a pattern from the top of the stack and returns the ID.
  197. // Patterns map multiple Parse::NodeKinds to SemIR::InstId always.
  198. // TODO: TuplePatterns store an InstBlockId instead and must be dealt with as
  199. // a special case before calling this function.
  200. auto PopPattern() -> SemIR::InstId { return PopPatternWithNodeId().second; }
  201. // Pops a name from the top of the stack and returns the ID.
  202. auto PopName() -> SemIR::NameId { return PopNameWithNodeId().second; }
  203. // Pops the top of the stack and returns the ID.
  204. template <const Parse::NodeKind& RequiredParseKind>
  205. auto Pop() -> auto {
  206. return PopWithNodeId<RequiredParseKind>().second;
  207. }
  208. // Pops the top of the stack and returns the ID.
  209. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  210. auto Pop() -> auto {
  211. return PopWithNodeId<RequiredParseCategory>().second;
  212. }
  213. // Pops the top of the stack and returns the ID.
  214. template <typename IdT>
  215. auto Pop() -> IdT {
  216. return PopWithNodeId<IdT>().second;
  217. }
  218. // Pops the top of the stack if it has the given kind, and returns the ID.
  219. // Otherwise returns std::nullopt.
  220. template <const Parse::NodeKind& RequiredParseKind>
  221. auto PopIf() -> std::optional<decltype(Pop<RequiredParseKind>())> {
  222. if (PeekIs(RequiredParseKind)) {
  223. return Pop<RequiredParseKind>();
  224. }
  225. return std::nullopt;
  226. }
  227. // Pops the top of the stack if it has the given category, and returns the ID.
  228. // Otherwise returns std::nullopt.
  229. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  230. auto PopIf() -> std::optional<decltype(Pop<RequiredParseCategory>())> {
  231. if (PeekIs(RequiredParseCategory)) {
  232. return Pop<RequiredParseCategory>();
  233. }
  234. return std::nullopt;
  235. }
  236. // Pops the top of the stack if it has the given category, and returns the ID.
  237. // Otherwise returns std::nullopt.
  238. template <typename IdT>
  239. auto PopIf() -> std::optional<IdT> {
  240. if (PeekIs<IdT>()) {
  241. return Pop<IdT>();
  242. }
  243. return std::nullopt;
  244. }
  245. // Pops the top of the stack and returns the node_id and the ID if it is
  246. // of the specified kind.
  247. template <const Parse::NodeKind& RequiredParseKind>
  248. auto PopWithNodeIdIf() -> std::pair<Parse::NodeIdForKind<RequiredParseKind>,
  249. decltype(PopIf<RequiredParseKind>())> {
  250. if (!PeekIs(RequiredParseKind)) {
  251. return {Parse::NodeId::None, std::nullopt};
  252. }
  253. return PopWithNodeId<RequiredParseKind>();
  254. }
  255. // Pops the top of the stack and returns the node_id and the ID if it is
  256. // of the specified category.
  257. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  258. auto PopWithNodeIdIf()
  259. -> std::pair<Parse::NodeIdInCategory<RequiredParseCategory>,
  260. decltype(PopIf<RequiredParseCategory>())> {
  261. if (!PeekIs(RequiredParseCategory)) {
  262. return {Parse::NodeId::None, std::nullopt};
  263. }
  264. return PopWithNodeId<RequiredParseCategory>();
  265. }
  266. // Peeks at the parse node of the top of the node stack.
  267. auto PeekNodeId() const -> Parse::NodeId { return stack_.back().node_id; }
  268. // Peeks at the kind of the parse node of the top of the node stack.
  269. auto PeekNodeKind() const -> Parse::NodeKind {
  270. return parse_tree_->node_kind(PeekNodeId());
  271. }
  272. // Peeks at the ID associated with the top of the name stack.
  273. template <const Parse::NodeKind& RequiredParseKind>
  274. auto Peek() const -> auto {
  275. Entry back = stack_.back();
  276. CARBON_CHECK(RequiredParseKind == parse_tree_->node_kind(back.node_id),
  277. "Expected {0}, found {1}", RequiredParseKind,
  278. parse_tree_->node_kind(back.node_id));
  279. constexpr Id::Kind RequiredIdKind = NodeKindToIdKind(RequiredParseKind);
  280. return Peek<RequiredIdKind>();
  281. }
  282. // Peeks at the ID associated with the top of the name stack.
  283. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  284. auto Peek() const -> auto {
  285. Entry back = stack_.back();
  286. RequireParseCategory<RequiredParseCategory>(back.node_id);
  287. constexpr std::optional<Id::Kind> RequiredIdKind =
  288. NodeCategoryToIdKind(RequiredParseCategory, false);
  289. static_assert(RequiredIdKind.has_value());
  290. return Peek<*RequiredIdKind>();
  291. }
  292. // Peeks at the ID associated with the pattern at the top of the stack.
  293. // Patterns map multiple Parse::NodeKinds to SemIR::InstId always.
  294. // TODO: TuplePatterns store an InstBlockId instead and must be dealt with as
  295. // a special case before calling this function.
  296. auto PeekPattern() const -> SemIR::InstId;
  297. // Prints the stack for a stack dump.
  298. auto PrintForStackDump(int indent, llvm::raw_ostream& output) const -> void;
  299. auto empty() const -> bool { return stack_.empty(); }
  300. auto size() const -> size_t { return stack_.size(); }
  301. private:
  302. // An ID that can be associated with a parse node.
  303. //
  304. // Each parse node kind has a corresponding Id::Kind indicating which kind of
  305. // ID is stored, computed by NodeKindToIdKind. Id::Kind::None indicates
  306. // that the parse node has no associated ID, in which case the *SoloNodeId
  307. // functions should be used to push and pop it. Id::Kind::Invalid indicates
  308. // that the parse node should not appear in the node stack at all.
  309. using Id = IdUnion;
  310. // An entry in stack_.
  311. struct Entry {
  312. // The parse node associated with the stack entry.
  313. Parse::NodeId node_id;
  314. // The ID associated with this parse node. The kind of ID is determined by
  315. // the kind of the parse node, so a separate discriminiator is not needed.
  316. Id id;
  317. };
  318. static_assert(sizeof(Entry) == 8, "Unexpected Entry size");
  319. // Translate a parse node category to the enum ID kind it should always
  320. // provide, if it is consistent.
  321. static constexpr auto NodeCategoryToIdKind(Parse::NodeCategory category,
  322. bool for_node_kind)
  323. -> std::optional<Id::Kind> {
  324. std::optional<Id::Kind> result;
  325. auto set_id_if_category_is = [&](Parse::NodeCategory cat, Id::Kind kind) {
  326. if (category.HasAnyOf(cat)) {
  327. // Check for no consistent Id::Kind due to category with multiple bits
  328. // set. When computing the Id::Kind for a node kind, a partial category
  329. // match is OK, so long as we don't match two inconsistent categories.
  330. // When computing the Id::Kind for a category query, the query can't
  331. // have any extra bits set or we could be popping a node that is not in
  332. // this category.
  333. if (for_node_kind ? result.has_value() : category.HasAnyOf(~cat)) {
  334. result = Id::Kind::Invalid;
  335. } else {
  336. result = kind;
  337. }
  338. }
  339. };
  340. set_id_if_category_is(Parse::NodeCategory::Pattern,
  341. Id::KindFor<SemIR::InstId>());
  342. set_id_if_category_is(Parse::NodeCategory::Expr,
  343. Id::KindFor<SemIR::InstId>());
  344. set_id_if_category_is(
  345. Parse::NodeCategory::MemberName | Parse::NodeCategory::NonExprName,
  346. Id::KindFor<SemIR::NameId>());
  347. set_id_if_category_is(Parse::NodeCategory::ImplAs,
  348. Id::KindFor<SemIR::TypeInstId>());
  349. set_id_if_category_is(Parse::NodeCategory::Decl |
  350. Parse::NodeCategory::Statement |
  351. Parse::NodeCategory::Modifier,
  352. Id::Kind::None);
  353. return result;
  354. }
  355. // Translate a parse node kind to the enum ID kind it should always
  356. // provide, for the cases where this is not known from the category.
  357. static constexpr auto NodeKindToIdKindSpecialCases(Parse::NodeKind node_kind)
  358. -> std::optional<Id::Kind> {
  359. switch (node_kind) {
  360. case Parse::NodeKind::CallExprStart:
  361. case Parse::NodeKind::FieldNameAndType:
  362. case Parse::NodeKind::IfExprThen:
  363. case Parse::NodeKind::ReturnType:
  364. case Parse::NodeKind::ShortCircuitOperandAnd:
  365. case Parse::NodeKind::ShortCircuitOperandOr:
  366. case Parse::NodeKind::StructLiteralField:
  367. case Parse::NodeKind::WhereOperand:
  368. return Id::KindFor<SemIR::InstId>();
  369. case Parse::NodeKind::ExplicitParamList:
  370. case Parse::NodeKind::ForIn:
  371. case Parse::NodeKind::IfCondition:
  372. case Parse::NodeKind::IfExprIf:
  373. case Parse::NodeKind::ImplicitParamList:
  374. case Parse::NodeKind::WhileConditionStart:
  375. return Id::KindFor<SemIR::InstBlockId>();
  376. case Parse::NodeKind::FunctionDefinitionStart:
  377. case Parse::NodeKind::BuiltinFunctionDefinitionStart:
  378. return Id::KindFor<SemIR::FunctionId>();
  379. case Parse::NodeKind::ChoiceDefinitionStart:
  380. // TODO: Should we have a separate SemIR::ChoiceId?
  381. case Parse::NodeKind::ClassDefinitionStart:
  382. return Id::KindFor<SemIR::ClassId>();
  383. case Parse::NodeKind::InterfaceDefinitionStart:
  384. return Id::KindFor<SemIR::InterfaceId>();
  385. case Parse::NodeKind::ImplDefinitionStart:
  386. return Id::KindFor<SemIR::ImplId>();
  387. case Parse::NodeKind::SelfTypeName:
  388. case Parse::NodeKind::SelfValueName:
  389. return Id::KindFor<SemIR::NameId>();
  390. case Parse::NodeKind::DefaultLibrary:
  391. case Parse::NodeKind::LibraryName:
  392. return Id::KindFor<SemIR::LibraryNameId>();
  393. case Parse::NodeKind::BuiltinName:
  394. case Parse::NodeKind::ChoiceIntroducer:
  395. case Parse::NodeKind::ClassIntroducer:
  396. case Parse::NodeKind::CodeBlockStart:
  397. case Parse::NodeKind::ExplicitParamListStart:
  398. case Parse::NodeKind::FieldInitializer:
  399. case Parse::NodeKind::FieldIntroducer:
  400. case Parse::NodeKind::ForHeaderStart:
  401. case Parse::NodeKind::FunctionIntroducer:
  402. case Parse::NodeKind::IfStatementElse:
  403. case Parse::NodeKind::ImplicitParamListStart:
  404. case Parse::NodeKind::ImplIntroducer:
  405. case Parse::NodeKind::InterfaceIntroducer:
  406. case Parse::NodeKind::LetInitializer:
  407. case Parse::NodeKind::LetIntroducer:
  408. case Parse::NodeKind::AssociatedConstantIntroducer:
  409. case Parse::NodeKind::AssociatedConstantInitializer:
  410. case Parse::NodeKind::ReturnStatementStart:
  411. case Parse::NodeKind::StructLiteralStart:
  412. case Parse::NodeKind::StructTypeLiteralField:
  413. case Parse::NodeKind::StructTypeLiteralStart:
  414. case Parse::NodeKind::TemplateBindingName:
  415. case Parse::NodeKind::TupleLiteralStart:
  416. case Parse::NodeKind::TuplePatternStart:
  417. case Parse::NodeKind::VariableInitializer:
  418. case Parse::NodeKind::VariableIntroducer:
  419. return Id::Kind::None;
  420. case Parse::NodeKind::AdaptIntroducer:
  421. case Parse::NodeKind::AliasInitializer:
  422. case Parse::NodeKind::AliasIntroducer:
  423. case Parse::NodeKind::ArrayExprComma:
  424. case Parse::NodeKind::ArrayExprKeyword:
  425. case Parse::NodeKind::ArrayExprOpenParen:
  426. case Parse::NodeKind::BaseColon:
  427. case Parse::NodeKind::BaseIntroducer:
  428. case Parse::NodeKind::BreakStatementStart:
  429. case Parse::NodeKind::CallExprComma:
  430. case Parse::NodeKind::ChoiceAlternativeListComma:
  431. case Parse::NodeKind::CodeBlock:
  432. case Parse::NodeKind::CompileTimeBindingPatternStart:
  433. case Parse::NodeKind::ContinueStatementStart:
  434. case Parse::NodeKind::CorePackageName:
  435. case Parse::NodeKind::ExportIntroducer:
  436. case Parse::NodeKind::FileEnd:
  437. case Parse::NodeKind::FileStart:
  438. case Parse::NodeKind::ForHeader:
  439. case Parse::NodeKind::Forall:
  440. case Parse::NodeKind::IdentifierNameQualifierWithParams:
  441. case Parse::NodeKind::IdentifierNameQualifierWithoutParams:
  442. case Parse::NodeKind::IdentifierPackageName:
  443. case Parse::NodeKind::IfConditionStart:
  444. case Parse::NodeKind::ImportIntroducer:
  445. case Parse::NodeKind::IndexExprStart:
  446. case Parse::NodeKind::InvalidParseStart:
  447. case Parse::NodeKind::LibraryIntroducer:
  448. case Parse::NodeKind::LibrarySpecifier:
  449. case Parse::NodeKind::InlineImportSpecifier:
  450. case Parse::NodeKind::InlineImportBody:
  451. case Parse::NodeKind::MatchCase:
  452. case Parse::NodeKind::MatchCaseEqualGreater:
  453. case Parse::NodeKind::MatchCaseGuard:
  454. case Parse::NodeKind::MatchCaseGuardIntroducer:
  455. case Parse::NodeKind::MatchCaseGuardStart:
  456. case Parse::NodeKind::MatchCaseIntroducer:
  457. case Parse::NodeKind::MatchCaseStart:
  458. case Parse::NodeKind::MatchCondition:
  459. case Parse::NodeKind::MatchConditionStart:
  460. case Parse::NodeKind::MatchDefault:
  461. case Parse::NodeKind::MatchDefaultEqualGreater:
  462. case Parse::NodeKind::MatchDefaultIntroducer:
  463. case Parse::NodeKind::MatchDefaultStart:
  464. case Parse::NodeKind::MatchIntroducer:
  465. case Parse::NodeKind::MatchStatementStart:
  466. case Parse::NodeKind::NamedConstraintDefinitionStart:
  467. case Parse::NodeKind::NamedConstraintIntroducer:
  468. case Parse::NodeKind::NamespaceStart:
  469. case Parse::NodeKind::PackageIntroducer:
  470. case Parse::NodeKind::ParenExprStart:
  471. case Parse::NodeKind::PatternListComma:
  472. case Parse::NodeKind::Placeholder:
  473. case Parse::NodeKind::RequirementAnd:
  474. case Parse::NodeKind::RequirementEqual:
  475. case Parse::NodeKind::RequirementEqualEqual:
  476. case Parse::NodeKind::RequirementImpls:
  477. case Parse::NodeKind::StructLiteralComma:
  478. case Parse::NodeKind::StructFieldDesignator:
  479. case Parse::NodeKind::StructTypeLiteralComma:
  480. case Parse::NodeKind::TupleLiteralComma:
  481. case Parse::NodeKind::WhileCondition:
  482. return Id::Kind::Invalid;
  483. default:
  484. // In this case, the kind must be determinable from the category, or we
  485. // will produce a build error.
  486. return std::nullopt;
  487. }
  488. }
  489. using IdKindTableType = std::array<Id::Kind, Parse::NodeKind::ValidCount>;
  490. // Lookup table to implement `NodeKindToIdKind`. Initialized to the
  491. // return value of `ComputeIdKindTable()`.
  492. static const IdKindTableType IdKindTable;
  493. static consteval auto ComputeIdKindTable() -> IdKindTableType {
  494. IdKindTableType table = {};
  495. auto to_id_kind =
  496. [](const Parse::NodeKind::Definition& node_kind) -> Id::Kind {
  497. if (auto from_category =
  498. NodeCategoryToIdKind(node_kind.category(), true)) {
  499. return *from_category;
  500. }
  501. // Assume any node kind that doesn't have an ID kind from its category nor
  502. // a special case can't appear on the stack just so we can build a table
  503. // and avoid follow-on errors. We'll enforce at compile time that a value
  504. // is actually specified in CheckIdKindTable.
  505. return NodeKindToIdKindSpecialCases(node_kind).value_or(
  506. Id::Kind::Invalid);
  507. };
  508. #define CARBON_PARSE_NODE_KIND(Name) \
  509. table[Parse::Name::Kind.AsInt()] = to_id_kind(Parse::Name::Kind);
  510. #include "toolchain/parse/node_kind.def"
  511. return table;
  512. }
  513. // Check that an Id::Kind is specified for every node kind.
  514. static auto CheckIdKindTable() -> void;
  515. // Translate a parse node kind to the enum ID kind it should always provide.
  516. static constexpr auto NodeKindToIdKind(Parse::NodeKind kind) -> Id::Kind {
  517. return IdKindTable[kind.AsInt()];
  518. }
  519. // Peeks at the ID associated with the top of the name stack.
  520. template <Id::Kind RequiredIdKind>
  521. auto Peek() const -> auto {
  522. Id id = stack_.back().id;
  523. return id.As<RequiredIdKind>();
  524. }
  525. // Pops an entry.
  526. template <typename IdT>
  527. auto PopEntry() -> Entry {
  528. Entry back = stack_.pop_back_val();
  529. CARBON_VLOG("Node Pop {0}: {1} -> {2}\n", stack_.size(),
  530. parse_tree_->node_kind(back.node_id),
  531. back.id.template As<IdT>());
  532. return back;
  533. }
  534. // Pops the top of the stack and returns the node_id and the ID.
  535. template <typename IdT>
  536. auto PopWithNodeId() -> std::pair<Parse::NodeId, IdT> {
  537. Entry back = PopEntry<IdT>();
  538. RequireIdKind(parse_tree_->node_kind(back.node_id), Id::KindFor<IdT>());
  539. return {back.node_id, back.id.template As<IdT>()};
  540. }
  541. // Require a Parse::NodeKind be mapped to a particular Id::Kind.
  542. auto RequireIdKind(Parse::NodeKind parse_kind, Id::Kind id_kind) const
  543. -> void {
  544. CARBON_CHECK(NodeKindToIdKind(parse_kind) == id_kind,
  545. "Unexpected Id::Kind mapping for {0}: expected {1}, found {2}",
  546. parse_kind, SemIR::IdKind(id_kind),
  547. SemIR::IdKind(NodeKindToIdKind(parse_kind)));
  548. }
  549. // Require an entry to have the given Parse::NodeCategory.
  550. template <Parse::NodeCategory::RawEnumType RequiredParseCategory>
  551. auto RequireParseCategory(Parse::NodeId node_id) const -> void {
  552. auto kind = parse_tree_->node_kind(node_id);
  553. CARBON_CHECK(kind.category().HasAnyOf(RequiredParseCategory),
  554. "Expected {0}, found {1} with category {2}",
  555. RequiredParseCategory, kind, kind.category());
  556. }
  557. // The file's parse tree.
  558. const Parse::Tree* parse_tree_;
  559. // Whether to print verbose output.
  560. llvm::raw_ostream* vlog_stream_;
  561. // The actual stack.
  562. // PushEntry and PopEntry control modification in order to centralize
  563. // vlogging.
  564. llvm::SmallVector<Entry> stack_;
  565. };
  566. constexpr NodeStack::IdKindTableType NodeStack::IdKindTable =
  567. ComputeIdKindTable();
  568. inline auto NodeStack::PopExprWithNodeId()
  569. -> std::pair<Parse::AnyExprId, SemIR::InstId> {
  570. return PopWithNodeId<Parse::NodeCategory::Expr>();
  571. }
  572. inline auto NodeStack::PeekPattern() const -> SemIR::InstId {
  573. return Peek<Id::KindFor<SemIR::InstId>()>();
  574. }
  575. } // namespace Carbon::Check
  576. #endif // CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_