2020-11-17 02:32:32 +01:00
# include "lang/validator.hpp"
2020-11-16 22:54:39 +01:00
# include <unordered_set>
# include <string>
2020-11-28 21:55:52 +01:00
# include "helpers/utils.hpp"
2020-11-27 21:20:23 +01:00
2020-11-16 22:54:39 +01:00
namespace hex : : lang {
Validator : : Validator ( ) {
}
bool Validator : : validate ( const std : : vector < ASTNode * > & ast ) {
std : : unordered_set < std : : string > typeNames ;
for ( const auto & node : ast ) {
switch ( node - > getType ( ) ) {
case ASTNode : : Type : : VariableDecl :
{
// Check for duplicate variable names
auto varDeclNode = static_cast < ASTNodeVariableDecl * > ( node ) ;
2020-11-27 21:20:23 +01:00
if ( ! typeNames . insert ( varDeclNode - > getVariableName ( ) ) . second ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " Redefinition of variable '%s' " , varDeclNode - > getVariableName ( ) . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-21 20:19:33 +01:00
if ( varDeclNode - > getArraySize ( ) = = 0 & & ! varDeclNode - > getArraySizeVariable ( ) . has_value ( ) | |
2020-11-27 21:20:23 +01:00
varDeclNode - > getArraySize ( ) ! = 0 & & varDeclNode - > getArraySizeVariable ( ) . has_value ( ) ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , " Invalid array size " } ;
2020-11-21 20:19:33 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
}
break ;
case ASTNode : : Type : : TypeDecl :
{
// Check for duplicate type names
auto typeDeclNode = static_cast < ASTNodeTypeDecl * > ( node ) ;
2020-11-27 21:20:23 +01:00
if ( ! typeNames . insert ( typeDeclNode - > getTypeName ( ) ) . second ) {
this - > m_error = { typeDeclNode - > getLineNumber ( ) , hex : : format ( " Redefinition of type '%s' " , typeDeclNode - > getTypeName ( ) . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-17 02:32:32 +01:00
2020-11-27 21:20:23 +01:00
if ( typeDeclNode - > getAssignedType ( ) = = Token : : TypeToken : : Type : : CustomType & & ! typeNames . contains ( typeDeclNode - > getAssignedCustomTypeName ( ) ) ) {
this - > m_error = { typeDeclNode - > getLineNumber ( ) , " Type declaration without a name " } ;
2020-11-17 02:32:32 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
}
2020-11-22 02:25:03 +01:00
break ;
2020-11-16 22:54:39 +01:00
case ASTNode : : Type : : Struct :
{
// Check for duplicate type name
auto structNode = static_cast < ASTNodeStruct * > ( node ) ;
2020-11-27 21:20:23 +01:00
if ( ! typeNames . insert ( structNode - > getName ( ) ) . second ) {
this - > m_error = { structNode - > getLineNumber ( ) , hex : : format ( " Redeclaration of type '%s' " , structNode - > getName ( ) . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
// Check for duplicate member names
std : : unordered_set < std : : string > memberNames ;
for ( const auto & member : structNode - > getNodes ( ) )
2020-11-27 21:20:23 +01:00
if ( ! memberNames . insert ( static_cast < ASTNodeVariableDecl * > ( member ) - > getVariableName ( ) ) . second ) {
this - > m_error = { member - > getLineNumber ( ) , hex : : format ( " Redeclaration of member '%s' " , static_cast < ASTNodeVariableDecl * > ( member ) - > getVariableName ( ) . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
}
2020-11-22 02:25:03 +01:00
break ;
2020-11-16 22:54:39 +01:00
case ASTNode : : Type : : Enum :
{
// Check for duplicate type name
auto enumNode = static_cast < ASTNodeEnum * > ( node ) ;
2020-11-27 21:20:23 +01:00
if ( ! typeNames . insert ( enumNode - > getName ( ) ) . second ) {
this - > m_error = { enumNode - > getLineNumber ( ) , hex : : format ( " Redeclaration of type '%s' " , enumNode - > getName ( ) . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
// Check for duplicate constant names
std : : unordered_set < std : : string > constantNames ;
for ( const auto & [ value , name ] : enumNode - > getValues ( ) )
2020-11-27 21:20:23 +01:00
if ( ! constantNames . insert ( name ) . second ) {
this - > m_error = { enumNode - > getLineNumber ( ) , hex : : format ( " Redeclaration of enum constant '%s' " , name . c_str ( ) ) } ;
2020-11-16 22:54:39 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-16 22:54:39 +01:00
}
2020-11-22 02:25:03 +01:00
break ;
2020-11-20 20:26:19 +01:00
case ASTNode : : Type : : Bitfield :
{
// Check for duplicate type name
auto bitfieldNode = static_cast < ASTNodeBitField * > ( node ) ;
2020-11-27 21:20:23 +01:00
if ( ! typeNames . insert ( bitfieldNode - > getName ( ) ) . second ) {
this - > m_error = { bitfieldNode - > getLineNumber ( ) , hex : : format ( " Redeclaration of type '%s' " , bitfieldNode - > getName ( ) . c_str ( ) ) } ;
2020-11-20 20:26:19 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 20:26:19 +01:00
size_t bitfieldSize = 0 ;
// Check for duplicate constant names
std : : unordered_set < std : : string > flagNames ;
for ( const auto & [ name , size ] : bitfieldNode - > getFields ( ) ) {
2020-11-27 21:20:23 +01:00
if ( ! flagNames . insert ( name ) . second ) {
this - > m_error = { bitfieldNode - > getLineNumber ( ) , hex : : format ( " Redeclaration of member '%s' " , name . c_str ( ) ) } ;
2020-11-20 20:26:19 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 20:26:19 +01:00
bitfieldSize + = size ;
}
2020-11-27 21:20:23 +01:00
if ( bitfieldSize > 64 ) {
this - > m_error = { bitfieldNode - > getLineNumber ( ) , " Bitfield exceeds maximum size of 64 bits " } ;
2020-11-20 20:26:19 +01:00
return false ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 20:26:19 +01:00
}
2020-11-22 02:25:03 +01:00
break ;
2020-11-16 22:54:39 +01:00
}
}
return true ;
}
}