Start node stack push/pop setting IdT based on ParseNodeKind. (#2985)

I think there's more we can do here, but this seemed like a good
checkpoint to make sure the path I'm going down is roughly what you
expected. There's one actual edit in if expression structure to match
the increased enforcement.
This commit is contained in:
Jon Ross-Perkins
2023-07-12 23:26:53 +00:00
committed by GitHub
parent c0d18a62eb
commit 9751b4701d
16 changed files with 167 additions and 66 deletions
+116 -15
View File
@@ -37,6 +37,9 @@ class SemanticsNodeStack {
// 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 {
CARBON_CHECK(ParseNodeKindToIdKind(parse_tree_->node_kind(parse_node)) ==
IdKind::Unused)
<< "Parse kind expects an Id: " << parse_tree_->node_kind(parse_node);
CARBON_VLOG() << "Node Push " << stack_.size() << ": "
<< parse_tree_->node_kind(parse_node) << " -> <none>\n";
CARBON_CHECK(stack_.size() < (1 << 20))
@@ -47,6 +50,12 @@ class SemanticsNodeStack {
// Pushes a parse tree node onto the stack with an ID.
template <typename IdT>
auto Push(ParseTree::Node parse_node, IdT id) -> void {
CARBON_CHECK(ParseNodeKindToIdKind(parse_tree_->node_kind(parse_node)) ==
IdTypeToIdKind<IdT>())
<< "Parse kind expected a different IdT: "
<< parse_tree_->node_kind(parse_node) << " -> " << id << "\n";
CARBON_CHECK(id.is_valid()) << "Push called with invalid id: "
<< parse_tree_->node_kind(parse_node);
CARBON_VLOG() << "Node Push " << stack_.size() << ": "
<< parse_tree_->node_kind(parse_node) << " -> " << id << "\n";
CARBON_CHECK(stack_.size() < (1 << 20))
@@ -65,15 +74,17 @@ class SemanticsNodeStack {
}
// Pops the top of the stack and returns the parse_node.
auto PopForSoloParseNode(ParseNodeKind pop_parse_kind) -> ParseTree::Node {
template <ParseNodeKind::RawEnumType PopParseKind>
auto PopForSoloParseNode() -> ParseTree::Node {
auto parse_node = PopForSoloParseNode();
RequireParseKind(parse_node, pop_parse_kind);
RequireParseKind(parse_node, ParseNodeKind::Create(PopParseKind));
return parse_node;
}
// Pops the top of the stack.
auto PopAndDiscardSoloParseNode(ParseNodeKind pop_parse_kind) -> void {
PopForSoloParseNode(pop_parse_kind);
template <ParseNodeKind::RawEnumType PopParseKind>
auto PopAndDiscardSoloParseNode() -> void {
PopForSoloParseNode<PopParseKind>();
}
// Pops the top of the stack and returns the parse_node and the ID.
@@ -85,12 +96,38 @@ class SemanticsNodeStack {
}
// Pops the top of the stack and returns the parse_node and the ID.
template <typename IdT>
auto PopWithParseNode(ParseNodeKind pop_parse_kind)
-> std::pair<ParseTree::Node, IdT> {
auto back = PopWithParseNode<IdT>();
RequireParseKind(back.first, pop_parse_kind);
return back;
template <ParseNodeKind::RawEnumType PopParseKind>
auto PopWithParseNode() -> auto {
if constexpr (ParseNodeKindToIdKind(ParseNodeKind::Create(PopParseKind)) ==
IdKind::SemanticsNodeId) {
auto back = PopWithParseNode<SemanticsNodeId>();
RequireParseKind(back.first, ParseNodeKind::Create(PopParseKind));
return back;
}
if constexpr (ParseNodeKindToIdKind(ParseNodeKind::Create(PopParseKind)) ==
IdKind::SemanticsNodeBlockId) {
auto back = PopWithParseNode<SemanticsNodeBlockId>();
RequireParseKind(back.first, ParseNodeKind::Create(PopParseKind));
return back;
}
if constexpr (ParseNodeKindToIdKind(ParseNodeKind::Create(PopParseKind)) ==
IdKind::SemanticsFunctionId) {
auto back = PopWithParseNode<SemanticsFunctionId>();
RequireParseKind(back.first, ParseNodeKind::Create(PopParseKind));
return back;
}
if constexpr (ParseNodeKindToIdKind(ParseNodeKind::Create(PopParseKind)) ==
IdKind::SemanticsStringId) {
auto back = PopWithParseNode<SemanticsStringId>();
RequireParseKind(back.first, ParseNodeKind::Create(PopParseKind));
return back;
}
if constexpr (ParseNodeKindToIdKind(ParseNodeKind::Create(PopParseKind)) ==
IdKind::SemanticsTypeId) {
auto back = PopWithParseNode<SemanticsTypeId>();
RequireParseKind(back.first, ParseNodeKind::Create(PopParseKind));
return back;
}
}
// Pops the top of the stack and returns the ID.
@@ -100,17 +137,18 @@ class SemanticsNodeStack {
}
// Pops the top of the stack and returns the ID.
template <typename IdT>
auto Pop(ParseNodeKind pop_parse_kind) -> IdT {
return PopWithParseNode<IdT>(pop_parse_kind).second;
template <ParseNodeKind::RawEnumType PopParseKind>
auto Pop() -> auto {
return PopWithParseNode<PopParseKind>().second;
}
// Pops the top of the stack, and discards the ID.
auto PopAndDiscardId() -> void { PopWithParseNode<SemanticsNodeId>(); }
// Pops the top of the stack, and discards the ID.
auto PopAndDiscardId(ParseNodeKind pop_parse_kind) -> void {
PopWithParseNode<SemanticsNodeId>(pop_parse_kind);
template <ParseNodeKind::RawEnumType PopParseKind>
auto PopAndDiscardId() -> void {
PopWithParseNode<PopParseKind>();
}
// Peeks at the parse_node of the top of the stack.
@@ -132,6 +170,15 @@ class SemanticsNodeStack {
auto size() const -> size_t { return stack_.size(); }
private:
enum class IdKind {
SemanticsNodeId,
SemanticsNodeBlockId,
SemanticsFunctionId,
SemanticsStringId,
SemanticsTypeId,
Unused,
};
// An entry in stack_.
struct Entry {
explicit Entry(ParseTree::Node parse_node, SemanticsNodeId node_id)
@@ -199,6 +246,60 @@ class SemanticsNodeStack {
};
static_assert(sizeof(Entry) == 8, "Unexpected Entry size");
// Translate a parse node kind to the enum ID kind it should always provide.
static constexpr auto ParseNodeKindToIdKind(ParseNodeKind kind) -> IdKind {
switch (kind) {
case Carbon::ParseNodeKind::CallExpression:
case Carbon::ParseNodeKind::CallExpressionStart:
case Carbon::ParseNodeKind::IfExpressionElse:
case Carbon::ParseNodeKind::InfixOperator:
case Carbon::ParseNodeKind::Literal:
case Carbon::ParseNodeKind::MemberAccessExpression:
case Carbon::ParseNodeKind::NameExpression:
case Carbon::ParseNodeKind::ParenExpression:
case Carbon::ParseNodeKind::PatternBinding:
case Carbon::ParseNodeKind::PrefixOperator:
case Carbon::ParseNodeKind::ShortCircuitOperand:
case Carbon::ParseNodeKind::StructFieldValue:
case Carbon::ParseNodeKind::StructLiteral:
case Carbon::ParseNodeKind::StructTypeLiteral:
return IdKind::SemanticsNodeId;
case Carbon::ParseNodeKind::IfExpressionThen:
case Carbon::ParseNodeKind::IfStatementElse:
case Carbon::ParseNodeKind::ParameterList:
return IdKind::SemanticsNodeBlockId;
case Carbon::ParseNodeKind::FunctionDefinitionStart:
return IdKind::SemanticsFunctionId;
case Carbon::ParseNodeKind::Name:
return IdKind::SemanticsStringId;
case Carbon::ParseNodeKind::ReturnType:
return IdKind::SemanticsTypeId;
default:
return IdKind::Unused;
}
}
// Translates an ID type to the enum ID kind for comparison with
// ParseNodeKindToIdKind.
template <typename IdT>
static constexpr auto IdTypeToIdKind() -> IdKind {
if constexpr (std::is_same_v<IdT, SemanticsNodeId>) {
return IdKind::SemanticsNodeId;
}
if constexpr (std::is_same_v<IdT, SemanticsNodeBlockId>) {
return IdKind::SemanticsNodeBlockId;
}
if constexpr (std::is_same_v<IdT, SemanticsFunctionId>) {
return IdKind::SemanticsFunctionId;
}
if constexpr (std::is_same_v<IdT, SemanticsStringId>) {
return IdKind::SemanticsStringId;
}
if constexpr (std::is_same_v<IdT, SemanticsTypeId>) {
return IdKind::SemanticsTypeId;
}
}
// Pops an entry.
template <typename IdT>
auto PopEntry() -> Entry {