trick/trick_source/codegen/Interface_Code_Gen/ConstructValues.cpp
2020-04-17 09:48:52 -05:00

222 lines
8.0 KiB
C++

#include <iostream>
#include <sstream>
#include <clang/AST/DeclTemplate.h>
#include "ConstructValues.hh"
//====================================================================================
bool ConstructValues::ContainerClass::extractTemplateArgType(const clang::TemplateArgument& ta) {
clang::QualType qt = ta.getAsType() ;
const clang::Type * t = qt.getTypePtrOrNull() ;
if ( t != NULL ) {
ContainerClass inner_cc ;
if (t->getTypeClass() == clang::Type::Record and t->getAsCXXRecordDecl()) {
clang::CXXRecordDecl * crd = t->getAsCXXRecordDecl() ;
if ( clang::isa<clang::ClassTemplateSpecializationDecl>(crd) ) {
// template argument is a template specialization
if (!inner_cc.extractType(clang::cast<clang::ClassTemplateSpecializationDecl>(crd))) {
return false ;
}
} else {
// template argument record type, but not a template specialization
inner_cc.name = qt.getAsString() ;
}
} else {
// template argument not a record type.
inner_cc.name = qt.getAsString() ;
}
template_args.push_back(inner_cc) ;
}
return true ;
}
bool ConstructValues::ContainerClass::extractType(const clang::RecordDecl * rd) {
if (! rd->getIdentifier()) {
return false ;
}
// Set the name of this type.
name = rd->getName().str() ;
// If this type is a template specialization we need to save the template argument types.
if (const clang::ClassTemplateSpecializationDecl *ctsd = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(rd)) {
for (const clang::TemplateArgument& ta : ctsd->getTemplateArgs().asArray()) {
if ( ta.getKind() == clang::TemplateArgument::Type ) {
// Class types and intrinsic types
if ( !extractTemplateArgType(ta) ) {
return false ;
}
} else if ( ta.getKind() == clang::TemplateArgument::Pack ) {
// a Pack is the variables in a variadric template
for (const clang::TemplateArgument& pack_ta : ta.getPackAsArray()) {
if ( pack_ta.getKind() == clang::TemplateArgument::Type ) {
if ( !extractTemplateArgType(pack_ta) ) {
return false ;
}
}
}
} else {
// This template argument is not a clang::TemplateArgument::Type. We don't currently handle these.
return false ;
}
}
}
// if we reach the end then we can deal with the class name, return true.
return true ;
}
static void mangle_template_param(std::string &work_string, const std::string & delimiter) {
if ( !delimiter.compare("__") ) {
std::replace( work_string.begin(), work_string.end(), '*', '_') ;
std::replace( work_string.begin(), work_string.end(), '[', '_') ;
std::replace( work_string.begin(), work_string.end(), ']', '_') ;
std::replace( work_string.begin(), work_string.end(), ':', '_') ;
work_string.erase(std::remove_if(work_string.begin(), work_string.end(),
(int(*)(int))std::isspace), work_string.end()) ;
}
}
void ConstructValues::ContainerClass::printTemplateList(std::ostream& ostream, const std::string& delimiter) {
if ( template_args.size() ) {
std::string obracket("<"), comma(","), cbracket(">"), work_string ;
if ( !delimiter.compare("__") ) {
obracket = comma = cbracket = "_" ;
}
ostream << obracket ;
unsigned int arg_size = template_args.size() - 1 ;
for (unsigned int ii = 0 ; ii < arg_size ; ii++ ) {
work_string = template_args[ii].name ;
mangle_template_param(work_string, delimiter) ;
ostream << work_string ;
template_args[ii].printTemplateList(ostream, delimiter);
ostream << comma ;
}
work_string = template_args[arg_size].name ;
mangle_template_param(work_string, delimiter) ;
ostream << work_string ;
template_args[arg_size].printTemplateList(ostream, delimiter);
ostream << cbracket ;
}
}
void ConstructValues::ContainerClass::printContainerClass(std::ostream& ostream, const std::string& delimiter) {
ostream << name ;
printTemplateList(ostream, delimiter) ;
ostream << delimiter ;
}
//====================================================================================
ConstructValues::ConstructValues() {}
void ConstructValues::setName(std::string in_name) {
name = in_name ;
}
std::string ConstructValues::getName() {
return name ;
}
void ConstructValues::setFileName(std::string in_name) {
file_name = in_name ;
}
std::string ConstructValues::getFileName() {
return file_name ;
}
void ConstructValues::clearNamespacesAndClasses() {
namespaces.clear() ;
container_classes.clear() ;
}
bool ConstructValues::getNamespacesAndClasses( const clang::DeclContext * Ctx ) {
// Save container namespaces and classes.
typedef clang::SmallVector<const clang::DeclContext *, 8> ContextsTy;
ContextsTy Contexts;
// Collect contexts.
while (Ctx && clang::isa<clang::NamedDecl>(Ctx)) {
Contexts.push_back(Ctx);
Ctx = Ctx->getParent();
};
for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) {
if (const clang::NamespaceDecl *nd = clang::dyn_cast<clang::NamespaceDecl>(*I)) {
if (! nd->isAnonymousNamespace()) {
//std::cout << "namespace " << nd->getIdentifier()->getName().str() << std::endl ;
std::string temp_name = nd->getIdentifier()->getName().str() ;
if ( temp_name.compare("std") and temp_name.compare("__1")) {
namespaces.push_back(nd->getIdentifier()->getName().str()) ;
}
}
} else if (const clang::RecordDecl *rd = clang::dyn_cast<clang::RecordDecl>(*I)) {
ContainerClass cc ;
if (!cc.extractType(rd)) {
return false ;
}
container_classes.push_back(cc) ;
}
}
return true ;
}
std::string ConstructValues::getFullyQualifiedName(const std::string& delimiter) {
std::ostringstream oss;
printNamespaces(oss, delimiter);
printContainerClasses(oss, delimiter);
oss << name;
return oss.str();
}
bool ConstructValues::isNameOrFileNameEmpty() {
return name.empty() or file_name.empty();
}
void ConstructValues::printOpenNamespaceBlocks(std::ostream& ostream) {
for (auto name : namespaces) {
ostream << "namespace " << name << " {" << std::endl;
}
}
void ConstructValues::printCloseNamespaceBlocks(std::ostream& ostream) {
for (auto name : namespaces) {
ostream << "}" << std::endl;
}
}
void ConstructValues::printNamespaces(std::ostream& ostream, const std::string& delimiter) {
for (auto name : namespaces) {
ostream << name << delimiter;
}
}
void ConstructValues::printContainerClasses(std::ostream& ostream, const std::string& delimiter) {
for (auto c : container_classes) {
c.printContainerClass(ostream, delimiter);
}
}
void ConstructValues::printNamespacesAndContainerClasses(std::ostream& ostream, const std::string& delimiter) {
printNamespaces(ostream, delimiter);
printContainerClasses(ostream, delimiter);
}
std::string ConstructValues::getNamespacesAndContainerClasses(const std::string& delimiter) {
std::string result = "";
for (auto name : namespaces) {
result += name + delimiter;
}
for (auto c : container_classes) {
std::stringstream ss ;
c.printContainerClass(ss, delimiter);
result += ss.str() ;
}
return result;
}
std::string ConstructValues::getFullyQualifiedTypeName(const std::string& delimiter) {
std::ostringstream oss ;
printNamespacesAndContainerClasses(oss, delimiter) ;
oss << name ;
return oss.str() ;
}