Alien-SmokeQt
view release on metacpan or search on metacpan
generator/generators/smoke/writeClasses.cpp view on Meta::CPAN
QString unionField = Util::stackItemField(type);
QString cast = type->toString();
cast.replace("&", "");
if (unionField == "s_class" && type->pointerDepth() == 0) {
out << '*';
cast += '*';
}
out << '(' << cast << ')' << "x[1]." << unionField << ";\n";
out << " }\n";
}
void SmokeClassFiles::generateEnumMemberCall(QTextStream& out, const QString& className, const QString& member, int index)
{
out << " static void x_" << index << "(Smoke::Stack x) {\n"
<< " x[0].s_enum = (long)";
if (!className.isEmpty())
out << className << "::";
out << member << ";\n"
<< " }\n";
}
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";
}
void SmokeClassFiles::writeClass(QTextStream& out, const Class* klass, const QString& className, QSet<QString>& includes)
{
const QString underscoreName = QString(className).replace("::", "__");
const QString smokeClassName = "x_" + underscoreName;
QString switchCode;
QTextStream switchOut(&switchCode);
out << QString("class %1").arg(smokeClassName);
if (!klass->isNameSpace()) {
out << QString(" : public %1").arg(className);
if (Util::hasClassVirtualDestructor(klass) && Util::hasClassPublicDestructor(klass)) {
out << ", public __internal_SmokeClass";
}
}
out << " {\n";
if (Util::canClassBeInstanciated(klass)) {
out << " SmokeBinding* _binding;\n";
out << "public:\n";
out << " void x_0(Smoke::Stack x) {\n";
out << " // set the smoke binding\n";
out << " _binding = (SmokeBinding*)x[1].s_class;\n";
out << " }\n";
switchOut << " case 0: xself->x_0(args);\tbreak;\n";
} else {
out << "public:\n";
}
int xcall_index = 1;
const Method *destructor = 0;
foreach (const Method& meth, klass->methods()) {
if (meth.access() == Access_private)
continue;
if (meth.isDestructor()) {
destructor = &meth;
continue;
}
switchOut << " case " << xcall_index << ": "
<< (((meth.flags() & Method::Static) || meth.isConstructor()) ? smokeClassName + "::" : "xself->")
<< "x_" << xcall_index << "(args);\tbreak;\n";
if (Util::fieldAccessors.contains(&meth)) {
// accessor method?
const Field* field = Util::fieldAccessors[&meth];
if (meth.name().startsWith("set")) {
generateSetAccessor(out, className, *field, meth.parameters()[0].type(), xcall_index);
} else {
generateGetAccessor(out, className, *field, meth.type(), xcall_index);
}
} else {
generateMethod(out, className, smokeClassName, meth, xcall_index, includes);
}
xcall_index++;
}
QString enumCode;
QTextStream enumOut(&enumCode);
const Enum* e = 0;
bool enumFound = false;
foreach (const BasicTypeDeclaration* decl, klass->children()) {
if (!(e = dynamic_cast<const Enum*>(decl)))
continue;
if (e->access() == Access_private)
continue;
foreach (const EnumMember& member, e->members()) {
switchOut << " case " << xcall_index << ": " << smokeClassName << "::x_" << xcall_index << "(args);\tbreak;\n";
if (e->parent())
generateEnumMemberCall(out, className, member.name(), xcall_index++);
else
generateEnumMemberCall(out, e->nameSpace(), member.name(), xcall_index++);
}
// only generate the xenum_call if the enum has a valid name
if (e->name().isEmpty())
continue;
enumFound = true;
// xenum_operation method code
QString enumString = e->toString();
enumOut << " case " << m_smokeData->typeIndex[&types[enumString]] << ": //" << enumString << '\n';
enumOut << " switch(xop) {\n";
enumOut << " case Smoke::EnumNew:\n";
enumOut << " xdata = (void*)new " << enumString << ";\n";
enumOut << " break;\n";
enumOut << " case Smoke::EnumDelete:\n";
enumOut << " delete (" << enumString << "*)xdata;\n";
enumOut << " break;\n";
enumOut << " case Smoke::EnumFromLong:\n";
enumOut << " *(" << enumString << "*)xdata = (" << enumString << ")xvalue;\n";
enumOut << " break;\n";
enumOut << " case Smoke::EnumToLong:\n";
enumOut << " xvalue = (long)*(" << enumString << "*)xdata;\n";
enumOut << " break;\n";
enumOut << " }\n";
enumOut << " break;\n";
}
foreach (const Method* meth, Util::virtualMethodsForClass(klass)) {
generateVirtualMethod(out, *meth, includes);
}
// this class contains enums, write out an xenum_operation method
if (enumFound) {
out << " static void xenum_operation(Smoke::EnumOperation xop, Smoke::Index xtype, void *&xdata, long &xvalue) {\n";
out << " switch(xtype) {\n";
out << enumCode;
out << " }\n";
out << " }\n";
}
// destructor
// if the class can't be instanstiated, a callback when it's deleted is unnecessary
if (Util::canClassBeInstanciated(klass)) {
out << " ~" << smokeClassName << "() ";
if (destructor && destructor->hasExceptionSpec()) {
out << "throw(";
for (int i = 0; i < destructor->exceptionTypes().count(); i++) {
if (i > 0) out << ", ";
out << destructor->exceptionTypes()[i].toString();
}
out << ") ";
}
out << QString("{ this->_binding->deleted(%1, (void*)this); }\n").arg(m_smokeData->classIndex[className]);
}
out << "};\n";
if (enumFound) {
out << "void xenum_" << underscoreName << "(Smoke::EnumOperation xop, Smoke::Index xtype, void *&xdata, long &xvalue) {\n";
out << " " << smokeClassName << "::xenum_operation(xop, xtype, xdata, xvalue);\n";
out << "}\n";
}
// xcall_class function
out << "void xcall_" << underscoreName << "(Smoke::Index xi, void *obj, Smoke::Stack args) {\n";
out << " " << smokeClassName << " *xself = (" << smokeClassName << "*)obj;\n";
out << " switch(xi) {\n";
out << switchCode;
if (Util::hasClassPublicDestructor(klass))
out << " case " << xcall_index << ": delete (" << className << "*)xself;\tbreak;\n";
out << " }\n";
out << "}\n";
}
( run in 0.460 second using v1.01-cache-2.11-cpan-2398b32b56e )