Squelched DNA_COUNT-referenced fields for smarter YAML handling

This commit is contained in:
Jack Andersen 2016-03-03 11:42:26 -10:00
parent 022142a9ec
commit a0515fe4aa
2 changed files with 185 additions and 67 deletions

View File

@ -83,6 +83,99 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
clang::ASTContext& context; clang::ASTContext& context;
StreamOut& fileOut; StreamOut& fileOut;
struct YAMLFieldNode
{
enum class Type
{
EnterSubVector,
LeaveSubVector,
Value,
VectorRefSize,
VectorNoRefSize,
Buffer,
String,
WString,
Record
} m_type;
std::string m_fieldNameBare;
std::string m_fieldName;
std::string m_sizeExpr;
std::string m_ioOp;
bool m_output = true;
YAMLFieldNode(Type tp) : m_type(tp) {}
void output(StreamOut& out, int p) const
{
if (m_output)
{
out << " /* " << m_fieldName << " */\n";
switch (m_type)
{
case Type::EnterSubVector:
if (!p)
out << " size_t __" << m_fieldName << "Count;\n " ATHENA_YAML_READER ".enterSubVector(\"" << m_fieldName << "\", __" << m_fieldName << "Count);\n";
else
out << " " ATHENA_YAML_WRITER ".enterSubVector(\"" << m_fieldName << "\");\n";
break;
case Type::LeaveSubVector:
if (!p)
out << " " ATHENA_YAML_READER ".leaveSubVector();\n";
else
out << " " ATHENA_YAML_WRITER ".leaveSubVector();\n";
break;
case Type::Value:
if (!p)
out << " " << m_fieldName << " = " << m_ioOp << ";\n";
else
out << " " << m_ioOp << "\n";
break;
case Type::VectorRefSize:
if (!p)
out << " " << m_sizeExpr << " = " ATHENA_YAML_READER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
else
out << " " ATHENA_YAML_WRITER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
break;
case Type::VectorNoRefSize:
if (!p)
out << " " ATHENA_YAML_READER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
else
out << " " ATHENA_YAML_WRITER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
break;
case Type::Buffer:
if (!p)
out << " " << m_fieldName << " = " ATHENA_YAML_READER ".readUBytes(\"" << m_fieldNameBare << "\");\n";
else
out << " " ATHENA_YAML_WRITER ".writeUBytes(\"" << m_fieldNameBare << "\", " << m_fieldName << ", " << m_sizeExpr << ");\n";
break;
case Type::String:
if (!p)
out << " " << m_fieldName << " = " ATHENA_YAML_READER ".readString(\"" << m_fieldNameBare << "\");\n";
else
out << " " ATHENA_YAML_WRITER ".writeString(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
break;
case Type::WString:
if (!p)
out << " " << m_fieldName << " = " ATHENA_YAML_READER ".readWString(\"" << m_fieldNameBare << "\");\n";
else
out << " " ATHENA_YAML_WRITER ".writeWString(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
break;
case Type::Record:
if (!p)
out << " " ATHENA_YAML_READER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
else
out << " " ATHENA_YAML_WRITER ".enumerate(\"" << m_fieldNameBare << "\", " << m_fieldName << ");\n";
break;
}
}
else
{
out << " /* " << m_fieldName << " squelched */\n";
}
}
};
bool isDNARecord(const clang::CXXRecordDecl* record, std::string& baseDNA, bool& isYAML) bool isDNARecord(const clang::CXXRecordDecl* record, std::string& baseDNA, bool& isYAML)
{ {
for (const clang::CXXBaseSpecifier& base : record->bases()) for (const clang::CXXBaseSpecifier& base : record->bases())
@ -1827,6 +1920,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
void emitYAMLFuncs(clang::CXXRecordDecl* decl, const std::string& baseDNA) void emitYAMLFuncs(clang::CXXRecordDecl* decl, const std::string& baseDNA)
{ {
std::vector<YAMLFieldNode> outputNodes;
/* Two passes - read then write */ /* Two passes - read then write */
for (int p=0 ; p<2 ; ++p) for (int p=0 ; p<2 ; ++p)
{ {
@ -1843,6 +1938,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
fileOut << " " << baseDNA << "::read(" ATHENA_YAML_READER ");\n"; fileOut << " " << baseDNA << "::read(" ATHENA_YAML_READER ");\n";
} }
outputNodes.clear();
outputNodes.reserve(std::distance(decl->field_begin(), decl->field_end()));
for (const clang::FieldDecl* field : decl->fields()) for (const clang::FieldDecl* field : decl->fields())
{ {
clang::QualType qualType = field->getType(); clang::QualType qualType = field->getType();
@ -1868,10 +1966,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (regType->getTypeClass() == clang::Type::Elaborated) if (regType->getTypeClass() == clang::Type::Elaborated)
regType = regType->getUnqualifiedDesugaredType(); regType = regType->getUnqualifiedDesugaredType();
if (!p) outputNodes.emplace_back(YAMLFieldNode::Type::EnterSubVector);
fileOut << " " ATHENA_YAML_READER ".enterSubVector(\"" << field->getName() << "\");\n"; outputNodes.back().m_fieldName = field->getNameAsString();
else
fileOut << " " ATHENA_YAML_WRITER ".enterSubVector(\"" << field->getName() << "\");\n";
} }
for (int e=0 ; e<arraySize ; ++e) for (int e=0 ; e<arraySize ; ++e)
@ -1939,11 +2035,10 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (ioOp.empty()) if (ioOp.empty())
continue; continue;
fileOut << " /* " << fieldName << " */\n"; outputNodes.emplace_back(YAMLFieldNode::Type::Value);
if (!p) YAMLFieldNode& outNode = outputNodes.back();
fileOut << " " << fieldName << " = " << ioOp << ";\n"; outNode.m_fieldName = fieldName;
else outNode.m_ioOp = ioOp;
fileOut << " " << ioOp << "\n";
} }
else if (!tsDecl->getName().compare("Vector")) else if (!tsDecl->getName().compare("Vector"))
{ {
@ -1970,6 +2065,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
const clang::TemplateArgument* sizeArg = nullptr; const clang::TemplateArgument* sizeArg = nullptr;
size_t idx = 0; size_t idx = 0;
bool bad = false; bool bad = false;
YAMLFieldNode::Type yamlFieldType;
for (const clang::TemplateArgument& arg : *tsType) for (const clang::TemplateArgument& arg : *tsType)
{ {
if (arg.getKind() == clang::TemplateArgument::Type) if (arg.getKind() == clang::TemplateArgument::Type)
@ -1992,6 +2088,22 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
const clang::Expr* argExpr = uExpr->getArgumentExpr(); const clang::Expr* argExpr = uExpr->getArgumentExpr();
while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass)
argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr();
if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass)
{
clang::DeclRefExpr* drExpr = (clang::DeclRefExpr*)argExpr;
std::string testName = drExpr->getFoundDecl()->getNameAsString();
for (auto i=outputNodes.rbegin() ; i != outputNodes.rend() ; ++i)
{
if (i->m_fieldName == testName)
{
i->m_output = false;
break;
}
}
yamlFieldType = YAMLFieldNode::Type::VectorRefSize;
}
else
yamlFieldType = YAMLFieldNode::Type::VectorNoRefSize;
llvm::raw_string_ostream strStream(sizeExpr); llvm::raw_string_ostream strStream(sizeExpr);
argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy());
} }
@ -2021,12 +2133,11 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (sizeExpr.empty()) if (sizeExpr.empty())
continue; continue;
fileOut << " /* " << fieldName << " */\n"; outputNodes.emplace_back(yamlFieldType);
if (!p) YAMLFieldNode& outNode = outputNodes.back();
fileOut << " " ATHENA_YAML_READER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ", " << sizeExpr << ");\n"; outNode.m_fieldName = fieldName;
else outNode.m_fieldNameBare = fieldNameBare;
fileOut << " " ATHENA_YAML_WRITER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n"; outNode.m_sizeExpr = sizeExpr;
} }
else if (!tsDecl->getName().compare("Buffer")) else if (!tsDecl->getName().compare("Buffer"))
{ {
@ -2052,20 +2163,19 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (sizeExprStr.empty()) if (sizeExprStr.empty())
continue; continue;
fileOut << " /* " << fieldName << " */\n"; outputNodes.emplace_back(YAMLFieldNode::Type::Buffer);
if (!p) YAMLFieldNode& outNode = outputNodes.back();
fileOut << " " << fieldName << " = " ATHENA_YAML_READER ".readUBytes(\"" << fieldNameBare << "\");\n"; outNode.m_fieldName = fieldName;
else outNode.m_fieldNameBare = fieldNameBare;
fileOut << " " ATHENA_YAML_WRITER ".writeUBytes(\"" << fieldNameBare << "\", " << fieldName << ", " << sizeExprStr << ");\n"; outNode.m_sizeExpr = sizeExprStr;
} }
else if (!tsDecl->getName().compare("String") || else if (!tsDecl->getName().compare("String") ||
!tsDecl->getName().compare("WStringAsString")) !tsDecl->getName().compare("WStringAsString"))
{ {
fileOut << " /* " << fieldName << " */\n"; outputNodes.emplace_back(YAMLFieldNode::Type::String);
if (!p) YAMLFieldNode& outNode = outputNodes.back();
fileOut << " " << fieldName << " = " ATHENA_YAML_READER ".readString(\"" << fieldNameBare << "\");\n"; outNode.m_fieldName = fieldName;
else outNode.m_fieldNameBare = fieldNameBare;
fileOut << " " ATHENA_YAML_WRITER ".writeString(\"" << fieldNameBare << "\", " << fieldName << ");\n";
} }
else if (!tsDecl->getName().compare("WString")) else if (!tsDecl->getName().compare("WString"))
{ {
@ -2110,11 +2220,10 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (endianVal != 0 && endianVal != 1) if (endianVal != 0 && endianVal != 1)
continue; continue;
fileOut << " /* " << fieldName << " */\n"; outputNodes.emplace_back(YAMLFieldNode::Type::WString);
if (!p) YAMLFieldNode& outNode = outputNodes.back();
fileOut << " " << fieldName << " = " ATHENA_YAML_READER ".readWString(\"" << fieldNameBare << "\");\n"; outNode.m_fieldName = fieldName;
else outNode.m_fieldNameBare = fieldNameBare;
fileOut << " " ATHENA_YAML_WRITER ".writeWString(\"" << fieldNameBare << "\", " << fieldName << ");\n";
} }
} }
@ -2126,16 +2235,10 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
bool isYAML = false; bool isYAML = false;
if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA, isYAML)) if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA, isYAML))
{ {
if (!p) outputNodes.emplace_back(YAMLFieldNode::Type::Record);
{ YAMLFieldNode& outNode = outputNodes.back();
fileOut << " /* " << fieldName << " */\n" outNode.m_fieldName = fieldName;
" " ATHENA_YAML_READER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n"; outNode.m_fieldNameBare = fieldNameBare;
}
else
{
fileOut << " /* " << fieldName << " */\n"
" " ATHENA_YAML_WRITER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n";
}
} }
} }
@ -2143,14 +2246,14 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (isArray) if (isArray)
{ {
if (!p) outputNodes.emplace_back(YAMLFieldNode::Type::LeaveSubVector);
fileOut << " " ATHENA_YAML_READER ".leaveSubVector();\n";
else
fileOut << " " ATHENA_YAML_WRITER ".leaveSubVector();\n";
} }
} }
for (const YAMLFieldNode& node : outputNodes)
node.output(fileOut, p);
fileOut << "}\n\n"; fileOut << "}\n\n";
} }
fileOut << "const char* " << decl->getQualifiedNameAsString() << "::DNAType()\n{\n return \"" << decl->getQualifiedNameAsString() << "\";\n}\n\n"; fileOut << "const char* " << decl->getQualifiedNameAsString() << "::DNAType()\n{\n return \"" << decl->getQualifiedNameAsString() << "\";\n}\n\n";

View File

@ -576,7 +576,7 @@ public:
leaveSubRecord(); leaveSubRecord();
} }
bool enterSubVector(const char* name) bool enterSubVector(const char* name, size_t& countOut)
{ {
YAMLNode* curSub = m_subStack.back(); YAMLNode* curSub = m_subStack.back();
for (const auto& item : curSub->m_mapChildren) for (const auto& item : curSub->m_mapChildren)
@ -584,11 +584,21 @@ public:
if (!item.first.compare(name)) if (!item.first.compare(name))
{ {
YAMLNode* nextSub = item.second.get(); YAMLNode* nextSub = item.second.get();
if (nextSub->m_type == YAML_SEQUENCE_NODE)
{
countOut = nextSub->m_seqChildren.size();
}
else
{
atError("'%s' is not a vector field", name);
countOut = 0;
}
m_subStack.push_back(nextSub); m_subStack.push_back(nextSub);
m_seqTrackerStack.push_back(0); m_seqTrackerStack.push_back(0);
return true; return true;
} }
} }
countOut = 0;
return false; return false;
} }
@ -600,18 +610,18 @@ public:
m_seqTrackerStack.pop_back(); m_seqTrackerStack.pop_back();
} }
} }
template <class T> template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count, size_t enumerate(const char* name, std::vector<T>& vector,
typename std::enable_if<!std::is_arithmetic<T>::value && typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value && !std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value && !std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>::type* = 0) !std::is_same<T, atVec4f>::value>::type* = 0)
{ {
size_t countOut;
enterSubVector(name, countOut);
vector.clear(); vector.clear();
vector.reserve(count); vector.reserve(countOut);
enterSubVector(name); for (size_t i=0 ; i<countOut ; ++i)
for (size_t i=0 ; i<count ; ++i)
{ {
vector.emplace_back(); vector.emplace_back();
enterSubRecord(nullptr); enterSubRecord(nullptr);
@ -619,31 +629,35 @@ public:
leaveSubRecord(); leaveSubRecord();
} }
leaveSubVector(); leaveSubVector();
return countOut;
} }
template <class T> template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count, size_t enumerate(const char* name, std::vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value>::type* = 0) std::is_same<T, atVec4f>::value>::type* = 0)
{ {
size_t countOut;
enterSubVector(name, countOut);
vector.clear(); vector.clear();
vector.reserve(count); vector.reserve(countOut);
enterSubVector(name); for (size_t i=0 ; i<countOut ; ++i)
for (size_t i=0 ; i<count ; ++i)
vector.push_back(readVal<T>(name)); vector.push_back(readVal<T>(name));
leaveSubVector(); leaveSubVector();
return countOut;
} }
template <class T> template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count, size_t enumerate(const char* name, std::vector<T>& vector,
std::function<void(YAMLDocReader&, T&)> readf) std::function<void(YAMLDocReader&, T&)> readf)
{ {
size_t countOut;
enterSubVector(name, countOut);
vector.clear(); vector.clear();
vector.reserve(count); vector.reserve(countOut);
enterSubVector(name); for (size_t i=0 ; i<countOut ; ++i)
for (size_t i=0 ; i<count ; ++i)
{ {
vector.emplace_back(); vector.emplace_back();
enterSubRecord(nullptr); enterSubRecord(nullptr);
@ -651,6 +665,7 @@ public:
leaveSubRecord(); leaveSubRecord();
} }
leaveSubVector(); leaveSubVector();
return countOut;
} }
template <typename RETURNTYPE> template <typename RETURNTYPE>