patterns: Fixed enum constant literals not being interpreted as correct type

This commit is contained in:
WerWolv 2021-03-31 22:10:06 +02:00
parent 356273d71e
commit a2c80e3fd6
2 changed files with 35 additions and 12 deletions

View File

@ -102,7 +102,8 @@ namespace hex::lang {
EndOfProgram
};
using IntegerLiteral = std::pair<ValueType, std::variant<u8, s8, u16, s16, u32, s32, u64, s64, u128, s128, float, double>>;
using Integers = std::variant<u8, s8, u16, s16, u32, s32, u64, s64, u128, s128, float, double>;
using IntegerLiteral = std::pair<ValueType, Integers>;
using ValueTypes = std::variant<Keyword, std::string, Operator, IntegerLiteral, ValueType, Separator>;
Token(Type type, auto value, u32 lineNumber) : type(type), value(value), lineNumber(lineNumber) {
@ -125,6 +126,27 @@ namespace hex::lang {
return static_cast<u32>(type) >> 4;
}
[[nodiscard]] constexpr static inline IntegerLiteral castTo(ValueType type, const Integers &literal) {
return std::visit([type](auto &&value) {
switch (type) {
case ValueType::Signed8Bit: return IntegerLiteral(type, static_cast<s8>(value));
case ValueType::Signed16Bit: return IntegerLiteral(type, static_cast<s16>(value));
case ValueType::Signed32Bit: return IntegerLiteral(type, static_cast<s32>(value));
case ValueType::Signed64Bit: return IntegerLiteral(type, static_cast<s64>(value));
case ValueType::Signed128Bit: return IntegerLiteral(type, static_cast<s128>(value));
case ValueType::Unsigned8Bit: return IntegerLiteral(type, static_cast<u8>(value));
case ValueType::Unsigned16Bit: return IntegerLiteral(type, static_cast<u16>(value));
case ValueType::Unsigned32Bit: return IntegerLiteral(type, static_cast<u32>(value));
case ValueType::Unsigned64Bit: return IntegerLiteral(type, static_cast<u64>(value));
case ValueType::Unsigned128Bit: return IntegerLiteral(type, static_cast<u128>(value));
case ValueType::Float: return IntegerLiteral(type, static_cast<float>(value));
case ValueType::Double: return IntegerLiteral(type, static_cast<double>(value));
case ValueType::Character: return IntegerLiteral(type, static_cast<char>(value));
default: __builtin_unreachable();
}
}, literal);
}
[[nodiscard]] constexpr static auto getTypeName(const lang::Token::ValueType type) {
switch (type) {
case ValueType::Signed8Bit: return "s8";

View File

@ -483,6 +483,17 @@ namespace hex::lang {
PatternData* Evaluator::evaluateEnum(ASTNodeEnum *node) {
std::vector<std::pair<Token::IntegerLiteral, std::string>> entryPatterns;
auto underlyingType = dynamic_cast<ASTNodeTypeDecl*>(node->getUnderlyingType());
if (underlyingType == nullptr)
this->getConsole().abortEvaluation("enum underlying type was not ASTNodeTypeDecl. This is a bug");
size_t size;
auto builtinUnderlyingType = dynamic_cast<ASTNodeBuiltinType*>(underlyingType->getType());
if (builtinUnderlyingType != nullptr)
size = Token::getTypeSize(builtinUnderlyingType->getType());
else
this->getConsole().abortEvaluation("invalid enum underlying type");
auto startOffset = this->m_currOffset;
for (auto &[name, value] : node->getEntries()) {
auto expression = dynamic_cast<ASTNodeNumericExpression*>(value);
@ -492,19 +503,9 @@ namespace hex::lang {
auto valueNode = evaluateMathematicalExpression(expression);
SCOPE_EXIT( delete valueNode; );
entryPatterns.push_back({{ valueNode->getType(), valueNode->getValue() }, name });
entryPatterns.push_back({ Token::castTo(builtinUnderlyingType->getType(), valueNode->getValue()), name });
}
auto underlyingType = dynamic_cast<ASTNodeTypeDecl*>(node->getUnderlyingType());
if (underlyingType == nullptr)
this->getConsole().abortEvaluation("enum underlying type was not ASTNodeTypeDecl. This is a bug");
size_t size;
if (auto builtinType = dynamic_cast<ASTNodeBuiltinType*>(underlyingType->getType()); builtinType != nullptr)
size = Token::getTypeSize(builtinType->getType());
else
this->getConsole().abortEvaluation("invalid enum underlying type");
this->m_currOffset += size;
return this->evaluateAttributes(node, new PatternDataEnum(startOffset, size, entryPatterns));