aboutsummaryrefslogtreecommitdiffstats
path: root/generator
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2011-04-13 20:55:47 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:15:21 -0300
commit1155fe8c710818eac3c0490724b34adef95d9999 (patch)
tree8b01b22519863425c44299421cb02894e6ca860c /generator
parent50d1b114b35f34f97aefca1f42c3dbf9327e0d3a (diff)
Implemented generation code for mapping protocol
Fixex bug #743. Reviewer: Marcelo Lira <marcelo.lira@openbossa.org> Hugo Parente Lima <hugo.pl@gmail.com>
Diffstat (limited to 'generator')
-rw-r--r--generator/cppgenerator.cpp84
-rw-r--r--generator/cppgenerator.h14
2 files changed, 95 insertions, 3 deletions
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<PyTypeObject*>(&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<QString, QString> 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<QString, QString> 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<QString, QString> 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<QString, QPair<QString, QString> > m_sequenceProtocol;
+
+ // Maps special function names to function parameters and return types
+ // used by CPython API in the mapping protocol.
+ QHash<QString, QPair<QString, QString> > m_mappingProtocol;
int m_currentErrorCode;
};