2020-11-19 11:36:52 +01:00
# include "lang/evaluator.hpp"
2020-12-27 15:54:12 +01:00
# include "lang/token.hpp"
2020-11-20 20:26:19 +01:00
# include <bit>
2020-11-19 11:36:52 +01:00
# include <unordered_map>
namespace hex : : lang {
2020-12-06 21:40:57 +01:00
Evaluator : : Evaluator ( prv : : Provider * & provider , std : : endian defaultDataEndianess ) : m_provider ( provider ) , m_defaultDataEndianess ( defaultDataEndianess ) {
2020-11-19 11:36:52 +01:00
}
std : : pair < PatternData * , size_t > Evaluator : : createStructPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
std : : vector < PatternData * > members ;
auto structNode = static_cast < ASTNodeStruct * > ( this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ) ;
2020-11-27 21:20:23 +01:00
if ( structNode = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-19 11:36:52 +01:00
size_t structSize = 0 ;
for ( const auto & node : structNode - > getNodes ( ) ) {
const auto & member = static_cast < ASTNodeVariableDecl * > ( node ) ;
2020-11-21 23:00:09 +01:00
u64 memberOffset = 0 ;
2020-11-19 11:36:52 +01:00
2020-11-22 16:22:02 +01:00
if ( member - > getPointerSize ( ) . has_value ( ) ) {
2020-11-21 23:00:09 +01:00
this - > m_provider - > read ( offset + structSize , & memberOffset , member - > getPointerSize ( ) . value ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-12-06 21:40:57 +01:00
memberOffset = hex : : changeEndianess ( memberOffset , member - > getPointerSize ( ) . value ( ) , member - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-22 16:22:02 +01:00
}
2020-11-21 23:00:09 +01:00
else
memberOffset = offset + structSize ;
2020-11-19 11:36:52 +01:00
2020-11-21 23:00:09 +01:00
const auto typeDeclNode = static_cast < ASTNodeTypeDecl * > ( this - > m_types [ member - > getCustomVariableTypeName ( ) ] ) ;
2020-11-19 11:36:52 +01:00
2020-11-21 23:00:09 +01:00
PatternData * pattern = nullptr ;
2020-12-18 21:44:13 +01:00
size_t memberSize = 0 ;
2020-11-21 23:00:09 +01:00
if ( member - > getVariableType ( ) = = Token : : TypeToken : : Type : : Signed8Bit & & member - > getArraySize ( ) > 1 ) {
std : : tie ( pattern , memberSize ) = this - > createStringPattern ( member , memberOffset ) ;
2020-11-19 11:36:52 +01:00
} else if ( member - > getVariableType ( ) = = Token : : TypeToken : : Type : : CustomType
2020-11-20 15:52:06 +01:00
& & typeDeclNode ! = nullptr & & typeDeclNode - > getAssignedType ( ) = = Token : : TypeToken : : Type : : Signed8Bit
2020-11-19 11:36:52 +01:00
& & member - > getArraySize ( ) > 1 ) {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createStringPattern ( member , memberOffset ) ;
2020-11-19 11:36:52 +01:00
}
2020-12-06 23:15:51 +01:00
else if ( member - > getArraySize ( ) > 1 | | member - > getVariableType ( ) = = Token : : TypeToken : : Type : : Padding ) {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createArrayPattern ( member , memberOffset ) ;
2020-11-19 11:36:52 +01:00
}
2020-11-21 20:19:33 +01:00
else if ( member - > getArraySizeVariable ( ) . has_value ( ) ) {
std : : optional < size_t > arraySize ;
for ( auto & prevMember : members ) {
if ( prevMember - > getPatternType ( ) = = PatternData : : Type : : Unsigned & & prevMember - > getName ( ) = = member - > getArraySizeVariable ( ) ) {
u64 value = 0 ;
this - > m_provider - > read ( prevMember - > getOffset ( ) , & value , prevMember - > getSize ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-12-06 21:40:57 +01:00
value = hex : : changeEndianess ( value , prevMember - > getSize ( ) , prevMember - > getEndianess ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-11-21 20:19:33 +01:00
arraySize = value ;
}
}
2020-11-27 21:20:23 +01:00
if ( ! arraySize . has_value ( ) ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a previous member of '%s' " , member - > getArraySizeVariable ( ) . value ( ) . c_str ( ) , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-21 20:19:33 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-21 20:19:33 +01:00
2020-12-06 22:52:15 +01:00
if ( arraySize . value ( ) = = 0 )
continue ;
2020-11-27 21:20:23 +01:00
ASTNodeVariableDecl * processedMember = new ASTNodeVariableDecl ( member - > getLineNumber ( ) , member - > getVariableType ( ) , member - > getVariableName ( ) , member - > getCustomVariableTypeName ( ) , member - > getOffset ( ) , arraySize . value ( ) ) ;
2020-11-21 20:19:33 +01:00
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createArrayPattern ( processedMember , memberOffset ) ;
2020-11-21 20:19:33 +01:00
}
2020-11-19 11:36:52 +01:00
else if ( member - > getVariableType ( ) ! = Token : : TypeToken : : Type : : CustomType ) {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createBuiltInTypePattern ( member , memberOffset ) ;
2020-11-19 11:36:52 +01:00
}
else {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createCustomTypePattern ( member , memberOffset ) ;
}
2020-11-19 11:36:52 +01:00
2020-11-21 23:00:09 +01:00
if ( pattern = = nullptr )
return { nullptr , 0 } ;
2020-11-19 11:36:52 +01:00
2020-12-06 21:40:57 +01:00
pattern - > setEndianess ( member - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-21 23:00:09 +01:00
if ( member - > getPointerSize ( ) . has_value ( ) ) {
2020-12-06 21:40:57 +01:00
members . push_back ( new PatternDataPointer ( offset + structSize , member - > getPointerSize ( ) . value ( ) , member - > getVariableName ( ) , pattern , member - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ) ;
2020-11-21 23:00:09 +01:00
structSize + = member - > getPointerSize ( ) . value ( ) ;
}
else {
2020-11-19 11:36:52 +01:00
members . push_back ( pattern ) ;
2020-11-21 23:00:09 +01:00
structSize + = memberSize ;
2020-11-19 11:36:52 +01:00
}
}
2020-12-06 21:40:57 +01:00
return { new PatternDataStruct ( offset , structSize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) , structNode - > getName ( ) , members , 0x00FFFFFF ) , structSize } ;
2020-11-19 11:36:52 +01:00
}
2020-11-20 21:29:28 +01:00
std : : pair < PatternData * , size_t > Evaluator : : createUnionPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
std : : vector < PatternData * > members ;
auto unionNode = static_cast < ASTNodeUnion * > ( this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ) ;
2020-11-27 21:20:23 +01:00
if ( unionNode = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-20 21:29:28 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 21:29:28 +01:00
size_t unionSize = 0 ;
for ( const auto & node : unionNode - > getNodes ( ) ) {
const auto & member = static_cast < ASTNodeVariableDecl * > ( node ) ;
2020-11-21 23:00:09 +01:00
u64 memberOffset = 0 ;
2020-11-22 16:22:02 +01:00
if ( member - > getPointerSize ( ) . has_value ( ) ) {
2020-11-21 23:00:09 +01:00
this - > m_provider - > read ( offset + unionSize , & memberOffset , member - > getPointerSize ( ) . value ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-12-06 21:40:57 +01:00
memberOffset = hex : : changeEndianess ( memberOffset , member - > getPointerSize ( ) . value ( ) , member - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ;
2020-11-22 16:22:02 +01:00
}
2020-11-21 23:00:09 +01:00
else
memberOffset = offset ;
2020-11-20 21:29:28 +01:00
const auto typeDeclNode = static_cast < ASTNodeTypeDecl * > ( this - > m_types [ member - > getCustomVariableTypeName ( ) ] ) ;
2020-11-21 23:00:09 +01:00
PatternData * pattern = nullptr ;
2020-12-18 21:44:13 +01:00
size_t memberSize = 0 ;
2020-11-20 21:29:28 +01:00
2020-11-21 23:00:09 +01:00
if ( member - > getVariableType ( ) = = Token : : TypeToken : : Type : : Signed8Bit & & member - > getArraySize ( ) > 1 ) {
std : : tie ( pattern , memberSize ) = this - > createStringPattern ( member , memberOffset ) ;
2020-11-20 21:29:28 +01:00
} else if ( member - > getVariableType ( ) = = Token : : TypeToken : : Type : : CustomType
& & typeDeclNode ! = nullptr & & typeDeclNode - > getAssignedType ( ) = = Token : : TypeToken : : Type : : Signed8Bit
& & member - > getArraySize ( ) > 1 ) {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createStringPattern ( member , memberOffset ) ;
2020-11-20 21:29:28 +01:00
}
2020-12-06 23:15:51 +01:00
else if ( member - > getArraySize ( ) > 1 | | member - > getVariableType ( ) = = Token : : TypeToken : : Type : : Padding ) {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createArrayPattern ( member , memberOffset ) ;
2020-11-20 21:29:28 +01:00
}
2020-11-21 23:00:09 +01:00
else if ( member - > getArraySizeVariable ( ) . has_value ( ) ) {
std : : optional < size_t > arraySize ;
for ( auto & prevMember : members ) {
if ( prevMember - > getPatternType ( ) = = PatternData : : Type : : Unsigned & & prevMember - > getName ( ) = = member - > getArraySizeVariable ( ) ) {
u64 value = 0 ;
this - > m_provider - > read ( prevMember - > getOffset ( ) , & value , prevMember - > getSize ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-12-06 21:40:57 +01:00
value = hex : : changeEndianess ( value , prevMember - > getSize ( ) , prevMember - > getEndianess ( ) ) ;
2020-11-22 16:22:02 +01:00
2020-11-21 23:00:09 +01:00
arraySize = value ;
}
}
2020-11-20 21:29:28 +01:00
2020-11-27 21:20:23 +01:00
if ( ! arraySize . has_value ( ) ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a previous member of '%s' " , member - > getArraySizeVariable ( ) . value ( ) . c_str ( ) , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-20 21:29:28 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 21:29:28 +01:00
2020-12-06 22:52:15 +01:00
if ( arraySize . value ( ) = = 0 )
continue ;
2020-12-05 10:36:30 +01:00
2020-11-27 21:20:23 +01:00
ASTNodeVariableDecl * processedMember = new ASTNodeVariableDecl ( member - > getLineNumber ( ) , member - > getVariableType ( ) , member - > getVariableName ( ) , member - > getCustomVariableTypeName ( ) , member - > getOffset ( ) , arraySize . value ( ) ) ;
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createArrayPattern ( processedMember , memberOffset ) ;
}
else if ( member - > getVariableType ( ) ! = Token : : TypeToken : : Type : : CustomType ) {
std : : tie ( pattern , memberSize ) = this - > createBuiltInTypePattern ( member , memberOffset ) ;
2020-11-20 21:29:28 +01:00
}
else {
2020-11-21 23:00:09 +01:00
std : : tie ( pattern , memberSize ) = this - > createCustomTypePattern ( member , memberOffset ) ;
}
2020-11-20 21:29:28 +01:00
2020-11-21 23:00:09 +01:00
if ( pattern = = nullptr )
return { nullptr , 0 } ;
2020-11-20 21:29:28 +01:00
2020-12-06 21:40:57 +01:00
pattern - > setEndianess ( member - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-21 23:00:09 +01:00
if ( member - > getPointerSize ( ) . has_value ( ) ) {
2020-12-06 21:40:57 +01:00
members . push_back ( new PatternDataPointer ( offset , member - > getPointerSize ( ) . value ( ) , member - > getVariableName ( ) , pattern , member - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-21 23:00:09 +01:00
unionSize = std : : max ( size_t ( member - > getPointerSize ( ) . value ( ) ) , unionSize ) ;
}
else {
2020-11-20 21:29:28 +01:00
members . push_back ( pattern ) ;
2020-11-21 23:00:09 +01:00
unionSize = std : : max ( memberSize , unionSize ) ;
2020-11-20 21:29:28 +01:00
}
}
2020-12-06 21:40:57 +01:00
return { new PatternDataUnion ( offset , unionSize , varDeclNode - > getVariableName ( ) , unionNode - > getName ( ) , members , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) , 0x00FFFFFF ) , unionSize } ;
2020-11-20 21:29:28 +01:00
}
2020-11-19 11:36:52 +01:00
std : : pair < PatternData * , size_t > Evaluator : : createEnumPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
auto * enumType = static_cast < ASTNodeEnum * > ( this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ) ;
2020-11-27 21:20:23 +01:00
if ( enumType = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-19 11:36:52 +01:00
2020-12-27 15:54:12 +01:00
size_t size = Token : : getTypeSize ( enumType - > getUnderlyingType ( ) ) ;
2020-11-19 11:36:52 +01:00
2020-12-06 21:40:57 +01:00
return { new PatternDataEnum ( offset , size , varDeclNode - > getVariableName ( ) , enumType - > getName ( ) , enumType - > getValues ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , size } ;
2020-11-19 11:36:52 +01:00
}
2020-11-20 20:26:19 +01:00
std : : pair < PatternData * , size_t > Evaluator : : createBitfieldPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
auto * bitfieldType = static_cast < ASTNodeBitField * > ( this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ) ;
2020-11-27 21:20:23 +01:00
if ( bitfieldType = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-20 20:26:19 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-20 20:26:19 +01:00
size_t size = 0 ;
for ( auto & [ fieldName , fieldSize ] : bitfieldType - > getFields ( ) )
size + = fieldSize ;
2020-12-18 21:44:13 +01:00
size = bit_ceil ( size ) / 8 ;
2020-11-20 20:26:19 +01:00
2020-12-06 21:40:57 +01:00
return { new PatternDataBitfield ( offset , size , varDeclNode - > getVariableName ( ) , bitfieldType - > getName ( ) , bitfieldType - > getFields ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , size } ;
2020-11-20 20:26:19 +01:00
}
2020-11-19 11:36:52 +01:00
std : : pair < PatternData * , size_t > Evaluator : : createArrayPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
std : : vector < PatternData * > entries ;
2020-11-20 21:59:27 +01:00
size_t arrayOffset = 0 ;
2020-11-21 20:19:33 +01:00
std : : optional < u32 > arrayColor ;
2020-11-19 11:36:52 +01:00
for ( u32 i = 0 ; i < varDeclNode - > getArraySize ( ) ; i + + ) {
2020-11-27 21:20:23 +01:00
ASTNodeVariableDecl * nonArrayVarDeclNode = new ASTNodeVariableDecl ( varDeclNode - > getLineNumber ( ) , varDeclNode - > getVariableType ( ) , " [ " + std : : to_string ( i ) + " ] " , varDeclNode - > getCustomVariableTypeName ( ) , varDeclNode - > getOffset ( ) , 1 ) ;
2020-11-19 11:36:52 +01:00
2020-11-21 20:19:33 +01:00
2020-11-20 21:59:27 +01:00
if ( varDeclNode - > getVariableType ( ) = = Token : : TypeToken : : Type : : Padding ) {
return { new PatternDataPadding ( offset , varDeclNode - > getArraySize ( ) ) , varDeclNode - > getArraySize ( ) } ;
} else if ( varDeclNode - > getVariableType ( ) ! = Token : : TypeToken : : Type : : CustomType ) {
2020-11-21 20:19:33 +01:00
const auto & [ pattern , size ] = this - > createBuiltInTypePattern ( nonArrayVarDeclNode , offset + arrayOffset ) ;
2020-11-19 11:36:52 +01:00
2020-12-06 21:40:57 +01:00
if ( pattern = = nullptr ) {
delete nonArrayVarDeclNode ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-12-06 21:40:57 +01:00
}
pattern - > setEndianess ( varDeclNode - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-19 11:36:52 +01:00
2020-11-21 20:19:33 +01:00
if ( ! arrayColor . has_value ( ) )
arrayColor = pattern - > getColor ( ) ;
pattern - > setColor ( arrayColor . value ( ) ) ;
2020-11-19 11:36:52 +01:00
entries . push_back ( pattern ) ;
2020-11-20 21:59:27 +01:00
arrayOffset + = size ;
2020-11-19 11:36:52 +01:00
} else {
2020-11-20 21:59:27 +01:00
const auto & [ pattern , size ] = this - > createCustomTypePattern ( nonArrayVarDeclNode , offset + arrayOffset ) ;
2020-11-19 11:36:52 +01:00
2020-12-06 21:40:57 +01:00
if ( pattern = = nullptr ) {
delete nonArrayVarDeclNode ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-12-06 21:40:57 +01:00
}
pattern - > setEndianess ( varDeclNode - > getEndianess ( ) . value_or ( varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) ) ;
2020-11-19 11:36:52 +01:00
2020-11-21 20:19:33 +01:00
if ( ! arrayColor . has_value ( ) )
arrayColor = pattern - > getColor ( ) ;
pattern - > setColor ( arrayColor . value ( ) ) ;
2020-11-19 11:36:52 +01:00
entries . push_back ( pattern ) ;
2020-11-20 21:59:27 +01:00
arrayOffset + = size ;
2020-11-19 11:36:52 +01:00
}
delete nonArrayVarDeclNode ;
}
2020-12-06 23:15:51 +01:00
return { new PatternDataArray ( offset , arrayOffset , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) , entries , arrayColor . value_or ( 0xFF000000 ) ) , arrayOffset } ;
2020-11-19 11:36:52 +01:00
}
std : : pair < PatternData * , size_t > Evaluator : : createStringPattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
size_t arraySize = varDeclNode - > getArraySize ( ) ;
2020-12-06 21:40:57 +01:00
return { new PatternDataString ( offset , arraySize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , arraySize } ;
2020-11-19 11:36:52 +01:00
}
std : : pair < PatternData * , size_t > Evaluator : : createCustomTypePattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
auto & currType = this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ;
2020-11-27 21:20:23 +01:00
if ( currType = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-19 11:36:52 +01:00
switch ( currType - > getType ( ) ) {
case ASTNode : : Type : : Struct :
return this - > createStructPattern ( varDeclNode , offset ) ;
2020-11-20 21:29:28 +01:00
case ASTNode : : Type : : Union :
return this - > createUnionPattern ( varDeclNode , offset ) ;
2020-11-19 11:36:52 +01:00
case ASTNode : : Type : : Enum :
return this - > createEnumPattern ( varDeclNode , offset ) ;
2020-11-20 20:26:19 +01:00
case ASTNode : : Type : : Bitfield :
return this - > createBitfieldPattern ( varDeclNode , offset ) ;
2020-11-19 11:36:52 +01:00
case ASTNode : : Type : : TypeDecl :
return this - > createBuiltInTypePattern ( varDeclNode , offset ) ;
}
return { nullptr , 0 } ;
}
std : : pair < PatternData * , size_t > Evaluator : : createBuiltInTypePattern ( ASTNodeVariableDecl * varDeclNode , u64 offset ) {
auto type = varDeclNode - > getVariableType ( ) ;
if ( type = = Token : : TypeToken : : Type : : CustomType ) {
const auto & currType = static_cast < ASTNodeTypeDecl * > ( this - > m_types [ varDeclNode - > getCustomVariableTypeName ( ) ] ) ;
2020-11-27 21:20:23 +01:00
if ( currType = = nullptr ) {
this - > m_error = { varDeclNode - > getLineNumber ( ) , hex : : format ( " '%s' does not name a type " , varDeclNode - > getCustomVariableTypeName ( ) . c_str ( ) ) } ;
2020-11-19 11:36:52 +01:00
return { nullptr , 0 } ;
2020-11-27 21:20:23 +01:00
}
2020-11-19 11:36:52 +01:00
type = currType - > getAssignedType ( ) ;
}
2020-12-27 15:54:12 +01:00
size_t typeSize = Token : : getTypeSize ( type ) ;
2020-11-19 11:36:52 +01:00
size_t arraySize = varDeclNode - > getArraySize ( ) ;
2020-12-27 15:54:12 +01:00
if ( Token : : isSigned ( type ) ) {
2020-11-19 11:36:52 +01:00
if ( typeSize = = 1 & & arraySize = = 1 )
2020-12-06 21:40:57 +01:00
return { new PatternDataCharacter ( offset , typeSize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , 1 } ;
2020-11-19 11:36:52 +01:00
else if ( arraySize > 1 )
return createArrayPattern ( varDeclNode , offset ) ;
else
2020-12-06 21:40:57 +01:00
return { new PatternDataSigned ( offset , typeSize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , typeSize * arraySize } ;
2020-12-27 15:54:12 +01:00
} else if ( Token : : isUnsigned ( varDeclNode - > getVariableType ( ) ) ) {
2020-11-19 11:36:52 +01:00
if ( arraySize > 1 )
return createArrayPattern ( varDeclNode , offset ) ;
else
2020-12-06 21:40:57 +01:00
return { new PatternDataUnsigned ( offset , typeSize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , typeSize * arraySize } ;
2020-12-27 15:54:12 +01:00
} else if ( Token : : isFloatingPoint ( varDeclNode - > getVariableType ( ) ) ) {
2020-11-19 11:36:52 +01:00
if ( arraySize > 1 )
return createArrayPattern ( varDeclNode , offset ) ;
else
2020-12-06 21:40:57 +01:00
return { new PatternDataFloat ( offset , typeSize , varDeclNode - > getVariableName ( ) , varDeclNode - > getEndianess ( ) . value_or ( this - > m_defaultDataEndianess ) ) , typeSize * arraySize } ;
2020-11-19 11:36:52 +01:00
}
return { nullptr , 0 } ;
}
2020-12-22 18:10:01 +01:00
std : : optional < std : : vector < PatternData * > > Evaluator : : evaluate ( const std : : vector < ASTNode * > & ast ) {
2020-11-19 11:36:52 +01:00
// Evaluate types
for ( const auto & node : ast ) {
switch ( node - > getType ( ) ) {
case ASTNode : : Type : : Struct :
{
auto * structNode = static_cast < ASTNodeStruct * > ( node ) ;
this - > m_types . emplace ( structNode - > getName ( ) , structNode ) ;
}
break ;
2020-11-20 21:29:28 +01:00
case ASTNode : : Type : : Union :
{
auto * unionNode = static_cast < ASTNodeUnion * > ( node ) ;
this - > m_types . emplace ( unionNode - > getName ( ) , unionNode ) ;
}
break ;
2020-11-19 11:36:52 +01:00
case ASTNode : : Type : : Enum :
{
auto * enumNode = static_cast < ASTNodeEnum * > ( node ) ;
this - > m_types . emplace ( enumNode - > getName ( ) , enumNode ) ;
}
break ;
2020-11-20 20:26:19 +01:00
case ASTNode : : Type : : Bitfield :
{
auto * bitfieldNode = static_cast < ASTNodeBitField * > ( node ) ;
this - > m_types . emplace ( bitfieldNode - > getName ( ) , bitfieldNode ) ;
}
break ;
2020-11-19 11:36:52 +01:00
case ASTNode : : Type : : TypeDecl :
{
auto * typeDeclNode = static_cast < ASTNodeTypeDecl * > ( node ) ;
if ( typeDeclNode - > getAssignedType ( ) = = Token : : TypeToken : : Type : : CustomType )
this - > m_types . emplace ( typeDeclNode - > getTypeName ( ) , this - > m_types [ typeDeclNode - > getAssignedCustomTypeName ( ) ] ) ;
else
this - > m_types . emplace ( typeDeclNode - > getTypeName ( ) , typeDeclNode ) ;
}
break ;
case ASTNode : : Type : : VariableDecl : break ;
case ASTNode : : Type : : Scope : break ;
}
}
// Evaluate variable declarations
std : : vector < PatternData * > variables ;
for ( const auto & node : ast ) {
if ( node - > getType ( ) ! = ASTNode : : Type : : VariableDecl )
continue ;
auto * varDeclNode = static_cast < ASTNodeVariableDecl * > ( node ) ;
if ( varDeclNode - > getVariableType ( ) = = Token : : TypeToken : : Type : : Signed8Bit & & varDeclNode - > getArraySize ( ) > 1 ) {
const auto & [ pattern , _ ] = createStringPattern ( varDeclNode , varDeclNode - > getOffset ( ) . value ( ) ) ;
variables . push_back ( pattern ) ;
}
else if ( varDeclNode - > getArraySize ( ) > 1 ) {
const auto & [ pattern , _ ] = this - > createArrayPattern ( varDeclNode , varDeclNode - > getOffset ( ) . value ( ) ) ;
variables . push_back ( pattern ) ;
} else if ( varDeclNode - > getVariableType ( ) ! = Token : : TypeToken : : Type : : CustomType ) {
const auto & [ pattern , _ ] = this - > createBuiltInTypePattern ( varDeclNode , varDeclNode - > getOffset ( ) . value ( ) ) ;
variables . push_back ( pattern ) ;
} else {
const auto & [ pattern , _ ] = this - > createCustomTypePattern ( varDeclNode , varDeclNode - > getOffset ( ) . value ( ) ) ;
variables . push_back ( pattern ) ;
}
}
for ( const auto & var : variables )
if ( var = = nullptr )
2020-12-22 18:10:01 +01:00
return { } ;
2020-11-19 11:36:52 +01:00
2020-12-22 18:10:01 +01:00
return variables ;
2020-11-19 11:36:52 +01:00
}
}