[cig-commits] r6938 - cs/babel/trunk
leif at geodynamics.org
leif at geodynamics.org
Tue May 22 14:47:04 PDT 2007
Author: leif
Date: 2007-05-22 14:47:04 -0700 (Tue, 22 May 2007)
New Revision: 6938
Modified:
cs/babel/trunk/babel.cc
Log:
Expose C++ classes as Python module attributes; initialize Python
extension types. Generate a unique Python method for each C++
function definition and/or prototype. A few bug fixes.
The generated Python extension module is now usable for simple test
cases.
Modified: cs/babel/trunk/babel.cc
===================================================================
--- cs/babel/trunk/babel.cc 2007-05-22 19:11:06 UTC (rev 6937)
+++ cs/babel/trunk/babel.cc 2007-05-22 21:47:04 UTC (rev 6938)
@@ -31,8 +31,11 @@
std::string source;
// interned strings
std::set<std::string> interns;
- // track overload sets to ensure uniqueness of PyMethods
+ // these ensure the uniqueness of PyMethods
+ std::set<Variable *> vars;
std::set<OverloadSet *> overloads;
+ // global method table
+ std::set<std::string> gmt;
Env &env;
@@ -41,7 +44,7 @@
collectInterns,
methods,
typeObjs,
- globalMethodTable,
+ modInitFunc,
};
State state;
@@ -52,12 +55,13 @@
void generate(TranslationUnit *unit);
void generatePreamble();
void generatePostamble();
- void generateModInitFunc();
+ void generateModInitFunc(TranslationUnit *unit);
+ void generateTypeInit(CompoundType *ct);
virtual bool visitDeclarator(Declarator *obj);
virtual bool visitFunction(Function *f);
- bool visitFunctionVariable(Variable *var);
+ void visitFunctionVariable(Variable *var);
void writePyMethod(Variable *var);
void writeNewMethod(CompoundType *ct);
void writeDeallocMethod(CompoundType *ct);
@@ -73,11 +77,12 @@
virtual bool visitMember(Member *obj);
virtual void postvisitTypeSpecifier(TypeSpecifier *ts);
void generateTypeObject(CompoundType *ct);
- bool isDiscardedFunction(Variable *var); std::string tpName(std::string funcName, CompoundType *ct);
+ bool isDiscardedFunction(Variable *var);
+ bool uniqify(Variable *var);
+ std::string tpName(std::string funcName, CompoundType *ct);
std::string mangledMemberFuncName(Variable *var, std::string ns = "m");
std::string mangledMemberFuncName(Variable *var, std::string funcName, std::string ns = "m");
std::string mangledMemberFuncName(CompoundType *ct, std::string funcName, std::string ns);
-
};
@@ -118,6 +123,10 @@
state = methods;
unit->traverse(*this);
cout << endl;
+
+ // reset uniquify
+ vars.clear();
+ overloads.clear();
cout << "static __Babel_InternTabEntry __babel_intern_tab[] = {" << endl;
for (std::set<std::string>::const_iterator i = interns.begin();
@@ -133,14 +142,17 @@
unit->traverse(*this);
cout << endl;
- state = globalMethodTable;
cout << "static struct PyMethodDef __babel_methods[] = {" << endl;
- unit->traverse(*this);
+ for (std::set<std::string>::const_iterator i = gmt.begin();
+ i != gmt.end();
+ ++i) {
+ cout << " {\"" << *i << "\", (PyCFunction)__babel_m_" << *i << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
+ }
cout << " {0, 0, 0, 0}" << endl
<< "};" << endl
<< endl;
- this->generateModInitFunc();
+ this->generateModInitFunc(unit);
this->generatePostamble();
@@ -173,28 +185,37 @@
}
-void PyExtModuleGenerator::generateModInitFunc()
+void PyExtModuleGenerator::generateModInitFunc(TranslationUnit *unit)
{
cout << "PyMODINIT_FUNC init" << name <<"(void) {" << endl
<< " __babel_m = Py_InitModule4(\"" << name << "\", __babel_methods, 0, 0, PYTHON_API_VERSION);" << endl
<< " if (!__babel_m) return;" << endl
- << " if (__Babel_InternStrings(__babel_intern_tab) < 0) return;" << endl
- << " return;" << endl
+ << " if (__Babel_InternStrings(__babel_intern_tab) < 0) return;" << endl;
+ state = modInitFunc;
+ unit->traverse(*this);
+ cout << " return;" << endl
<< "}" << endl
<< endl;
}
+void PyExtModuleGenerator::generateTypeInit(CompoundType *ct)
+{
+ std::string ptype = std::string("&__babel_type_") + ct->name;
+ cout << " if (PyType_Ready(" << ptype << ") < 0) return;" << endl
+ << " if (PyObject_SetAttrString(__babel_m, \"" << ct->name << "\", "
+ << "(PyObject *)" << ptype << ") < 0) return;" << endl
+ << " __babel_ptype_" << ct->name << " = " << ptype << ";" << endl;
+}
+
+
bool PyExtModuleGenerator::visitDeclarator(Declarator *obj)
{
Variable *var = obj->var;
if (var->type->isFunctionType()) {
- if (false) {
- // This would generate methods for function
- // prototypes... currently, we have no way of
- // filtering-out system headers, etc.
- return this->visitFunctionVariable(obj->var);
- }
+ if (!this->isDiscardedFunction(var)) {
+ this->visitFunctionVariable(var);
+ }
}
return true;
}
@@ -202,19 +223,20 @@
bool PyExtModuleGenerator::visitFunction(Function *f)
{
- Variable *var = f->nameAndParams->var;
- if (this->isDiscardedFunction(var)) {
- return true;
- }
- this->visitFunctionVariable(var);
+ // This is called only for function bodies. But 'visitDeclarator'
+ // is called for prototypes as well; so all our processing is done
+ // there.
if (false) {
- cout << "function " << *(f->nameAndParams->getDeclaratorId()) << " (" << var->name << ")" << endl;
+ Variable *var = f->nameAndParams->var;
+ if (!this->isDiscardedFunction(var)) {
+ this->visitFunctionVariable(var);
+ }
}
return true;
}
-bool PyExtModuleGenerator::visitFunctionVariable(Variable *var)
+void PyExtModuleGenerator::visitFunctionVariable(Variable *var)
{
switch (state) {
case typeDecls:
@@ -223,29 +245,30 @@
interns.insert(var->name);
break;
case methods:
- if (var->isOverloaded()) {
- if (overloads.find(var->overload) != overloads.end()) {
- return true;
+ if (this->uniqify(var)) {
+ this->writePyMethod(var);
+ cout << endl;
+ if (!var->isMember()) {
+ gmt.insert(var->name);
}
- overloads.insert(var->overload);
}
- this->writePyMethod(var);
- cout << endl;
break;
case typeObjs:
- break;
- case globalMethodTable:
- FunctionType *t = var->type->asFunctionType();
- if (!t->isMethod()) {
- cout << " {\"" << var->name << "\", (PyCFunction)__babel_m_" << var->name << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
+ if (var->isMember() && this->uniqify(var)) {
+ // write a method table entry
+ cout << " {\"" << var->name << "\", "
+ << "(PyCFunction)" << mangledMemberFuncName(var)
+ << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
}
break;
+ default:
+ break;
}
if (false) {
cout << " " << var->toCString() << endl;
cout << " " << var->toQualifiedString() << endl;
}
- return true;
+ return;
}
@@ -538,6 +561,8 @@
// start the method table
cout << "static struct PyMethodDef __babel_methods_" << ct->name << "[] = {" << endl;
break;
+ case modInitFunc:
+ this->generateTypeInit(ct);
default:
break;
}
@@ -552,31 +577,19 @@
bool PyExtModuleGenerator::visitMember(Member *obj)
{
if (obj->isMR_func()) {
- Function *f = obj->asMR_func()->f;
- Variable *var = f->nameAndParams->var;
- if (this->isDiscardedFunction(var)) {
- return true;
- }
+ // This fires for function bodies inside class declarations.
if (false) {
+ Function *f = obj->asMR_func()->f;
+ Variable *var = f->nameAndParams->var;
cout << "member function " << *(f->nameAndParams->getDeclaratorId()) << " (" << var->name << ")" << endl;
cout << " " << var->toCString() << endl;
cout << " " << var->toQualifiedString() << endl;
}
- switch (state) {
- case typeObjs: {
- // write a method table entry
- cout << " {\"" << var->name << "\", "
- << "(PyCFunction)" << mangledMemberFuncName(var)
- << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
- break; }
- default:
- break;
- }
} else if (obj->isMR_access()) {
} else if (obj->isMR_decl()) {
- if (false) cout << "member decl" << endl;
- Declaration *d = obj->asMR_decl()->d;
if (false) {
+ cout << "member decl" << endl;
+ Declaration *d = obj->asMR_decl()->d;
d->debugPrint(cout, 0);
}
}
@@ -619,7 +632,8 @@
void PyExtModuleGenerator::generateTypeObject(CompoundType *ct)
{
- std::string dealloc = tpName("dealloc", ct);
+ std::string tpDealloc = tpName("dealloc", ct);
+ std::string tpNew = tpName("new", ct);
cout <<
"PyTypeObject __babel_type_" << ct->name << " = {\n"
" PyObject_HEAD_INIT(0)\n"
@@ -627,7 +641,7 @@
" \"" << name << "." << ct->name << "\", /*tp_name*/\n"
" sizeof(struct __babel_obj_" << ct->name << "), /*tp_basicsize*/\n"
" 0, /*tp_itemsize*/\n"
- " " << dealloc << ", /*tp_dealloc*/\n"
+ " " << tpDealloc << ", /*tp_dealloc*/\n"
" 0, /*tp_print*/\n"
" 0, /*tp_getattr*/\n"
" 0, /*tp_setattr*/\n"
@@ -660,7 +674,7 @@
" 0, /*tp_dictoffset*/\n"
" 0, /*tp_init*/\n"
" 0, /*tp_alloc*/\n"
- " 0,\n" //__babel_tp_new_" << ct->name << ", /*tp_new*/\n"
+ " " << tpNew << ", /*tp_new*/\n"
" 0, /*tp_free*/\n"
" 0, /*tp_is_gc*/\n"
" 0, /*tp_bases*/\n"
@@ -687,6 +701,22 @@
}
+bool PyExtModuleGenerator::uniqify(Variable *var)
+{
+ if (vars.find(var) != vars.end()) {
+ return false;
+ }
+ vars.insert(var);
+ if (var->isOverloaded()) {
+ if (overloads.find(var->overload) != overloads.end()) {
+ return false;
+ }
+ overloads.insert(var->overload);
+ }
+ return true;
+}
+
+
std::string PyExtModuleGenerator::tpName(std::string funcName, CompoundType *ct)
{
return this->mangledMemberFuncName(ct, funcName, "tp");
More information about the cig-commits
mailing list