| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- // Exceptions. See /LICENSE for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- #ifndef CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_STACK_H_
- #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_STACK_H_
- #include <type_traits>
- #include "llvm/ADT/SmallVector.h"
- #include "toolchain/parser/parse_node_kind.h"
- #include "toolchain/parser/parse_tree.h"
- #include "toolchain/semantics/semantics_node.h"
- namespace Carbon {
- // Wraps the stack of nodes for SemanticsParseTreeHandler.
- //
- // All pushes and pops will be vlogged.
- //
- // Pop APIs will run basic verification:
- //
- // - If receiving a pop_parse_kind, verify that the parse_node being popped is
- // of pop_parse_kind.
- // - Validates presence of node_id based on whether it's a solo
- // parse_node.
- //
- // These should be assumed API constraints unless otherwise mentioned on a
- // method. The main exception is PopAndIgnore, which doesn't do verification.
- class SemanticsNodeStack {
- public:
- SemanticsNodeStack(const ParseTree& parse_tree,
- llvm::raw_ostream* vlog_stream)
- : parse_tree_(&parse_tree), vlog_stream_(vlog_stream) {}
- // Pushes a solo parse tree node onto the stack. Used when there is no
- // IR generated by the node.
- auto Push(ParseTree::Node parse_node) -> void {
- PushEntry(
- {.parse_node = parse_node, .node_id = SemanticsNodeId::MakeInvalid()},
- DebugLog::None);
- }
- // Pushes a parse tree node onto the stack.
- auto Push(ParseTree::Node parse_node, SemanticsNodeId node_id) -> void {
- PushEntry({.parse_node = parse_node, .node_id = node_id}, DebugLog::NodeId);
- }
- // Pushes a PatternBinding parse tree node onto the stack with its name.
- auto Push(ParseTree::Node parse_node, SemanticsStringId name_id) -> void {
- CARBON_CHECK(parse_tree_->node_kind(parse_node) ==
- ParseNodeKind::PatternBinding);
- PushEntry({.parse_node = parse_node, .name_id = name_id}, DebugLog::NameId);
- }
- // Pops the top of the stack without any verification.
- auto PopAndIgnore() -> void { PopEntry(); }
- // Pops the top of the stack.
- auto PopAndDiscardSoloParseNode(ParseNodeKind pop_parse_kind) -> void;
- // Pops the top of the stack, and discards the ID.
- auto PopAndDiscardId() -> void;
- // Pops the top of the stack, and discards the ID.
- auto PopAndDiscardId(ParseNodeKind pop_parse_kind) -> void;
- // Pops the top of the stack and returns the parse_node.
- auto PopForSoloParseNode() -> ParseTree::Node;
- // Pops the top of the stack and returns the parse_node.
- auto PopForSoloParseNode(ParseNodeKind pop_parse_kind) -> ParseTree::Node;
- // Pops the top of the stack and returns the node_id.
- auto PopForNodeId(ParseNodeKind pop_parse_kind) -> SemanticsNodeId;
- // Pops the top of the stack and returns the parse_node and node_id.
- auto PopForParseNodeAndNodeId()
- -> std::pair<ParseTree::Node, SemanticsNodeId>;
- // Pops the top of the stack and returns the parse_node and node_id.
- auto PopForParseNodeAndNodeId(ParseNodeKind pop_parse_kind)
- -> std::pair<ParseTree::Node, SemanticsNodeId>;
- // Pops the top of the stack and returns the node_id.
- auto PopForNodeId() -> SemanticsNodeId;
- // Pops the top of the stack and returns the parse_node and name_id.
- // Verifies that the parse_node is a PatternBinding.
- auto PopForParseNodeAndNameId()
- -> std::pair<ParseTree::Node, SemanticsStringId>;
- // Peeks at the parse_node of the top of the stack.
- auto PeekParseNode() -> ParseTree::Node { return stack_.back().parse_node; }
- // Peeks at the name_id of the top of the stack.
- // Verifies that the parse_node is a PatternBinding.
- auto PeekForNameId() -> SemanticsStringId;
- // Prints the stack for a stack dump.
- auto PrintForStackDump(llvm::raw_ostream& output) const -> void;
- private:
- // An entry in stack_.
- struct Entry {
- // The node associated with the stack entry.
- ParseTree::Node parse_node;
- // The entries will evaluate as invalid if and only if they're a solo
- // parse_node. Invalid is used instead of optional to save space.
- //
- // A discriminator isn't needed because the caller can determine which field
- // is used based on the ParseNodeKind.
- union {
- SemanticsNodeId node_id;
- // Right now name_id is exclusively for PatternBinding, which is enforced.
- SemanticsStringId name_id;
- };
- };
- static_assert(sizeof(Entry) == 8, "Unexpected Entry size");
- // Which Entry union member to log.
- enum DebugLog {
- None,
- NodeId,
- NameId,
- };
- // Pushes an entry onto the stack.
- auto PushEntry(Entry entry, DebugLog debug_log) -> void;
- // Pops an entry.
- auto PopEntry() -> Entry;
- // Pops an entry, requiring the specific kind.
- auto PopEntry(ParseNodeKind pop_parse_kind) -> Entry;
- // Require an entry to have the given ParseNodeKind.
- auto RequireParseKind(Entry entry, ParseNodeKind require_kind) -> void;
- // Requires an entry to have a invalid node_id.
- auto RequireSoloParseNode(Entry entry) -> void;
- // Requires an entry to have a valid id.
- auto RequireValidId(Entry entry) -> void;
- // The file's parse tree.
- const ParseTree* parse_tree_;
- // Whether to print verbose output.
- llvm::raw_ostream* vlog_stream_;
- // The actual stack.
- // PushEntry and PopEntry control modification in order to centralize
- // vlogging.
- llvm::SmallVector<Entry> stack_;
- };
- } // namespace Carbon
- #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_STACK_H_
|