#include "lang/evaluator.hpp" #include namespace hex::lang { Evaluator::Evaluator() { } std::pair Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { std::vector members; auto structNode = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); if (structNode == nullptr) return { nullptr, 0 }; size_t structSize = 0; for (const auto &node : structNode->getNodes()) { const auto &member = static_cast(node); const auto typeDeclNode = static_cast(this->m_types[member->getCustomVariableTypeName()]); if (member->getVariableType() == Token::TypeToken::Type::Signed8Bit && member->getArraySize() > 1) { const auto &[pattern, size] = this->createStringPattern(member, offset + structSize); if (pattern == nullptr) return { nullptr, 0 }; members.push_back(pattern); structSize += size; } else if (member->getVariableType() == Token::TypeToken::Type::CustomType && typeDeclNode != nullptr && typeDeclNode->getAssignedType() == Token::TypeToken::Type::Signed8Bit && member->getArraySize() > 1) { const auto &[pattern, size] = this->createStringPattern(member, offset + structSize); if (pattern == nullptr) return { nullptr, 0 }; members.push_back(pattern); structSize += size; } else if (member->getArraySize() > 1) { const auto &[pattern, size] = this->createArrayPattern(member, offset + structSize); if (pattern == nullptr) return { nullptr, 0 }; members.push_back(pattern); structSize += size; } else if (member->getVariableType() != Token::TypeToken::Type::CustomType) { const auto &[pattern, size] = this->createBuiltInTypePattern(member, offset + structSize); if (pattern == nullptr) return { nullptr, 0 }; members.push_back(pattern); structSize += size; } else { const auto &[pattern, size] = this->createCustomTypePattern(member, offset + structSize); if (pattern == nullptr) return { nullptr, 0 }; members.push_back(pattern); structSize += size; } } return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), structNode->getName(), members, 0x00FFFFFF), structSize }; } std::pair Evaluator::createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { std::vector> enumValues; auto *enumType = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); if (enumType == nullptr) return { nullptr, 0 }; size_t size = getTypeSize(enumType->getUnderlyingType()); return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues()), size }; } std::pair Evaluator::createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { std::vector entries; size_t arraySize = 0; for (u32 i = 0; i < varDeclNode->getArraySize(); i++) { ASTNodeVariableDecl *nonArrayVarDeclNode = new ASTNodeVariableDecl(varDeclNode->getVariableType(), "[" + std::to_string(i) + "]", varDeclNode->getCustomVariableTypeName(), varDeclNode->getOffset(), 1); if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) { const auto &[pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arraySize); if (pattern == nullptr) return { nullptr, 0 }; entries.push_back(pattern); arraySize += size; } else { const auto &[pattern, size] = this->createCustomTypePattern(nonArrayVarDeclNode, offset + arraySize); if (pattern == nullptr) return { nullptr, 0 }; entries.push_back(pattern); arraySize += size; } delete nonArrayVarDeclNode; } return { new PatternDataArray(offset, arraySize, varDeclNode->getVariableName(), entries, 0x00FFFFFF), arraySize }; } std::pair Evaluator::createStringPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { size_t arraySize = varDeclNode->getArraySize(); return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName()), arraySize }; } std::pair Evaluator::createCustomTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { auto &currType = this->m_types[varDeclNode->getCustomVariableTypeName()]; if (currType == nullptr) return { nullptr, 0 }; switch (currType->getType()) { case ASTNode::Type::Struct: return this->createStructPattern(varDeclNode, offset); case ASTNode::Type::Enum: return this->createEnumPattern(varDeclNode, offset); case ASTNode::Type::TypeDecl: return this->createBuiltInTypePattern(varDeclNode, offset); } return { nullptr, 0 }; } std::pair Evaluator::createBuiltInTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { auto type = varDeclNode->getVariableType(); if (type == Token::TypeToken::Type::CustomType) { const auto &currType = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); if (currType == nullptr) return { nullptr, 0 }; type = currType->getAssignedType(); } size_t typeSize = getTypeSize(type); size_t arraySize = varDeclNode->getArraySize(); if (isSigned(type)) { if (typeSize == 1 && arraySize == 1) return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName()), 1 }; else if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; } else if (isUnsigned(varDeclNode->getVariableType())) { if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; } else if (isFloatingPoint(varDeclNode->getVariableType())) { if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; } return { nullptr, 0 }; } std::pair> Evaluator::evaluate(const std::vector &ast) { // Evaluate types for (const auto &node : ast) { switch(node->getType()) { case ASTNode::Type::Struct: { auto *structNode = static_cast(node); this->m_types.emplace(structNode->getName(), structNode); } break; case ASTNode::Type::Enum: { auto *enumNode = static_cast(node); this->m_types.emplace(enumNode->getName(), enumNode); } break; case ASTNode::Type::TypeDecl: { auto *typeDeclNode = static_cast(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 variables; for (const auto &node : ast) { if (node->getType() != ASTNode::Type::VariableDecl) continue; auto *varDeclNode = static_cast(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) return { ResultEvaluatorError, { } }; return { ResultSuccess, variables }; } }