Alien-SmokeQt

 view release on metacpan or  search on metacpan

generator/generators/smoke/writeClasses.cpp  view on Meta::CPAN

/*
    Generator for the SMOKE sources
    Copyright (C) 2009 Arno Rehn <arno@arnorehn.de>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QMap>
#include <QSet>
#include <QTextStream>

#include <type.h>

#include "globals.h"
#include "../../options.h"

SmokeClassFiles::SmokeClassFiles(SmokeDataFile *data)
    : m_smokeData(data)
{
}

void SmokeClassFiles::write()
{
    write(m_smokeData->includedClasses);
}

void SmokeClassFiles::write(const QList<QString>& keys)
{
    qDebug("writing out x_*.cpp [%s]", qPrintable(Options::module));
    
    // how many classes go in one file
    int count = keys.count() / Options::parts;
    int count2 = count;
    
    for (int i = 0; i < Options::parts; i++) {
        QSet<QString> includes;
        QString classCode;
        QTextStream classOut(&classCode);
        
        // write the class code to a QString so we can later prepend the #includes
        if (i == Options::parts - 1) count2 = -1;
        foreach (const QString& str, keys.mid(count * i, count2)) {
            const Class* klass = &classes[str];
            includes.insert(klass->fileName());
            writeClass(classOut, klass, str, includes);
        }
        
        // create the file
        QFile file(Options::outputDir.filePath("x_" + QString::number(i + 1) + ".cpp"));
        file.open(QFile::ReadWrite | QFile::Truncate);

        QTextStream fileOut(&file);
        
        // write out the header
        fileOut << "//Auto-generated by " << QCoreApplication::arguments()[0] << ". DO NOT EDIT.\n";

        // ... and the #includes
        QList<QString> sortedIncludes = includes.toList();
        qSort(sortedIncludes.begin(), sortedIncludes.end());
        foreach (const QString& str, sortedIncludes) {
            if (str.isEmpty())
                continue;
            fileOut << "#include <" << str << ">\n";
        }

        fileOut << "\n#include <smoke.h>\n#include <" << Options::module << "_smoke.h>\n";

        fileOut << "\nclass __internal_SmokeClass {};\n";

        fileOut << "\nnamespace __smoke" << Options::module << " {\n\n";

        // now the class code
        fileOut << classCode;
        
        fileOut << "\n}\n";
        
        file.close();
    }
}

QString SmokeClassFiles::generateMethodBody(const QString& indent, const QString& className, const QString& smokeClassName, const Method& meth,
                                            int index, bool dynamicDispatch, QSet<QString>& includes)
{
    QString methodBody;
    QTextStream out(&methodBody);

    out << indent;

    if (meth.isConstructor()) {
        out << smokeClassName << "* xret = new " << smokeClassName << "(";
    } else {
        const Function* func = Util::globalFunctionMap[&meth];
        if (func)
            includes.insert(func->fileName());

        if (meth.type()->getClass())
            includes.insert(meth.type()->getClass()->fileName());

        if (meth.type()->isFunctionPointer() || meth.type()->isArray())
            out << meth.type()->toString("xret") << " = ";
        else if (meth.type() != Type::Void)
            out << meth.type()->toString() << " xret = ";

        if (!(meth.flags() & Method::Static)) {
            if (meth.isConst()) {
                out << "((const " << smokeClassName << "*)this)->";
            } else {
                out << "this->";
            }
        }
        if (!dynamicDispatch && !func) {
            // dynamic dispatch not wanted, call with 'this->Foo::method()'
            out << className << "::";
        } else if (func) {
            if (!func->nameSpace().isEmpty())
                out << func->nameSpace() << "::";
        }
        out << meth.name() << "(";
    }

    for (int j = 0; j < meth.parameters().count(); j++) {
        const Parameter& param = meth.parameters()[j];

        if (param.type()->getClass())
            includes.insert(param.type()->getClass()->fileName());

        if (j > 0) out << ",";

        QString field = Util::stackItemField(param.type());
        QString typeName = param.type()->toString();
        if (param.type()->isArray()) {
            Type t = *param.type();
            t.setPointerDepth(t.pointerDepth() + 1);
            t.setIsRef(false);
            typeName = t.toString();
            out << '*';
        } else if (field == "s_class" && (param.type()->pointerDepth() == 0 || param.type()->isRef()) && !param.type()->isFunctionPointer()) {
            // references and classes are passed in s_class
            typeName.append('*');
            out << '*';
        }
        // casting to a reference doesn't make sense in this case
        if (param.type()->isRef() && !param.type()->isFunctionPointer()) typeName.replace('&', "");
        out << "(" << typeName << ")" << "x[" << j + 1 << "]." << field;
    }

    // if the method has any other default parameters, append them here as values
    if (!meth.remainingDefaultValues().isEmpty()) {
        const QStringList& defaultParams = meth.remainingDefaultValues();
        if (meth.parameters().count() > 0)
            out << "," ;
        out << defaultParams.join(",");



( run in 0.717 second using v1.01-cache-2.11-cpan-13bb782fe5a )