[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