[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