semantics_node_stack.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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_SEMANTICS_SEMANTICS_NODE_STACK_H_
  5. #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_STACK_H_
  6. #include <type_traits>
  7. #include "llvm/ADT/SmallVector.h"
  8. #include "toolchain/parser/parse_node_kind.h"
  9. #include "toolchain/parser/parse_tree.h"
  10. #include "toolchain/semantics/semantics_node.h"
  11. namespace Carbon {
  12. // Wraps the stack of nodes for SemanticsParseTreeHandler.
  13. //
  14. // All pushes and pops will be vlogged.
  15. //
  16. // Pop APIs will run basic verification:
  17. //
  18. // - If receiving a pop_parse_kind, verify that the parse_node being popped is
  19. // of pop_parse_kind.
  20. // - Validates presence of node_id based on whether it's a solo
  21. // parse_node.
  22. //
  23. // These should be assumed API constraints unless otherwise mentioned on a
  24. // method. The main exception is PopAndIgnore, which doesn't do verification.
  25. class SemanticsNodeStack {
  26. public:
  27. SemanticsNodeStack(const ParseTree& parse_tree,
  28. llvm::raw_ostream* vlog_stream)
  29. : parse_tree_(&parse_tree), vlog_stream_(vlog_stream) {}
  30. // Pushes a solo parse tree node onto the stack. Used when there is no
  31. // IR generated by the node.
  32. auto Push(ParseTree::Node parse_node) -> void {
  33. PushEntry(
  34. {.parse_node = parse_node, .node_id = SemanticsNodeId::MakeInvalid()},
  35. DebugLog::None);
  36. }
  37. // Pushes a parse tree node onto the stack.
  38. auto Push(ParseTree::Node parse_node, SemanticsNodeId node_id) -> void {
  39. PushEntry({.parse_node = parse_node, .node_id = node_id}, DebugLog::NodeId);
  40. }
  41. // Pushes a PatternBinding parse tree node onto the stack with its name.
  42. auto Push(ParseTree::Node parse_node, SemanticsStringId name_id) -> void {
  43. CARBON_CHECK(parse_tree_->node_kind(parse_node) ==
  44. ParseNodeKind::PatternBinding);
  45. PushEntry({.parse_node = parse_node, .name_id = name_id}, DebugLog::NameId);
  46. }
  47. // Pops the top of the stack without any verification.
  48. auto PopAndIgnore() -> void { PopEntry(); }
  49. // Pops the top of the stack.
  50. auto PopAndDiscardSoloParseNode(ParseNodeKind pop_parse_kind) -> void;
  51. // Pops the top of the stack, and discards the ID.
  52. auto PopAndDiscardId() -> void;
  53. // Pops the top of the stack, and discards the ID.
  54. auto PopAndDiscardId(ParseNodeKind pop_parse_kind) -> void;
  55. // Pops the top of the stack and returns the parse_node.
  56. auto PopForSoloParseNode() -> ParseTree::Node;
  57. // Pops the top of the stack and returns the parse_node.
  58. auto PopForSoloParseNode(ParseNodeKind pop_parse_kind) -> ParseTree::Node;
  59. // Pops the top of the stack and returns the node_id.
  60. auto PopForNodeId(ParseNodeKind pop_parse_kind) -> SemanticsNodeId;
  61. // Pops the top of the stack and returns the parse_node and node_id.
  62. auto PopForParseNodeAndNodeId()
  63. -> std::pair<ParseTree::Node, SemanticsNodeId>;
  64. // Pops the top of the stack and returns the parse_node and node_id.
  65. auto PopForParseNodeAndNodeId(ParseNodeKind pop_parse_kind)
  66. -> std::pair<ParseTree::Node, SemanticsNodeId>;
  67. // Pops the top of the stack and returns the node_id.
  68. auto PopForNodeId() -> SemanticsNodeId;
  69. // Pops the top of the stack and returns the parse_node and name_id.
  70. // Verifies that the parse_node is a PatternBinding.
  71. auto PopForParseNodeAndNameId()
  72. -> std::pair<ParseTree::Node, SemanticsStringId>;
  73. // Peeks at the parse_node of the top of the stack.
  74. auto PeekParseNode() -> ParseTree::Node { return stack_.back().parse_node; }
  75. // Peeks at the name_id of the top of the stack.
  76. // Verifies that the parse_node is a PatternBinding.
  77. auto PeekForNameId() -> SemanticsStringId;
  78. // Prints the stack for a stack dump.
  79. auto PrintForStackDump(llvm::raw_ostream& output) const -> void;
  80. auto empty() const -> bool { return stack_.empty(); }
  81. auto size() const -> size_t { return stack_.size(); }
  82. private:
  83. // An entry in stack_.
  84. struct Entry {
  85. // The node associated with the stack entry.
  86. ParseTree::Node parse_node;
  87. // The entries will evaluate as invalid if and only if they're a solo
  88. // parse_node. Invalid is used instead of optional to save space.
  89. //
  90. // A discriminator isn't needed because the caller can determine which field
  91. // is used based on the ParseNodeKind.
  92. union {
  93. SemanticsNodeId node_id;
  94. // Right now name_id is exclusively for PatternBinding, which is enforced.
  95. SemanticsStringId name_id;
  96. };
  97. };
  98. static_assert(sizeof(Entry) == 8, "Unexpected Entry size");
  99. // Which Entry union member to log.
  100. enum DebugLog {
  101. None,
  102. NodeId,
  103. NameId,
  104. };
  105. // Pushes an entry onto the stack.
  106. auto PushEntry(Entry entry, DebugLog debug_log) -> void;
  107. // Pops an entry.
  108. auto PopEntry() -> Entry;
  109. // Pops an entry, requiring the specific kind.
  110. auto PopEntry(ParseNodeKind pop_parse_kind) -> Entry;
  111. // Require an entry to have the given ParseNodeKind.
  112. auto RequireParseKind(Entry entry, ParseNodeKind require_kind) -> void;
  113. // Requires an entry to have a invalid node_id.
  114. auto RequireSoloParseNode(Entry entry) -> void;
  115. // Requires an entry to have a valid id.
  116. auto RequireValidId(Entry entry) -> void;
  117. // The file's parse tree.
  118. const ParseTree* parse_tree_;
  119. // Whether to print verbose output.
  120. llvm::raw_ostream* vlog_stream_;
  121. // The actual stack.
  122. // PushEntry and PopEntry control modification in order to centralize
  123. // vlogging.
  124. llvm::SmallVector<Entry> stack_;
  125. };
  126. } // namespace Carbon
  127. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_STACK_H_