From: Armin Groesslinger <
armin.gro...@uni-passau.de>
This change is large, but mostly mechanical. In generator.cc the prefix
'generator::' is added to turn static functions into class methods. In
python.cc functions are moved into the newly introduced
python_generator. This sometimes requires the introduction of a new
isl_class argument.
The only non-trivial change is the separation of generate_python into
generator::generator() and python_generator::generate(). The former now
constructs the set of isl_classses which we want to generate bindings
for, whereas the latter prints for each class the corresponding bindings.
Signed-off-by: Tobias Grosser <
tob...@grosser.es>
---
interface/extract_interface.cc | 3 +-
interface/generator.cc | 100 +++++++++++++++++----
interface/generator.h | 65 ++++++++------
interface/python.cc | 191 +++++++++++++++--------------------------
interface/python.h | 39 ++++++++-
5 files changed, 231 insertions(+), 167 deletions(-)
diff --git a/interface/extract_interface.cc b/interface/extract_interface.cc
index 9013f66..ddca368 100644
--- a/interface/extract_interface.cc
+++ b/interface/extract_interface.cc
@@ -423,8 +423,9 @@ int main(int argc, char *argv[])
ParseAST(*sema);
Diags.getClient()->EndSourceFile();
- generate_python(consumer.exported_types, consumer.exported_functions,
+ python_generator gen(consumer.exported_types, consumer.exported_functions,
consumer.functions);
+ gen.generate();
delete sema;
delete Clang;
diff --git a/interface/generator.cc b/interface/generator.cc
index 63b21f9..9cc6e2d 100644
--- a/interface/generator.cc
+++ b/interface/generator.cc
@@ -40,9 +40,77 @@
#include <iostream>
+/* Should "method" be considered to be a static method?
+ * That is, is the first argument something other than
+ * an instance of the class?
+ */
+bool generator::is_static(const isl_class &clazz, FunctionDecl *method)
+{
+ ParmVarDecl *param = method->getParamDecl(0);
+ QualType type = param->getOriginalType();
+
+ if (!is_isl_type(type))
+ return true;
+ return extract_type(type) !=
clazz.name;
+}
+
+/* Collect all functions that belong to a certain type, separating
+ * constructors from regular methods and keeping track of the _to_str and
+ * _free functions, if any, separately. If there are any overloaded
+ * functions, then they are grouped based on their name after removing the
+ * argument type suffix.
+ */
+generator::generator(set<RecordDecl *> &exported_types,
+ set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions)
+{
+ map<string, isl_class>::iterator ci;
+
+ set<FunctionDecl *>::iterator in;
+ for (in = functions.begin(); in != functions.end(); ++in) {
+ FunctionDecl *decl = *in;
+ functions_by_name[decl->getName()] = decl;
+ }
+
+ set<RecordDecl *>::iterator it;
+ for (it = exported_types.begin(); it != exported_types.end(); ++it) {
+ RecordDecl *decl = *it;
+ map<string, FunctionDecl *>::iterator i;
+
+ string name = decl->getName();
+ classes[name].name = name;
+ classes[name].type = decl;
+ classes[name].fn_to_str = NULL;
+ classes[name].fn_free = NULL;
+
+ i = functions_by_name.find(name + "_to_str");
+ if (i != functions_by_name.end())
+ classes[name].fn_to_str = i->second;
+
+ i = functions_by_name.find (name + "_free");
+ if (i == functions_by_name.end())
+ die("No _free function found");
+ classes[name].fn_free = i->second;
+ }
+
+ for (in = exported_functions.begin(); in != exported_functions.end();
+ ++in) {
+ isl_class *c = method2class(classes, *in);
+ if (!c)
+ continue;
+ if (is_constructor(*in)) {
+ c->constructors.insert(*in);
+ } else {
+ FunctionDecl *method = *in;
+ string fullname = method->getName();
+ fullname = drop_type_suffix(fullname, method);
+ c->methods[fullname].insert(method);
+ }
+ }
+}
+
/* Print error message "msg" and abort.
*/
-void die(const char *msg)
+void generator::die(const char *msg)
{
fprintf(stderr, "%s", msg);
abort();
@@ -53,7 +121,7 @@ void die(const char *msg)
* return the modified name (or the original name if
* no modifications were made).
*/
-string drop_type_suffix(string name, FunctionDecl *method)
+string generator::drop_type_suffix(string name, FunctionDecl *method)
{
int num_params;
ParmVarDecl *param;
@@ -79,7 +147,7 @@ string drop_type_suffix(string name, FunctionDecl *method)
/* Return a sequence of the types of which the given type declaration is
* marked as being a subtype.
*/
-std::vector<string> find_superclasses(RecordDecl *decl)
+std::vector<string> generator::find_superclasses(RecordDecl *decl)
{
vector<string> super;
@@ -105,28 +173,28 @@ std::vector<string> find_superclasses(RecordDecl *decl)
/* Is decl marked as being part of an overloaded method?
*/
-bool is_overload(Decl *decl)
+bool generator::is_overload(Decl *decl)
{
return has_annotation(decl, "isl_overload");
}
/* Is decl marked as a constructor?
*/
-bool is_constructor(Decl *decl)
+bool generator::is_constructor(Decl *decl)
{
return has_annotation(decl, "isl_constructor");
}
/* Is decl marked as consuming a reference?
*/
-bool takes(Decl *decl)
+bool generator::takes(Decl *decl)
{
return has_annotation(decl, "isl_take");
}
/* Is decl marked as returning a reference that is required to be freed.
*/
-bool gives(Decl *decl)
+bool generator::gives(Decl *decl)
{
return has_annotation(decl, "isl_give");
}
@@ -134,7 +202,7 @@ bool gives(Decl *decl)
/* Return the class that has a name that matches the initial part
* of the name of function "fd" or NULL if no such class could be found.
*/
-isl_class *method2class(map<string, isl_class> &classes,
+isl_class *generator::method2class(map<string, isl_class> &classes,
FunctionDecl *fd)
{
string best;
@@ -156,7 +224,7 @@ isl_class *method2class(map<string, isl_class> &classes,
/* Is "type" the type "isl_ctx *"?
*/
-bool is_isl_ctx(QualType type)
+bool generator::is_isl_ctx(QualType type)
{
if (!type->isPointerType())
return 0;
@@ -169,7 +237,7 @@ bool is_isl_ctx(QualType type)
/* Is the first argument of "fd" of type "isl_ctx *"?
*/
-bool first_arg_is_isl_ctx(FunctionDecl *fd)
+bool generator::first_arg_is_isl_ctx(FunctionDecl *fd)
{
ParmVarDecl *param;
@@ -182,7 +250,7 @@ bool first_arg_is_isl_ctx(FunctionDecl *fd)
/* Is "type" that of a pointer to an isl_* structure?
*/
-bool is_isl_type(QualType type)
+bool generator::is_isl_type(QualType type)
{
if (type->isPointerType()) {
string s;
@@ -199,7 +267,7 @@ bool is_isl_type(QualType type)
/* Is "type" the type isl_bool?
*/
-bool is_isl_bool(QualType type)
+bool generator::is_isl_bool(QualType type)
{
string s;
@@ -212,7 +280,7 @@ bool is_isl_bool(QualType type)
/* Is "type" that of a pointer to char.
*/
-bool is_string_type(QualType type)
+bool generator::is_string_type(QualType type)
{
if (type->isPointerType()) {
string s;
@@ -229,7 +297,7 @@ bool is_string_type(QualType type)
/* Is "type" that of a pointer to a function?
*/
-bool is_callback(QualType type)
+bool generator::is_callback(QualType type)
{
if (!type->isPointerType())
return false;
@@ -239,7 +307,7 @@ bool is_callback(QualType type)
/* Is "type" that of "char *" of "const char *"?
*/
-bool is_string(QualType type)
+bool generator::is_string(QualType type)
{
if (type->isPointerType()) {
string s = type->getPointeeType().getAsString();
@@ -252,7 +320,7 @@ bool is_string(QualType type)
/* Return the name of the type that "type" points to.
* The input "type" is assumed to be a pointer type.
*/
-string extract_type(QualType type)
+string generator::extract_type(QualType type)
{
if (type->isPointerType())
return type->getPointeeType().getAsString();
diff --git a/interface/generator.h b/interface/generator.h
index d577b4d..b55de99 100644
--- a/interface/generator.h
+++ b/interface/generator.h
@@ -24,35 +24,44 @@ struct isl_class {
map<string, set<FunctionDecl *> > methods;
FunctionDecl *fn_to_str;
FunctionDecl *fn_free;
-
- bool is_static(FunctionDecl *method);
-
- void print(map<string, isl_class> &classes, set<string> &done);
- void print_constructor(FunctionDecl *method);
- void print_representation(const string &python_name);
- void print_method_type(FunctionDecl *fd);
- void print_method_types();
- void print_method(FunctionDecl *method, vector<string> super);
- void print_method_overload(FunctionDecl *method, vector<string> super);
- void print_method(const string &fullname,
- const set<FunctionDecl *> &methods, vector<string> super);
};
-void die(const char *msg) __attribute__((noreturn));
-string drop_type_suffix(string name, FunctionDecl *method);
-vector<string> find_superclasses(RecordDecl *decl);
-bool is_overload(Decl *decl);
-bool is_constructor(Decl *decl);
-bool takes(Decl *decl);
-bool gives(Decl *decl);
-isl_class *method2class(map<string, isl_class> &classes, FunctionDecl *fd);
-bool is_isl_ctx(QualType type);
-bool first_arg_is_isl_ctx(FunctionDecl *fd);
-bool is_isl_type(QualType type);
-bool is_isl_bool(QualType type);
-bool is_string_type(QualType type);
-bool is_callback(QualType type);
-bool is_string(QualType type);
-string extract_type(QualType type);
+/* Base class for interface generators.
+ */
+class generator {
+protected:
+ map<string,isl_class> classes;
+ map<string, FunctionDecl *> functions_by_name;
+
+public:
+ generator(set<RecordDecl *> &exported_types,
+ set<FunctionDecl *> exported_functions,
+ set<FunctionDecl *> functions);
+
+ virtual void generate() = 0;
+ virtual ~generator() {};
+
+protected:
+ void print_class_header(const isl_class &clazz, const string &name,
+ const vector<string> &super);
+ string drop_type_suffix(string name, FunctionDecl *method);
+ void die(const char *msg) __attribute__((noreturn));
+ vector<string> find_superclasses(RecordDecl *decl);
+ bool is_overload(Decl *decl);
+ bool is_constructor(Decl *decl);
+ bool takes(Decl *decl);
+ bool gives(Decl *decl);
+ isl_class *method2class(map<string, isl_class> &classes,
+ FunctionDecl *fd);
+ bool is_isl_ctx(QualType type);
+ bool first_arg_is_isl_ctx(FunctionDecl *fd);
+ bool is_isl_type(QualType type);
+ bool is_isl_bool(QualType type);
+ bool is_string_type(QualType type);
+ bool is_callback(QualType type);
+ bool is_string(QualType type);
+ bool is_static(const isl_class &clazz, FunctionDecl *method);
+ string extract_type(QualType type);
+};
#endif /* ISL_INTERFACE_GENERATOR_H */
diff --git a/interface/python.cc b/interface/python.cc
index 4ec166f..3b23c79 100644
--- a/interface/python.cc
+++ b/interface/python.cc
@@ -39,25 +39,17 @@
#include <vector>
#include "python.h"
-/* Drop the "isl_" initial part of the type name "name".
- */
-static string type2python(string name)
+python_generator::python_generator( set<RecordDecl *> &exported_types,
+ set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions)
+ : generator(exported_types, exported_functions, functions)
{
- return name.substr(4);
}
-/* Should "method" be considered to be a static method?
- * That is, is the first argument something other than
- * an instance of the class?
+/* Drop the "isl_" initial part of the type name "name".
*/
-bool isl_class::is_static(FunctionDecl *method)
+static string type2python(string name)
{
- ParmVarDecl *param = method->getParamDecl(0);
- QualType type = param->getOriginalType();
-
- if (!is_isl_type(type))
- return true;
- return extract_type(type) != name;
+ return name.substr(4);
}
/* Print the header of the method "name" with "n_arg" arguments.
@@ -66,7 +58,8 @@ bool isl_class::is_static(FunctionDecl *method)
* If the method is called "from", then rename it to "convert_from"
* because "from" is a python keyword.
*/
-static void print_method_header(bool is_static, const string &name, int n_arg)
+void python_generator::print_method_header(bool is_static, const string &name,
+ int n_arg)
{
const char *s;
@@ -95,8 +88,8 @@ static void print_method_header(bool is_static, const string &name, int n_arg)
* If "upcast" is not set, then the "super", "name" and "n" arguments
* to this function are ignored.
*/
-static void print_type_check(const string &type, int pos, bool upcast,
- const string &super, const string &name, int n)
+void python_generator::print_type_check(const string &type, int pos,
+ bool upcast, const string &super, const string &name, int n)
{
printf(" try:\n");
printf(" if not arg%d.__class__ is %s:\n",
@@ -125,7 +118,7 @@ static void print_type_check(const string &type, int pos, bool upcast,
* If any exception is thrown, the wrapper keeps track of it in exc_info[0]
* and returns -1. Otherwise the wrapper returns 0.
*/
-static void print_callback(QualType type, int arg)
+void python_generator::print_callback(QualType type, int arg)
{
const FunctionProtoType *fn = type->getAs<FunctionProtoType>();
unsigned n_arg = fn->getNumArgs();
@@ -179,7 +172,7 @@ static void print_callback(QualType type, int arg)
* Otherwise, if the argument is a pointer, then pass this pointer itself.
* Otherwise, pass the argument directly.
*/
-static void print_arg_in_call(FunctionDecl *fd, int arg, int skip)
+void python_generator::print_arg_in_call(FunctionDecl *fd, int arg, int skip)
{
ParmVarDecl *param = fd->getParamDecl(arg);
QualType type = param->getOriginalType();
@@ -205,7 +198,7 @@ static void print_arg_in_call(FunctionDecl *fd, int arg, int skip)
* If the return type is isl_bool, then convert the result to
* a Python boolean, raising an error on isl_bool_error.
*/
-static void print_method_return(FunctionDecl *method)
+void python_generator::print_method_return(FunctionDecl *method)
{
QualType return_type = method->getReturnType();
@@ -256,10 +249,11 @@ static void print_method_return(FunctionDecl *method)
* If the function consumes a reference, then we pass it a copy of
* the actual argument.
*/
-void isl_class::print_method(FunctionDecl *method, vector<string> super)
+void python_generator::print_method(const isl_class &clazz,
+ FunctionDecl *method, vector<string> super)
{
string fullname = method->getName();
- string cname = fullname.substr(name.length() + 1);
+ string cname = fullname.substr(clazz.name.length() + 1);
int num_params = method->getNumParams();
int drop_user = 0;
int drop_ctx = first_arg_is_isl_ctx(method);
@@ -271,7 +265,7 @@ void isl_class::print_method(FunctionDecl *method, vector<string> super)
drop_user = 1;
}
- print_method_header(is_static(method), cname,
+ print_method_header(is_static(clazz, method), cname,
num_params - drop_ctx - drop_user);
for (int i = drop_ctx; i < num_params; ++i) {
@@ -328,15 +322,15 @@ void isl_class::print_method(FunctionDecl *method, vector<string> super)
* the python method correspond to the arguments expected by "method"
* and to call "method" if they do.
*/
-void isl_class::print_method_overload(FunctionDecl *method,
- vector<string> super)
+void python_generator::print_method_overload(const isl_class &clazz,
+ FunctionDecl *method, vector<string> super)
{
string fullname = method->getName();
int num_params = method->getNumParams();
int first;
string type;
- first = is_static(method) ? 0 : 1;
+ first = is_static(clazz, method) ? 0 : 1;
printf(" if ");
for (int i = first; i < num_params; ++i) {
@@ -372,8 +366,9 @@ void isl_class::print_method_overload(FunctionDecl *method,
* Otherwise, print an overloaded method with pieces corresponding
* to each function in "methods".
*/
-void isl_class::print_method(const string &fullname,
- const set<FunctionDecl *> &methods, vector<string> super)
+void python_generator::print_method(const isl_class &clazz,
+ const string &fullname, const set<FunctionDecl *> &methods,
+ vector<string> super)
{
string cname;
set<FunctionDecl *>::const_iterator it;
@@ -382,17 +377,17 @@ void isl_class::print_method(const string &fullname,
any_method = *methods.begin();
if (methods.size() == 1 && !is_overload(any_method)) {
- print_method(any_method, super);
+ print_method(clazz, any_method, super);
return;
}
- cname = fullname.substr(name.length() + 1);
+ cname = fullname.substr(clazz.name.length() + 1);
num_params = any_method->getNumParams();
- print_method_header(is_static(any_method), cname, num_params);
+ print_method_header(is_static(clazz, any_method), cname, num_params);
for (it = methods.begin(); it != methods.end(); ++it)
- print_method_overload(*it, super);
+ print_method_overload(clazz, *it, super);
}
/* Print part of the constructor for this isl_class.
@@ -404,10 +399,11 @@ void isl_class::print_method(const string &fullname,
* If the function consumes a reference, then we pass it a copy of
* the actual argument.
*/
-void isl_class::print_constructor(FunctionDecl *cons)
+void python_generator::print_constructor(const isl_class &clazz,
+ FunctionDecl *cons)
{
string fullname = cons->getName();
- string cname = fullname.substr(name.length() + 1);
+ string cname = fullname.substr(clazz.name.length() + 1);
int num_params = cons->getNumParams();
int drop_ctx = first_arg_is_isl_ctx(cons);
@@ -452,7 +448,8 @@ void isl_class::print_constructor(FunctionDecl *cons)
/* Print the header of the class "name" with superclasses "super".
*/
-static void print_class_header(const string &name, const vector<string> &super)
+void python_generator::print_class_header(const isl_class &clazz,
+ const string &name, const vector<string> &super)
{
printf("class %s", name.c_str());
if (super.size() > 0) {
@@ -474,7 +471,7 @@ static void print_class_header(const string &name, const vector<string> &super)
* then tell ctypes it returns a "c_bool".
* If "fd" returns a char *, then simply tell ctypes.
*/
-static void print_restype(FunctionDecl *fd)
+void python_generator::print_restype(FunctionDecl *fd)
{
string fullname = fd->getName();
QualType type = fd->getReturnType();
@@ -488,7 +485,7 @@ static void print_restype(FunctionDecl *fd)
/* Tell ctypes about the types of the arguments of the function "fd".
*/
-static void print_argtypes(FunctionDecl *fd)
+void python_generator::print_argtypes(FunctionDecl *fd)
{
string fullname = fd->getName();
int n = fd->getNumParams();
@@ -518,7 +515,7 @@ static void print_argtypes(FunctionDecl *fd)
/* Print type definitions for the method 'fd'.
*/
-void isl_class::print_method_type(FunctionDecl *fd)
+void python_generator::print_method_type(FunctionDecl *fd)
{
print_restype(fd);
print_argtypes(fd);
@@ -536,15 +533,16 @@ void isl_class::print_method_type(FunctionDecl *fd)
* Check the type of the argument before calling the *_to_str function
* on it in case the method was called on an object from a subclass.
*/
-void isl_class::print_representation(const string &python_name)
+void python_generator::print_representation(const isl_class &clazz,
+ const string &python_name)
{
- if (!fn_to_str)
+ if (!clazz.fn_to_str)
return;
printf(" def __str__(arg0):\n");
print_type_check(python_name, 0, false, "", "", -1);
printf(" ptr = isl.%s(arg0.ptr)\n",
- string(fn_to_str->getName()).c_str());
+ string(clazz.fn_to_str->getName()).c_str());
printf(" res = str(cast(ptr, c_char_p).value)\n");
printf(" libc.free(ptr)\n");
printf(" return res\n");
@@ -566,21 +564,22 @@ void isl_class::print_representation(const string &python_name)
* Assuming each exported class has a *_free method,
* also unconditionally set the type of such methods.
*/
-void isl_class::print_method_types()
+void python_generator::print_method_types(const isl_class &clazz)
{
- set<FunctionDecl *>::iterator in;
- map<string, set<FunctionDecl *> >::iterator it;
+ set<FunctionDecl *>::const_iterator in;
+ map<string, set<FunctionDecl *> >::const_iterator it;
- for (in = constructors.begin(); in != constructors.end(); ++in)
+ for (in = clazz.constructors.begin(); in != clazz.constructors.end();
+ ++in)
print_method_type(*in);
- for (it = methods.begin(); it != methods.end(); ++it)
+ for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
for (in = it->second.begin(); in != it->second.end(); ++in)
print_method_type(*in);
- print_method_type(fn_free);
- if (fn_to_str)
- print_method_type(fn_to_str);
+ print_method_type(clazz.fn_free);
+ if (clazz.fn_to_str)
+ print_method_type(clazz.fn_to_str);
}
/* Print out the definition of this isl_class.
@@ -599,20 +598,20 @@ void isl_class::print_method_types()
* constructor functions and the return types of those function returning
* an isl object.
*/
-void isl_class::print(map<string, isl_class> &classes, set<string> &done)
+void python_generator::print(const isl_class &clazz)
{
- string p_name = type2python(name);
- set<FunctionDecl *>::iterator in;
- map<string, set<FunctionDecl *> >::iterator it;
- vector<string> super = find_superclasses(type);
+ string p_name = type2python(
clazz.name);
+ set<FunctionDecl *>::const_iterator in;
+ map<string, set<FunctionDecl *> >::const_iterator it;
+ vector<string> super = find_superclasses(clazz.type);
for (unsigned i = 0; i < super.size(); ++i)
if (done.find(super[i]) == done.end())
- classes[super[i]].print(classes, done);
- done.insert(name);
+ print(classes[super[i]]);
+ done.insert(
clazz.name);
printf("\n");
- print_class_header(p_name, super);
+ print_class_header(clazz, p_name, super);
printf(" def __init__(self, *args, **keywords):\n");
printf(" if \"ptr\" in keywords:\n");
@@ -620,85 +619,37 @@ void isl_class::print(map<string, isl_class> &classes, set<string> &done)
printf(" self.ptr = keywords[\"ptr\"]\n");
printf(" return\n");
- for (in = constructors.begin(); in != constructors.end(); ++in)
- print_constructor(*in);
+ for (in = clazz.constructors.begin(); in != clazz.constructors.end();
+ ++in)
+ print_constructor(clazz, *in);
printf(" raise Error\n");
printf(" def __del__(self):\n");
printf(" if hasattr(self, 'ptr'):\n");
- printf(" isl.%s_free(self.ptr)\n", name.c_str());
+ printf(" isl.%s_free(self.ptr)\n", clazz.name.c_str());
- print_representation(p_name);
+ print_representation(clazz, p_name);
- for (it = methods.begin(); it != methods.end(); ++it)
- print_method(it->first, it->second, super);
+ for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
+ print_method(clazz, it->first, it->second, super);
printf("\n");
- print_method_types();
+ print_method_types(clazz);
}
-/* Generate a python interface based on the extracted types and functions.
- * We first collect all functions that belong to a certain type,
- * separating constructors from regular methods and keeping track
- * of the _to_str and _free functions, if any, separately. If there are any
- * overloaded functions, then they are grouped based on their name
- * after removing the argument type suffix.
+/* Generate a python interface based on the extracted types and
+ * functions.
*
- * Then we print out each class in turn. If one of these is a subclass
- * of some other class, it will make sure the superclass is printed out first.
+ * Print out each class in turn. If one of these is a subclass of some
+ * other class, make sure the superclass is printed out first.
+ * functions.
*/
-void generate_python(set<RecordDecl *> &exported_types,
- set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions)
+void python_generator::generate()
{
- map<string, isl_class> classes;
map<string, isl_class>::iterator ci;
- set<string> done;
- map<string, FunctionDecl *> functions_by_name;
-
- set<FunctionDecl *>::iterator in;
- for (in = functions.begin(); in != functions.end(); ++in) {
- FunctionDecl *decl = *in;
- functions_by_name[decl->getName()] = decl;
- }
-
- set<RecordDecl *>::iterator it;
- for (it = exported_types.begin(); it != exported_types.end(); ++it) {
- RecordDecl *decl = *it;
- map<string, FunctionDecl *>::iterator i;
-
- string name = decl->getName();
- classes[name].name = name;
- classes[name].type = decl;
- classes[name].fn_to_str = NULL;
- classes[name].fn_free = NULL;
-
- i = functions_by_name.find(name + "_to_str");
- if (i != functions_by_name.end())
- classes[name].fn_to_str = i->second;
-
- i = functions_by_name.find (name + "_free");
- if (i == functions_by_name.end())
- die("No _free function found");
- classes[name].fn_free = i->second;
- }
-
- for (in = exported_functions.begin(); in != exported_functions.end();
- ++in) {
- isl_class *c = method2class(classes, *in);
- if (!c)
- continue;
- if (is_constructor(*in)) {
- c->constructors.insert(*in);
- } else {
- FunctionDecl *method = *in;
- string fullname = method->getName();
- fullname = drop_type_suffix(fullname, method);
- c->methods[fullname].insert(method);
- }
- }
for (ci = classes.begin(); ci != classes.end(); ++ci) {
if (done.find(ci->first) == done.end())
- ci->second.print(classes, done);
+ print(ci->second);
}
}
diff --git a/interface/python.h b/interface/python.h
index 1706dd7..ea361b0 100644
--- a/interface/python.h
+++ b/interface/python.h
@@ -3,5 +3,40 @@
using namespace std;
using namespace clang;
-void generate_python(set<RecordDecl *> &exported_types,
- set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions);
+class python_generator : public generator {
+private:
+ set<string> done;
+
+public:
+ python_generator(set<RecordDecl *> &exported_types,
+ set<FunctionDecl *> exported_functions,
+ set<FunctionDecl *> functions);
+
+ virtual void generate() override;
+
+private:
+ void print(const isl_class &clazz);
+ void print_method_header(bool is_static, const string &name, int n_arg);
+ void print_class_header(const isl_class &clazz, const string &name,
+ const vector<string> &super);
+ void print_type_check(const string &type, int pos, bool upcast,
+ const string &super, const string &name, int n);
+ void print_callback(QualType type, int arg);
+ void print_arg_in_call(FunctionDecl *fd, int arg, int skip);
+ void print_argtypes(FunctionDecl *fd);
+ void print_method_return(FunctionDecl *method);
+ void print_restype(FunctionDecl *fd);
+ void print(map<string, isl_class> &classes, set<string> &done);
+ void print_constructor(const isl_class &clazz, FunctionDecl *method);
+ void print_representation(const isl_class &clazz,
+ const string &python_name);
+ void print_method_type(FunctionDecl *fd);
+ void print_method_types(const isl_class &clazz);
+ void print_method(const isl_class &clazz, FunctionDecl *method,
+ vector<string> super);
+ void print_method_overload(const isl_class &clazz,
+ FunctionDecl *method, vector<string> super);
+ void print_method(const isl_class &clazz, const string &fullname,
+ const set<FunctionDecl *> &methods, vector<string> super);
+
+};
--
2.7.4