Skip to content

Commit

Permalink
[SymbolTable] Add support of enumeration types
Browse files Browse the repository at this point in the history
Testing covers anonymous enumeration type with two items.

Signed-off-by: Lukasz Dalek <[email protected]>
  • Loading branch information
Lukasz Dalek committed Feb 16, 2021
1 parent 9d63188 commit 231ce1b
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
34 changes: 34 additions & 0 deletions verilog/analysis/symbol_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static const verible::EnumNameMap<SymbolMetaType> kSymbolMetaTypeNames({
{"function", SymbolMetaType::kFunction},
{"task", SymbolMetaType::kTask},
{"struct", SymbolMetaType::kStruct},
{"enum", SymbolMetaType::kEnum},
{"interface", SymbolMetaType::kInterface},
{"<unspecified>", SymbolMetaType::kUnspecified},
{"<callable>", SymbolMetaType::kCallable},
Expand Down Expand Up @@ -261,6 +262,9 @@ class SymbolTable::Builder : public TreeContextVisitor {
case NodeEnum::kStructType:
DescendStructType(node);
break;
case NodeEnum::kEnumType:
DescendEnumType(node);
break;
default:
Descend(node);
break;
Expand Down Expand Up @@ -455,6 +459,29 @@ class SymbolTable::Builder : public TreeContextVisitor {
}
}

void DescendEnumType(const SyntaxTreeNode& enum_type) {
CHECK(enum_type.MatchesTag(NodeEnum::kEnumType));
const absl::string_view anon_name =
current_scope_->Value().CreateAnonymousScope("enum");
SymbolTableNode& new_enum = DeclareScopedElementAndDescend(
enum_type, anon_name, SymbolMetaType::kEnum);

const ReferenceComponent anon_type_ref{
.identifier = anon_name,
.ref_type = ReferenceType::kImmediate,
.required_metatype = SymbolMetaType::kEnum,
// pre-resolve this symbol immediately
.resolved_symbol = &new_enum,
};

const CaptureDependentReference capture(this);
capture.Ref().PushReferenceComponent(anon_type_ref);

if (declaration_type_info_ != nullptr) {
declaration_type_info_->user_defined_type = capture.Ref().LastLeaf();
}
}

void HandleIdentifier(const SyntaxTreeLeaf& leaf) {
const absl::string_view text = leaf.get().text();
VLOG(2) << __FUNCTION__ << ": " << text;
Expand Down Expand Up @@ -546,6 +573,13 @@ class SymbolTable::Builder : public TreeContextVisitor {
return;
}

if (Context().DirectParentsAre({NodeEnum::kEnumName,
NodeEnum::kEnumNameList})) {
EmplaceTypedElementInCurrentScope(
leaf, text, SymbolMetaType::kUnspecified);
return;
}

// In DeclareInstance(), we already planted a self-reference that is
// resolved to the instance being declared.
if (Context().DirectParentIs(NodeEnum::kGateInstance)) return;
Expand Down
1 change: 1 addition & 0 deletions verilog/analysis/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum class SymbolMetaType {
kFunction,
kTask,
kStruct,
kEnum,
kInterface,

// The following enums represent classes/groups of the above types,
Expand Down
73 changes: 73 additions & 0 deletions verilog/analysis/symbol_table_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6132,6 +6132,79 @@ TEST(BuildSymbolTableTest, AnonymousStructTypeNestedMemberReference) {
}
}

TEST(BuildSymbolTableTest, AnonymousEnumTypeData) {
TestVerilogSourceFile src("enumy.sv",
"enum {\n"
" idle, busy\n"
"} data;\n");
const auto status = src.Parse();
ASSERT_TRUE(status.ok()) << status.message();
SymbolTable symbol_table(nullptr);
const SymbolTableNode& root_symbol(symbol_table.Root());

const auto build_diagnostics = BuildSymbolTable(src, &symbol_table);
EXPECT_EMPTY_STATUSES(build_diagnostics);

// Expect one anonymous enum definition and reference.
EXPECT_EQ(root_symbol.Value().anonymous_scope_names.size(), 1);
ASSERT_EQ(root_symbol.Children().size(), 2);
// Find the symbol that is a enum (anon), which is not "data".
const auto found =
std::find_if(root_symbol.Children().begin(), root_symbol.Children().end(),
[](const SymbolTableNode::key_value_type& p) {
return p.first != "data";
});
ASSERT_NE(found, root_symbol.Children().end());
const SymbolTableNode& anon_enum(found->second);
const SymbolInfo& anon_enum_info(anon_enum.Value());
EXPECT_EQ(anon_enum_info.metatype, SymbolMetaType::kEnum);
EXPECT_TRUE(anon_enum_info.local_references_to_bind.empty());

// Enum has two members.
MUST_ASSIGN_LOOKUP_SYMBOL(idle, anon_enum, "idle");
EXPECT_EQ(idle_info.metatype, SymbolMetaType::kUnspecified);
EXPECT_EQ(idle_info.file_origin, &src);
//EXPECT_EQ(
// verible::StringSpanOfSymbol(
// *ABSL_DIE_IF_NULL(idle_info.declared_type.syntax_origin)),
// "idle");
//EXPECT_EQ(idle_info.declared_type.user_defined_type, nullptr);

MUST_ASSIGN_LOOKUP_SYMBOL(busy, anon_enum, "busy");
EXPECT_EQ(busy_info.metatype, SymbolMetaType::kUnspecified);
EXPECT_EQ(busy_info.file_origin, &src);
//EXPECT_EQ(
// verible::StringSpanOfSymbol(
// *ABSL_DIE_IF_NULL(busy_info.declared_type.syntax_origin)),
// "idle");
//EXPECT_EQ(busy_info.declared_type.user_defined_type, nullptr);

// Expect to bind anonymous enum immediately.
ASSERT_EQ(root_symbol.Value().local_references_to_bind.size(), 1);
const DependentReferences& anon_enum_ref(
root_symbol.Value().local_references_to_bind.front());
const ReferenceComponent& anon_enum_ref_comp(
anon_enum_ref.components->Value());
EXPECT_EQ(anon_enum_ref_comp.ref_type, ReferenceType::kImmediate);
EXPECT_EQ(anon_enum_ref_comp.required_metatype, SymbolMetaType::kEnum);
EXPECT_EQ(anon_enum_ref_comp.resolved_symbol, &anon_enum);

// "data"'s type is the (internal) anonymous enum type reference.
MUST_ASSIGN_LOOKUP_SYMBOL(data, root_symbol, "data");
EXPECT_EQ(data_info.metatype, SymbolMetaType::kDataNetVariableInstance);
EXPECT_EQ(data_info.file_origin, &src);
EXPECT_EQ(data_info.declared_type.user_defined_type,
anon_enum_ref.LastLeaf());

{
std::vector<absl::Status> resolve_diagnostics;
symbol_table.Resolve(&resolve_diagnostics);
EXPECT_EMPTY_STATUSES(resolve_diagnostics);

EXPECT_EQ(anon_enum_ref_comp.resolved_symbol, &anon_enum); // unchanged
}
}

TEST(BuildSymbolTableTest, TypedefPrimitive) {
TestVerilogSourceFile src("typedef.sv",
"typedef int number;\n"
Expand Down

0 comments on commit 231ce1b

Please sign in to comment.