Skip to content

Commit

Permalink
Symbol Resolver Pass
Browse files Browse the repository at this point in the history
* improved symbol resolving checks to include the arity of a symbol
  - e.g. function artiy, rule parameter arity, derived parameter arity,
  builtin argument arity, enumeration size (=arity), and for parameter
  (variable), let etc. the arity is by default zero (0)
  - related to ref sealangdotorg/sea#22
* discovers a bug in the initialization of the program function in the
  AST grammar specification
  - bug ref sealangdotorg/sea#24
  • Loading branch information
ppaulweber committed Apr 3, 2017
1 parent 4548f31 commit 4376d84
Showing 1 changed file with 45 additions and 26 deletions.
71 changes: 45 additions & 26 deletions src/analyze/SymbolResolverPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,15 @@ class SymbolResolverVisitor final : public RecursiveVisitor
void visit( ForallRule& node ) override;

private:
void registerSymbol(
const IdentifierNode& node, CallExpression::TargetType targetType );
void registerSymbol( const IdentifierNode& node,
const CallExpression::TargetType targetType,
const std::size_t arity = 0 );

void unregisterSymbol( const IdentifierNode& node );
void unregisterSymbol(
const IdentifierNode& node, const std::size_t arity = 0 );

std::string key(
const IdentifierNode& node, const std::size_t arity ) const;

Logger& log;

Expand Down Expand Up @@ -118,13 +123,15 @@ void SymbolResolverVisitor::visit( Specification& node )

void SymbolResolverVisitor::visit( FunctionDefinition& node )
{
registerSymbol( *node.identifier(), CallExpression::TargetType::FUNCTION );
registerSymbol( *node.identifier(), CallExpression::TargetType::FUNCTION,
node.argumentTypes()->size() );
RecursiveVisitor::visit( node );
}

void SymbolResolverVisitor::visit( DerivedDefinition& node )
{
registerSymbol( *node.identifier(), CallExpression::TargetType::DERIVED );
registerSymbol( *node.identifier(), CallExpression::TargetType::DERIVED,
node.arguments()->size() );

for( auto e : *node.arguments() )
{
Expand All @@ -142,7 +149,8 @@ void SymbolResolverVisitor::visit( DerivedDefinition& node )

void SymbolResolverVisitor::visit( RuleDefinition& node )
{
registerSymbol( *node.identifier(), CallExpression::TargetType::RULE );
registerSymbol( *node.identifier(), CallExpression::TargetType::RULE,
node.arguments()->size() );

for( auto e : *node.arguments() )
{
Expand All @@ -160,8 +168,8 @@ void SymbolResolverVisitor::visit( RuleDefinition& node )

void SymbolResolverVisitor::visit( EnumerationDefinition& node )
{
registerSymbol(
*node.identifier(), CallExpression::TargetType::ENUMERATION );
registerSymbol( *node.identifier(), CallExpression::TargetType::ENUMERATION,

This comment has been minimized.

Copy link
@emmanuel099

emmanuel099 Apr 3, 2017

Member

How is this supposed to work?? Calling a type?!

I think that only the enumerators should be registered.

This comment has been minimized.

Copy link
@ppaulweber

ppaulweber Apr 3, 2017

Author Member
  • you have to think about constructs like forall i in <enumeration> do /* ... */, where the enumeration (appears in the Term grammar rule) gets constructed in the AST from a DirectExpressionCall
  • the enumerators are TargetType::CONSTANT and the type inference will set those later to libcasm_ir::EnumerationConstant

This comment has been minimized.

Copy link
@emmanuel099

emmanuel099 Apr 3, 2017

Member

Ok makes sense, but then the arity should be 0 ;)

This comment has been minimized.

Copy link
@ppaulweber

ppaulweber Apr 3, 2017

Author Member
  • true, I've fixed it already, because this would lead otherwise to a enum naming bug, because to detect overlapping enumeration definitions, this pass can detect it, but only if the arity is 0
  • see: 167294b
node.enumerators()->size() );

for( auto e : *node.enumerators() )
{
Expand All @@ -173,30 +181,33 @@ void SymbolResolverVisitor::visit( EnumerationDefinition& node )

void SymbolResolverVisitor::visit( DirectCallExpression& node )
{
const auto identifier = node.identifier()->identifier();
const auto arity = node.arguments()->size();
const auto _key = key( *node.identifier(), arity );

auto result = m_symbolTable.find( identifier );
auto result = m_symbolTable.find( _key );
if( result != m_symbolTable.end() )
{
node.setTargetType( result->second );
}
else
{
if( libcasm_ir::Builtin::available(
identifier, node.arguments()->size() ) )
const auto name = node.identifier()->identifier();

if( libcasm_ir::Builtin::available( name, arity ) )
{
registerSymbol(
*node.identifier(), CallExpression::TargetType::BUILTIN );
registerSymbol( *node.identifier(),
CallExpression::TargetType::BUILTIN, arity );

node.setTargetType( CallExpression::TargetType::BUILTIN );
}
else
{
log.debug( "memorize '" + identifier + "'" );
m_late_resolve.emplace( identifier, &node );
log.debug( "memorize '" + _key + "'" );
m_late_resolve.emplace( _key, &node );
}
}

log.debug( "Call: " + identifier + "{ " + node.targetTypeName() + " }" );
log.debug( "call: " + _key + "{ " + node.targetTypeName() + " }" );

RecursiveVisitor::visit( node );
}
Expand Down Expand Up @@ -237,12 +248,12 @@ void SymbolResolverVisitor::visit( ForallRule& node )
unregisterSymbol( id );
}

void SymbolResolverVisitor::registerSymbol(
const IdentifierNode& node, CallExpression::TargetType targetType )
void SymbolResolverVisitor::registerSymbol( const IdentifierNode& node,
const CallExpression::TargetType targetType, const std::size_t arity )
{
const auto identifier = node.identifier();
const auto _key = key( node, arity );

auto result = m_symbolTable.emplace( identifier, targetType );
auto result = m_symbolTable.emplace( _key, targetType );

if( not result.second )
{
Expand All @@ -258,17 +269,25 @@ void SymbolResolverVisitor::registerSymbol(
+ "'" );
}

void SymbolResolverVisitor::unregisterSymbol( const IdentifierNode& node )
void SymbolResolverVisitor::unregisterSymbol(
const IdentifierNode& node, const std::size_t arity )
{
const auto identifier = node.identifier();
const auto _key = key( node, arity );

if( m_symbolTable.erase( identifier ) != 1 )
if( m_symbolTable.erase( _key ) != 1 )
{
throw std::domain_error(
"symbol '" + identifier + "' was erased more than once" );
"symbol '" + _key + "' was erased more than once" );
}

log.debug( "unregistered symbol '" + identifier + "'" );
log.debug( "unregistered symbol '" + _key + "'" );
}

std::string SymbolResolverVisitor::key(
const IdentifierNode& node, const std::size_t arity ) const
{
const auto identifier = node.identifier();
return std::to_string( arity ) + "@" + identifier;
}

u64 SymbolResolverVisitor::errors( void ) const
Expand Down

0 comments on commit 4376d84

Please sign in to comment.