[cig-commits] r6980 - cs/babel/trunk
leif at geodynamics.org
leif at geodynamics.org
Sun May 27 04:25:19 PDT 2007
Author: leif
Date: 2007-05-27 04:25:19 -0700 (Sun, 27 May 2007)
New Revision: 6980
Modified:
cs/babel/trunk/mkpyxm.cc
Log:
Cleanly separated syntax processing (C++ AST treewalk) from semantics
(a Python extension module). This elminates the clumsy 'state'
variable and the multiple passes over the AST.
Modified: cs/babel/trunk/mkpyxm.cc
===================================================================
--- cs/babel/trunk/mkpyxm.cc 2007-05-26 23:38:07 UTC (rev 6979)
+++ cs/babel/trunk/mkpyxm.cc 2007-05-27 11:25:19 UTC (rev 6980)
@@ -2,6 +2,7 @@
#include <iostream> // cout
#include <sstream>
#include <set>
+#include <vector>
#include <stdlib.h> // exit, atoi
#include <string.h>
@@ -20,266 +21,83 @@
#include "cc_print.h" // PrintEnv
-// ---------------------- PyExtModuleVisitor ------------------------
+/**********************************************************************
+ * PyMethod & PyType *
+ **********************************************************************/
-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;
+class PyType;
-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);
+class PyMethod {
+ Variable *var;
+ PyType *type;
- 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);
+public:
+ PyMethod(Variable *v, PyType *t);
+ void generateSource();
- 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);
+ std::string name() const { return var->name; }
+
+ static void writePrologue(Variable *var, std::string &args);
+ static void scanFunctionParams(Variable *var,
+ std::string &format,
+ std::string &argnames,
+ std::string &varargs,
+ std::string &args);
+private:
+ void writePrologue(std::string &args) { writePrologue(var, args); }
+ const char *returnValueConversionFunction();
+ std::string mangledName();
};
-PyExtModuleGenerator::PyExtModuleGenerator(std::string n, std::string s, Env &env) :
- name(n),
- source(s),
- env(env)
-{
-}
+class PyType {
+ CompoundType *ct;
+ Env &env;
+public:
+ std::vector<PyMethod *> methods;
-void PyExtModuleGenerator::generate(TranslationUnit *unit)
-{
- cout << "/* Generated by Babel */" << endl
- << endl;
+public:
+ PyType(CompoundType *t, Env &e);
+ void addMethod(PyMethod *method) { methods.push_back(method); }
- cout << "#include \"" << source << "\"" << endl
- << endl;
-
- cout << "#include \"Python.h\"" << endl
- << endl;
+ void generateDecl();
+ void generateSource(std::string moduleName);
+ void generateInitCode();
- this->generatePreamble();
+ void writeThisDecl();
- state = typeDecls;
- unit->traverse(*this);
- cout << endl;
+private:
+ void generateMethodTable();
+ void generateNewMethod();
+ void generateDeallocMethod();
+ void generateObject(std::string moduleName);
- 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;
+ std::string tpName(std::string funcName);
- // 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;
+public:
+ std::string mangledMemberFuncName(std::string funcName, std::string ns = "m");
+};
- 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);
+/**********************************************************************
+ * PyMethod methods *
+ **********************************************************************/
- this->generatePostamble();
-
-}
-
-void PyExtModuleGenerator::generatePreamble()
+PyMethod::PyMethod(Variable *v, PyType *t) :
+ var(v),
+ type(t)
{
- 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()
+void PyMethod::generateSource()
{
- 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;
- }
+ std::string mname = this->mangledName();
cout << "static PyObject *" << mname << "(PyObject *self, PyObject *args, PyObject *kwds) {" << endl;
if (var->isOverloaded()) {
@@ -291,14 +109,13 @@
}
std::string args;
- this->writeMethodPrologue(var, args);
- const char *pyXXX_FromXXX = this->returnValueConversionFunction(var);
+ this->writePrologue(args);
+ const char *pyXXX_FromXXX = this->returnValueConversionFunction();
- if (var->isMember() && !var->isStaticMember()) {
+ if (type && !var->isStaticMember()) {
// method
- CompoundType *ct = var->scope->curCompound;
- cout << " Py_INCREF(self);" << endl
- << " " << ct->toCString() << " *_this = ((struct __babel_obj_" << ct->name << " *)self)->_this;" << endl;
+ cout << " Py_INCREF(self);" << endl;
+ type->writeThisDecl();
if (pyXXX_FromXXX) {
cout << " r = " << pyXXX_FromXXX << "(_this->" << var->name << "(" << args << "));" << endl;
} else {
@@ -318,64 +135,10 @@
}
-void PyExtModuleGenerator::writeNewMethod(CompoundType *ct)
+void PyMethod::writePrologue(Variable *var, std::string &args)
{
- 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);
+ scanFunctionParams(var, format, argnames, varargs, args);
cout << " PyObject *r;" << endl;
cout << " static char *argnames[] = {" << argnames << "0};" << endl
@@ -385,11 +148,11 @@
}
-void PyExtModuleGenerator::scanFunctionParams(Variable *var,
- std::string &format,
- std::string &argnames,
- std::string &varargs,
- std::string &args)
+void PyMethod::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) {
@@ -473,7 +236,7 @@
}
-const char *PyExtModuleGenerator::returnValueConversionFunction(Variable *var)
+const char *PyMethod::returnValueConversionFunction()
{
Type *rt = var->type->asFunctionType()->retType;
const char *pyXXX_FromXXX = "<error>";
@@ -538,107 +301,136 @@
}
-bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
+std::string PyMethod::mangledName()
{
- 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;
+ std::string mname;
+ if (type) {
+ mname = type->mangledMemberFuncName(var->name);
+ } else {
+ mname = std::string("__babel_m_") + var->name;
}
- return true;
+ return mname;
}
-bool PyExtModuleGenerator::visitMember(Member *obj)
+/**********************************************************************
+ * PyType methods *
+ **********************************************************************/
+
+
+PyType::PyType(CompoundType *t, Env &e) :
+ ct(t),
+ env(e)
{
- 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);
- }
+}
+
+
+void PyType::generateDecl()
+{
+ 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;
+}
+
+
+void PyType::generateSource(std::string moduleName)
+{
+ this->generateMethodTable();
+ cout << endl;
+ this->generateNewMethod();
+ cout << endl;
+ this->generateDeallocMethod();
+ cout << endl;
+ this->generateObject(moduleName);
+ cout << endl;
+}
+
+
+void PyType::generateMethodTable()
+{
+ cout << "static struct PyMethodDef __babel_methods_" << ct->name << "[] = {" << endl;
+
+ for (std::vector<PyMethod *>::const_iterator m = methods.begin();
+ m != methods.end();
+ ++m) {
+ std::string name = (*m)->name();
+ cout << " {\"" << name << "\", "
+ << "(PyCFunction)" << mangledMemberFuncName(name)
+ << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
}
- return true;
+
+ cout << " {0, 0, 0, 0}" << endl
+ << "};" << endl;
}
-void PyExtModuleGenerator::postvisitTypeSpecifier(TypeSpecifier *ts)
+void PyType::generateNewMethod()
{
- 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
+ std::string tpNew = tpName("new");
+ 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;
+ }
}
- 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;
+ } else {
+ ctor = ctor0;
}
- return;
+ 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;
+ PyMethod::writePrologue(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::generateTypeObject(CompoundType *ct)
+void PyType::generateDeallocMethod()
{
- std::string tpDealloc = tpName("dealloc", ct);
- std::string tpNew = tpName("new", ct);
+ std::string tpDealloc = tpName("dealloc");
+ cout << "static void " << tpDealloc << "(PyObject *self) {" << endl;
+ this->writeThisDecl();
+ cout << " delete _this;" << endl
+ << " (*self->ob_type->tp_free)(self);" << endl
+ << "}" << endl;
+}
+
+
+void PyType::generateObject(std::string moduleName)
+{
+ std::string tpDealloc = tpName("dealloc");
+ std::string tpNew = tpName("new");
cout <<
"PyTypeObject __babel_type_" << ct->name << " = {\n"
" PyObject_HEAD_INIT(0)\n"
" 0, /*ob_size*/\n"
- " \"" << name << "." << ct->name << "\", /*tp_name*/\n"
+ " \"" << moduleName << "." << ct->name << "\", /*tp_name*/\n"
" sizeof(struct __babel_obj_" << ct->name << "), /*tp_basicsize*/\n"
" 0, /*tp_itemsize*/\n"
" " << tpDealloc << ", /*tp_dealloc*/\n"
@@ -686,6 +478,412 @@
}
+void PyType::generateInitCode()
+{
+ 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;
+}
+
+
+std::string PyType::tpName(std::string funcName)
+{
+ return this->mangledMemberFuncName(funcName, "tp");
+}
+
+
+std::string PyType::mangledMemberFuncName(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();
+}
+
+
+void PyType::writeThisDecl()
+{
+ cout << " " << ct->toCString() << " *_this = ((struct __babel_obj_" << ct->name << " *)self)->_this;" << endl;
+}
+
+
+/**********************************************************************
+ * PyExtModule *
+ **********************************************************************/
+
+
+class PyExtModule {
+
+ std::string name; // name of module
+ std::vector<PyType *> types; // global methods
+ std::vector<PyMethod *> methods; // global methods
+ std::set<std::string> interns; // interned strings
+
+ std::string source; // C/C++ source filename (for #include)
+
+public:
+ PyExtModule(std::string n, std::string s);
+ void addMethod(PyMethod *method) { methods.push_back(method); }
+ void addType(PyType *type) { types.push_back(type); }
+ void generateSource();
+
+private:
+ void collectInterns();
+
+ void generatePreamble();
+ void generateTypeDecls();
+ void generateInternDecls();
+ void generateMethods();
+ void generateInternTable();
+ void generateTypeObjects();
+ void generateMethodTable();
+ void generateModInitFunc();
+ void generatePostamble();
+
+};
+
+
+//----------------------------------------------------------------------
+
+
+PyExtModule::PyExtModule(std::string n, std::string s) :
+ name(n),
+ source(s)
+{
+}
+
+
+void PyExtModule::collectInterns()
+{
+ // Intern the names of all methods.
+
+ for (std::vector<PyMethod *>::const_iterator m = methods.begin();
+ m != methods.end();
+ ++m) {
+ interns.insert((*m)->name());
+ }
+ for (std::vector<PyType *>::const_iterator t = types.begin();
+ t != types.end();
+ ++t) {
+ for (std::vector<PyMethod *>::const_iterator m = (*t)->methods.begin();
+ m != (*t)->methods.end();
+ ++m) {
+ interns.insert((*m)->name());
+ }
+ }
+}
+
+
+void PyExtModule::generateSource()
+{
+ this->collectInterns();
+
+ cout << "/* Generated by Babel */" << endl
+ << endl;
+
+ cout << "#include \"" << source << "\"" << endl
+ << endl;
+
+ cout << "#include \"Python.h\"" << endl
+ << endl;
+
+ this->generatePreamble();
+
+ this->generateTypeDecls();
+ this->generateInternDecls();
+ this->generateMethods();
+ this->generateInternTable();
+ this->generateTypeObjects();
+ this->generateMethodTable();
+
+ this->generateModInitFunc();
+
+ this->generatePostamble();
+
+}
+
+
+void PyExtModule::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 PyExtModule::generateTypeDecls()
+{
+ for (std::vector<PyType *>::const_iterator t = types.begin();
+ t != types.end();
+ ++t) {
+ (*t)->generateDecl();
+ }
+}
+
+
+void PyExtModule::generateInternDecls()
+{
+ for (std::set<std::string>::const_iterator i = interns.begin();
+ i != interns.end();
+ ++i) {
+ cout << "static PyObject *__babel_n_" << *i << ";" << endl;
+ }
+ cout << endl;
+}
+
+
+void PyExtModule::generateMethods()
+{
+ for (std::vector<PyMethod *>::const_iterator m = methods.begin();
+ m != methods.end();
+ ++m) {
+ (*m)->generateSource();
+ cout << endl;
+ }
+ for (std::vector<PyType *>::const_iterator t = types.begin();
+ t != types.end();
+ ++t) {
+ for (std::vector<PyMethod *>::const_iterator m = (*t)->methods.begin();
+ m != (*t)->methods.end();
+ ++m) {
+ (*m)->generateSource();
+ cout << endl;
+ }
+ }
+}
+
+
+void PyExtModule::generateInternTable()
+{
+ 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;
+}
+
+
+void PyExtModule::generateTypeObjects()
+{
+ for (std::vector<PyType *>::const_iterator t = types.begin();
+ t != types.end();
+ ++t) {
+ (*t)->generateSource(name);
+ }
+}
+
+
+void PyExtModule::generateMethodTable()
+{
+ cout << "static struct PyMethodDef __babel_methods[] = {" << endl;
+
+ for (std::vector<PyMethod *>::const_iterator m = methods.begin();
+ m != methods.end();
+ ++m) {
+ cout << " {\"" << (*m)->name() << "\", (PyCFunction)__babel_m_" << (*m)->name()
+ << ", METH_VARARGS|METH_KEYWORDS, 0}," << endl;
+ }
+
+ cout << " {0, 0, 0, 0}" << endl
+ << "};" << endl
+ << endl;
+}
+
+
+void PyExtModule::generateModInitFunc()
+{
+ 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;
+
+ for (std::vector<PyType *>::const_iterator t = types.begin();
+ t != types.end();
+ ++t) {
+ (*t)->generateInitCode();
+ }
+
+ cout << " return;" << endl
+ << "}" << endl
+ << endl;
+}
+
+
+void PyExtModule::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;
+}
+
+
+/**********************************************************************
+ * PyExtModuleGenerator *
+ **********************************************************************/
+
+
+class PyExtModuleGenerator : public ASTVisitor {
+ PyExtModule *module;
+ Env &env;
+
+ PyType *currentType;
+
+ // these ensure the uniqueness of PyMethods
+ std::set<Variable *> vars;
+ std::set<OverloadSet *> overloads;
+
+public:
+ PyExtModuleGenerator(PyExtModule *m, Env &env);
+ virtual ~PyExtModuleGenerator();
+
+ virtual bool visitDeclarator(Declarator *obj);
+ virtual bool visitFunction(Function *f);
+
+ virtual bool visitTypeSpecifier(TypeSpecifier *ts);
+ virtual bool visitMember(Member *obj);
+ virtual void postvisitTypeSpecifier(TypeSpecifier *ts);
+
+private:
+ void visitFunctionVariable(Variable *var);
+
+ bool isDiscardedFunction(Variable *var);
+ bool uniqify(Variable *var);
+};
+
+
+//----------------------------------------------------------------------
+
+
+PyExtModuleGenerator::PyExtModuleGenerator(PyExtModule *m, Env &e) :
+ module(m),
+ env(e),
+ currentType(0)
+{
+}
+
+
+PyExtModuleGenerator::~PyExtModuleGenerator()
+{
+}
+
+
+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)
+{
+ if (this->uniqify(var)) {
+ PyMethod *method = new PyMethod(var, currentType);
+ if (currentType) {
+ xassert(var->isMember());
+ currentType->addMethod(method);
+ } else {
+ module->addMethod(method);
+ }
+ }
+ if (false) {
+ cout << " " << var->toCString() << endl;
+ cout << " " << var->toQualifiedString() << endl;
+ }
+ return;
+}
+
+
+bool PyExtModuleGenerator::visitTypeSpecifier(TypeSpecifier *ts)
+{
+ if (ts->kind() == TypeSpecifier::TS_CLASSSPEC) {
+ TS_classSpec *spec = ts->asTS_classSpec();
+ CompoundType *ct = spec->ctype;
+ if (ct->name) { // skip anonymous classes
+ currentType = new PyType(ct, env);
+ module->addType(currentType);
+ }
+ }
+ 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)
+{
+ if (ts->kind() == TypeSpecifier::TS_CLASSSPEC) {
+ currentType = 0;
+ }
+}
+
+
bool PyExtModuleGenerator::isDiscardedFunction(Variable *var)
{
FunctionType *t = var->type->asFunctionType();
@@ -717,45 +915,11 @@
}
-std::string PyExtModuleGenerator::tpName(std::string funcName, CompoundType *ct)
-{
- return this->mangledMemberFuncName(ct, funcName, "tp");
-}
+/**********************************************************************
+ * main *
+ **********************************************************************/
-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;
@@ -781,8 +945,7 @@
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..)
+ // grab the lexer so we can check it for errors
Lexer *lexer = dynamic_cast<Lexer*>(tree.lexer);
xassert(lexer);
@@ -827,8 +990,10 @@
unit->traverse(vis.loweredVisitor);
// generate Python module
- PyExtModuleGenerator visitor(argv[2], argv[1], env);
- visitor.generate(unit);
+ PyExtModule module(argv[2], argv[1]);
+ PyExtModuleGenerator visitor(&module, env);
+ unit->traverse(visitor);
+ module.generateSource();
}
More information about the cig-commits
mailing list