semantics_node_stack.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. #include "toolchain/semantics/semantics_node_stack.h"
  5. #include "common/vlog.h"
  6. #include "toolchain/semantics/semantics_node.h"
  7. namespace Carbon {
  8. auto SemanticsNodeStack::PushEntry(Entry entry, DebugLog debug_log) -> void {
  9. CARBON_VLOG() << "Node Push " << stack_.size() << ": "
  10. << parse_tree_->node_kind(entry.parse_node) << " -> ";
  11. switch (debug_log) {
  12. case DebugLog::None:
  13. CARBON_VLOG() << "<none>";
  14. break;
  15. case DebugLog::NodeId:
  16. CARBON_VLOG() << entry.node_id;
  17. break;
  18. case DebugLog::NodeBlockId:
  19. CARBON_VLOG() << entry.node_block_id;
  20. break;
  21. case DebugLog::NameId:
  22. CARBON_VLOG() << entry.name_id;
  23. break;
  24. case DebugLog::TypeId:
  25. CARBON_VLOG() << entry.type_id;
  26. break;
  27. }
  28. CARBON_VLOG() << "\n";
  29. CARBON_CHECK(stack_.size() < (1 << 20))
  30. << "Excessive stack size: likely infinite loop";
  31. stack_.push_back(entry);
  32. }
  33. auto SemanticsNodeStack::PopEntry() -> Entry {
  34. auto back = stack_.pop_back_val();
  35. CARBON_VLOG() << "Node Pop " << stack_.size() << ": any ("
  36. << parse_tree_->node_kind(back.parse_node) << ") -> "
  37. << back.node_id << "\n";
  38. return back;
  39. }
  40. auto SemanticsNodeStack::PopEntry(ParseNodeKind pop_parse_kind) -> Entry {
  41. auto back = stack_.pop_back_val();
  42. CARBON_VLOG() << "Node Pop " << stack_.size() << ": " << pop_parse_kind
  43. << " -> " << back.node_id << "\n";
  44. RequireParseKind(back, pop_parse_kind);
  45. return back;
  46. }
  47. auto SemanticsNodeStack::RequireParseKind(Entry entry,
  48. ParseNodeKind require_kind) -> void {
  49. auto actual_kind = parse_tree_->node_kind(entry.parse_node);
  50. CARBON_CHECK(require_kind == actual_kind)
  51. << "Expected " << require_kind << ", found " << actual_kind;
  52. }
  53. // RequireSoloParseNode and RequireValidId rely on type punning. They read
  54. // node_id.is_valid, even though that may not be the active union member.
  55. // These asserts enforce standard layout in order to help ensure that works.
  56. // TODO: Use is_layout_compatible in C++20.
  57. static_assert(std::is_standard_layout_v<SemanticsNodeId>,
  58. "Need standard layout for type punning");
  59. static_assert(std::is_standard_layout_v<SemanticsStringId>,
  60. "Need standard layout for type punning");
  61. auto SemanticsNodeStack::RequireSoloParseNode(Entry entry) -> void {
  62. // See above comment on type punning.
  63. CARBON_CHECK(!entry.node_id.is_valid())
  64. << "Expected invalid id on " << parse_tree_->node_kind(entry.parse_node)
  65. << ", was " << entry.node_id << " (may not be node)";
  66. }
  67. auto SemanticsNodeStack::RequireValidId(Entry entry) -> void {
  68. // See above comment on type punning.
  69. CARBON_CHECK(entry.node_id.is_valid())
  70. << "Expected valid id on " << parse_tree_->node_kind(entry.parse_node);
  71. }
  72. auto SemanticsNodeStack::PopAndDiscardId() -> void {
  73. auto back = PopEntry();
  74. RequireValidId(back);
  75. }
  76. auto SemanticsNodeStack::PopAndDiscardId(ParseNodeKind pop_parse_kind) -> void {
  77. auto back = PopEntry(pop_parse_kind);
  78. RequireValidId(back);
  79. }
  80. auto SemanticsNodeStack::PopAndDiscardSoloParseNode(
  81. ParseNodeKind pop_parse_kind) -> void {
  82. auto back = PopEntry(pop_parse_kind);
  83. RequireSoloParseNode(back);
  84. }
  85. auto SemanticsNodeStack::PopForSoloParseNode() -> ParseTree::Node {
  86. auto back = PopEntry();
  87. RequireSoloParseNode(back);
  88. return back.parse_node;
  89. }
  90. auto SemanticsNodeStack::PopForSoloParseNode(ParseNodeKind pop_parse_kind)
  91. -> ParseTree::Node {
  92. auto back = PopEntry(pop_parse_kind);
  93. RequireSoloParseNode(back);
  94. return back.parse_node;
  95. }
  96. auto SemanticsNodeStack::PopForNodeId() -> SemanticsNodeId {
  97. auto back = PopEntry();
  98. RequireValidId(back);
  99. return back.node_id;
  100. }
  101. auto SemanticsNodeStack::PopForNodeId(ParseNodeKind pop_parse_kind)
  102. -> SemanticsNodeId {
  103. auto back = PopEntry(pop_parse_kind);
  104. RequireValidId(back);
  105. return back.node_id;
  106. }
  107. auto SemanticsNodeStack::PopForParseNodeAndNodeId()
  108. -> std::pair<ParseTree::Node, SemanticsNodeId> {
  109. auto back = PopEntry();
  110. RequireValidId(back);
  111. return {back.parse_node, back.node_id};
  112. }
  113. auto SemanticsNodeStack::PopForParseNodeAndNodeId(ParseNodeKind pop_parse_kind)
  114. -> std::pair<ParseTree::Node, SemanticsNodeId> {
  115. auto back = PopEntry(pop_parse_kind);
  116. RequireValidId(back);
  117. return {back.parse_node, back.node_id};
  118. }
  119. auto SemanticsNodeStack::PopForNodeBlockId(ParseNodeKind pop_parse_kind)
  120. -> SemanticsNodeBlockId {
  121. auto back = PopEntry(pop_parse_kind);
  122. RequireValidId(back);
  123. return back.node_block_id;
  124. }
  125. auto SemanticsNodeStack::PopForTypeId(ParseNodeKind pop_parse_kind)
  126. -> SemanticsTypeId {
  127. auto back = PopEntry(pop_parse_kind);
  128. RequireValidId(back);
  129. return back.type_id;
  130. }
  131. auto SemanticsNodeStack::PopForParseNodeAndNameId(ParseNodeKind pop_parse_kind)
  132. -> std::pair<ParseTree::Node, SemanticsStringId> {
  133. auto back = PopEntry(pop_parse_kind);
  134. RequireValidId(back);
  135. return {back.parse_node, back.name_id};
  136. }
  137. auto SemanticsNodeStack::PeekForNameId(ParseNodeKind parse_kind)
  138. -> SemanticsStringId {
  139. auto back = stack_.back();
  140. RequireParseKind(back, parse_kind);
  141. RequireValidId(back);
  142. return back.name_id;
  143. }
  144. auto SemanticsNodeStack::PrintForStackDump(llvm::raw_ostream& output) const
  145. -> void {
  146. output << "SemanticsNodeStack:\n";
  147. for (int i = 0; i < static_cast<int>(stack_.size()); ++i) {
  148. const auto& entry = stack_[i];
  149. auto parse_node_kind = parse_tree_->node_kind(entry.parse_node);
  150. output << "\t" << i << ".\t" << parse_node_kind;
  151. if (parse_node_kind == ParseNodeKind::PatternBinding) {
  152. output << " -> " << entry.name_id;
  153. } else {
  154. if (entry.node_id.is_valid()) {
  155. output << " -> " << entry.node_id;
  156. }
  157. }
  158. output << "\n";
  159. }
  160. }
  161. } // namespace Carbon