Пример #1
0
void SmokeClassFiles::generateMethod(QTextStream& out, const QString& className, const QString& smokeClassName,
                                     const Method& meth, int index, QSet<QString>& includes)
{
    out << "    ";
    if ((meth.flags() & Method::Static) || meth.isConstructor())
        out << "static ";
    out << QString("void x_%1(Smoke::Stack x) {\n").arg(index);
    out << "        // " << meth.toString() << "\n";

    bool dynamicDispatch = ((meth.flags() & Method::PureVirtual) || (meth.flags() & Method::DynamicDispatch));

    if (dynamicDispatch || !Util::virtualMethodsForClass(meth.getClass()).contains(&meth)) {
        // This is either already flagged as dynamic dispatch or just a normal method. We can generate a normal method call for it.

        out << generateMethodBody("        ",   // indent
                                  className, smokeClassName, meth, index, dynamicDispatch, includes);
    } else {
        // This is a virtual method. To know whether we should call with dynamic dispatch, we need a bit of RTTI magic.
        includes.insert("typeinfo");
        out << "        if (dynamic_cast<__internal_SmokeClass*>(static_cast<" << className << "*>(this))) {\n";   //
        out << generateMethodBody("            ",   // indent
                                  className, smokeClassName, meth, index, false, includes);
        out << "        } else {\n";
        out << generateMethodBody("            ",   // indent
                                  className, smokeClassName, meth, index, true, includes);
        out << "        }\n";
    }

    out << "    }\n";
    
    // If the constructor was generated from another one with default parameteres, we don't need to explicitly create
    // it here again. The x_* call will append the default parameters at the end and thus choose the right constructor.
    if (meth.isConstructor() && meth.remainingDefaultValues().isEmpty()) {
        out << "    explicit " << smokeClassName << '(';
        QStringList x_list;
        for (int i = 0; i < meth.parameters().count(); i++) {
            if (i > 0) out << ", ";
            Type *paramType = meth.parameters()[i].type();
            QString paramName = " x" + QString::number(i + 1);
            out << paramType->toString(paramName);
            if (!paramType->isFunctionPointer())
              out << paramName;
            x_list << "x" + QString::number(i + 1);
        }
        out << ") : " << meth.getClass()->name() << '(' << x_list.join(", ") << ") {}\n";
    }
}
Пример #2
0
void SmokeClassFiles::generateMethod(QTextStream& out, const QString& className, const QString& smokeClassName,
                                     const Method& meth, int index, QSet<QString>& includes)
{
    out << "    ";
    if ((meth.flags() & Method::Static) || meth.isConstructor())
        out << "static ";
    out << QString("void x_%1(Smoke::Stack x) {\n").arg(index);
    out << "        // " << meth.toString() << "\n";
    out << "        ";
    
    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 (!(meth.flags() & Method::PureVirtual) && !func) {
            // dynamic dispatch for virtuals
            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, so 
    
    if (!meth.remainingDefaultValues().isEmpty()) {
        const QStringList& defaultParams = meth.remainingDefaultValues();
        if (meth.parameters().count() > 0)
            out << "," ;
        out << defaultParams.join(",");
    }
    
    out << ");\n";
    if (meth.type() != Type::Void) {
        out << "        x[0]." << Util::stackItemField(meth.type()) << " = " << Util::assignmentString(meth.type(), "xret") << ";\n";
    } else {
        out << "        (void)x; // noop (for compiler warning)\n";
    }
    
    out << "    }\n";
    
    // If the constructor was generated from another one with default parameteres, we don't need to explicitly create
    // it here again. The x_* call will append the default parameters at the end and thus choose the right constructor.
    if (meth.isConstructor() && meth.remainingDefaultValues().isEmpty()) {
        out << "    explicit " << smokeClassName << '(';
        QStringList x_list;
        for (int i = 0; i < meth.parameters().count(); i++) {
            if (i > 0) out << ", ";
            out << meth.parameters()[i].type()->toString() << " x" << QString::number(i + 1);
            x_list << "x" + QString::number(i + 1);
        }
        out << ") : " << meth.getClass()->name() << '(' << x_list.join(", ") << ") {}\n";
    }
}
Пример #3
0
void SmokeClassFiles::generateVirtualMethod(QTextStream& out, const Method& meth, QSet<QString>& includes)
{
    QString x_params, x_list;
    QString type = meth.type()->toString();
    if (meth.type()->getClass())
        includes.insert(meth.type()->getClass()->fileName());
    
    out << "    virtual " << type << " " << meth.name() << "(";
    for (int i = 0; i < meth.parameters().count(); i++) {
        if (i > 0) { out << ", "; x_list.append(", "); }
        const Parameter& param = meth.parameters()[i];
        
        if (param.type()->getClass())
            includes.insert(param.type()->getClass()->fileName());
        
        out << param.type()->toString() << " x" << i + 1;
        x_params += QString("        x[%1].%2 = %3;\n")
            .arg(QString::number(i + 1)).arg(Util::stackItemField(param.type()))
            .arg(Util::assignmentString(param.type(), "x" + QString::number(i + 1)));
        x_list += "x" + QString::number(i + 1);
    }
    out << ") ";
    if (meth.isConst())
        out << "const ";
    if (meth.hasExceptionSpec()) {
        out << "throw(";
        for (int i = 0; i < meth.exceptionTypes().count(); i++) {
            if (i > 0) out << ", ";
            out << meth.exceptionTypes()[i].toString();
        }
        out << ") ";
    }
    out << "{\n";
    out << QString("        Smoke::StackItem x[%1];\n").arg(meth.parameters().count() + 1);
    out << x_params;
    
    if (meth.flags() & Method::PureVirtual) {
        out << QString("        this->_binding->callMethod(%1, (void*)this, x, true /*pure virtual*/);\n").arg(m_smokeData->methodIdx[&meth]);
        if (meth.type() != Type::Void) {
            QString field = Util::stackItemField(meth.type());
            if (meth.type()->pointerDepth() == 0 && field == "s_class") {
                QString tmpType = type;
                if (meth.type()->isRef()) tmpType.replace('&', "");
                tmpType.append('*');
                out << "        " << tmpType << " xptr = (" << tmpType << ")x[0].s_class;\n";
                out << "        " << type << " xret(*xptr);\n";
                out << "        delete xptr;\n";
                out << "        return xret;\n";
            } else {
                out << QString("        return (%1)x[0].%2;\n").arg(type, Util::stackItemField(meth.type()));
            }
        }
    } else {
        out << QString("        if (this->_binding->callMethod(%1, (void*)this, x)) ").arg(m_smokeData->methodIdx[&meth]);
        if (meth.type() == Type::Void) {
            out << "return;\n";
        } else {
            QString field = Util::stackItemField(meth.type());
            if (meth.type()->pointerDepth() == 0 && field == "s_class") {
                QString tmpType = type;
                if (meth.type()->isRef()) tmpType.replace('&', "");
                tmpType.append('*');
                out << "{\n";
                out << "            " << tmpType << " xptr = (" << tmpType << ")x[0].s_class;\n";
                out << "            " << type << " xret(*xptr);\n";
                out << "            delete xptr;\n";
                out << "            return xret;\n";
                out << "        }\n";
            } else {
                out << QString("return (%1)x[0].%2;\n").arg(type, Util::stackItemField(meth.type()));
            }
        }
        out << "        ";
        if (meth.type() != Type::Void)
            out << "return ";
        out << QString("this->%1::%2(%3);\n").arg(meth.getClass()->toString()).arg(meth.name()).arg(x_list);
    }
    out << "    }\n";
}