From 1155fe8c710818eac3c0490724b34adef95d9999 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Wed, 13 Apr 2011 20:55:47 -0300 Subject: Implemented generation code for mapping protocol Fixex bug #743. Reviewer: Marcelo Lira Hugo Parente Lima --- generator/cppgenerator.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++-- generator/cppgenerator.h | 14 +++++++- 2 files changed, 95 insertions(+), 3 deletions(-) (limited to 'generator') diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 8a9ee4571..a8d6c32ae 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -105,6 +105,11 @@ CppGenerator::CppGenerator() : m_currentErrorCode(0) m_sequenceProtocol.insert("__setslice__", StrPair("PyObject* self, Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value", "int")); m_sequenceProtocol.insert("__contains__", StrPair("PyObject* self, PyObject* _value", "int")); m_sequenceProtocol.insert("__concat__", StrPair("PyObject* self, PyObject* _other", "PyObject*")); + + // mapping protocol function + m_mappingProtocol.insert("__mlen__", StrPair("PyObject* self", "Py_ssize_t")); + m_mappingProtocol.insert("__mgetitem__", StrPair("PyObject* self, PyObject* _key", "PyObject*")); + m_mappingProtocol.insert("__msetitem__", StrPair("PyObject* self, PyObject* _key, PyObject* _value", "int")); } QString CppGenerator::fileNameForClass(const AbstractMetaClass *metaClass) const @@ -355,7 +360,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl continue; const AbstractMetaFunction* rfunc = overloads.first(); - if (m_sequenceProtocol.contains(rfunc->name())) + if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name())) continue; if (rfunc->isConstructor()) @@ -459,6 +464,12 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl writeTypeAsSequenceDefinition(s, metaClass); } + if (supportsMappingProtocol(metaClass)) { + writeMappingMethods(s, metaClass); + writeTypeAsMappingDefinition(s, metaClass); + } + + if (hasComparisonOperator) { s << "// Rich comparison" << endl; writeRichCompareFunction(s, metaClass); @@ -2430,6 +2441,16 @@ QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractM return QString("%1_mi_init").arg(cpythonBaseName(metaClass->typeEntry())); } +bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass* metaClass) +{ + foreach(QString funcName, m_mappingProtocol.keys()) { + if (metaClass->hasFunction(funcName)) + return true; + } + + return false; +} + bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) { foreach(QString funcName, m_sequenceProtocol.keys()) { @@ -2461,6 +2482,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* QString tp_dealloc; QString tp_as_number('0'); QString tp_as_sequence('0'); + QString tp_as_mapping('0'); QString tp_hash('0'); QString tp_call('0'); QString cppClassName = metaClass->qualifiedCppName(); @@ -2480,6 +2502,9 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (supportsSequenceProtocol(metaClass)) tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName); + if (supportsMappingProtocol(metaClass)) + tp_as_mapping = QString("&Py%1_as_mapping").arg(cppClassName); + if (!metaClass->baseClass()) baseClassName = "reinterpret_cast(&SbkObject_Type)"; @@ -2570,7 +2595,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << INDENT << "/*tp_repr*/ " << m_tpFuncs["__repr__"] << "," << endl; s << INDENT << "/*tp_as_number*/ " << tp_as_number << ',' << endl; s << INDENT << "/*tp_as_sequence*/ " << tp_as_sequence << ',' << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; + s << INDENT << "/*tp_as_mapping*/ " << tp_as_mapping << ',' << endl; s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl; s << INDENT << "/*tp_call*/ " << tp_call << ',' << endl; s << INDENT << "/*tp_str*/ " << m_tpFuncs["__str__"] << ',' << endl; @@ -2612,6 +2637,33 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "} //extern" << endl; } +void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass) +{ + + QMap funcs; + bool injectedCode = false; + + QHash< QString, QPair< QString, QString > >::const_iterator it = m_mappingProtocol.begin(); + for (; it != m_mappingProtocol.end(); ++it) { + const AbstractMetaFunction* func = metaClass->findFunction(it.key()); + if (!func) + continue; + injectedCode = true; + QString funcName = cpythonFunctionName(func); + QString funcArgs = it.value().first; + QString funcRetVal = it.value().second; + + CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode); + s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; + writeInvalidCppObjectCheck(s); + + writeCppSelfDefinition(s, func); + + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips,CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg); + s << '}' << endl << endl; + } +} void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass) { @@ -2679,6 +2731,34 @@ void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractM << "};\n\n"; } +void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString className = metaClass->qualifiedCppName(); + QMap funcs; + + bool hasFunctions = false; + foreach(QString funcName, m_mappingProtocol.keys()) { + const AbstractMetaFunction* func = metaClass->findFunction(funcName); + funcs[funcName] = func ? cpythonFunctionName(func).prepend("&") : "0"; + if (!hasFunctions && func) + hasFunctions = true; + } + + //use default implementation + if (!hasFunctions) { + QString baseName = cpythonBaseName(metaClass->typeEntry()); + funcs["__mlen__"] = '0'; + funcs["__mgetitem__"] = '0'; + funcs["__msetitem__"] = '0'; + } + + s << "static PyMappingMethods Py" << className << "_as_mapping = {\n" + << INDENT << "/*mp_length*/ " << funcs["__mlen__"] << ",\n" + << INDENT << "/*mp_subscript*/ " << funcs["__mgetitem__"] << ",\n" + << INDENT << "/*mp_ass_subscript*/ " << funcs["__msetitem__"] << "\n" + << "};\n\n"; +} + void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass) { QMap nb; diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index d7674385b..2115230f7 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -131,10 +131,15 @@ private: void writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass); void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads); void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads); + /// Writes the implementation of all methods part of python sequence protocol void writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass); - /// Writes the struct PySequenceMethods for types thats supports the python sequence protocol void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + + /// Writes the struct PyMappingMethods for types thats supports the python mapping protocol + void writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + void writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass); + void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass); void writeCopyFunction(QTextStream& s, const AbstractMetaClass *metaClass); @@ -185,6 +190,9 @@ private: /// Returns true if the given class supports the python sequence protocol bool supportsSequenceProtocol(const AbstractMetaClass* metaClass); + /// Returns true if the given class supports the python mapping protocol + bool supportsMappingProtocol(const AbstractMetaClass* metaClass); + /// Returns true if generator should produce getters and setters for the given class. bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); @@ -201,6 +209,10 @@ private: // Maps special function names to function parameters and return types // used by CPython API in the sequence protocol. QHash > m_sequenceProtocol; + + // Maps special function names to function parameters and return types + // used by CPython API in the mapping protocol. + QHash > m_mappingProtocol; int m_currentErrorCode; }; -- cgit v1.2.3