From ae3abca2b15794bdde313eed3f7f9391cd68f72d Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 26 Oct 2009 09:31:08 -0300 Subject: forked boostpythongenerator project to separate the generatorrunner so that it could be used independently; the qtdoc generator module remained part of generatorrunner --- generators/CMakeLists.txt | 1 - generators/boostpython/CMakeLists.txt | 19 - generators/boostpython/boostpython.cpp | 29 - generators/boostpython/boostpythongenerator.cpp | 321 ----- generators/boostpython/boostpythongenerator.h | 124 -- generators/boostpython/convertergenerator.cpp | 178 --- generators/boostpython/convertergenerator.h | 77 -- generators/boostpython/cppgenerator.cpp | 1560 ----------------------- generators/boostpython/cppgenerator.h | 107 -- generators/boostpython/hppgenerator.cpp | 220 ---- generators/boostpython/hppgenerator.h | 51 - generators/boostpython/main.cpp | 34 - generators/qtdoc/main.cpp | 2 +- generators/qtdoc/qtdocgenerator.cpp | 2 +- generators/qtdoc/qtdocgenerator.h | 2 +- 15 files changed, 3 insertions(+), 2724 deletions(-) delete mode 100644 generators/boostpython/CMakeLists.txt delete mode 100644 generators/boostpython/boostpython.cpp delete mode 100644 generators/boostpython/boostpythongenerator.cpp delete mode 100644 generators/boostpython/boostpythongenerator.h delete mode 100644 generators/boostpython/convertergenerator.cpp delete mode 100644 generators/boostpython/convertergenerator.h delete mode 100644 generators/boostpython/cppgenerator.cpp delete mode 100644 generators/boostpython/cppgenerator.h delete mode 100644 generators/boostpython/hppgenerator.cpp delete mode 100644 generators/boostpython/hppgenerator.h delete mode 100644 generators/boostpython/main.cpp (limited to 'generators') diff --git a/generators/CMakeLists.txt b/generators/CMakeLists.txt index 73b5eea22..f26def274 100644 --- a/generators/CMakeLists.txt +++ b/generators/CMakeLists.txt @@ -1,2 +1 @@ -add_subdirectory(boostpython) add_subdirectory(qtdoc) diff --git a/generators/boostpython/CMakeLists.txt b/generators/boostpython/CMakeLists.txt deleted file mode 100644 index f94d800be..000000000 --- a/generators/boostpython/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -project(boostpython) - -set(boostpython_generator_SRC -boostpythongenerator.cpp -convertergenerator.cpp -cppgenerator.cpp -hppgenerator.cpp -boostpython.cpp -) - -add_executable(boostpythongenerator main.cpp) -target_link_libraries(boostpythongenerator ${QT_QTCORE_LIBRARY}) - -add_library(boostpython_generator SHARED ${boostpython_generator_SRC}) -target_link_libraries(boostpython_generator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} genrunner) - -install(TARGETS boostpython_generator DESTINATION ${generator_plugin_DIR}) -install(TARGETS boostpythongenerator DESTINATION bin) - diff --git a/generators/boostpython/boostpython.cpp b/generators/boostpython/boostpython.cpp deleted file mode 100644 index e165f93b9..000000000 --- a/generators/boostpython/boostpython.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* This file is part of the API Extractor project. -* -* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -* -* Contact: PySide team -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -* 02110-1301 USA -* -*/ - -#include "generator.h" -#include "hppgenerator.h" -#include "cppgenerator.h" -#include "convertergenerator.h" - -EXPORT_GENERATOR_PLUGIN(new HppGenerator << new CppGenerator << new ConverterGenerator) diff --git a/generators/boostpython/boostpythongenerator.cpp b/generators/boostpython/boostpythongenerator.cpp deleted file mode 100644 index d266d395a..000000000 --- a/generators/boostpython/boostpythongenerator.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "boostpythongenerator.h" -#include - -#include -#include -#include -#include -#include - -#define NULL_VALUE "NULL" -#define COMMENT_LINE_WIDTH 77 - -static Indentor INDENT; -static void dump_function(AbstractMetaFunctionList lst); - -QString BoostPythonGenerator::getWrapperName(const AbstractMetaClass* metaClass) -{ - QString result = metaClass->typeEntry()->qualifiedCppName().toLower(); - result.replace("::", "_"); - result += "_wrapper"; - return result; -} - -QString BoostPythonGenerator::argumentString(const AbstractMetaFunction *cppFunction, - const AbstractMetaArgument *cppArgument, - Options options) const -{ - QString modifiedType = cppFunction->typeReplaced(cppArgument->argumentIndex() + 1); - QString arg; - - if ((options & OriginalTypeDescription) || modifiedType.isEmpty()) - arg = translateType(cppArgument->type(), cppFunction->implementingClass(), options); - else - arg = modifiedType.replace('$', '.'); - - if (!(options & Generator::SkipName)) { - arg += " "; - arg += cppArgument->argumentName(); - } - - QList referenceCounts; - referenceCounts = cppFunction->referenceCounts(cppFunction->implementingClass(), cppArgument->argumentIndex() + 1); - if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues && - !cppArgument->defaultValueExpression().isEmpty()) { - QString defaultValue = cppArgument->defaultValueExpression(); - if (defaultValue == "NULL") - defaultValue = NULL_VALUE; - - //WORKAROUND: fix this please - if (defaultValue.startsWith("new ")) - defaultValue.remove(0, 4); - - arg += " = " + defaultValue; - } - - return arg; -} - -void BoostPythonGenerator::writeArgument(QTextStream &s, - const AbstractMetaFunction *func, - const AbstractMetaArgument *cppArgument, - Options options) const -{ - s << argumentString(func, cppArgument, options); -} - -void BoostPythonGenerator::writeFunctionArguments(QTextStream &s, - const AbstractMetaFunction *func, - Options options) const -{ - AbstractMetaArgumentList arguments = func->arguments(); - - if (options & Generator::WriteSelf) { - s << func->implementingClass()->name() << '&'; - if (!(options & SkipName)) - s << " self"; - } - - int argUsed = 0; - for (int i = 0; i < arguments.size(); ++i) { - if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i + 1)) - continue; - - if ((options & Generator::WriteSelf) || argUsed) - s << ", "; - - writeArgument(s, func, arguments[i], options); - argUsed++; - } -} - -QString BoostPythonGenerator::functionReturnType(const AbstractMetaFunction* func, Options options) -{ - QString modifiedReturnType = QString(func->typeReplaced(0)); - if (!modifiedReturnType.isNull() && (!(options & OriginalTypeDescription))) - return modifiedReturnType; - else - return translateType(func->type(), func->implementingClass(), options); -} - -QString BoostPythonGenerator::functionSignature(const AbstractMetaFunction *func, - QString prepend, - QString append, - Options options, - int argCount) -{ - AbstractMetaArgumentList arguments = func->arguments(); - int argument_count = argCount < 0 ? arguments.size() : argCount; - - - QString result; - QTextStream s(&result); - // The actual function - if (!(func->isEmptyFunction() || - func->isNormal() || - func->isSignal())) { - options |= Generator::SkipReturnType; - } else { - s << functionReturnType(func, options) << ' '; - } - - // name - QString name(func->originalName()); - if (func->isConstructor()) - name = getWrapperName(func->ownerClass()); - - s << prepend << name << append << "("; - writeFunctionArguments(s, func, options); - s << ")"; - - if (func->isConstant() && (!(options & Generator::ExcludeMethodConst))) - s << " const"; - - return result; -} - -QString BoostPythonGenerator::signatureForDefaultVirtualMethod(const AbstractMetaFunction *cppFunction, - QString prepend, - QString append, - Options options, - int arg_count) -{ - QString defaultMethodSignature = functionSignature(cppFunction, prepend, append, options, arg_count); - QString staticSelf("("); - if (cppFunction->isConstant()) - staticSelf += "const "; - - staticSelf += cppFunction->ownerClass()->qualifiedCppName() + "& "; - if (!(options & SkipName)) - staticSelf += " self"; - - if (cppFunction->arguments().size() > 0) - staticSelf += ", "; - - defaultMethodSignature.replace(defaultMethodSignature.lastIndexOf(") const"), 7, ")"); - defaultMethodSignature.replace(defaultMethodSignature.indexOf('('), 1, staticSelf); - return defaultMethodSignature; -} - -void BoostPythonGenerator::writeArgumentNames(QTextStream &s, - const AbstractMetaFunction *func, - Options options) const -{ - AbstractMetaArgumentList arguments = func->arguments(); - int argCount = 0; - for (int j = 0, max = arguments.size(); j < max; j++) { - - if ((options & Generator::SkipRemovedArguments) && - (func->argumentRemoved(arguments.at(j)->argumentIndex() + 1))) { - continue; - } - - if (argCount > 0) - s << ", "; - - QString argName = arguments.at(j)->argumentName(); - if (((options & Generator::VirtualCall) == 0) && - (!func->conversionRule(TypeSystem::NativeCode, arguments.at(j)->argumentIndex() + 1).isEmpty() || - !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty()) - ) - argName += "_out"; - - if ((options & Generator::BoxedPrimitive) && - !arguments.at(j)->type()->isReference() && - (arguments.at(j)->type()->isQObject() || - arguments.at(j)->type()->isObject())) { - - s << "PySide::ptr( " << argName << ")"; - } else { - s << argName; - } - argCount++; - } -} - -void BoostPythonGenerator::writeFunctionCall(QTextStream &s, - const AbstractMetaFunction* func, - Options options) - -{ - if (!(options & Generator::SkipName)) - s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName()); - - s << '('; - writeArgumentNames(s, func, options); - s << ')'; -} - -void BoostPythonGenerator::writeCodeSnips(QTextStream &s, - const CodeSnipList &codeSnips, - CodeSnip::Position position, - TypeSystem::Language language, - const AbstractMetaFunction *func) -{ - Indentation indentation(INDENT); - foreach (CodeSnip snip, codeSnips) { - if ((snip.position != position) || - !(snip.language & language)) { - continue; - } - - QString code; - QTextStream tmpStream(&code); - formatCode(tmpStream, snip.code(), INDENT); - - if (func) - replaceTemplateVariables(code, func); - - s << code << endl; - } -} - -bool BoostPythonGenerator::canCreateWrapperFor(const AbstractMetaClass* cppClass) -{ - return !cppClass->hasPrivateDestructor() && !cppClass->isNamespace(); -} - - - -QStringList BoostPythonGenerator::getBaseClasses(const AbstractMetaClass *cppClass) -{ - QStringList baseClass; - - if (!cppClass->baseClassName().isEmpty() && - (cppClass->name() != cppClass->baseClassName())) { - baseClass.append(cppClass->baseClassName()); - } - - foreach (AbstractMetaClass *interface, cppClass->interfaces()) { - AbstractMetaClass *aux = interface->primaryInterfaceImplementor(); - if (!aux) - continue; - - //skip templates - if (aux->templateArguments().size() > 0) - continue; - - if (!aux->name().isEmpty() && (cppClass->qualifiedCppName() != aux->qualifiedCppName())) - baseClass.append(aux->qualifiedCppName()); - } - - return baseClass; -} - - -bool BoostPythonGenerator::isCopyable(const AbstractMetaClass *cppClass) -{ - if (cppClass->isNamespace()) - return false; - else if (cppClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) - return cppClass->hasCloneOperator(); - else - return (cppClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet); - - return false; -} - -static void dump_function(AbstractMetaFunctionList lst) -{ - qDebug() << "DUMP FUNCTIONS: "; - foreach (AbstractMetaFunction *func, lst) { - qDebug() << "*" << func->ownerClass()->name() - << func->signature() - << "Private: " << func->isPrivate() - << "Empty: " << func->isEmptyFunction() - << "Static:" << func->isStatic() - << "Signal:" << func->isSignal() - << "ClassImplements: " << (func->ownerClass() != func->implementingClass()) - << "is operator:" << func->isOperatorOverload() - << "is global:" << func->isInGlobalScope(); - } -} - - -bool BoostPythonGenerator::doSetup(const QMap&) -{ - return true; -} diff --git a/generators/boostpython/boostpythongenerator.h b/generators/boostpython/boostpythongenerator.h deleted file mode 100644 index e41081f6d..000000000 --- a/generators/boostpython/boostpythongenerator.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef BOOSTPYTHONGENERATOR_H -#define BOOSTPYTHONGENERATOR_H - -#include -#include "generator.h" - -class DocParser; - -/** -* Abstract generator that contains common methods used in CppGenerator and HppGenerator. -*/ -class BoostPythonGenerator : public Generator -{ -public: - /** - * Write a function argument in the boost::python format in the text stream \p s. - * This function just call \code s << argumentString(); \endcode - * \param s text stream used to write the output. - * \param boost_fuction the current metafunction. - * \param boost_argument metaargument information to be parsed. - * \param options some extra options. - */ - void writeArgument(QTextStream &s, - const AbstractMetaFunction *boost_function, - const AbstractMetaArgument *boost_argument, - Options options = NoOption) const; - /** - * Create a QString in the boost::python format to an function argument. - * \param boost_fuction the current metafunction. - * \param boost_argument metaargument information to be parsed. - * \param options some extra options. - */ - QString argumentString(const AbstractMetaFunction *boost_function, - const AbstractMetaArgument *boost_argument, - Options options = NoOption) const; - - void writeArgumentNames(QTextStream &s, - const AbstractMetaFunction *cpp_function, - Options options = NoOption) const; - - /** - * Function used to write the fucntion arguments on the class buffer. - * \param s the class output buffer - * \param boost_function the pointer to metafunction information - * \param count the number of function arguments - * \param options some extra options used during the parser - */ - void writeFunctionArguments(QTextStream &s, - const AbstractMetaFunction *boost_function, - Options options = NoOption) const; - QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption); - /** - * Write a code snip into the buffer \p s. - * CodeSnip are codes inside inject-code tags. - * \param s the buffer - * \param cpp_function the cpp function - * \param code_snips a list of code snips - * \param position the position to insert the code snip - * \param language the kind of code snip - */ - void writeCodeSnips(QTextStream &s, - const CodeSnipList &code_snips, - CodeSnip::Position position, - TypeSystem::Language language, - const AbstractMetaFunction *cpp_function = 0); - static bool canCreateWrapperFor(const AbstractMetaClass* cppClass); - /** - * Function witch parse the metafunction information - * \param cpp_function the function witch will be parserd - * \param option some extra options - * \param arg_count the number of function arguments - */ - QString functionSignature(const AbstractMetaFunction *boost_function, - QString prepend = "", - QString append = "", - Options options = NoOption, - int arg_count = -1); - - QString signatureForDefaultVirtualMethod(const AbstractMetaFunction *cpp_function, - QString prepend = "", - QString append = "_default", - Options = NoOption, - int arg_count = -1); - - QStringList getBaseClasses(const AbstractMetaClass* cppClass); - - static QString getWrapperName(const AbstractMetaClass* clazz); - - - virtual bool doSetup(const QMap& args); - -protected: - // verify if the class is copyalbe - bool isCopyable(const AbstractMetaClass *cpp_class); - - void writeFunctionCall(QTextStream &s, const AbstractMetaFunction *cpp_func, Options options = NoOption); -}; - - -#endif // BOOSTPYTHONGENERATOR_H - diff --git a/generators/boostpython/convertergenerator.cpp b/generators/boostpython/convertergenerator.cpp deleted file mode 100644 index 23a5d3601..000000000 --- a/generators/boostpython/convertergenerator.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include "convertergenerator.h" - -static Indentor INDENT; - -ConverterGenerator::ConverterGenerator() -{ - // QPair - m_conversions << qMakePair(QString("QPair<"), &m_qpairTypes); - // QList - m_conversions << qMakePair(QString("QList<"), &m_qlistTypes); - // QVector - m_conversions << qMakePair(QString("QVector<"), &m_qvectorTypes); - // QMap - m_conversions << qMakePair(QString("QMap<"), &m_qmapTypes); - // QHash - m_conversions << qMakePair(QString("QHash<"), &m_qhashTypes); - // QMultiMap - m_conversions << qMakePair(QString("QMultiMap<"), &m_qmultiMapTypes); - -} - -void ConverterGenerator::finishGeneration() -{ - if (!classes().size()) - return; - - QString fileOutPath; - - foreach (AbstractMetaClass *cls, classes()) { - if (!shouldGenerate(cls)) - continue; - - if (fileOutPath.isNull()) { - m_packageName = cls->package(); - fileOutPath = outputDirectory() + '/' + subDirectoryForClass(cls) - + "/converter_register_" + moduleName().toLower() + ".hpp"; - } - - foreach (AbstractMetaFunction* func, filterFunctions(cls)) - checkFunctionMetaTypes(func); - } - - FileOut fileOut(fileOutPath); - QTextStream& s = fileOut.stream; - - // write license comment - s << licenseComment() << endl; - - s << "#ifndef CONVERTERREGISTER_" << moduleName().toUpper() << "_HPP\n"; - s << "#define CONVERTERREGISTER_" << moduleName().toUpper() << "_HPP\n\n"; - - //Includes - QStringList includes; - foreach (AbstractMetaClass *cls, classes()) { - if (cls->typeEntry()->include().isValid()) { - QString include_file = cls->typeEntry()->include().toString(); - if (!includes.contains(include_file)) { - s << include_file << endl; - includes << include_file; - } - } - - if (cls->typeEntry()->generateCode()) { - QList extra_includes = cls->typeEntry()->extraIncludes(); - foreach (Include include, extra_includes) { - if (!includes.contains(include.toString())) { - s << include.toString() << endl; - includes << include.toString(); - } - } - } - } - - s << "#include \"type_converter.hpp\"\n\n"; - - s << "void register_type_converters_" << moduleName().toLower() << "()\n{\n"; - Indentation indent(INDENT); - writeConverterRegistration(s, "register_qpair_converter", "QPair", m_qpairTypes); - writeConverterRegistration(s, "register_container_converter", "QList", m_qlistTypes); - writeConverterRegistration(s, "register_container_converter", "QVector", m_qvectorTypes); - writeConverterRegistration(s, "register_dict_converter", "QMap", m_qmapTypes); - writeConverterRegistration(s, "register_dict_converter", "QHash", m_qhashTypes); - writeConverterRegistration(s, "register_multimap_converter", "QMultiMap", m_qmultiMapTypes); - s << "}\n\n"; - s << "#endif\n\n"; - - m_numGeneratedWritten = m_qpairTypes.size() + m_qlistTypes.size() + - m_qvectorTypes.size() + m_qmapTypes.size() + - m_qhashTypes.size(); -} - -void ConverterGenerator::writeConverterRegistration(QTextStream& out, - const QString& funcName, - const QString& type, - const QSet& params) -{ - foreach (QString param, params) { - QString completeType(QMetaObject::normalizedType( - (type + '<' + param + " >").toLatin1().data())); - out << INDENT << "PySide::" << funcName; - out << '<' << completeType << " >(\""; - out << completeType << "\");" << endl; - } -} - -void ConverterGenerator::checkFunctionMetaTypes(AbstractMetaFunction* func) -{ - if (func->type()) - checkMetaType(functionReturnType(func)); - - foreach (AbstractMetaArgument* arg, func->arguments()) { - if (arg->type()) - checkMetaType(argumentString(func, arg, Options(SkipName) | SkipDefaultValues)); - } -} - -// FIXME Use some AbstracyMetaAnything info instead of parse the cpp signature? -void ConverterGenerator::checkMetaType(const QString& cppSignature) -{ - QRegExp typeRegex("Q\\w+"); - - foreach (Conversion conv, m_conversions) { - int index = cppSignature.indexOf(conv.first); - if (index >= 0) { - QString templateArg = extractTemplateArgument(cppSignature.right(cppSignature.length() - index - conv.first.length())); - conv.second->insert(templateArg); - // detect types to generate includes - int offset = 0; - while ((offset = typeRegex.indexIn(templateArg, offset)) != -1) { - const QString cap(typeRegex.cap(0)); - offset += cap.length(); - } - } - } -} - -QString ConverterGenerator::extractTemplateArgument(const QString& templateParams) -{ - int stack = 0; - for (int i = 0; i < templateParams.length(); ++i) { - QChar c = templateParams[i]; - if (c == '<') { - stack++; - } else if (c == '>') { - stack--; - if (stack < 0) - return templateParams.left(i).trimmed(); - } - } - Q_ASSERT(false); - return QString(); -} - diff --git a/generators/boostpython/convertergenerator.h b/generators/boostpython/convertergenerator.h deleted file mode 100644 index 8f91377c0..000000000 --- a/generators/boostpython/convertergenerator.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef CONVERTERGENERATOR_H -#define CONVERTERGENERATOR_H - -// #include -#include -#include "boostpythongenerator.h" - -/** -* Generator for convertions between python collections and Qt collections. -* -* It generates a file called converter_register_MODULENAME.hpp with only one -* function called register_type_converters_MODULENAME, where MODULENAME is the current module name. -* QPair are converted to python tuples, QList, QVector and QLinkedList to python lists, QHash and QMap to python dicts. -*/ -class ConverterGenerator : public BoostPythonGenerator -{ -public: - ConverterGenerator(); - - const char* name() const - { - return "ConverterGenerator"; - } - -protected: - void generateClass(QTextStream& s, const AbstractMetaClass* clazz) - { - } - - void finishGeneration(); - QString fileNameForClass(const AbstractMetaClass* cppClass) const - { - return QString(); - } -private: - void checkFunctionMetaTypes(AbstractMetaFunction* func); - void checkMetaType(const QString& cppSignature); - QString extractTemplateArgument(const QString& templateParams); - - void writeConverterRegistration(QTextStream& out, const QString& func_name, const QString& type, const QSet& params); - - typedef QPair* > Conversion; - typedef QList ConversionList; - ConversionList m_conversions; - QSet m_qpairTypes; - QSet m_qlistTypes; - QSet m_qvectorTypes; - QSet m_qmapTypes; - QSet m_qhashTypes; - QSet m_qmultiMapTypes; -}; - -#endif // CONVERSIONGENERATOR_H - diff --git a/generators/boostpython/cppgenerator.cpp b/generators/boostpython/cppgenerator.cpp deleted file mode 100644 index f144e297a..000000000 --- a/generators/boostpython/cppgenerator.cpp +++ /dev/null @@ -1,1560 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include "cppgenerator.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static Indentor INDENT; - -// utiliy functions -inline void writeConversionRule(QTextStream &s, TypeSystem::Language lang, const AbstractMetaFunction *function, const AbstractMetaArgument *arg) -{ - QString convRule = function->conversionRule(lang, arg->argumentIndex() + 1); - if (!convRule.isEmpty()) { - convRule.replace("%in", arg->argumentName()); - convRule.replace("%out", arg->argumentName() + "_out"); - s << convRule; - } -} - -inline QString getMethodPointerString(const AbstractMetaFunction* func) -{ - QString className; - if (!func->declaringClass()->isAbstract()) - className = func->declaringClass()->qualifiedCppName(); - else - className = func->ownerClass()->qualifiedCppName(); - - return '&' + className + "::" + func->originalName(); -} - -static QString nameForModifiedCtorFunction(const AbstractMetaFunction* func) { - QString res = func->ownerClass()->name().toLower().replace("::", "_"); - res += "_constructor"; - foreach (AbstractMetaArgument* arg, func->arguments()) { - res += '_'; - res += arg->type()->name().toLower(); - } - return res; -} - -static QString createStaticFunctionName(const AbstractMetaFunction* func) -{ - QString funcName; - QString originalName(func->name()); - - - funcName = func->ownerClass()->name().toLower(); - - //remove initial 'Q' - if (funcName.startsWith('q')) - funcName = funcName.remove(0, 1); - - //upercase first letter - funcName += originalName[0].toUpper() + originalName.mid(1); - - return funcName; -} - -QString CppGenerator::fileNameForClass(const AbstractMetaClass* cppClass) const -{ - return getWrapperName(cppClass) + QLatin1String(".cpp"); -} - -QString CppGenerator::getFuncTypedefName(const AbstractMetaFunction* func) const -{ - return func->name() + QLatin1String("_type"); -} - -void CppGenerator::writeConstructorInitialization(QTextStream &s, const AbstractMetaFunction *function) -{ - QStringList nonOpts; - QStringList opts; - - Options options = Options(SkipName) | SkipDefaultValues; - foreach (AbstractMetaArgument *arg, function->arguments()) { - QString argType = argumentString(function, arg, options); - if (arg->defaultValueExpression().isEmpty()) - nonOpts << argType; - else - opts << argType; - } - - bool hasModifications = function->allowThread() || function->hasInjectedCode(); - - if (hasModifications) { - s << "\"__init__\", python::make_constructor(" - << nameForModifiedCtorFunction(function); - } else { - s << "python::init< "; - - if (nonOpts.size() > 0) - s << nonOpts.join(", "); - - if (opts.size() > 0) { - if (nonOpts.size() > 0) - s << ", "; - - s << "python::optional< " << opts.join(",") << " > "; - } - - s << " > ()"; - } - - QString callPolicy = getFunctionCallPolicy(function); - QString parentType; - const AbstractMetaClass *cppClass = function->ownerClass(); - uint closePolicy = 0; - bool hasPolicy = false; - - if ( - !hasModifications && - (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor() || cppClass->isNamespace()) - ) { - closePolicy++; - hasPolicy = true; - s << "[ PySide::register_wrapper_object< " - << function->ownerClass()->qualifiedCppName(); - } - - if (callPolicy.isEmpty()) { - int parentIndex = -1; - //try find for parent arg to create callPolicy - foreach (AbstractMetaArgument *arg, function->arguments()) { - if (arg->argumentName() == "parent") { - parentIndex = arg->argumentIndex(); - parentType = translateType(arg->type(), function->ownerClass(), - Options(ExcludeConst) | ExcludeReference).replace("*", ""); - break; - } - } - if (parentIndex != -1) { - if (!closePolicy) - s << (hasModifications ? ", " : "[ "); - else - s << ", "; - - s << "parent_policy_add< " << parentIndex + 2 << ", 1, " - << parentType << " , " << function->ownerClass()->qualifiedCppName(); - - hasPolicy = true; - closePolicy++; - } - } else { - if (!closePolicy) - s << (hasModifications ? ", " : "[ "); - else - s << ", "; - - if (callPolicy.endsWith("()")) - callPolicy = callPolicy.remove(callPolicy.size() - 2, 2); - - s << callPolicy; - hasPolicy = true; - } - - while(closePolicy) { - s << " > "; - closePolicy--; - } - - if (hasModifications) - s << ')'; - else if (hasPolicy) - s << "() ]"; -} - -QString CppGenerator::getFunctionReturnType(const AbstractMetaFunction* func) -{ - QString modifiedReturnType = QString(func->typeReplaced(0)); - - return modifiedReturnType.isNull() ? translateType(func->type(), func->implementingClass()) : modifiedReturnType; -} - -QString CppGenerator::writeFunctionCast(QTextStream &s, - const AbstractMetaFunction* func, - const QString& castNameSuffix, - const QString& className) -{ - QString castName = getFuncTypedefName(func) + castNameSuffix; - const AbstractMetaClass* cppClass = func->ownerClass(); - bool isWrapped = !func->isVirtual() && - (func->hasInjectedCode() || func->isThread() || func->allowThread()); - bool isVirtualMethodDefault = castNameSuffix == "_default"; - - s << INDENT << "typedef "; - s << getFunctionReturnType(func); - s << " ("; - if (cppClass && !func->isStatic() && func->ownerClass() && !isVirtualMethodDefault) { - if (!isWrapped) { - // pointer to a class method - if (!className.isEmpty()) - s << className; - else if (func->isVirtual() && !func->declaringClass()->isAbstract()) - s << func->declaringClass()->qualifiedCppName(); - else - s << cppClass->qualifiedCppName(); - - s << "::"; - } - } - - s << '*' << castName << ") ("; - if (isVirtualMethodDefault) { - if (func->isConstant()) - s << "const "; - - s << func->implementingClass()->qualifiedCppName() << "&"; - if (func->arguments().size() > 0) - s << ", "; - } - Options options = Options(SkipName) | SkipDefaultValues | SkipRemovedArguments; - if (isWrapped && !func->isStatic()) - options |= WriteSelf; - - writeFunctionArguments(s, func, options); - s << ')'; - - if (func->isConstant() && !isWrapped && !isVirtualMethodDefault) - s << " const"; - - s << ';' << endl; - - return castName; -} - -QString CppGenerator::verifyDefaultReturnPolicy(const AbstractMetaFunction *cppFunction, const QString& callPolicy) -{ - AbstractMetaType *type = cppFunction->type(); - - //If return type replaced, the return policy need be set manually. - if (!type || !cppFunction->typeReplaced(0).isEmpty()) { - return QString(); - } - - QString returnPolicy; - - if (type->isReference()) { - QString detail; - if (type->isConstant()) { - detail = "copy_const_reference"; - } else { - detail = "copy_non_const_reference"; - } - - returnPolicy = "python::return_value_policyisQObject() || type->isObject() || type->isValuePointer()) { - bool cppOwnership = type->isConstant(); - if (cppFunction->isStatic() || cppOwnership) { - returnPolicy = QString("python::return_value_policy >()"); - } else { - returnPolicy = QString("PySide::return_object<1, 0, %1, %2 %3 %4 >()") - .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, -1)) - .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, 0)) - .arg(callPolicy.isEmpty() ? "" : ",") - .arg(callPolicy); - } - } else if (!callPolicy.isEmpty()) { - returnPolicy = callPolicy + "()"; - } - - return returnPolicy; -} - -static int boost_parent_policy_index(int i, const AbstractMetaFunction* func = 0) -{ - if (func && func->isStatic()) - return i; - - if (i == -1) - return 1; - else if (i > 0) - return i + 1; - else - return i; -} - -QString CppGenerator::getArgumentType(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func, int idx) -{ - QString retval; - if (idx == -1) { - retval = cppClass->qualifiedCppName(); - } else if (idx == 0 && func->type()) { - retval = translateType(func->type(), cppClass, - Options(Generator::ExcludeConst) | Generator::ExcludeReference); - } else if (idx > 0) { - retval = argumentString(func, func->arguments()[idx-1], - Options(SkipDefaultValues) | ExcludeConst | - ExcludeReference | SkipName); - } - - retval = retval.trimmed(); - if (retval.endsWith('*')) - retval.chop(1); - return retval; -} - -QString CppGenerator::getFunctionCallPolicy(const AbstractMetaFunction *func) -{ - QString callPolicy; - QStringList callPolicies; - bool returnChild = false; - const AbstractMetaClass* cppClass = func->implementingClass(); - - const int numArgs = func->arguments().count(); - - if (func->type() && (func->type()->name() == "HANDLE")) { - return "python::return_value_policy()"; - } - - for (int i = -1; i <= numArgs; ++i) { - ArgumentOwner ao = func->argumentOwner(cppClass, i); - //Parent Policy - if ((ao.index != -2) && (ao.index != i)) { - switch (ao.action) { - case ArgumentOwner::Add: - if (!i) { - callPolicy = "return_object<"; - returnChild = true; - } else { - callPolicy = "parent_policy_add<"; - } - break; - case ArgumentOwner::Remove: - callPolicy = "parent_policy_remove<"; - break; - default: - continue; - } - - callPolicy += QString("%1, %2, %3, %4") - .arg(boost_parent_policy_index(ao.index, func)) - .arg(boost_parent_policy_index(i, func)) - .arg(getArgumentType(cppClass, func, ao.index)) - .arg(getArgumentType(cppClass, func, i)); - - callPolicies << callPolicy; - } else if (i) { //only function args ignore return value - //Ownership policy - bool changeOwnership = false; - bool releaseOwnership = false; - TypeSystem::Ownership owner = func->ownership(cppClass, - TypeSystem::TargetLangCode, i); - - switch(owner) - { - case TypeSystem::CppOwnership: - releaseOwnership = true; - case TypeSystem::TargetLangOwnership: - changeOwnership = true; - break; - default: - changeOwnership = false; - } - - if (changeOwnership) - { - QString ownershipPolicy = QString("transfer_ownership<%1, %2, %3") - .arg(boost_parent_policy_index(i, func)) - .arg(releaseOwnership ? "true" : "false") - .arg(getArgumentType(cppClass, func, i)); - callPolicies << ownershipPolicy; - } - } - } - - if (callPolicies.size() > 0) { - callPolicy = callPolicies.join(", "); - for (int i = 0; i < callPolicies.count(); ++i) - callPolicy += " >"; - } - - QString returnPolicy; - - //return value - bool cppOwnership = false; - - if (!returnChild) { - switch (func->ownership(cppClass, TypeSystem::TargetLangCode, 0)) - { - case TypeSystem::CppOwnership: - cppOwnership = true; - case TypeSystem::TargetLangOwnership: - { - QString cppOwnershipFlag = (cppOwnership ? "true" : "false"); - returnPolicy = "python::return_value_policy< PySide::return_ptr_object<" + cppOwnershipFlag + "> "; - if (!callPolicy.isEmpty()) - returnPolicy += ", " + callPolicy; - returnPolicy += " >()"; - break; - } - default: - returnPolicy = verifyDefaultReturnPolicy(func, callPolicy); - break; - } - } - - //return policy - if (func->shouldReturnThisObject()) - return "python::return_self< " + callPolicy + " >()"; - else if (!returnPolicy.isEmpty()) - return returnPolicy; - else if (!callPolicy.isEmpty()) - return callPolicy + "()"; - - return QString(); -} - -/*!\internal - Function used to write the enum boost code on the buffer - \param s the output buffer - \param cpp_enum the pointer to metaenum information to be translated to boost -*/ -void CppGenerator::writeEnum(QTextStream &s, - const AbstractMetaEnum *cppEnum, - const QString &nameSpace) -{ - s << INDENT << "python::enum_<" << nameSpace << cppEnum->name(); - s << ">(\"" << cppEnum->name() << "\")" << endl; - const AbstractMetaEnumValueList &values = cppEnum->values(); - EnumTypeEntry *ete = cppEnum->typeEntry(); - - foreach (const AbstractMetaEnumValue* enumValue, values) { - Indentation indent(INDENT); - if (ete->isEnumValueRejected(enumValue->name())) - continue; - - s << INDENT << ".value(\"" << enumValue->name() << "\", "; - s << nameSpace << enumValue->name() << ")" << endl; - } - - //Export values to current scope - s << INDENT << INDENT << ".export_values()" << endl; - s << INDENT << ";" << endl << endl; - - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - - if (flagsEntry) { - s << INDENT << "PySide::declare_" << (cppEnum->typeEntry()->forceInteger() ? "int_" : "") << "qflags< " - << flagsEntry->originalName() << " >(\"" << flagsEntry->flagsName() << "\");" << endl; - } - - //register enum in typemanager - s << INDENT - << "type_manager::instance().register_native_type(\"" - << nameSpace << cppEnum->name() << "\");\n\n"; -} - -void CppGenerator::writeEnums(QTextStream &s, const AbstractMetaClass *cppClass, bool useNamespace) -{ - AbstractMetaEnumList enums = cppClass->enums(); - if (!enums.size()) - return; - - s << INDENT << "// Enums" << endl; - QString name_space; - if (useNamespace || !cppClass->isPolymorphic() || cppClass->hasPrivateDestructor()) - name_space = cppClass->qualifiedCppName() + "::"; - - foreach (AbstractMetaEnum *cpp_enum, enums) - writeEnum(s, cpp_enum, name_space); -} - -void CppGenerator::writeImplicitlyConversion(QTextStream &s, const AbstractMetaClass *cppClass) -{ -#if 0 - if (cppClass->isNamespace()) - return; - s << endl << "// Implicitly conversions" << endl; - QStringList interfaces = getBaseClasses(cppClass); - - if (!interfaces.size()) { - s << INDENT << "python::implicitly_convertible< " << endl; - s << INDENT << INDENT << "std::auto_ptr< " << getWrapperName(cppClass->name()) << " >," << endl; - s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " > >();" << endl; - } else { - foreach (QString base_class, interfaces) { - s << INDENT << "python::implicitly_convertible< " << endl; - s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " >," << endl; - s << INDENT << INDENT << "std::auto_ptr< " << base_class << " > >();" << endl; - } - } -#endif -} - - -void CppGenerator::writeDestructor(QTextStream &s, const AbstractMetaClass *cppClass) -{ - Indentation indentation(INDENT); - QString wrapperName = getWrapperName(cppClass); - s << wrapperName << "::~" << wrapperName << "()" << endl << "{" << endl - << INDENT << "PySide::qptr_base::invalidate(this);" << endl << "}" << endl; -} - -/*! - Function used to write the class generated boost code on the buffer - \param s the output buffer - \param cppClass the pointer to metaclass information -*/ -void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass) -{ - ReportHandler::debugSparse("Generating wrapper implementation for " + cppClass->fullName()); - - // write license comment - s << licenseComment() << endl; - - QString localStr, globalStr; - QTextStream includesLocal(&localStr); - QTextStream includesGlobal(&globalStr); - - bool canCreateWrapper = canCreateWrapperFor(cppClass); - - QList includes = cppClass->typeEntry()->extraIncludes(); - qSort(includes.begin(), includes.end()); - - foreach (Include inc, includes) { - if (inc.type == Include::IncludePath) - includesGlobal << inc.toString() << endl; - else - includesLocal << inc.toString() << endl; - } - - //workaround to access protected functions - s << "//workaround to access protected functions" << endl; - s << "#define protected public" << endl; - - s << "//Base Class" << endl; - if (cppClass->typeEntry()->include().isValid()) - s << cppClass->typeEntry()->include().toString() << endl << endl; - - s << "//Extra includes [global]" << endl; - s << globalStr << endl; - - s << "#undef protected" << endl; - s << "//Base include" << endl; - s << "#include \"pyside.hpp\"" << endl; - s << "#include \"" << getWrapperName(cppClass) << ".hpp\"" << endl; - foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) { - if (shouldGenerate(innerClass)) - s << "#include \"" << getWrapperName(innerClass) << ".hpp\"" << endl; - } - s << endl << "//Extra includes [local]" << endl; - s << localStr << endl; - - s << endl << "using namespace boost;" << endl; - s << "using namespace PySide;" << endl; - s << endl; - - if (cppClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) - s << "#Deprecated" << endl; - - if (canCreateWrapper) { - writePrelude(s, cppClass); - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) - writeDestructor(s, cppClass); - } - - writeFieldsAccessFunctions(s, cppClass); - - //inject code native end - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::End, TypeSystem::NativeCode); - - writeBoostDeclaration(s, cppClass); -} - -void CppGenerator::writeFieldsAccessFunctions(QTextStream& s, const AbstractMetaClass* cppClass) -{ - //Fields - foreach (AbstractMetaField *field, cppClass->fields()) { - if (field->isPublic()) { - writeFieldAccess(s, cppClass, field); - } - } -} - -void CppGenerator::writePrelude(QTextStream& s, const AbstractMetaClass* cppClass) -{ - //inject code native beginner - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::Beginning, TypeSystem::NativeCode); - - foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) { - if ((func->isPrivate() || func->isModifiedRemoved()) && !func->isAbstract()) - continue; - - if (func->isConstructor() && (func->allowThread() || func->hasInjectedCode())) { - writeModifiedConstructorImpl(s, func); - } else if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() && - func->isConstructor() && !func->isCopyConstructor()) { - writeConstructorImpl(s, func); - } else if (func->isVirtual() || func->isAbstract()) { - writeVirtualMethodImpl(s, func); - } else if (func->hasInjectedCode() || func->isThread() || func->allowThread()) { - writeNonVirtualModifiedFunctionImpl(s, func); - } else if (func->isInGlobalScope() && func->isOperatorOverload()) { - writeGlobalOperatorOverloadImpl(s, func); - } - } -} - - -void CppGenerator::writeModifiedConstructorImpl ( QTextStream& s, const AbstractMetaFunction* func ) -{ - Indentation indentation(INDENT); - const AbstractMetaClass* clazz = func->ownerClass(); - s << "static " << clazz->name() << "* " << nameForModifiedCtorFunction(func) << '('; - writeFunctionArguments(s, func, SkipDefaultValues); - s << ")\n{" << endl; - - s << INDENT << clazz->name() << "* _self = 0;" << endl; - s << INDENT << '{' << endl; - { - Indentation indentation(INDENT); - if (func->allowThread()) - s << INDENT << "py_allow_threads allow_threads;" << endl; - - s << INDENT << "_self = new "; - writeFunctionCall(s, func); - s << ';' << endl; - } - s << INDENT << '}' << endl; - writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func); - writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func); - s << INDENT << "python::object _obj(PySide::ptr(_self));" << endl; - s << INDENT << "return _self;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeConstructorImpl(QTextStream& s, const AbstractMetaFunction* func) -{ - QString wrapperName = getWrapperName(func->ownerClass()); - s << wrapperName << "::" << wrapperName << "(PyObject *py_self" << (func->arguments().size() ? ", " : ""); - writeFunctionArguments(s, func, Options(OriginalTypeDescription) | SkipDefaultValues); - s << ")" << endl; - s << INDENT << " : "; - writeFunctionCall(s, func); - s << ", wrapper(py_self)" << endl << "{" << endl; - writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func); - writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func); - s << '}' << endl << endl; -} - -void CppGenerator::writeVirtualMethodImplHead(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - s << INDENT << "thread_locker lock;" << endl; - - if (func->hasInjectedCode()) { - writeCodeSnips(s, getCodeSnips(func), - CodeSnip::Beginning, TypeSystem::NativeCode, func); - } - - s << INDENT << "python::object method = get_override(\"" << func->implementingClass()->name(); - if (func->implementingClass()->typeEntry()->isObject() || func->implementingClass()->typeEntry()->isQObject()) - s << '*'; - - s << "\", \"" << func->name() << "\");" << endl - << INDENT << "if (method)" << endl << INDENT << "{" << endl; - - { - Indentation indentation(INDENT); - s << INDENT << "try {" << endl << INDENT << INDENT; - if (func->type()) - s << "python::object __result = "; - - foreach(AbstractMetaArgument *arg, func->arguments()) { - writeConversionRule(s, TypeSystem::TargetLangCode, func, arg); - } - - s << INDENT << "method("; - writeArgumentNames(s, func, Generator::Options(Generator::BoxedPrimitive | Generator::SkipRemovedArguments)); - s << ");" << endl; - - QString typeName = getFunctionReturnType(func); - if (!typeName.isEmpty()) { - - CodeSnipList codeSnips = getCodeSnips(func); - bool hasVirtualBeginningCode = false; - foreach(CodeSnip cs, codeSnips) { - if ((cs.position == CodeSnip::Beginning) && (cs.language == TypeSystem::TargetLangCode)) { - hasVirtualBeginningCode = true; - break; - } - } - - if (hasVirtualBeginningCode) { - writeCodeSnips(s, codeSnips, CodeSnip::Beginning, TypeSystem::TargetLangCode, func); - } else if (func->type()) { - s << INDENT << typeName << " __return_value = " << "python::extract<" << typeName << " >(__result);" << endl; - bool boxedPointer = false; - if (func->type() && !func->type()->isConstant() && - (func->type()->isObject() || func->type()->isQObject())) { - - s << INDENT << "PySide::qptr<" << QString(typeName).replace("*", "") << " > __ptr(__result.ptr());" << endl - << INDENT << "python::incref(__result.ptr());" << endl - << INDENT << "__ptr.release_ownership();" << endl; - } - - s << INDENT << "return __return_value;" << endl; - } - } - - s << INDENT << "} catch (boost::python::error_already_set) {" << endl; - s << INDENT << INDENT << "PyErr_Print();" << endl; - s << INDENT << INDENT << "throw boost::python::error_already_set();" << endl; - s << INDENT << "}" << endl; - - - } - s << INDENT << "}" << endl; -} - -void CppGenerator::writeVirtualMethodImpl(QTextStream& s, const AbstractMetaFunction* func) -{ - if (func->isModifiedRemoved()) - return; - - if (!func->isAbstract() && !func->ownerClass()->hasPrivateDestructor() && - func->implementingClass() == func->ownerClass()) { - writeVirtualDefaultFunction(s, func); - } - - - QString prefix = getWrapperName(func->ownerClass()) + "::"; - s << functionSignature(func, prefix, "", - Options(Generator::OriginalTypeDescription) | Generator::SkipDefaultValues | Generator::VirtualCall) - << endl << "{" << endl; - - writeVirtualMethodImplHead(s, func); - - if (func->isAbstract()) - writePureVirtualMethodImplFoot(s, func); - else - writeVirtualMethodImplFoot(s, func); - - s << '}' << endl << endl; -} - - -void CppGenerator::writePureVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - s << INDENT << "else" << endl - << INDENT << "{" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"" - << func->ownerClass()->name() << "." << func->name() << " : " - << "You need to implement pure virtual functions in python\");" << endl - << INDENT << "throw python::error_already_set();" << endl; - } - s << INDENT << "}" << endl; -} - -void CppGenerator::writeVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - s << INDENT << "else" << endl << INDENT << "{" << endl; - { - Indentation indentation(INDENT); - QString returnKeyword = func->type() ? QLatin1String("return ") : QString(); - - if (func->allowThread()) - s << INDENT << "py_allow_threads allow_threads;" << endl; - - s << INDENT << returnKeyword << func->implementingClass()->qualifiedCppName() << "::"; - writeFunctionCall(s, func, Generator::VirtualCall); - s << ';' << endl; - } - s << INDENT << '}' << endl; -} - -void CppGenerator::writeVirtualDefaultFunction(QTextStream &s, const AbstractMetaFunction *func) -{ - Indentation indentation(INDENT); - QString returnKeyword = func->type() ? QLatin1String("return ") : QString(); - Generator::Options opt = Generator::Options(Generator::SkipDefaultValues); - QString defaultMethodSignature = signatureForDefaultVirtualMethod(func, getWrapperName(func->ownerClass()) + "::", "_default", - opt | Generator::SkipRemovedArguments | Generator::VirtualCall); - s << defaultMethodSignature << endl << '{' << endl; - - if (func->allowThread()) - s << INDENT << "py_allow_threads allow_threads;" << endl; - - CodeSnipList codeSnips = getCodeSnips(func); - bool hasVirtualEndCode = false; - foreach(CodeSnip cs, codeSnips) { - if ((cs.position == CodeSnip::End) && (cs.language == TypeSystem::TargetLangCode)) { - hasVirtualEndCode = true; - break; - } - } - - foreach(AbstractMetaArgument *arg, func->arguments()) { - writeConversionRule(s, TypeSystem::NativeCode, func, arg); - } - - if (!hasVirtualEndCode) { - s << INDENT << returnKeyword << "self." << func->implementingClass()->qualifiedCppName() << "::"; - writeFunctionCall(s, func, opt); - s << ";" << endl; - } else { - writeCodeSnips(s, getCodeSnips(func), - CodeSnip::End, TypeSystem::TargetLangCode, func); - } - s << '}' << endl << endl; - -} - - - -void CppGenerator::writeNonVirtualModifiedFunctionImpl(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - - s << "static " << getFunctionReturnType(func) << ' '; - s << func->ownerClass()->name() << '_' << func->originalName() << "_modified("; - - Options options = Options(SkipRemovedArguments) | SkipDefaultValues; - if (!func->isStatic()) - options |= WriteSelf; - - writeFunctionArguments(s, func, options); - s << ")" << endl << "{" << endl; - - if (func->isThread()) - s << INDENT << "thread_locker lock;" << endl; - - if (func->allowThread()) - s << INDENT << "py_allow_threads allow_threads;" << endl; - - if (getCodeSnips(func).size() > 0) { - writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func); - writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func); - } else { - s << INDENT; - if (func->type()) - s << "return "; - - if (func->isStatic()) - s << func->declaringClass()->name() << "::"; - else - s << "self."; - - writeFunctionCall(s, func); - s << ";" << endl; - } - - s << '}' << endl << endl; -} - -AbstractMetaFunction* CppGenerator::findMainConstructor(const AbstractMetaClass* clazz) -{ - foreach (AbstractMetaFunction* func, filterFunctions(clazz)) { - if (func->isConstructor() && - func->isPublic() && - !func->isModifiedRemoved() && - !func->isPrivate()) { - - //do not use copy constructor here - if (func->isCopyConstructor()) - continue; - return func; - } - } - return 0; -} - -void CppGenerator::writeGetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field) -{ - s << "static "; - - bool pointer = false; - if (field->type()->isQObject() || field->type()->isObject()) - pointer = true; - - if (pointer) - s << "python::object"; - else - s << field->type()->cppSignature(); - - s << " getter_" << cppClass->name() << "_" << field->name() << "("; - - if (!field->isStatic()) - s << cppClass->qualifiedCppName() << " &self"; - - s << ")" << endl << "{" << endl - << INDENT << "return "; - - if (pointer) - s << "python::object(PySide::ptr("; - - if (!field->isStatic()) - s << "self."; - else - s << field->enclosingClass()->typeEntry()->qualifiedCppName() << "::"; - - s << field->name(); - - if (pointer) - s << "))"; - - s << ";" << endl << "}" << endl; -} - -void CppGenerator::writeSetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field) -{ - s << "static void setter_" << cppClass->name() << "_" << field->name() << "("; - - if (!field->isStatic()) - s << cppClass->qualifiedCppName() << " &self, "; - - s << field->type()->cppSignature() << " _value)" << endl << "{" << endl - << INDENT; - - if (!field->isStatic()) - s << "self."; - else - s << field->enclosingClass()->typeEntry()->qualifiedCppName() << "::"; - - s << field->name() << " = _value;" << endl << "}" << endl; -} - - -void CppGenerator::writeFieldAccess(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field) -{ - Indentation indent(INDENT); - - writeGetterFieldFunction(s, cppClass, field); - if (!field->type()->isConstant()) - writeSetterFieldFunction(s, cppClass, field); -} - - -void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* cppClass) -{ - QString argType; - - //WORKAROUND: diferent way to QChar - if (cppClass->name() == "QChar") - argType = "QChar"; - else - argType = "const " + cppClass->name() + "&"; - - s << "// Hash function" << endl - << "{" << endl - << INDENT << INDENT << "typedef uint (*hash_type) ( " << argType << " );" - << INDENT << INDENT << "python_cls.def(\"__hash__\", hash_type(&" - << cppClass->typeEntry()->hashFunction() << "));" << endl - << "}" << endl; -} - -QString CppGenerator::baseClassName(const QString& name) -{ - QStringList lst = name.split("::"); - return lst.last(); -} - -void CppGenerator::writeBoostDeclaration(QTextStream& s, const AbstractMetaClass* cppClass) -{ - Indentation indent(INDENT); - QString wrapperName = getWrapperName(cppClass); - - s << "void " << wrapperName << "::define_python_class() throw() {" << endl; - - const AbstractMetaFunction* mainCtor = 0; - bool mainCtorHasModifications = false; - if (!cppClass->isNamespace()) { - // python_cls declaration - mainCtor = findMainConstructor(cppClass); - if (mainCtor) - mainCtorHasModifications = mainCtor->allowThread() || mainCtor->hasInjectedCode(); - - s << INDENT; - if (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor()) - s << wrapperName << "::"; - - s << "class_type python_cls(\"" - << baseClassName(cppClass->name()) << "\", "; - - if (!mainCtor || mainCtorHasModifications) - s << "python::no_init"; - else - writeConstructorInitialization(s, mainCtor); - - s << ");" << endl << endl; - } else { - QRegExp reg("(?:\\w+::)*(\\w+)"); - reg.indexIn(cppClass->name()); - s << INDENT << "python::class_ python_cls(\"" << reg.cap(1) << "\");" << endl; - } - // scope declaration - s << INDENT << "python::scope " << wrapperName << "_scope(python_cls);" << endl; - - if (cppClass->templateBaseClass() && cppClass->templateBaseClass()->typeEntry()->isContainer()) { - s << endl << INDENT << "//Index suite for QContainer" << endl - << INDENT << "python_cls.def(qcontainer_indexing_suite< " << cppClass->qualifiedCppName() << " >());" << endl << endl; - } - - - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() && canCreateWrapperFor(cppClass)) { - QString heldType = cppClass->typeEntry()->heldTypeValue(); - if (heldType.isEmpty()) - heldType = "PySide::qptr"; - - s << INDENT << "python::implicitly_convertible< " - << heldType << "<" << wrapperName << ">, " - << heldType << "<" << cppClass->qualifiedCppName() << "> >();" << endl; - } - - //Enums - writeEnums(s, cppClass, cppClass->hasPrivateDestructor() || cppClass->isNamespace()); - - if (cppClass->innerClasses().count()) { - s << endl << INDENT << "// Inner classes" << endl; - foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) { - if (!innerClass->typeEntry()->generateCode()) - continue; - s << INDENT << getWrapperName(innerClass) << "::define_python_class();" << endl; - } - } - - //Fields - foreach (AbstractMetaField *field, cppClass->fields()) { - QString strAccess; - - if (field->isPublic()) { - - s << INDENT << "python_cls.add_property(" - << "\"" << field->name() << "\"" - << ", getter_" << cppClass->name() << "_" << field->name(); - if (!field->type()->isConstant()) - s << ", setter_" << cppClass->name() << "_" << field->name(); - - s << ");" << endl; - - } - } - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::Beginning, TypeSystem::TargetLangCode); - - QSet staticMethods; - AbstractMetaFunctionList functionList = filterFunctions(cppClass); - - if (!cppClass->isNamespace()) { - //search for all static methods to match with normal functions - //to rename when match with one member function - foreach (AbstractMetaFunction *func, functionList) { - if (func->isStatic() && !func->isOperatorOverload()) - staticMethods << func->name(); - } - } - - foreach (AbstractMetaFunction *func, functionList) { - if (func->isModifiedRemoved() || func->isPrivate() || func->isSignal()) - continue; - - //rename static function when is the same name as member function - if (!cppClass->isNamespace() && func->isStatic()) { - QString staticName(createStaticFunctionName(func)); - QSet::iterator staticFuncInter = staticMethods.find(staticName); - if (staticFuncInter != staticMethods.end()) - func->setName(staticName); - } else { - QSet::iterator staticFuncInter = staticMethods.find(func->name()); - if (staticFuncInter != staticMethods.end()) { - staticMethods.erase(staticFuncInter); - staticMethods << createStaticFunctionName(func); - } - } - - if (func->isOperatorOverload()) { - // Do not join the ifs -- isOperatorOverload must be checked alone - if (func->originalName() == func->name()) - writeOperatorOverload(s, func); - } else if (func->isConstructor()) { - //Use same rule as hpp genenrator for copy constructor - if ((mainCtorHasModifications || func != mainCtor) && !func->isCopyConstructor()) { - writeConstructor(s, func); - } - } else if (!func->isVirtual() && - (func->hasInjectedCode() || - func->isThread() || func->allowThread())) { - writeModifiedMethodDef(s, func); - } else if (func->implementingClass() == func->ownerClass()) { - writeNormalMethodDef(s, func); - } - - //if is namespace all methothds is stattic - if (cppClass->isNamespace()) - s << INDENT << "python_cls.staticmethod(\"" << func->name() << "\");" << endl; - } - - //write copy constructor here - if (isCopyable(cppClass) && !cppClass->isNamespace()) { - s << INDENT << "python_cls.def(python::initqualifiedCppName() << "&>());" << endl; - } - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::End, TypeSystem::TargetLangCode); - - if (!cppClass->isNamespace()) { - // Static methods - if (!staticMethods.isEmpty()) - s << INDENT << "// Static methods" << endl; - - foreach (QString funcName, staticMethods) - s << INDENT << "python_cls.staticmethod(\"" << funcName << "\");" << endl; - } - - // qHash usage - if (!cppClass->typeEntry()->hashFunction().isEmpty()) - writeHashFunction(s, cppClass); - - // implicity conversions - writeImplicitlyConversion(s, cppClass); - - // register object/value type - if (!cppClass->isNamespace()) { - QString className = cppClass->qualifiedCppName(); - const char* funcName = (cppClass->typeEntry()->isObject() || !isCopyable(cppClass)) ? "object" : "value"; - s << INDENT - << "type_manager::instance().register_" - << funcName - << "_type<" << className << " >(\"" - << cppClass->qualifiedCppName() << (cppClass->typeEntry()->isObject() ? "*" : "") << "\");\n"; - } - s << '}' << endl; -} - -void CppGenerator::writeConstructor(QTextStream& s, const AbstractMetaFunction* func) -{ - s << INDENT << "python_cls.def("; - writeConstructorInitialization(s, func); - s << ");" << endl; -} - -void CppGenerator::writeFunctionArgsDef(QTextStream &sOut, - const AbstractMetaFunction *cppFunction) -{ - bool hasDefaultValue = false; - int argUsed = 0; - QString aux; - QTextStream s(&aux); - - foreach (const AbstractMetaArgument *arg, cppFunction->arguments()) { - if (cppFunction->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - if (argUsed > 0) - s << ", "; - - if (!m_disableNamedArgs) - s << "python::arg(\"" << arg->argumentName() << "\")"; - else - s << "python::arg(0)"; - - if (!arg->defaultValueExpression().isEmpty()) { - QString defaultValue = arg->defaultValueExpression(); - bool isPointer = arg->type()->isObject() || - arg->type()->isQObject() || - arg->type()->isValuePointer() || - arg->type()->isNativePointer(); - - if (isPointer && defaultValue == "0") { - defaultValue = "python::object()"; - } else if (arg->type()->isFlags()) { - defaultValue = " (int) " + defaultValue; - } else if (arg->type()->isEnum()) { - QString enumName = arg->type()->minimalSignature(); - QRegExp reg("(.*::)"); - reg.indexIn(enumName); - if (!defaultValue.startsWith(reg.cap(1))) - defaultValue = reg.cap(1) + defaultValue; - } - - s << "=" << defaultValue; - hasDefaultValue = true; - } - argUsed++; - } - - if (hasDefaultValue || ((argUsed > 0) && !m_disableNamedArgs)) - sOut << "," << endl << INDENT << INDENT << "(" << aux << ")"; -} - -void CppGenerator::writeNormalMethodDef(QTextStream& s, const AbstractMetaFunction* func) -{ - s << INDENT << '{' << endl; - { - Indentation indentation(INDENT); - QString wrapperClassName = getWrapperName(func->ownerClass()); - bool needDefaultFunction = func->isVirtual() && !func->isAbstract() && !func->ownerClass()->hasPrivateDestructor(); - QString castName; - - if (needDefaultFunction) - castName = writeFunctionCast(s, func, "_default", func->implementingClass()->qualifiedCppName()); - else - castName = writeFunctionCast(s, func); - - s << INDENT << "python_cls.def(\"" << func->name() << "\", "; - - if (needDefaultFunction) { // add the default function - s << castName << "(&" << wrapperClassName << "::" << func->originalName() << "_default)"; - } else { - if (func->isAbstract()) - s << "python::pure_virtual"; - s << '(' << castName << '(' << getMethodPointerString(func) << "))"; - } - - QString functionPolicy = getFunctionCallPolicy(func); - if (!functionPolicy.isEmpty()) - s << ", " << functionPolicy; - - writeFunctionArgsDef(s, func); - s << ");" << endl; - } - s << INDENT << '}' << endl; -} - -void CppGenerator::writeModifiedMethodDef(QTextStream& s, const AbstractMetaFunction* func) -{ - s << INDENT << '{' << endl; - { - Indentation indentation(INDENT); - QString castName = writeFunctionCast(s, func); - s << INDENT - << "python_cls.def(\"" - << func->name() << "\", " - << castName - << "(&" << func->implementingClass()->name() - << "_" << func->originalName() - << "_modified)"; - QString functionPolicy = getFunctionCallPolicy(func); - if (!functionPolicy.isEmpty()) - s << ", " << functionPolicy; - - writeFunctionArgsDef(s, func); - s << ");" << endl; - } - s << INDENT << '}' << endl; -} - -QString CppGenerator::operatorFunctionName(const AbstractMetaFunction *cppFunction) -{ - QString funcName = QString("%1_operator_%2_") - .arg(cppFunction->arguments()[0]->type()->name()) - .arg(cppFunction->arguments()[1]->type()->name()); - - if (cppFunction->name().contains(">>")) { - funcName += "rshift"; - } else if (cppFunction->name().contains("<<")) { - funcName += "lshift"; - } else { - //TODO: implemente support to others operators - return QString(); - } - - return funcName; -} - -void CppGenerator::writeGlobalOperatorOverloadImpl(QTextStream& s, const AbstractMetaFunction* cppFunction) -{ - Indentation indent(INDENT); - QString operatorStr; - - if (cppFunction->name().contains(">>")) { - operatorStr = " >> "; - } else if (cppFunction->name().contains("<<")) { - operatorStr = " << "; - } else { - //TODO: implemente support to others operators - return; - } - - QString funcName = operatorFunctionName(cppFunction); - bool reverse = cppFunction->isReverseOperator(); - - const AbstractMetaClass *klass = cppFunction->ownerClass(); - s << "python::object " << funcName << "("; - writeFunctionArguments(s, cppFunction, Options(SkipDefaultValues) | SkipRemovedArguments); - s << ")" << endl << "{" << endl - << INDENT << cppFunction->arguments()[reverse]->argumentName() - << operatorStr << cppFunction->arguments()[!reverse]->argumentName() << ";" << endl - << INDENT << "return python::object(PySide::ptr(&" - << cppFunction->arguments()[reverse]->argumentName() << "));" << endl - << "}" << endl; -} - -void CppGenerator::writeGlobalOperatorOverload(QTextStream &s, const AbstractMetaFunction *cppFunction) -{ - QString funcName = operatorFunctionName(cppFunction); - if (funcName.isEmpty()) - return; - - bool reverse = cppFunction->isReverseOperator(); - QString operatorStr; - if (cppFunction->name().contains(">>")) { - operatorStr = QString("__%1rshift__").arg(reverse ? "r" : ""); - } else if (cppFunction->name().contains("<<")) { - operatorStr = QString("__%1lshift__").arg(reverse ? "r" : ""); - } else { - //TODO: implemente support to others operators - return; - } - - s << INDENT << "python_cls.def(\"" << operatorStr << "\", " << funcName << ");\n"; -} - -QString CppGenerator::getOperatorArgumentTypeName(const AbstractMetaFunction *cppFunction, int argumentIndex) -{ - AbstractMetaType* type = cppFunction->arguments()[argumentIndex]->type(); - if (type->name() == cppFunction->implementingClass()->name()) - return QLatin1String("python::self"); - - QString typeName = translateType(type, cppFunction->implementingClass(), - (Option)(ExcludeReference)); - return type->isPrimitive() ? "(" + typeName + ")(0)" : "python::other<" + typeName + " >()"; -} - -void CppGenerator::writeOperatorOverload(QTextStream& s, const AbstractMetaFunction* cppFunction) -{ - static QRegExp operatorRegex("operator(.+)"); - - if (!operatorRegex.exactMatch(cppFunction->originalName())) { - qWarning("What kind of operator is that!? %s", - cppFunction->originalName().toLocal8Bit().data()); - return; - } - - QString op(operatorRegex.cap(1)); - if (op == "=" || op == "[]") { - // = is handled by type boost and type conversions, [] by someone... - return; - } - - // no args == member unary operator - if (!cppFunction->arguments().count()) { - // check if it is a name instead of an operator symbol - // this means it is a conversion operator that will be ignored for now - static QRegExp ConversionOperatorRegex("[A-Za-z]+"); - if (ConversionOperatorRegex.indexIn(op) < 0) - s << INDENT << "python_cls.def(" << op << "python::self);" << endl; - return; - } - - //this because global operators use first arg with current class - if (cppFunction->isInGlobalScope()) { - writeGlobalOperatorOverload(s, cppFunction); - return; - } - - QString operand1, operand2; - if (cppFunction->arguments().count() == 1) { - operand1 = "python::self"; - operand2 = getOperatorArgumentTypeName(cppFunction, 0); - } else { - operand1 = getOperatorArgumentTypeName(cppFunction, 0); - operand2 = getOperatorArgumentTypeName(cppFunction, 1); - } - s << INDENT << "python_cls.def(" << operand1 << ' ' << op << ' ' << operand2 << ");\n"; -} - -void CppGenerator::finishGeneration() -{ - //Generate boost wrapper file - QString classFiles; - QTextStream sClassFiles(&classFiles); - QString classPythonDefines; - QTextStream sClassPythonDefines(&classPythonDefines); - - Indentation indent(INDENT); - - foreach (AbstractMetaClass *cls, classes()) { - if (!shouldGenerate(cls) || cls->enclosingClass()) - continue; - - if (m_packageName.isEmpty()) - m_packageName = cls->package(); - - QString wrapperName = getWrapperName(cls); - QString boostFilename; - boostFilename += wrapperName + ".hpp"; - sClassFiles << "#include \"" << boostFilename << "\"" << endl; - - QString define_str = wrapperName + "::"; - define_str += "define_python_class();"; - - sClassPythonDefines << INDENT << define_str << endl; - } - - QString moduleFileName(outputDirectory() + "/" + subDirectoryForPackage(m_packageName)); - moduleFileName += "/" + moduleName().toLower() + "_module_wrapper.cpp"; - - QFile file(moduleFileName); - if (file.open(QFile::WriteOnly)) { - QTextStream s(&file); - - // write license comment - s << licenseComment() << endl; - - s << "#include \"converter_register_" << moduleName().toLower(); - s << ".hpp\"" << endl << endl; - - s << classFiles << endl; - - s << "using namespace boost;" << endl << endl; - s << "using namespace PySide;" << endl << endl; - - s << "// forward decl. for global func. register\n"; - s << "void register_global_functions_" << moduleName().toLower() << "();\n\n"; - - s << "BOOST_PYTHON_MODULE(" << moduleName() << ")" << endl; - s << "{" << endl; - - foreach (QString requiredModule, TypeDatabase::instance()->requiredTargetImports()) { - s << INDENT << "if ("; - s << "PyImport_ImportModule(\"" << requiredModule << "\") == NULL) {" << endl; - s << INDENT << INDENT << "PyErr_SetString(PyExc_ImportError,"; - s << "\"could not import " << requiredModule << "\");" << endl; - s << INDENT << INDENT << "return;" << endl; - s << INDENT << "}" << endl; - } - s << endl; - - - - s << INDENT << "register_type_converters_" << moduleName().toLower() << "();" << endl << endl - << classPythonDefines << endl - << INDENT << "register_global_functions_" << moduleName().toLower() << "();" << endl - << INDENT << "//Namespaces" << endl; - - s << "}" << endl << endl; - } - - writeGlobalFunctions(); -} - -void CppGenerator::writeGlobalFunctions() -{ - QString fileName = moduleName().toLower() + "_globals_wrapper.cpp"; - - FileOut fileOut(outputDirectory() + "/" + subDirectoryForPackage(m_packageName) + "/" + fileName); - - QSet includes; - QString defsStr; - QTextStream defsStream(&defsStr); - - foreach (AbstractMetaFunction* func, globalFunctions()) { - QString incFile = func->includeFile(); - QRegExp regex("\\b" + moduleName() + "\\b"); - //FIXME: this regex doesn't work with all cases, e.g.: - // moduleName() = local - // incFile = /usr/local/include/local - if (regex.indexIn(incFile) == -1) - continue; - - int idx = incFile.indexOf(moduleName()); - QString cleanPath = QDir::cleanPath(incFile.mid(idx)); - if (!cleanPath.startsWith(moduleName())) - continue; - - includes << cleanPath; - defsStream << INDENT << "{\n" << INDENT; - QString castName = writeFunctionCast(defsStream, func); - defsStream << INDENT << INDENT << "python::def(\"" << func->name(); - defsStream << "\", " << castName << '(' << func->name() << ')'; - if (func->type() && func->type()->isReference()) - defsStream << ", python::return_internal_reference<>()"; - defsStream << ");\n"; - defsStream << INDENT << "}\n"; - } - - QTextStream& s = fileOut.stream; - - // write license comment - s << licenseComment() << endl; - - s << "#include \"pyside.hpp\"" << endl; - - foreach (QString include, includes) - s << "#include <" << include << ">\n"; - - s << "using namespace boost;\n\n"; - s << "using namespace PySide;\n\n"; - - // Add module level code snippets to 'Global' class - TypeSystemTypeEntry *moduleEntry = dynamic_cast( - TypeDatabase::instance()->findType(m_packageName)); - QString sEnd; - QTextStream snipEnd(&sEnd); - if (moduleEntry && moduleEntry->codeSnips().size() > 0) { - foreach (CodeSnip snip, moduleEntry->codeSnips()) { - if (snip.position == CodeSnip().Beginning) - formatCode(s, snip.code(), INDENT); - else - formatCode(snipEnd, snip.code(), INDENT); - } - } - - s << "\nvoid register_global_functions_" << moduleName().toLower() << "() {\n"; - { //global enums - QString name_space; - - foreach (AbstractMetaEnum *cppEnum, globalEnums()) { - if (cppEnum) - writeEnum(s, cppEnum, name_space); - } - } - s << sEnd; - s << defsStr; - s << "}\n"; -} - -QMap CppGenerator::options() const -{ - QMap res; - res.insert("disable-named-arg", "Disable Python names arguments."); - return res; -} - -bool CppGenerator::doSetup(const QMap& args ) -{ - m_disableNamedArgs = args.contains("disable-named-arg"); - return BoostPythonGenerator::doSetup(args); -} diff --git a/generators/boostpython/cppgenerator.h b/generators/boostpython/cppgenerator.h deleted file mode 100644 index d2d65a4e5..000000000 --- a/generators/boostpython/cppgenerator.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef CPPGENERATOR_H -#define CPPGENERATOR_H - -#include "boostpythongenerator.h" - -/** -* The CppGenerator generate the implementation of boost::python bindings classes. -*/ -class CppGenerator : public BoostPythonGenerator -{ -public: - const char* name() const - { - return "CppGenerator"; - } - - QMap options() const; - bool doSetup(const QMap& args); - -protected: - QString fileNameForClass(const AbstractMetaClass *cppClass) const; - void generateClass(QTextStream &s, const AbstractMetaClass *cppClass); - void finishGeneration(); - -private: - void writePrelude(QTextStream &s, const AbstractMetaClass *cppClass); - void writeBoostDeclaration(QTextStream &s, const AbstractMetaClass *cppClass); - - // method declaration writers - void writeConstructor(QTextStream &s, const AbstractMetaFunction *func); - void writeConstructorInitialization(QTextStream &s, const AbstractMetaFunction *func); - void writeNormalMethodDef(QTextStream &s, const AbstractMetaFunction *func); - void writeModifiedMethodDef(QTextStream &s, const AbstractMetaFunction *func); - void writeOperatorOverload(QTextStream &s, const AbstractMetaFunction *func); - void writeGlobalOperatorOverload(QTextStream &s, const AbstractMetaFunction *func); - void writeFunctionArgsDef(QTextStream &s_out, const AbstractMetaFunction *func); - void writeGlobalFunctions(); - void writeDestructor(QTextStream &s, const AbstractMetaClass *cppClass); - - // method implementation writers - void writeModifiedConstructorImpl(QTextStream &s, const AbstractMetaFunction *func); - void writeConstructorImpl(QTextStream &s, const AbstractMetaFunction *func); - void writeVirtualMethodImpl(QTextStream &s, const AbstractMetaFunction *func); - void writeVirtualMethodImplHead(QTextStream &s, const AbstractMetaFunction *func); - void writeVirtualMethodImplFoot(QTextStream &s, const AbstractMetaFunction *func); - void writePureVirtualMethodImplFoot(QTextStream &s, const AbstractMetaFunction *func); - void writeNonVirtualModifiedFunctionImpl(QTextStream &s, const AbstractMetaFunction *func); - void writeGlobalOperatorOverloadImpl(QTextStream& s, const AbstractMetaFunction* func); - - // helper functions - QString writeFunctionCast(QTextStream& s, const AbstractMetaFunction* func, const QString& castNameSuffix = QString(), const QString& className = QString()); - QString getFuncTypedefName(const AbstractMetaFunction *func) const; - QString getFunctionReturnType(const AbstractMetaFunction *func); - AbstractMetaFunction* findMainConstructor(const AbstractMetaClass *clazz); - QString getArgumentType(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func, int idx); - QString operatorFunctionName(const AbstractMetaFunction *func); - QString getOperatorArgumentTypeName(const AbstractMetaFunction *func, int argumentIndex); - - // Field access related - void writeSetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field); - void writeGetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field); - void writeFieldAccess(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field); - void writeFieldsAccessFunctions(QTextStream& s, const AbstractMetaClass* cppClass); - - // call policy related - QString verifyDefaultReturnPolicy(const AbstractMetaFunction *func, const QString &callPolicy); - QString getFunctionCallPolicy(const AbstractMetaFunction *func); - - // enum related - void writeEnums(QTextStream &s, const AbstractMetaClass *cppClass, bool useNamespace); - void writeEnum(QTextStream &s, const AbstractMetaEnum *cppEnum, const QString &nameSpace); - - // write implicitly conversions - void writeImplicitlyConversion(QTextStream &s, const AbstractMetaClass *cppClass); - void writeVirtualDefaultFunction(QTextStream &s, const AbstractMetaFunction *arg2); - - void writeHashFunction(QTextStream &s, const AbstractMetaClass *cppClass); - QString baseClassName(const QString &name); - - bool m_disableNamedArgs; -}; - -#endif // CPPGENERATOR_H - diff --git a/generators/boostpython/hppgenerator.cpp b/generators/boostpython/hppgenerator.cpp deleted file mode 100644 index 334cee505..000000000 --- a/generators/boostpython/hppgenerator.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include "hppgenerator.h" -#include - -#include -#include -#include -#include -#include - -static Indentor INDENT; - -QString HppGenerator::fileNameForClass(const AbstractMetaClass *cppClass) const -{ - return getWrapperName(cppClass) + QLatin1String(".hpp"); -} - -void HppGenerator::writeCopyCtor(QTextStream &s, const AbstractMetaClass *cppClass) -{ - s << INDENT << getWrapperName(cppClass) << "(PyObject *py_self, const " << cppClass->qualifiedCppName() << "& self)" - << " : " << cppClass->qualifiedCppName() << "(self), wrapper(py_self)" << endl - << INDENT << "{" << endl - << INDENT << "}" << endl; -} - -void HppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass) -{ - ReportHandler::debugSparse("Generating header for " + cppClass->fullName()); - Indentation indent(INDENT); - - // write license comment - s << licenseComment() << endl; - - QString wrapperName = HppGenerator::getWrapperName(cppClass); - // Header - s << "#ifndef __" << wrapperName.toUpper() << "__" << endl; - s << "#define __" << wrapperName.toUpper() << "__" << endl << endl; - - s << "#include " << endl; - //Includes - if (cppClass->typeEntry()->include().isValid()) - s << cppClass->typeEntry()->include().toString() << endl << endl; - - s << "using namespace PySide;" << endl << endl; - - if (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor() || cppClass->isNamespace()) - s << "namespace " << wrapperName << " {" << endl << endl; - - bool needWriteBackReference = false; - if (cppClass->isNamespace()) { - s << INDENT << "struct Namespace {};" << endl; - } else { - QString className; - bool create_wrapper = canCreateWrapperFor(cppClass); - bool is_wrapper = false; - // detect the held type - QString held_type = cppClass->typeEntry()->heldTypeValue(); - if (held_type.isEmpty() && create_wrapper) - held_type = "qptr"; - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::Declaration, TypeSystem::NativeCode); - - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) { - // Class - s << "class PYSIDE_LOCAL " << wrapperName; - if (create_wrapper) { - s << " : public " << cppClass->qualifiedCppName() << ", public PySide::wrapper"; - } - s << endl; - s << "{" << endl; - } - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::Declaration, TypeSystem::ShellDeclaration); - - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) { - s << endl << "private:" << endl; - className = wrapperName; - is_wrapper = true; - } else { - className = cppClass->qualifiedCppName(); - } - - // print the huge boost::python::class_ typedef - s << INDENT << "typedef boost::python::class_< " << cppClass->qualifiedCppName(); - - writeBaseClass(s, cppClass); - - if (!held_type.isEmpty()) - s << ", PySide::" << held_type << " < " << className << ", qptr_base::no_check_cache | qptr_base::" - << ( is_wrapper ? "wrapper_pointer" : "no_wrapper_pointer") << "> "; - - if (!isCopyable(cppClass)) - s << ", boost::noncopyable"; - - s << " > class_type;" << endl; - - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) { - s << "public:" << endl; - - if (isCopyable(cppClass)) - writeCopyCtor(s, cppClass); - - foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) - writeFunction(s, func); - - if (create_wrapper) { - //destructor - s << INDENT << "~" << wrapperName << "();" << endl; - - if (cppClass->isQObject() && (cppClass->name() != "QObject")) - s << INDENT << "using QObject::parent;" << endl; - } - } - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::End, TypeSystem::ShellDeclaration); - } - - QString staticKeyword = cppClass->isNamespace() ? QLatin1String("") : QLatin1String("static "); - s << INDENT; - if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) { - s << "//static member used to export class" << endl; - s << INDENT << staticKeyword; - } - s << "void define_python_class() throw();" << endl << endl; - - writeCodeSnips(s, cppClass->typeEntry()->codeSnips(), - CodeSnip::PrototypeInitialization, TypeSystem::NativeCode); - - - s << "};" << endl << endl; - - s << "#endif // __" << wrapperName.toUpper() << "__" << endl << endl; -} - -void HppGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction* func) -{ - // pure virtual functions need a default implementation - if ((func->isPrivate() && !func->isConstructor()) || (func->isModifiedRemoved() && !func->isAbstract())) - return; - - // do not write copy ctors here. - if (func->isCopyConstructor()) - return; - - if (func->isConstructor() || func->isAbstract() || func->isVirtual()) { - if (func->isVirtual() && !func->isAbstract() && !func->isConstructor() - && !func->ownerClass()->hasPrivateDestructor() - && func->implementingClass() == func->ownerClass()) { - s << INDENT << "static " << signatureForDefaultVirtualMethod(func, "", "_default", Generator::Options( Generator::SkipName | Generator::SkipRemovedArguments) ) << ';' << endl; - } - - if (func->isConstructor()) { - s << INDENT << getWrapperName(func->ownerClass()) << "(PyObject *py_self" << (func->arguments().size() ? "," : ""); - writeFunctionArguments(s, func, Options(OriginalTypeDescription) | SkipName); - s << ")"; - } else { - s << INDENT << functionSignature(func, "", "", Options(OriginalTypeDescription) | SkipName); - } - - if (func->isModifiedRemoved() && func->isAbstract()) - writeDefaultImplementation(s, func); - else - s << ';' << endl; - } -} - -void HppGenerator::writeDefaultImplementation(QTextStream& s, const AbstractMetaFunction* func) -{ - QString returnValue; - if (func->type()) { - if (func->type()->isObject() || func->type()->isQObject() || func->type()->name() == "void") - returnValue = "0"; - else - returnValue = functionReturnType(func) + "()"; - } - s << " { return " << returnValue << "; }" << endl; -} - -void HppGenerator::writeBaseClass(QTextStream& s, const AbstractMetaClass* cppClass) -{ - if (!cppClass->isNamespace() && !cppClass->isInterface()) { - QStringList baseClass = getBaseClasses(cppClass); - - if (baseClass.isEmpty()) { - const ComplexTypeEntry *type = cppClass->typeEntry(); - if (cppClass->name() != type->defaultSuperclass()) { - QString sc = type->defaultSuperclass(); - if (!sc.isEmpty()) - s << ", python::bases< " << sc << "> "; - } - } else { - s << ", boost::python::bases< " << baseClass.join(", ") << " > "; - } - } -} - diff --git a/generators/boostpython/hppgenerator.h b/generators/boostpython/hppgenerator.h deleted file mode 100644 index 8e0f5f03b..000000000 --- a/generators/boostpython/hppgenerator.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef HPPGENERATOR_H -#define HPPGENERATOR_H - -#include "boostpythongenerator.h" - -/** -* The HppGenerator generate the declarations of boost::python bindings classes. -*/ -class HppGenerator : public BoostPythonGenerator -{ -protected: - QString fileNameForClass(const AbstractMetaClass* cppClass) const; - void generateClass(QTextStream& s, const AbstractMetaClass* cppClass); - void finishGeneration() {} - const char* name() const - { - return "HppGenerator"; - } -private: - void writeFunction(QTextStream& s, const AbstractMetaFunction* func); - void writePureVirtualEmptyImpl(QTextStream& , const AbstractMetaFunction* func); - void writeBaseClass(QTextStream& s, const AbstractMetaClass* cppClass); - void writeCopyCtor(QTextStream &s, const AbstractMetaClass* cppClass); - void writeDefaultImplementation(QTextStream& s, const AbstractMetaFunction* func); -}; - -#endif // HPPGENERATOR_H - diff --git a/generators/boostpython/main.cpp b/generators/boostpython/main.cpp deleted file mode 100644 index b4e81a878..000000000 --- a/generators/boostpython/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the Boost Python Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include - -int main(int argc, char *argv[]) -{ - QStringList args; - args.append("--generatorSet=boostpython"); - for (int i = 1; i < argc; i++) - args.append(argv[i]); - return QProcess::execute("generatorrunner", args); -} - diff --git a/generators/qtdoc/main.cpp b/generators/qtdoc/main.cpp index c513147d3..76d695bf6 100644 --- a/generators/qtdoc/main.cpp +++ b/generators/qtdoc/main.cpp @@ -1,5 +1,5 @@ /* - * This file is part of the Boost Python Generator project. + * This file is part of the PySide project. * * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * diff --git a/generators/qtdoc/qtdocgenerator.cpp b/generators/qtdoc/qtdocgenerator.cpp index 67e53b187..ff05d9336 100644 --- a/generators/qtdoc/qtdocgenerator.cpp +++ b/generators/qtdoc/qtdocgenerator.cpp @@ -1,5 +1,5 @@ /* - * This file is part of the Boost Python Generator project. + * This file is part of the PySide project. * * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * diff --git a/generators/qtdoc/qtdocgenerator.h b/generators/qtdoc/qtdocgenerator.h index af25ccea5..01717a0cd 100644 --- a/generators/qtdoc/qtdocgenerator.h +++ b/generators/qtdoc/qtdocgenerator.h @@ -1,5 +1,5 @@ /* - * This file is part of the Boost Python Generator project. + * This file is part of the PySide project. * * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * -- cgit v1.2.3