diff --git a/src/Namespace.cpp b/src/Namespace.cpp index 78ea3016a..58f89a3f6 100644 --- a/src/Namespace.cpp +++ b/src/Namespace.cpp @@ -32,56 +32,77 @@ using namespace Ast; static std::string key( const IdentifierNode& node, const std::size_t arity ); -Namespace::Namespace( void ) +// +// Symbol +// + +Namespace::Symbol::Symbol( const Ast::IdentifierNode& identifier, + Ast::Node& definition, + const Ast::CallExpression::TargetType targetType, + const std::size_t arity ) +: m_identifier( identifier ) +, m_definition( definition ) +, m_targetType( targetType ) +, m_arity( arity ) { } -u64 Namespace::registerSymbol( Logger& log, const IdentifierNode& node, - const CallExpression::TargetType targetType, const std::size_t arity ) +const Ast::IdentifierNode& Namespace::Symbol::identifier( void ) const { - const auto _key = key( node, arity ); + return m_identifier; +} - auto result = m_symboltable.emplace( _key, targetType ); +Ast::Node& Namespace::Symbol::definition( void ) +{ + return m_definition; +} - if( not result.second ) - { - log.error( { node.sourceLocation() }, - "symbol '" + result.first->first + "' already defined as '" - + CallExpression::targetTypeString( result.first->second ) - + "'" ); +Ast::CallExpression::TargetType Namespace::Symbol::targetType( void ) const +{ + return m_targetType; +} - return 1; - } +std::size_t Namespace::Symbol::arity( void ) const +{ + return m_arity; +} - log.debug( "registered new symbol '" + result.first->first + "' as '" - + CallExpression::targetTypeString( result.first->second ) - + "'" ); +// +// Namespace +// - return 0; +Namespace::Namespace( void ) +{ +} + +u64 Namespace::registerSymbol( Logger& log, const DirectCallExpression& node ) +{ + return registerSymbol( log, *node.identifier(), node, + CallExpression::TargetType::FUNCTION, node.arguments()->size() ); } u64 Namespace::registerSymbol( Logger& log, const FunctionDefinition& node ) { - return registerSymbol( log, *node.identifier(), + return registerSymbol( log, *node.identifier(), node, CallExpression::TargetType::FUNCTION, node.argumentTypes()->size() ); } u64 Namespace::registerSymbol( Logger& log, const DerivedDefinition& node ) { - return registerSymbol( log, *node.identifier(), + return registerSymbol( log, *node.identifier(), node, CallExpression::TargetType::DERIVED, node.arguments()->size() ); } u64 Namespace::registerSymbol( Logger& log, const RuleDefinition& node ) { - return registerSymbol( log, *node.identifier(), + return registerSymbol( log, *node.identifier(), node, CallExpression::TargetType::RULE, node.arguments()->size() ); } u64 Namespace::registerSymbol( Logger& log, const EnumerationDefinition& node ) { - auto err = registerSymbol( - log, *node.identifier(), CallExpression::TargetType::ENUMERATION ); + auto err = registerSymbol( log, *node.identifier(), node, + CallExpression::TargetType::ENUMERATION ); auto enumerationNamespace = libstdhl::make< Namespace >(); @@ -99,27 +120,41 @@ u64 Namespace::registerSymbol( Logger& log, const EnumerationDefinition& node ) for( auto e : *node.enumerators() ) { err += enumerationNamespace->registerSymbol( - log, *e, CallExpression::TargetType::CONSTANT ); + log, *e, node, CallExpression::TargetType::CONSTANT ); } return err; } -CallExpression::TargetType Namespace::find( - const DirectCallExpression& node ) const +Namespace::Symbol Namespace::find( const DirectCallExpression& node ) const { const auto arity = node.arguments()->size(); const auto _key = key( *node.identifier(), arity ); auto result = m_symboltable.find( _key ); - if( result != m_symboltable.end() ) + if( result == m_symboltable.end() ) { - return result->second; + throw std::domain_error( "unable to find " + std::to_string( arity ) + + " symbol '" + + node.identifier()->identifier() + + "'" ); } - else + + return result->second; +} + +Namespace::Symbol Namespace::find( const BasicType& node ) const +{ + const auto _key = key( *node.name(), 0 ); + + auto result = m_symboltable.find( _key ); + if( result == m_symboltable.end() ) { - return CallExpression::TargetType::UNKNOWN; + throw std::domain_error( + "unable to find type symbol '" + node.name()->identifier() + "'" ); } + + return result->second; } std::string Namespace::dump( const std::string& indention ) const @@ -135,8 +170,8 @@ std::string Namespace::dump( const std::string& indention ) const const auto& name = parts[ 1 ]; s << indention << name << " : " - << CallExpression::targetTypeString( v.second ) << "( " << arity - << "-ary)\n"; + << CallExpression::targetTypeString( v.second.targetType() ) << "( " + << arity << "-ary)\n"; } for( auto v : m_namespaces ) @@ -150,6 +185,34 @@ std::string Namespace::dump( const std::string& indention ) const return s.str(); } +u64 Namespace::registerSymbol( Logger& log, const IdentifierNode& node, + const Node& definition, const CallExpression::TargetType targetType, + const std::size_t arity ) +{ + const auto _key = key( node, arity ); + + auto result = m_symboltable.emplace( _key, + Symbol{ node, const_cast< Node& >( definition ), targetType, arity } ); + + if( not result.second ) + { + log.error( { node.sourceLocation() }, + "symbol '" + result.first->first + "' already defined as '" + + CallExpression::targetTypeString( + result.first->second.targetType() ) + + "'" ); + + return 1; + } + + log.debug( + "registered new symbol '" + result.first->first + "' as '" + + CallExpression::targetTypeString( result.first->second.targetType() ) + + "'" ); + + return 0; +} + static std::string key( const IdentifierNode& node, const std::size_t arity ) { const auto identifier = node.identifier(); diff --git a/src/Namespace.h b/src/Namespace.h index 601db23aa..5b30ec958 100644 --- a/src/Namespace.h +++ b/src/Namespace.h @@ -37,14 +37,34 @@ namespace libcasm_fe */ class Namespace { + public: + class Symbol + { + public: + Symbol( const Ast::IdentifierNode& identifier, + Ast::Node& definition, + const Ast::CallExpression::TargetType targetType, + const std::size_t arity ); + + const Ast::IdentifierNode& identifier( void ) const; + Ast::Node& definition( void ); + Ast::CallExpression::TargetType targetType( void ) const; + std::size_t arity( void ) const; + + private: + const Ast::IdentifierNode& m_identifier; + Ast::Node& m_definition; + Ast::CallExpression::TargetType m_targetType; + std::size_t m_arity; + }; + public: using Ptr = std::shared_ptr< Namespace >; Namespace( void ); - u64 registerSymbol( Logger& log, const Ast::IdentifierNode& node, - const Ast::CallExpression::TargetType targetType, - const std::size_t arity = 0 ); + u64 registerSymbol( + Logger& log, const Ast::DirectCallExpression& node ); u64 registerSymbol( Logger& log, const Ast::FunctionDefinition& node ); @@ -55,14 +75,19 @@ namespace libcasm_fe u64 registerSymbol( Logger& log, const Ast::EnumerationDefinition& node ); - Ast::CallExpression::TargetType find( - const Ast::DirectCallExpression& node ) const; + Symbol find( const Ast::DirectCallExpression& node ) const; + + Symbol find( const Ast::BasicType& node ) const; std::string dump( const std::string& indention = "" ) const; private: - std::unordered_map< std::string, Ast::CallExpression::TargetType > - m_symboltable; + u64 registerSymbol( Logger& log, const Ast::IdentifierNode& node, + const Ast::Node& definition, + const Ast::CallExpression::TargetType targetType, + const std::size_t arity = 0 ); + + std::unordered_map< std::string, Symbol > m_symboltable; std::unordered_map< std::string, Namespace::Ptr > m_namespaces; }; diff --git a/src/analyze/SymbolResolverPass.cpp b/src/analyze/SymbolResolverPass.cpp index 931bb8935..86c138f66 100644 --- a/src/analyze/SymbolResolverPass.cpp +++ b/src/analyze/SymbolResolverPass.cpp @@ -151,23 +151,18 @@ SymbolResolveVisitor::SymbolResolveVisitor( void SymbolResolveVisitor::visit( DirectCallExpression& node ) { - const auto targetType = m_symboltable.find( node ); - const auto name = node.identifier()->identifier(); - if( targetType != CallExpression::TargetType::UNKNOWN ) + try { - node.setTargetType( targetType ); + const auto symbol = m_symboltable.find( node ); + node.setTargetType( symbol.targetType() ); } - else + catch( const std::domain_error& e ) { - const auto arity = node.arguments()->size(); - - if( libcasm_ir::Builtin::available( name, arity ) ) + if( libcasm_ir::Builtin::available( name, node.arguments()->size() ) ) { - m_err += m_symboltable.registerSymbol( m_log, *node.identifier(), - CallExpression::TargetType::BUILTIN, arity ); - + m_err += m_symboltable.registerSymbol( m_log, node ); node.setTargetType( CallExpression::TargetType::BUILTIN ); } else if( m_variables.find( name ) != m_variables.end() )