diff --git a/include/slang/ast/SemanticModel.h b/include/slang/ast/SemanticModel.h deleted file mode 100644 index 60f382a91..000000000 --- a/include/slang/ast/SemanticModel.h +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -//! @file SemanticModel.h -//! @brief Query semantic information for a syntax tree -// -// SPDX-FileCopyrightText: Michael Popoloski -// SPDX-License-Identifier: MIT -//------------------------------------------------------------------------------ -#pragma once - -#include "slang/ast/symbols/BlockSymbols.h" -#include "slang/ast/symbols/CompilationUnitSymbols.h" -#include "slang/ast/symbols/InstanceSymbols.h" -#include "slang/ast/symbols/SubroutineSymbols.h" -#include "slang/ast/types/AllTypes.h" -#include "slang/syntax/SyntaxFwd.h" -#include "slang/util/Hash.h" - -namespace slang::ast { - -class SLANG_EXPORT SemanticModel { -public: - explicit SemanticModel(Compilation& compilation); - - void withContext(const syntax::SyntaxNode& node, const Symbol& symbol); - - const Symbol* getDeclaredSymbol(const syntax::SyntaxNode& syntax); - - const CompilationUnitSymbol* getDeclaredSymbol(const syntax::CompilationUnitSyntax& syntax); - const InstanceSymbol* getDeclaredSymbol(const syntax::HierarchyInstantiationSyntax& syntax); - const StatementBlockSymbol* getDeclaredSymbol(const syntax::BlockStatementSyntax& syntax); - const ProceduralBlockSymbol* getDeclaredSymbol(const syntax::ProceduralBlockSyntax& syntax); - const GenerateBlockSymbol* getDeclaredSymbol(const syntax::IfGenerateSyntax& syntax); - const GenerateBlockArraySymbol* getDeclaredSymbol(const syntax::LoopGenerateSyntax& syntax); - const SubroutineSymbol* getDeclaredSymbol(const syntax::FunctionDeclarationSyntax& syntax); - const EnumType* getDeclaredSymbol(const syntax::EnumTypeSyntax& syntax); - const TypeAliasType* getDeclaredSymbol(const syntax::TypedefDeclarationSyntax& syntax); - -private: - Compilation& compilation; - - flat_hash_map symbolCache; -}; - -} // namespace slang::ast diff --git a/source/ast/CMakeLists.txt b/source/ast/CMakeLists.txt index f349d7539..558516b54 100644 --- a/source/ast/CMakeLists.txt +++ b/source/ast/CMakeLists.txt @@ -59,7 +59,6 @@ target_sources( Scope.cpp ScriptSession.cpp SemanticFacts.cpp - SemanticModel.cpp SFormat.cpp Statements.cpp Symbol.cpp diff --git a/source/ast/SemanticModel.cpp b/source/ast/SemanticModel.cpp deleted file mode 100644 index 31c69a32c..000000000 --- a/source/ast/SemanticModel.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//------------------------------------------------------------------------------ -// SemanticModel.cpp -// Query semantic information for a syntax tree -// -// SPDX-FileCopyrightText: Michael Popoloski -// SPDX-License-Identifier: MIT -//------------------------------------------------------------------------------ -#include "slang/ast/SemanticModel.h" - -#include "slang/ast/Compilation.h" -#include "slang/syntax/AllSyntax.h" - -namespace slang::ast { - -using namespace syntax; - -SemanticModel::SemanticModel(Compilation& compilation) : compilation(compilation) { -} - -void SemanticModel::withContext(const SyntaxNode& node, const Symbol& symbol) { - symbolCache[&node] = &symbol; -} - -const Symbol* SemanticModel::getDeclaredSymbol(const SyntaxNode& syntax) { - // If we've already cached this node, return that. - if (auto it = symbolCache.find(&syntax); it != symbolCache.end()) - return it->second; - - // If we hit the top of the syntax tree, look in the compilation for the correct symbol. - if (syntax.kind == SyntaxKind::CompilationUnit) { - auto result = compilation.getCompilationUnit(syntax.as()); - if (result) - symbolCache[&syntax] = result; - return result; - } - else if (syntax.kind == SyntaxKind::ModuleDeclaration || - syntax.kind == SyntaxKind::InterfaceDeclaration || - syntax.kind == SyntaxKind::ProgramDeclaration) { - auto def = compilation.getDefinition(syntax.as()); - if (!def) - return nullptr; - - // There is no symbol to use here so create a placeholder instance. - auto result = &InstanceSymbol::createDefault(compilation, *def); - symbolCache[&syntax] = result; - return result; - } - - // Otherwise try to find the parent symbol first. - auto parent = syntax.parent ? getDeclaredSymbol(*syntax.parent) : nullptr; - if (!parent) - return nullptr; - - // If this is a type alias, unwrap its target type to look at the syntax node. - if (parent->kind == SymbolKind::TypeAlias) { - auto& target = parent->as().targetType.getType(); - if (target.getSyntax() == &syntax) { - symbolCache.emplace(&syntax, &target); - return ⌖ - } - return nullptr; - } - - if (parent->kind == SymbolKind::Instance) - parent = &parent->as().body; - else if (!parent->isScope()) - return nullptr; - - // Search among the parent's children to see if we can find ourself. - for (auto& child : parent->as().members()) { - if (child.getSyntax() == &syntax) { - // We found ourselves, hurray. - symbolCache.emplace(&syntax, &child); - return &child; - } - } - - return nullptr; -} - -const CompilationUnitSymbol* SemanticModel::getDeclaredSymbol(const CompilationUnitSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const InstanceSymbol* SemanticModel::getDeclaredSymbol(const HierarchyInstantiationSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const StatementBlockSymbol* SemanticModel::getDeclaredSymbol(const BlockStatementSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const ProceduralBlockSymbol* SemanticModel::getDeclaredSymbol(const ProceduralBlockSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const GenerateBlockSymbol* SemanticModel::getDeclaredSymbol(const IfGenerateSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const GenerateBlockArraySymbol* SemanticModel::getDeclaredSymbol(const LoopGenerateSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const SubroutineSymbol* SemanticModel::getDeclaredSymbol(const FunctionDeclarationSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const EnumType* SemanticModel::getDeclaredSymbol(const EnumTypeSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -const TypeAliasType* SemanticModel::getDeclaredSymbol(const TypedefDeclarationSyntax& syntax) { - auto result = getDeclaredSymbol((const SyntaxNode&)syntax); - return result ? &result->as() : nullptr; -} - -} // namespace slang::ast diff --git a/tests/unittests/parsing/VisitorTests.cpp b/tests/unittests/parsing/VisitorTests.cpp index 534ccb880..3d99d39c1 100644 --- a/tests/unittests/parsing/VisitorTests.cpp +++ b/tests/unittests/parsing/VisitorTests.cpp @@ -5,11 +5,122 @@ #include #include "slang/ast/ASTVisitor.h" -#include "slang/ast/SemanticModel.h" #include "slang/parsing/ParserMetadata.h" #include "slang/syntax/SyntaxPrinter.h" #include "slang/syntax/SyntaxVisitor.h" +class SemanticModel { +public: + explicit SemanticModel(Compilation& compilation) : compilation(compilation) {} + + const Symbol* getDeclaredSymbol(const syntax::SyntaxNode& syntax) { + // If we've already cached this node, return that. + if (auto it = symbolCache.find(&syntax); it != symbolCache.end()) + return it->second; + + // If we hit the top of the syntax tree, look in the compilation for the correct symbol. + if (syntax.kind == SyntaxKind::CompilationUnit) { + auto result = compilation.getCompilationUnit(syntax.as()); + if (result) + symbolCache[&syntax] = result; + return result; + } + else if (syntax.kind == SyntaxKind::ModuleDeclaration || + syntax.kind == SyntaxKind::InterfaceDeclaration || + syntax.kind == SyntaxKind::ProgramDeclaration) { + auto def = compilation.getDefinition(syntax.as()); + if (!def) + return nullptr; + + // There is no symbol to use here so create a placeholder instance. + auto result = &InstanceSymbol::createDefault(compilation, *def); + symbolCache[&syntax] = result; + return result; + } + + // Otherwise try to find the parent symbol first. + auto parent = syntax.parent ? getDeclaredSymbol(*syntax.parent) : nullptr; + if (!parent) + return nullptr; + + // If this is a type alias, unwrap its target type to look at the syntax node. + if (parent->kind == SymbolKind::TypeAlias) { + auto& target = parent->as().targetType.getType(); + if (target.getSyntax() == &syntax) { + symbolCache.emplace(&syntax, &target); + return ⌖ + } + return nullptr; + } + + if (parent->kind == SymbolKind::Instance) + parent = &parent->as().body; + else if (!parent->isScope()) + return nullptr; + + // Search among the parent's children to see if we can find ourself. + for (auto& child : parent->as().members()) { + if (child.getSyntax() == &syntax) { + // We found ourselves, hurray. + symbolCache.emplace(&syntax, &child); + return &child; + } + } + + return nullptr; + } + + const CompilationUnitSymbol* getDeclaredSymbol(const CompilationUnitSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const InstanceSymbol* getDeclaredSymbol(const HierarchyInstantiationSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const StatementBlockSymbol* getDeclaredSymbol(const BlockStatementSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const ProceduralBlockSymbol* getDeclaredSymbol(const ProceduralBlockSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const GenerateBlockSymbol* getDeclaredSymbol(const IfGenerateSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const GenerateBlockArraySymbol* getDeclaredSymbol(const LoopGenerateSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const SubroutineSymbol* getDeclaredSymbol(const FunctionDeclarationSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const EnumType* getDeclaredSymbol(const EnumTypeSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + + const TypeAliasType* getDeclaredSymbol(const TypedefDeclarationSyntax& syntax) { + auto result = getDeclaredSymbol((const SyntaxNode&)syntax); + return result ? &result->as() : nullptr; + } + +private: + Compilation& compilation; + + flat_hash_map symbolCache; +}; + class TestRewriter : public SyntaxRewriter { public: Compilation compilation;