[cig-commits] r6961 - in cs/babel/trunk: . elsa/elsa

leif at geodynamics.org leif at geodynamics.org
Thu May 24 18:41:59 PDT 2007


Author: leif
Date: 2007-05-24 18:41:58 -0700 (Thu, 24 May 2007)
New Revision: 6961

Added:
   cs/babel/trunk/mkpyxm.cc
Removed:
   cs/babel/trunk/babel.cc
Modified:
   cs/babel/trunk/Makefile.am
   cs/babel/trunk/configure.ac
   cs/babel/trunk/elsa/elsa/Makefile.in
Log:
Build 'libelsa.a', so that I can link stuff against it.  Updated my
PyExtModuleGenerator ASTVisitor for this new version of Elsa from the
Oink repository (I wrote it against Elsa 2005.08.22b).  Build
PyExtModuleGenerator as the 'mkpyxm' (make Python extension module)
command.


Modified: cs/babel/trunk/Makefile.am
===================================================================
--- cs/babel/trunk/Makefile.am	2007-05-25 00:59:19 UTC (rev 6960)
+++ cs/babel/trunk/Makefile.am	2007-05-25 01:41:58 UTC (rev 6961)
@@ -5,9 +5,26 @@
 SUBDIRS = elsa spike
 
 
-bin_PROGRAMS = pyspike
+bin_PROGRAMS = mkpyxm pyspike
 bin_SCRIPTS = spikec
 
+INCLUDES =
+
+# ~~~ mkpyxm ~~~
+
+
+INCLUDES += -Ielsa/elsa -Ielsa/elkhound -Ielsa/ast -Ielsa/smbase
+mkpyxm_SOURCES = mkpyxm.cc
+mkpyxm_LDADD = \
+	elsa/elsa/libelsa.a \
+	elsa/elkhound/libelkhound.a \
+	elsa/ast/libast.a \
+	elsa/smbase/libsmbase.a
+
+
+# ~~~ spike ~~~
+
+
 abs_top_srcdir = @abs_top_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_builddir = @abs_builddir@
@@ -41,7 +58,7 @@
 
 # pyspike (parser + embedded Python interpreter)
 
-INCLUDES = -I$(srcdir)/spike/Spike/Compiler -I$(PYTHON_INCDIR)
+INCLUDES += -I$(srcdir)/spike/Spike/Compiler -I$(PYTHON_INCDIR)
 AM_YFLAGS = -dv
 
 pyspike_SOURCES = \

Deleted: cs/babel/trunk/babel.cc
===================================================================
--- cs/babel/trunk/babel.cc	2007-05-25 00:59:19 UTC (rev 6960)
+++ cs/babel/trunk/babel.cc	2007-05-25 01:41:58 UTC (rev 6961)
@@ -1,864 +0,0 @@
-
-#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
-#include "cc_env.h"       // Env
-#include "cc_ast.h"       // C++ AST (r)
-#include "cc_lang.h"      // CCLang
-#include "parsetables.h"  // ParseTables
-#include "cc.gr.gen.h"    // CCParse
-#include "strtokp.h"      // StrtokParse
-
-#include "cc_elaborate.h" // ElabVisitor
-
-#include "cc_print.h"     // PrintEnv
-
-// ---------------------- PyExtModuleVisitor ------------------------
-
-
-class PyExtModuleGenerator : public ASTVisitor {
-private:      // data
-    // name of module
-    std::string name;
-    // C/C++ source filename
-    std::string source;
-    // interned strings
-    std::set<std::string> interns;
-    // these ensure the uniqueness of PyMethods
-    std::set<Variable *> vars;
-    std::set<OverloadSet *> overloads;
-    // global method table
-    std::set<std::string> gmt;
-
-    Env &env;
-    
-    enum State {
-        typeDecls,
-        collectInterns,
-        methods,
-        typeObjs,
-        modInitFunc,
-    };
-    State state;
-
-public:      // funcs
-    PyExtModuleGenerator(std::string n, std::string s, Env &env);
-    virtual ~PyExtModuleGenerator() {}
-
-    void generate(TranslationUnit *unit);
-    void generatePreamble();
-    void generatePostamble();
-    void generateModInitFunc(TranslationUnit *unit);
-    void generateTypeInit(CompoundType *ct);
-
-    virtual bool visitDeclarator(Declarator *obj);
-    virtual bool visitFunction(Function *f);
-    
-    void visitFunctionVariable(Variable *var);
-    void writePyMethod(Variable *var);
-    void writeNewMethod(CompoundType *ct);
-    void writeDeallocMethod(CompoundType *ct);
-    void writeMethodPrologue(Variable *var, std::string &args);
-    void scanFunctionParams(Variable *var,
-                            std::string &format,
-                            std::string &argnames,
-                            std::string &varargs,
-                            std::string &args);
-    const char *returnValueConversionFunction(Variable *var);
-
-    virtual bool visitTypeSpecifier(TypeSpecifier *ts);
-    virtual bool visitMember(Member *obj);
-    virtual void postvisitTypeSpecifier(TypeSpecifier *ts);
-    void generateTypeObject(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);
-};
-
-
-PyExtModuleGenerator::PyExtModuleGenerator(std::string n, std::string s, Env &env) :
-    name(n),
-    source(s),
-    env(env)
-{
-}
-
-
-void PyExtModuleGenerator::generate(TranslationUnit *unit)
-{
-    cout << "/* Generated by Babel */" << endl
-         << endl;
-    
-    cout << "#include \"" << source << "\"" << endl
-         << endl;
-    
-    cout << "#include \"Python.h\"" << endl
-         << endl;
-
-    this->generatePreamble();
-
-    state = typeDecls;
-    unit->traverse(*this);
-    cout << endl;
-    
-    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;
-
-    // reset uniquify
-    vars.clear();
-    overloads.clear();
-    
-    cout << "static __Babel_InternTabEntry __babel_intern_tab[] = {" << endl;
-    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;
-    
-    cout << "static struct PyMethodDef __babel_methods[] = {" << endl;
-    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(unit);
-
-    this->generatePostamble();
-    
-}
-
-
-void PyExtModuleGenerator::generatePreamble()
-{
-    cout << "typedef struct {PyObject **p; char *s;} __Babel_InternTabEntry;" << endl
-         << endl
-         << "static PyObject *__babel_m;" << endl
-         << endl
-         << "static int __Babel_InternStrings(__Babel_InternTabEntry *t);" << endl
-         << endl;
-}
-
-
-void PyExtModuleGenerator::generatePostamble()
-{
-    cout << "static int __Babel_InternStrings(__Babel_InternTabEntry *t) {" << endl
-         << "    while (t->p) {" << endl
-         << "        *t->p = PyString_InternFromString(t->s);" << endl
-         << "        if (!*t->p)" << endl
-         << "            return -1;" << endl
-         << "        ++t;" << endl
-         << "    }" << endl
-         << "    return 0;" << endl
-         << "}" << endl
-         << endl;
-}
-
-
-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;
-    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 (!this->isDiscardedFunction(var)) {
-            this->visitFunctionVariable(var);
-       }
-    }
-    return true;
-}
-
-
-bool PyExtModuleGenerator::visitFunction(Function *f)
-{
-    // This is called only for function bodies.  But 'visitDeclarator'
-    // is called for prototypes as well; so all our processing is done
-    // there.
-    if (false) {
-        Variable *var = f->nameAndParams->var;
-        if (!this->isDiscardedFunction(var)) {
-            this->visitFunctionVariable(var);
-        }
-    }
-    return true;
-}
-
-
-void PyExtModuleGenerator::visitFunctionVariable(Variable *var)
-{
-    switch (state) {
-    case typeDecls:
-        break;
-    case collectInterns:
-        interns.insert(var->name);
-        break;
-    case methods:
-        if (this->uniqify(var)) {
-            this->writePyMethod(var);
-            cout << endl;
-            if (!var->isMember()) {
-                gmt.insert(var->name);
-            }
-        }
-        break;
-    case typeObjs:
-        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;
-}
-
-
-void PyExtModuleGenerator::writePyMethod(Variable *var)
-{
-    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;
-    
-    if (var->isOverloaded()) {
-        cout << "    PyErr_SetString(PyExc_NotImplementedError, \"cannot call overloaded function '"
-             << var->name << "' from Python\");" << endl
-             << "    return 0;" << endl
-             << "}" << endl;
-        return;
-    }
-    
-    std::string args;
-    this->writeMethodPrologue(var, args);
-    const char *pyXXX_FromXXX = this->returnValueConversionFunction(var);
-    
-    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;
-        cout << "    r = Py_None; Py_INCREF(Py_None);" << endl;
-    }
-    
-    cout << "    return r;" << endl
-         << "}" << endl;
-}
-
-
-void PyExtModuleGenerator::writeNewMethod(CompoundType *ct)
-{
-    std::string tpNew = tpName("new", ct);
-    cout << "static PyObject *" << tpNew << "(PyTypeObject *type, PyObject *args, PyObject *kwds) {" << endl;
-    Variable *ctor0 = ct->getNamedField(env.constructorSpecialName, env, LF_INNER_ONLY);
-    // This is an elaborated AST, so there must be at least one constructor.
-    xassert(ctor0);
-    Variable *ctor = NULL;
-    if (ctor0->overload) {
-        SFOREACH_OBJLIST_NC(Variable, ctor0->overload->set, iter) {
-            Variable *ctorN = iter.data();
-            if (isCopyConstructor(ctorN, ct)) {
-                // skip
-            } else if (ctor) {
-                // we already found one
-                ctor = NULL;
-                break;
-            } else {
-                ctor = ctorN;
-            }
-        }
-    } else {
-        ctor = ctor0;
-    }
-    if (!ctor) {
-        cout << "    PyErr_SetString(PyExc_NotImplementedError, \"cannot call overloaded constructor from Python\");" << endl
-             << "    return 0;" << endl
-             << "}" << endl;
-        return;
-    }
-
-    // We found a unique constructor.
-    std::string args;
-    this->writeMethodPrologue(ctor, args);
-    
-    cout << "    PyObject *o = (*type->tp_alloc)(type, 0);" << endl
-         << "    ((struct __babel_obj_" << ct->name << " *)o)->_this = "
-         << "new " << ct->typedefVar->fullyQualifiedName() << "(" << args << ");" << endl
-         << "    return o;" << endl
-         << "}" << endl;
-}
-
-
-void PyExtModuleGenerator::writeDeallocMethod(CompoundType *ct)
-{
-    std::string tpDealloc = tpName("dealloc", ct);
-    cout << "static void " << tpDealloc << "(PyObject *o) {" << endl
-         << "    " << ct->toCString() << " *_this = ((struct __babel_obj_" << ct->name << " *)o)->_this;" << endl
-         << "    delete _this;" << endl
-         << "    (*o->ob_type->tp_free)(o);" << endl
-         << "}" << endl;
-}
-
-
-void PyExtModuleGenerator::writeMethodPrologue(Variable *var, std::string &args)
-{
-    std::string format, argnames, varargs;
-    this->scanFunctionParams(var, format, argnames, varargs, args);
-    cout << "    PyObject *r;" << endl;
-    
-    cout << "    static char *argnames[] = {" << argnames << "0};" << endl
-         << "    if (!PyArg_ParseTupleAndKeywords(args, kwds, \"" << format << "\", argnames" << varargs << ")) return 0;" << endl;
-
-    return;
-}
-
-
-void PyExtModuleGenerator::scanFunctionParams(Variable *var,
-                                              std::string &format,
-                                              std::string &argnames,
-                                              std::string &varargs,
-                                              std::string &args)
-{
-    int ct = 0;
-    SFOREACH_OBJLIST(Variable, var->type->asFunctionType()->params, iter) {
-        ct++;
-        if (var->type->isMethod() && ct==1) {
-            // "this"
-            continue;
-        }
-        
-        const Variable *param = iter.data();
-
-        cout << "    " << param->toCString() << ";" << endl;
-        
-        char c = '?';
-        if (param->type->isSimpleType()) {
-            SimpleTypeId id = param->type->asSimpleTypeC()->type;
-            switch (id) {
-            case ST_CHAR:                c = 'b'; break;
-            case ST_UNSIGNED_CHAR:       c = 'B'; break;
-            case ST_SIGNED_CHAR:         c = 'b'; break; // Is 'char' signed?
-            case ST_BOOL:                break; // ???
-            case ST_INT:                 c = 'i'; break;
-            case ST_UNSIGNED_INT:        c = 'I'; break;
-            case ST_LONG_INT:            c = 'l'; break;
-            case ST_UNSIGNED_LONG_INT:   c = 'k'; break;
-            case ST_LONG_LONG:           c = 'L'; break;
-            case ST_UNSIGNED_LONG_LONG:  c = 'K'; break;
-            case ST_SHORT_INT:           c = 'h'; break;
-            case ST_UNSIGNED_SHORT_INT:  c = 'H'; break;
-            case ST_WCHAR_T:             break; // ???
-            case ST_FLOAT:               c = 'f'; break;
-            case ST_DOUBLE:              c = 'd'; break;
-            case ST_LONG_DOUBLE:
-            case ST_FLOAT_COMPLEX:
-            case ST_DOUBLE_COMPLEX:
-            case ST_LONG_DOUBLE_COMPLEX:
-            case ST_FLOAT_IMAGINARY:
-            case ST_DOUBLE_IMAGINARY:
-            case ST_LONG_DOUBLE_IMAGINARY:
-            case ST_VOID:
-                // ???
-                // ERROR
-                break;
-            default:
-                // ERROR
-                break;
-            }
-        } else if (param->type->isPointerType()) {
-            PointerType *pt = param->type->asPointerType();
-            if (pt->atType->isSimpleType()) {
-                SimpleTypeId id = pt->atType->asSimpleTypeC()->type;
-                switch (id) {
-                case ST_CHAR:
-                case ST_UNSIGNED_CHAR:
-                case ST_SIGNED_CHAR:
-                    c = 's';
-                    break;
-                case ST_WCHAR_T:
-                    break; // ???
-                default:
-                    // ERROR
-                    break;
-                }
-            } else {
-                // ERROR
-            }
-        } else {
-            // ERROR
-        }
-        format += c;
-        
-        argnames += std::string("\"") + param->name + "\",";
-        varargs += std::string(", &") + param->name;
-        
-        if (ct >= 3 || (!var->type->isMethod() && ct>=2)) {
-            args += ", ";
-        }
-        args += param->name;
-    }
-    return;
-}
-
-
-const char *PyExtModuleGenerator::returnValueConversionFunction(Variable *var)
-{
-    Type *rt = var->type->asFunctionType()->retType;
-    const char *pyXXX_FromXXX = "<error>";
-    if (rt->isSimpleType()) {
-        SimpleTypeId id = rt->asSimpleTypeC()->type;
-        switch (id) {
-        case ST_CHAR:                pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_UNSIGNED_CHAR:       pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
-        case ST_SIGNED_CHAR:         pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_BOOL:                pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_INT:                 pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_UNSIGNED_INT:        pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
-        case ST_LONG_INT:            pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_UNSIGNED_LONG_INT:   pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
-        case ST_LONG_LONG:           pyXXX_FromXXX = "PyLong_FromLongLong"; break;
-        case ST_UNSIGNED_LONG_LONG:  pyXXX_FromXXX = "PyLong_FromUnsignedLongLong"; break;
-        case ST_SHORT_INT:           pyXXX_FromXXX = "PyInt_FromLong"; break;
-        case ST_UNSIGNED_SHORT_INT:  pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
-        case ST_WCHAR_T:             break; // ???
-        case ST_FLOAT:               pyXXX_FromXXX = "PyFloat_FromDouble"; break;
-        case ST_DOUBLE:              pyXXX_FromXXX = "PyFloat_FromDouble"; break;
-        case ST_LONG_DOUBLE:
-        case ST_FLOAT_COMPLEX:
-        case ST_DOUBLE_COMPLEX:
-        case ST_LONG_DOUBLE_COMPLEX:
-        case ST_FLOAT_IMAGINARY:
-        case ST_DOUBLE_IMAGINARY:
-        case ST_LONG_DOUBLE_IMAGINARY:
-            // ???
-            // ERROR
-            break;
-        case ST_VOID:
-            pyXXX_FromXXX = 0; // no conversion
-            break;
-        default:
-            // ERROR
-            break;
-        }
-    } else if (rt->isPointerType()) {
-        PointerType *pt = rt->asPointerType();
-        if (pt->atType->isSimpleType()) {
-            SimpleTypeId id = pt->atType->asSimpleTypeC()->type;
-            switch (id) {
-            case ST_CHAR:
-            case ST_UNSIGNED_CHAR:
-            case ST_SIGNED_CHAR:
-                pyXXX_FromXXX = "PyString_FromString";
-                break;
-            case ST_WCHAR_T:
-                break; // ???
-            default:
-                // ERROR
-                break;
-            }
-        } else {
-            // ERROR
-        }
-    } else {
-        // ERROR
-    }
-    return pyXXX_FromXXX;
-}
-
-
-bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
-{
-    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
-        }
-        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;
-        case modInitFunc:
-            this->generateTypeInit(ct);
-        default:
-            break;
-        }
-        break; }
-    default:
-        break;
-    }
-    return true;
-}
-
-
-bool PyExtModuleGenerator::visitMember(Member *obj)
-{
-    if (obj->isMR_func()) {
-        // 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;
-        }
-    } else if (obj->isMR_access()) {
-    } else if (obj->isMR_decl()) {
-        if (false) {
-            cout << "member decl" << endl;
-            Declaration *d = obj->asMR_decl()->d;
-            d->debugPrint(cout, 0);
-        }
-    }
-    return true;
-}
-
-
-void PyExtModuleGenerator::postvisitTypeSpecifier(TypeSpecifier *ts)
-{
-    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->writeNewMethod(ct);
-            cout << endl;
-            this->writeDeallocMethod(ct);
-            cout << endl;
-            this->generateTypeObject(ct);
-            cout << endl;
-            break;
-        default:
-            break;
-        }
-        break; }
-    default:
-        break;
-    }
-    return;
-}
-
-
-void PyExtModuleGenerator::generateTypeObject(CompoundType *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"
-        "    0, /*ob_size*/\n"
-        "    \"" << name << "." << ct->name << "\", /*tp_name*/\n"
-        "    sizeof(struct __babel_obj_" << ct->name << "), /*tp_basicsize*/\n"
-        "    0, /*tp_itemsize*/\n"
-        "    " << tpDealloc << ", /*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"
-        "    " << tpNew << ", /*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";
-}
-
-
-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;
-}
-
-
-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");
-}
-
-
-std::string PyExtModuleGenerator::mangledMemberFuncName(Variable *var, std::string ns)
-{
-    return this->mangledMemberFuncName(var, var->name, ns);
-}
-
-
-std::string PyExtModuleGenerator::mangledMemberFuncName(Variable *var, std::string funcName, std::string ns)
-{
-    return this->mangledMemberFuncName(var->scope->curCompound, funcName, ns);
-}
-
-
-std::string PyExtModuleGenerator::mangledMemberFuncName(CompoundType *ct, std::string funcName, std::string ns)
-{
-    std::string className = ct->typedefVar->fullyQualifiedName().c_str();
-    std::stringstream s;
-    s << "__babel_" << ns << "_" << 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)
-{
-    xBase::logExceptions = false;
-
-    SourceLocManager mgr;
-    StringTable strTable;
-
-    // parsing language options
-    CCLang lang;
-    lang.GNU_Cplusplus();
-
-    // process command-line arguments
-    if (argc != 3) {
-        cout << "usage: " << argv[0] << " input.cc modulename\n";
-        return;
-    }
-
-    string inputFname = argv[1];
-
-    // parse+tcheck (TODO: make this more convenient)
-    TranslationUnit *unit;
-    {
-        SemanticValue treeTop;
-        ParseTreeAndTokens tree(lang, treeTop, strTable, inputFname.c_str());
-
-        // grab the lexer so we can check it for errors (damn this
-        // 'tree' thing is stupid..)
-        Lexer *lexer = dynamic_cast<Lexer*>(tree.lexer);
-        xassert(lexer);
-
-        CCParse *parseContext = new CCParse(strTable, lang);
-        tree.userAct = parseContext;
-
-        ParseTables *tables = parseContext->makeTables();
-        tree.tables = tables;
-
-        // parse
-        if (!toplevelParse(tree, inputFname.c_str())) {
-            exit(2); // parse error
-        }
-
-        // check for parse errors
-        if (parseContext->errors || lexer->errors) {
-            exit(2);
-        }
-
-        // treeTop is a TranslationUnit pointer
-        unit = (TranslationUnit*)treeTop;
-
-        delete parseContext;
-        delete tables;
-
-        // tcheck
-        BasicTypeFactory tfac;
-        Env env(strTable, lang, tfac, unit);
-        unit->tcheck(env);
-
-        int numErrors = env.errors.numErrors();
-        if (numErrors) {
-            env.errors.print(cerr);
-            cerr << numErrors << " errors\n";
-            exit(4);
-        }
-
-        // do elaboration
-        ElabVisitor vis(strTable, tfac, unit);
-        unit->traverse(vis.loweredVisitor);
-
-        // generate Python module
-        PyExtModuleGenerator visitor(argv[2], argv[1], env);
-        visitor.generate(unit);
-
-    }
-
-    if (false) {
-        // pretty printing
-        OStreamOutStream out0(cout);
-        CodeOutStream codeOut(out0);
-        TypePrinterC typePrinter;
-        PrintEnv env(typePrinter, &codeOut);
-        cout << "---- START ----" << endl;
-        cout << "// -*-c++-*-" << endl;
-        unit->print(env);
-        codeOut.finish();
-        cout << "---- STOP ----" << endl;
-    }
-
-}
-
-
-int main(int argc, char **argv)
-{
-    try {
-        doit(argc, argv);
-    }
-    catch (xBase &x) {
-        HANDLER();
-        cout << x << endl;
-        abort();
-    }
-
-    return 0;
-}
-
-
-// end of file

Modified: cs/babel/trunk/configure.ac
===================================================================
--- cs/babel/trunk/configure.ac	2007-05-25 00:59:19 UTC (rev 6960)
+++ cs/babel/trunk/configure.ac	2007-05-25 01:41:58 UTC (rev 6961)
@@ -5,7 +5,7 @@
 AC_PREREQ(2.59)
 AC_INIT([babel], [0.1.0], [cig-cs at geodynamics.org], [babel])
 AC_CONFIG_AUX_DIR([./aux-config])
-AC_CONFIG_SRCDIR([babel.cc])
+AC_CONFIG_SRCDIR([mkpyxm.cc])
 AC_CONFIG_HEADER([config.h])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign])

Modified: cs/babel/trunk/elsa/elsa/Makefile.in
===================================================================
--- cs/babel/trunk/elsa/elsa/Makefile.in	2007-05-25 00:59:19 UTC (rev 6960)
+++ cs/babel/trunk/elsa/elsa/Makefile.in	2007-05-25 01:41:58 UTC (rev 6961)
@@ -4,7 +4,7 @@
 #temporary: iptree iptparse cipart smin
 
 # main target: a C++ parser
-all: cc.ast.gen.h tlexer ccparse quicktest packedword_test
+all: cc.ast.gen.h tlexer ccparse quicktest packedword_test libelsa.a
 
 # work in progress..
 #iptree smin cipart
@@ -107,6 +107,9 @@
 libraries := $(LIBELKHOUND) $(LIBAST) $(LIBSMBASE)
 LDFLAGS := @LDFLAGS@ $(libraries)
 
+# some other tools
+AR     := ar
+RANLIB := ranlib
 
 # compile .cc in this directory to a .o
 TOCLEAN += *.o *.d
@@ -330,6 +333,16 @@
 	@echo BUILD FINISHED
 
 
+# -------------------- exported library ----------------
+# 
+
+libelsa.a: $(CCPARSE_OBJS)
+	rm -f $@
+	$(AR) -r $@ $(CCPARSE_OBJS)
+	-$(RANLIB) $@
+
+TOCLEAN += libelsa.a
+
 # -------------------- semgrep --------------------
 TOCLEAN += semgrep
 semgrep: $(CCPARSE_OBJS) semgrep.o $(libraries) $(LIBSMBASE)

Copied: cs/babel/trunk/mkpyxm.cc (from rev 6960, cs/babel/trunk/babel.cc)
===================================================================
--- cs/babel/trunk/babel.cc	2007-05-25 00:59:19 UTC (rev 6960)
+++ cs/babel/trunk/mkpyxm.cc	2007-05-25 01:41:58 UTC (rev 6961)
@@ -0,0 +1,866 @@
+
+#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
+#include "cc_env.h"       // Env
+#include "cc_ast.h"       // C++ AST (r)
+#include "cc_lang.h"      // CCLang
+#include "parsetables.h"  // ParseTables
+#include "cc.gr.gen.h"    // CCParse
+#include "strtokp.h"      // StrtokParse
+
+#include "cc_elaborate.h" // ElabVisitor
+
+#include "cc_print.h"     // PrintEnv
+
+// ---------------------- PyExtModuleVisitor ------------------------
+
+
+class PyExtModuleGenerator : public ASTVisitor {
+private:      // data
+    // name of module
+    std::string name;
+    // C/C++ source filename
+    std::string source;
+    // interned strings
+    std::set<std::string> interns;
+    // these ensure the uniqueness of PyMethods
+    std::set<Variable *> vars;
+    std::set<OverloadSet *> overloads;
+    // global method table
+    std::set<std::string> gmt;
+
+    Env &env;
+    
+    enum State {
+        typeDecls,
+        collectInterns,
+        methods,
+        typeObjs,
+        modInitFunc,
+    };
+    State state;
+
+public:      // funcs
+    PyExtModuleGenerator(std::string n, std::string s, Env &env);
+    virtual ~PyExtModuleGenerator() {}
+
+    void generate(TranslationUnit *unit);
+    void generatePreamble();
+    void generatePostamble();
+    void generateModInitFunc(TranslationUnit *unit);
+    void generateTypeInit(CompoundType *ct);
+
+    virtual bool visitDeclarator(Declarator *obj);
+    virtual bool visitFunction(Function *f);
+    
+    void visitFunctionVariable(Variable *var);
+    void writePyMethod(Variable *var);
+    void writeNewMethod(CompoundType *ct);
+    void writeDeallocMethod(CompoundType *ct);
+    void writeMethodPrologue(Variable *var, std::string &args);
+    void scanFunctionParams(Variable *var,
+                            std::string &format,
+                            std::string &argnames,
+                            std::string &varargs,
+                            std::string &args);
+    const char *returnValueConversionFunction(Variable *var);
+
+    virtual bool visitTypeSpecifier(TypeSpecifier *ts);
+    virtual bool visitMember(Member *obj);
+    virtual void postvisitTypeSpecifier(TypeSpecifier *ts);
+    void generateTypeObject(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);
+};
+
+
+PyExtModuleGenerator::PyExtModuleGenerator(std::string n, std::string s, Env &env) :
+    name(n),
+    source(s),
+    env(env)
+{
+}
+
+
+void PyExtModuleGenerator::generate(TranslationUnit *unit)
+{
+    cout << "/* Generated by Babel */" << endl
+         << endl;
+    
+    cout << "#include \"" << source << "\"" << endl
+         << endl;
+    
+    cout << "#include \"Python.h\"" << endl
+         << endl;
+
+    this->generatePreamble();
+
+    state = typeDecls;
+    unit->traverse(*this);
+    cout << endl;
+    
+    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;
+
+    // reset uniquify
+    vars.clear();
+    overloads.clear();
+    
+    cout << "static __Babel_InternTabEntry __babel_intern_tab[] = {" << endl;
+    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;
+    
+    cout << "static struct PyMethodDef __babel_methods[] = {" << endl;
+    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(unit);
+
+    this->generatePostamble();
+    
+}
+
+
+void PyExtModuleGenerator::generatePreamble()
+{
+    cout << "typedef struct {PyObject **p; char *s;} __Babel_InternTabEntry;" << endl
+         << endl
+         << "static PyObject *__babel_m;" << endl
+         << endl
+         << "static int __Babel_InternStrings(__Babel_InternTabEntry *t);" << endl
+         << endl;
+}
+
+
+void PyExtModuleGenerator::generatePostamble()
+{
+    cout << "static int __Babel_InternStrings(__Babel_InternTabEntry *t) {" << endl
+         << "    while (t->p) {" << endl
+         << "        *t->p = PyString_InternFromString(t->s);" << endl
+         << "        if (!*t->p)" << endl
+         << "            return -1;" << endl
+         << "        ++t;" << endl
+         << "    }" << endl
+         << "    return 0;" << endl
+         << "}" << endl
+         << endl;
+}
+
+
+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;
+    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 (!this->isDiscardedFunction(var)) {
+            this->visitFunctionVariable(var);
+       }
+    }
+    return true;
+}
+
+
+bool PyExtModuleGenerator::visitFunction(Function *f)
+{
+    // This is called only for function bodies.  But 'visitDeclarator'
+    // is called for prototypes as well; so all our processing is done
+    // there.
+    if (false) {
+        Variable *var = f->nameAndParams->var;
+        if (!this->isDiscardedFunction(var)) {
+            this->visitFunctionVariable(var);
+        }
+    }
+    return true;
+}
+
+
+void PyExtModuleGenerator::visitFunctionVariable(Variable *var)
+{
+    switch (state) {
+    case typeDecls:
+        break;
+    case collectInterns:
+        interns.insert(var->name);
+        break;
+    case methods:
+        if (this->uniqify(var)) {
+            this->writePyMethod(var);
+            cout << endl;
+            if (!var->isMember()) {
+                gmt.insert(var->name);
+            }
+        }
+        break;
+    case typeObjs:
+        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;
+}
+
+
+void PyExtModuleGenerator::writePyMethod(Variable *var)
+{
+    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;
+    
+    if (var->isOverloaded()) {
+        cout << "    PyErr_SetString(PyExc_NotImplementedError, \"cannot call overloaded function '"
+             << var->name << "' from Python\");" << endl
+             << "    return 0;" << endl
+             << "}" << endl;
+        return;
+    }
+    
+    std::string args;
+    this->writeMethodPrologue(var, args);
+    const char *pyXXX_FromXXX = this->returnValueConversionFunction(var);
+    
+    if (var->isMember() && !var->isStaticMember()) {
+        // 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;
+        cout << "    r = Py_None; Py_INCREF(Py_None);" << endl;
+    }
+    
+    cout << "    return r;" << endl
+         << "}" << endl;
+}
+
+
+void PyExtModuleGenerator::writeNewMethod(CompoundType *ct)
+{
+    std::string tpNew = tpName("new", ct);
+    cout << "static PyObject *" << tpNew << "(PyTypeObject *type, PyObject *args, PyObject *kwds) {" << endl;
+    Variable *ctor0 = ct->getNamedField(env.constructorSpecialName, env, LF_INNER_ONLY);
+    // This is an elaborated AST, so there must be at least one constructor.
+    xassert(ctor0);
+    Variable *ctor = NULL;
+    if (ctor0->overload) {
+        SFOREACH_OBJLIST_NC(Variable, ctor0->overload->set, iter) {
+            Variable *ctorN = iter.data();
+            if (isCopyConstructor(ctorN, ct)) {
+                // skip
+            } else if (ctor) {
+                // we already found one
+                ctor = NULL;
+                break;
+            } else {
+                ctor = ctorN;
+            }
+        }
+    } else {
+        ctor = ctor0;
+    }
+    if (!ctor) {
+        cout << "    PyErr_SetString(PyExc_NotImplementedError, \"cannot call overloaded constructor from Python\");" << endl
+             << "    return 0;" << endl
+             << "}" << endl;
+        return;
+    }
+
+    // We found a unique constructor.
+    std::string args;
+    this->writeMethodPrologue(ctor, args);
+    
+    cout << "    PyObject *o = (*type->tp_alloc)(type, 0);" << endl
+         << "    ((struct __babel_obj_" << ct->name << " *)o)->_this = "
+         << "new " << ct->typedefVar->fullyQualifiedName0() << "(" << args << ");" << endl
+         << "    return o;" << endl
+         << "}" << endl;
+}
+
+
+void PyExtModuleGenerator::writeDeallocMethod(CompoundType *ct)
+{
+    std::string tpDealloc = tpName("dealloc", ct);
+    cout << "static void " << tpDealloc << "(PyObject *o) {" << endl
+         << "    " << ct->toCString() << " *_this = ((struct __babel_obj_" << ct->name << " *)o)->_this;" << endl
+         << "    delete _this;" << endl
+         << "    (*o->ob_type->tp_free)(o);" << endl
+         << "}" << endl;
+}
+
+
+void PyExtModuleGenerator::writeMethodPrologue(Variable *var, std::string &args)
+{
+    std::string format, argnames, varargs;
+    this->scanFunctionParams(var, format, argnames, varargs, args);
+    cout << "    PyObject *r;" << endl;
+    
+    cout << "    static char *argnames[] = {" << argnames << "0};" << endl
+         << "    if (!PyArg_ParseTupleAndKeywords(args, kwds, \"" << format << "\", argnames" << varargs << ")) return 0;" << endl;
+
+    return;
+}
+
+
+void PyExtModuleGenerator::scanFunctionParams(Variable *var,
+                                              std::string &format,
+                                              std::string &argnames,
+                                              std::string &varargs,
+                                              std::string &args)
+{
+    int ct = 0;
+    SFOREACH_OBJLIST(Variable, var->type->asFunctionType()->params, iter) {
+        ct++;
+        if (var->type->isMethod() && ct==1) {
+            // "this"
+            continue;
+        }
+        
+        const Variable *param = iter.data();
+
+        cout << "    " << param->toCString() << ";" << endl;
+        
+        char c = '?';
+        if (param->type->isSimpleType()) {
+            SimpleTypeId id = param->type->asSimpleTypeC()->type;
+            switch (id) {
+            case ST_CHAR:                c = 'b'; break;
+            case ST_UNSIGNED_CHAR:       c = 'B'; break;
+            case ST_SIGNED_CHAR:         c = 'b'; break; // Is 'char' signed?
+            case ST_BOOL:                break; // ???
+            case ST_INT:                 c = 'i'; break;
+            case ST_UNSIGNED_INT:        c = 'I'; break;
+            case ST_LONG_INT:            c = 'l'; break;
+            case ST_UNSIGNED_LONG_INT:   c = 'k'; break;
+            case ST_LONG_LONG:           c = 'L'; break;
+            case ST_UNSIGNED_LONG_LONG:  c = 'K'; break;
+            case ST_SHORT_INT:           c = 'h'; break;
+            case ST_UNSIGNED_SHORT_INT:  c = 'H'; break;
+            case ST_WCHAR_T:             break; // ???
+            case ST_FLOAT:               c = 'f'; break;
+            case ST_DOUBLE:              c = 'd'; break;
+            case ST_LONG_DOUBLE:
+            case ST_FLOAT_COMPLEX:
+            case ST_DOUBLE_COMPLEX:
+            case ST_LONG_DOUBLE_COMPLEX:
+            case ST_FLOAT_IMAGINARY:
+            case ST_DOUBLE_IMAGINARY:
+            case ST_LONG_DOUBLE_IMAGINARY:
+            case ST_VOID:
+                // ???
+                // ERROR
+                break;
+            default:
+                // ERROR
+                break;
+            }
+        } else if (param->type->isPointerType()) {
+            PointerType *pt = param->type->asPointerType();
+            if (pt->atType->isSimpleType()) {
+                SimpleTypeId id = pt->atType->asSimpleTypeC()->type;
+                switch (id) {
+                case ST_CHAR:
+                case ST_UNSIGNED_CHAR:
+                case ST_SIGNED_CHAR:
+                    c = 's';
+                    break;
+                case ST_WCHAR_T:
+                    break; // ???
+                default:
+                    // ERROR
+                    break;
+                }
+            } else {
+                // ERROR
+            }
+        } else {
+            // ERROR
+        }
+        format += c;
+        
+        argnames += std::string("\"") + param->name + "\",";
+        varargs += std::string(", &") + param->name;
+        
+        if (ct >= 3 || (!var->type->isMethod() && ct>=2)) {
+            args += ", ";
+        }
+        args += param->name;
+    }
+    return;
+}
+
+
+const char *PyExtModuleGenerator::returnValueConversionFunction(Variable *var)
+{
+    Type *rt = var->type->asFunctionType()->retType;
+    const char *pyXXX_FromXXX = "<error>";
+    if (rt->isSimpleType()) {
+        SimpleTypeId id = rt->asSimpleTypeC()->type;
+        switch (id) {
+        case ST_CHAR:                pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_UNSIGNED_CHAR:       pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
+        case ST_SIGNED_CHAR:         pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_BOOL:                pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_INT:                 pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_UNSIGNED_INT:        pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
+        case ST_LONG_INT:            pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_UNSIGNED_LONG_INT:   pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
+        case ST_LONG_LONG:           pyXXX_FromXXX = "PyLong_FromLongLong"; break;
+        case ST_UNSIGNED_LONG_LONG:  pyXXX_FromXXX = "PyLong_FromUnsignedLongLong"; break;
+        case ST_SHORT_INT:           pyXXX_FromXXX = "PyInt_FromLong"; break;
+        case ST_UNSIGNED_SHORT_INT:  pyXXX_FromXXX = "PyLong_FromUnsignedLong"; break;
+        case ST_WCHAR_T:             break; // ???
+        case ST_FLOAT:               pyXXX_FromXXX = "PyFloat_FromDouble"; break;
+        case ST_DOUBLE:              pyXXX_FromXXX = "PyFloat_FromDouble"; break;
+        case ST_LONG_DOUBLE:
+        case ST_FLOAT_COMPLEX:
+        case ST_DOUBLE_COMPLEX:
+        case ST_LONG_DOUBLE_COMPLEX:
+        case ST_FLOAT_IMAGINARY:
+        case ST_DOUBLE_IMAGINARY:
+        case ST_LONG_DOUBLE_IMAGINARY:
+            // ???
+            // ERROR
+            break;
+        case ST_VOID:
+            pyXXX_FromXXX = 0; // no conversion
+            break;
+        default:
+            // ERROR
+            break;
+        }
+    } else if (rt->isPointerType()) {
+        PointerType *pt = rt->asPointerType();
+        if (pt->atType->isSimpleType()) {
+            SimpleTypeId id = pt->atType->asSimpleTypeC()->type;
+            switch (id) {
+            case ST_CHAR:
+            case ST_UNSIGNED_CHAR:
+            case ST_SIGNED_CHAR:
+                pyXXX_FromXXX = "PyString_FromString";
+                break;
+            case ST_WCHAR_T:
+                break; // ???
+            default:
+                // ERROR
+                break;
+            }
+        } else {
+            // ERROR
+        }
+    } else {
+        // ERROR
+    }
+    return pyXXX_FromXXX;
+}
+
+
+bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
+{
+    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
+        }
+        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;
+        case modInitFunc:
+            this->generateTypeInit(ct);
+        default:
+            break;
+        }
+        break; }
+    default:
+        break;
+    }
+    return true;
+}
+
+
+bool PyExtModuleGenerator::visitMember(Member *obj)
+{
+    if (obj->isMR_func()) {
+        // 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;
+        }
+    } else if (obj->isMR_access()) {
+    } else if (obj->isMR_decl()) {
+        if (false) {
+            cout << "member decl" << endl;
+            Declaration *d = obj->asMR_decl()->d;
+            d->debugPrint(cout, 0);
+        }
+    }
+    return true;
+}
+
+
+void PyExtModuleGenerator::postvisitTypeSpecifier(TypeSpecifier *ts)
+{
+    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->writeNewMethod(ct);
+            cout << endl;
+            this->writeDeallocMethod(ct);
+            cout << endl;
+            this->generateTypeObject(ct);
+            cout << endl;
+            break;
+        default:
+            break;
+        }
+        break; }
+    default:
+        break;
+    }
+    return;
+}
+
+
+void PyExtModuleGenerator::generateTypeObject(CompoundType *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"
+        "    0, /*ob_size*/\n"
+        "    \"" << name << "." << ct->name << "\", /*tp_name*/\n"
+        "    sizeof(struct __babel_obj_" << ct->name << "), /*tp_basicsize*/\n"
+        "    0, /*tp_itemsize*/\n"
+        "    " << tpDealloc << ", /*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"
+        "    " << tpNew << ", /*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";
+}
+
+
+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;
+}
+
+
+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");
+}
+
+
+std::string PyExtModuleGenerator::mangledMemberFuncName(Variable *var, std::string ns)
+{
+    return this->mangledMemberFuncName(var, var->name, ns);
+}
+
+
+std::string PyExtModuleGenerator::mangledMemberFuncName(Variable *var, std::string funcName, std::string ns)
+{
+    return this->mangledMemberFuncName(var->scope->curCompound, funcName, ns);
+}
+
+
+std::string PyExtModuleGenerator::mangledMemberFuncName(CompoundType *ct, std::string funcName, std::string ns)
+{
+    std::string className = ct->typedefVar->fullyQualifiedName0().c_str();
+    std::stringstream s;
+    s << "__babel_" << ns << "_" << 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)
+{
+    xBase::logExceptions = false;
+
+    SourceLocManager mgr;
+    StringTable strTable;
+
+    // parsing language options
+    CCLang lang;
+    lang.GNU_Cplusplus();
+
+    // process command-line arguments
+    if (argc != 3) {
+        cout << "usage: " << argv[0] << " input.cc modulename\n";
+        return;
+    }
+
+    string inputFname = argv[1];
+
+    // parse+tcheck (TODO: make this more convenient)
+    TranslationUnit *unit;
+    {
+        SemanticValue treeTop;
+        ParseTreeAndTokens tree(lang, treeTop, strTable, inputFname.c_str());
+
+        // grab the lexer so we can check it for errors (damn this
+        // 'tree' thing is stupid..)
+        Lexer *lexer = dynamic_cast<Lexer*>(tree.lexer);
+        xassert(lexer);
+
+        CCParse *parseContext = new CCParse(strTable, lang);
+        tree.userAct = parseContext;
+
+        ParseTables *tables = parseContext->makeTables();
+        tree.tables = tables;
+
+        // parse
+        if (!toplevelParse(tree, inputFname.c_str())) {
+            exit(2); // parse error
+        }
+
+        // check for parse errors
+        if (parseContext->errors || lexer->errors) {
+            exit(2);
+        }
+
+        // treeTop is a TranslationUnit pointer
+        unit = (TranslationUnit*)treeTop;
+
+        delete parseContext;
+        delete tables;
+
+        // tcheck
+        BasicTypeFactory tfac;
+        ArrayStack<Variable*> madeUpVariables;
+        ArrayStack<Variable*> builtinVars;
+        Env env(strTable, lang, tfac, madeUpVariables, builtinVars, unit);
+        unit->tcheck(env);
+
+        int numErrors = env.errors.numErrors();
+        if (numErrors) {
+            env.errors.print(cerr);
+            cerr << numErrors << " errors\n";
+            exit(4);
+        }
+
+        // do elaboration
+        ElabVisitor vis(strTable, tfac, unit);
+        unit->traverse(vis.loweredVisitor);
+
+        // generate Python module
+        PyExtModuleGenerator visitor(argv[2], argv[1], env);
+        visitor.generate(unit);
+
+    }
+
+    if (false) {
+        // pretty printing
+        OStreamOutStream out0(cout);
+        CodeOutStream codeOut(out0);
+        CTypePrinter typePrinter;
+        PrintEnv env(typePrinter, &codeOut);
+        cout << "---- START ----" << endl;
+        cout << "// -*-c++-*-" << endl;
+        unit->print(env);
+        codeOut.finish();
+        cout << "---- STOP ----" << endl;
+    }
+
+}
+
+
+int main(int argc, char **argv)
+{
+    try {
+        doit(argc, argv);
+    }
+    catch (xBase &x) {
+        HANDLER();
+        cout << x << endl;
+        abort();
+    }
+
+    return 0;
+}
+
+
+// end of file



More information about the cig-commits mailing list