[cig-commits] r6914 - cs/babel/trunk

leif at geodynamics.org leif at geodynamics.org
Thu May 17 02:17:32 PDT 2007


Author: leif
Date: 2007-05-17 02:17:32 -0700 (Thu, 17 May 2007)
New Revision: 6914

Modified:
   cs/babel/trunk/babel.cc
Log:
Began extending my ASTVisitor to handle C++: Generate a Python
extension type as a proxy for each C++ class, and a Python method
wrapper for each C++ member function.  (Work in progress.)


Modified: cs/babel/trunk/babel.cc
===================================================================
--- cs/babel/trunk/babel.cc	2007-05-17 07:13:31 UTC (rev 6913)
+++ cs/babel/trunk/babel.cc	2007-05-17 09:17:32 UTC (rev 6914)
@@ -1,6 +1,11 @@
 
-#include <iostream.h>     // cout
+#include <iostream>       // cout
+#include <sstream>
+#include <set>
+
 #include <stdlib.h>       // exit, atoi
+#include <string.h>
+#include <ctype.h>
 
 #include "parssppt.h"     // ParseTreeAndTokens
 #include "srcloc.h"       // SourceLocManager
@@ -15,7 +20,6 @@
 
 #include "cc_print.h"     // PrintEnv
 
-
 // ---------------------- PyExtModuleVisitor ------------------------
 
 
@@ -25,12 +29,15 @@
     std::string name;
     // C/C++ source filename
     std::string source;
+    // interned strings
+    std::set<std::string> interns;
     
     enum State {
-        internDecls,
+        typeDecls,
+        collectInterns,
         methods,
-        internTable,
-        methodTable,
+        typeObjs,
+        globalMethodTable,
     };
     State state;
 
@@ -43,8 +50,7 @@
     void generatePostamble();
     void generateModInitFunc();
 
-    virtual bool visitExpression(Expression *obj);
-    virtual bool visitDeclarator(Declarator *obj);
+    virtual bool visitExpression(Expression *obj);    virtual bool visitDeclarator(Declarator *obj);
     virtual bool visitFunction(Function *f);
     
     bool visitFunctionVariable(Variable *var);
@@ -55,11 +61,13 @@
                             std::string &varargs,
                             std::string &args);
     const char *returnValueConversionFunction(Variable *var);
-    void xxx(Variable *var);
 
+    virtual bool visitTypeSpecifier(TypeSpecifier *ts);
     virtual bool visitMember(Member *obj);
-
-    virtual bool visitTypeSpecifier(TypeSpecifier *ts);
+    virtual void postvisitTypeSpecifier(TypeSpecifier *ts);
+    void generateTypeObject(CompoundType *ct);
+    bool isDiscardedFunction(Variable *var);
+    std::string mangledMemberFuncName(Variable *var);
     
 };
 
@@ -83,23 +91,39 @@
          << endl;
 
     this->generatePreamble();
+
+    state = typeDecls;
+    unit->traverse(*this);
+    cout << endl;
     
-    state = internDecls;
+    state = collectInterns;
     unit->traverse(*this);
+    for (std::set<std::string>::const_iterator i = interns.begin();
+         i != interns.end();
+         ++i) {
+        cout << "static PyObject *__babel_n_" << *i << ";" << endl;
+    }
     cout << endl;
     
     state = methods;
     unit->traverse(*this);
     cout << endl;
     
-    state = internTable;
     cout << "static __Babel_InternTabEntry __babel_intern_tab[] = {" << endl;
-    unit->traverse(*this);
+    for (std::set<std::string>::const_iterator i = interns.begin();
+         i != interns.end();
+         ++i) {
+        cout << "    {&__babel_n_" << *i << ", \"" << *i << "\"}," << endl;
+    }
     cout << "    {0, 0}" << endl
          << "};" << endl
          << endl;
+
+    state = typeObjs;
+    unit->traverse(*this);
+    cout << endl;
     
-    state = methodTable;
+    state = globalMethodTable;
     cout << "static struct PyMethodDef __babel_methods[] = {" << endl;
     unit->traverse(*this);
     cout << "    {0, 0, 0, 0}" << endl
@@ -186,6 +210,9 @@
 bool PyExtModuleGenerator::visitFunction(Function *f)
 {
     Variable *var = f->nameAndParams->var;
+    if (this->isDiscardedFunction(var)) {
+        return true;
+    }
     this->visitFunctionVariable(var);
     if (false) {
         cout << "function " << *(f->nameAndParams->getDeclaratorId()) << " (" << var->name << ")" << endl;
@@ -197,18 +224,22 @@
 bool PyExtModuleGenerator::visitFunctionVariable(Variable *var)
 {
     switch (state) {
-    case internDecls:
-        cout << "static PyObject *__babel_n_" << var->name << ";" << endl;
+    case typeDecls:
         break;
+    case collectInterns:
+        interns.insert(var->name);
+        break;
     case methods:
         this->writePyMethod(var);
         cout << endl;
         break;
-    case internTable:
-        cout << "    {&__babel_n_" << var->name << ", \"" << var->name << "\"}," << endl;
+    case typeObjs:
         break;
-    case methodTable:
-        cout << "    {\"" << var->name << "\", (PyCFunction)__babel_m_" << var->name << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
+    case globalMethodTable:
+        FunctionType *t = var->type->asFunctionType();
+        if (!t->isMethod()) {
+            cout << "    {\"" << var->name << "\", (PyCFunction)__babel_m_" << var->name << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
+        }
         break;
     }
     if (false) {
@@ -221,7 +252,13 @@
 
 void PyExtModuleGenerator::writePyMethod(Variable *var)
 {
-    cout << "static PyObject *__babel_m_" << var->name << "(PyObject *self, PyObject *args, PyObject *kwds) {" << endl;
+    std::string mname;
+    if (var->isMember()) {
+        mname = this->mangledMemberFuncName(var);
+    } else {
+        mname = std::string("__babel_m_") + var->name;
+    }
+    cout << "static PyObject *" << mname << "(PyObject *self, PyObject *args, PyObject *kwds) {" << endl;
     
     std::string format, argnames, varargs, args;
     this->scanFunctionParams(var, format, argnames, varargs, args);
@@ -232,7 +269,19 @@
 
     const char *pyXXX_FromXXX = this->returnValueConversionFunction(var);
     
-    if (pyXXX_FromXXX) {
+    if (var->isMember() && !var->isStatic()) {
+        // method
+        CompoundType *ct = var->scope->curCompound;
+        cout << "    Py_INCREF(self);" << endl
+             << "    " << ct->toCString() << " *_this = ((struct __babel_obj_" << ct->name << " *)self)->_this;" << endl;
+        if (pyXXX_FromXXX) {
+            cout << "    r = " << pyXXX_FromXXX << "(_this->" << var->name << "(" << args << "));" << endl;
+        } else {
+            cout << "    _this->" << var->name << "(" << args << ");" << endl;
+            cout << "    r = Py_None; Py_INCREF(Py_None);" << endl;
+        }
+        cout << "    Py_DECREF(self);" << endl;
+    } else if (pyXXX_FromXXX) {
         cout << "    r = " << pyXXX_FromXXX << "(" << var->name << "(" << args << "));" << endl;
     } else {
         cout << "    " << var->name << "(" << args << ");" << endl;
@@ -397,55 +446,193 @@
 }
 
 
-void PyExtModuleGenerator::xxx(Variable *var)
+bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
 {
-    int ct = 0;
-    SFOREACH_OBJLIST(Variable, var->type->asFunctionType()->params, iter) {
-        ct++;
-        if (var->type->isMethod() && ct==1) {
-            // don't actually print the first parameter;
-            // the 'm' stands for nonstatic member function
-            cout << "/""*m: " << iter.data()->type->toCString() << " *""/ ";
-            continue;
+    switch (ts->kind()) {
+    case TypeSpecifier::TS_CLASSSPEC: {
+        TS_classSpec *spec = ts->asTS_classSpec();
+        CompoundType *ct = spec->ctype;
+        if (!ct->name) {
+            return true; // bail on anonymous classes
         }
-        if (ct >= 3 || (!var->type->isMethod() && ct>=2)) {
-            cout << ", ";
+        switch (state) {
+        case typeDecls:
+            cout << "struct __babel_obj_" << ct->name << " {" << endl
+                 << "    PyObject_HEAD" << endl
+                 << "    " << ct->toCString() << " *_this;" << endl
+                 << "};" << endl
+                 << endl
+                 << "static PyTypeObject *__babel_ptype_"<< ct->name << " = 0;" << endl
+                 << endl;
+            break;
+        case typeObjs:
+            // start the method table
+            cout << "static struct PyMethodDef __babel_methods_" << ct->name << "[] = {" << endl;
+            break;
+        default:
+            break;
         }
-        cout << iter.data()->toCStringAsParameter();
+        break; }
+    default:
+        break;
     }
+    return true;
 }
 
 
 bool PyExtModuleGenerator::visitMember(Member *obj)
 {
-    return true;
     if (obj->isMR_func()) {
         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;
+        if (this->isDiscardedFunction(var)) {
+            return true;
+        }
+        if (false) {
+            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()) {
-        cout << "access" << endl;
     } else if (obj->isMR_decl()) {
-        cout << "member decl" << endl;
+        if (false) cout << "member decl" << endl;
         Declaration *d = obj->asMR_decl()->d;
         if (false) {
             d->debugPrint(cout, 0);
         }
-    } else {
-        cout << "visitMember ???" << endl;
     }
     return true;
 }
 
 
-bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
+void PyExtModuleGenerator::postvisitTypeSpecifier(TypeSpecifier *ts)
 {
-    return true;
+    switch (ts->kind()) {
+    case TypeSpecifier::TS_CLASSSPEC: {
+        TS_classSpec *spec = ts->asTS_classSpec();
+        CompoundType *ct = spec->ctype;
+        if (!ct->name) {
+            return; // bail on anonymous classes
+        }
+        switch (state) {
+        case typeObjs:
+            // finish the method table
+            cout << "    {0, 0, 0, 0}" << endl
+                 << "};" << endl
+                 << endl;
+            this->generateTypeObject(ct);
+            break;
+        default:
+            break;
+        }
+        break; }
+    default:
+        break;
+    }
+    return;
 }
 
 
+void PyExtModuleGenerator::generateTypeObject(CompoundType *ct)
+{
+    cout <<
+        "PyTypeObject __babel_type_" << ct->name << " = {\n"
+        "    PyObject_HEAD_INIT(0)\n"
+        "    0, /*ob_size*/\n"
+        "    \"" << name << "." << ct->name << "\", /*tp_name*/\n"
+        "    sizeof(struct __babel_obj_" << ct->name << "), /*tp_basicsize*/\n"
+        "    0, /*tp_itemsize*/\n"
+        "    0,\n" //__babel_tp_dealloc_" << ct->name << ", /*tp_dealloc*/\n"
+        "    0, /*tp_print*/\n"
+        "    0, /*tp_getattr*/\n"
+        "    0, /*tp_setattr*/\n"
+        "    0, /*tp_compare*/\n"
+        "    0, /*tp_repr*/\n"
+        "    0, /*tp_as_number*/\n"
+        "    0, /*tp_as_sequence*/\n"
+        "    0, /*tp_as_mapping*/\n"
+        "    0, /*tp_hash*/\n"
+        "    0, /*tp_call*/\n"
+        "    0, /*tp_str*/\n"
+        "    0, /*tp_getattro*/\n"
+        "    0, /*tp_setattro*/\n"
+        "    0, /*tp_as_buffer*/\n"
+        "    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/\n"
+        "    0, /*tp_doc*/\n"
+        "    0, /*tp_traverse*/\n"
+        "    0, /*tp_clear*/\n"
+        "    0, /*tp_richcompare*/\n"
+        "    0, /*tp_weaklistoffset*/\n"
+        "    0, /*tp_iter*/\n"
+        "    0, /*tp_iternext*/\n"
+        "    __babel_methods_" << ct->name << ", /*tp_methods*/\n"
+        "    0, /*tp_members*/\n"
+        "    0, /*tp_getset*/\n"
+        "    0, /*tp_base*/\n"
+        "    0, /*tp_dict*/\n"
+        "    0, /*tp_descr_get*/\n"
+        "    0, /*tp_descr_set*/\n"
+        "    0, /*tp_dictoffset*/\n"
+        "    0, /*tp_init*/\n"
+        "    0, /*tp_alloc*/\n"
+        "    0,\n" //__babel_tp_new_" << ct->name << ", /*tp_new*/\n"
+        "    0, /*tp_free*/\n"
+        "    0, /*tp_is_gc*/\n"
+        "    0, /*tp_bases*/\n"
+        "    0, /*tp_mro*/\n"
+        "    0, /*tp_cache*/\n"
+        "    0, /*tp_subclasses*/\n"
+        "    0, /*tp_weaklist*/\n"
+        "};\n"
+        "\n";
+}
+
+
+bool PyExtModuleGenerator::isDiscardedFunction(Variable *var)
+{
+    FunctionType *t = var->type->asFunctionType();
+    if (t->isConstructor() || t->isDestructor() ||
+        t->isConversionOperator()) {
+        return true;
+    }
+    if (strncmp(var->name, "operator", 8) == 0 &&
+        !(isalpha(var->name[8]) || isdigit(var->name[8]))) {
+        return true;
+    }
+    return false;
+}
+
+
+std::string PyExtModuleGenerator::mangledMemberFuncName(Variable *var)
+{
+    std::string className = var->scope->curCompound->typedefVar->fullyQualifiedName().c_str();
+    std::string funcName = var->name;
+    std::stringstream s;
+    s << "__babel_m_" << className.length();
+    for (std::string::const_iterator i = className.begin(); i != className.end(); ++i) {
+        char c = *i;
+        if (c == ':') {
+            s << '_';
+            ++i;
+        } else {
+            s << *i;
+        }
+    }
+    s << "_" << funcName;
+    return s.str();
+}
+
+
 // ---------------------- main -------------------------
 
 void doit(int argc, char **argv)



More information about the cig-commits mailing list