bindings: drop "get_" prefix of methods that start this way
[isl.git] / interface / python.cc
bloba3e939056412e4bd539b9fbc6feb3f516a0557d6
1 /*
2 * Copyright 2011,2015 Sven Verdoolaege. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Sven Verdoolaege.
32 */
34 #include "isl_config.h"
36 #include <stdarg.h>
37 #include <stdio.h>
39 #include <iostream>
40 #include <map>
41 #include <vector>
43 #include "python.h"
44 #include "generator.h"
46 /* Drop the "isl_" initial part of the type name "name".
48 static string type2python(string name)
50 return name.substr(4);
53 /* Print the arguments of a method with "n_arg" arguments, starting at "first".
55 void python_generator::print_method_arguments(int first, int n_arg)
57 for (int i = first; i < n_arg; ++i) {
58 if (i > first)
59 printf(", ");
60 printf("arg%d", i);
64 /* Print the header of the method "name" with "n_arg" arguments.
65 * If "is_static" is set, then mark the python method as static.
67 * If the method is called "from", then rename it to "convert_from"
68 * because "from" is a python keyword.
70 void python_generator::print_method_header(bool is_static, const string &name,
71 int n_arg)
73 const char *s;
75 if (is_static)
76 printf(" @staticmethod\n");
78 s = name.c_str();
79 if (name == "from")
80 s = "convert_from";
82 printf(" def %s(", s);
83 print_method_arguments(0, n_arg);
84 printf("):\n");
87 /* Print a check that the argument in position "pos" is of type "type".
88 * If this fails and if "upcast" is set, then convert the first
89 * argument to "super" and call the method "name" on it, passing
90 * the remaining of the "n" arguments.
91 * If the check fails and "upcast" is not set, then simply raise
92 * an exception.
93 * If "upcast" is not set, then the "super", "name" and "n" arguments
94 * to this function are ignored.
96 void python_generator::print_type_check(const string &type, int pos,
97 bool upcast, const string &super, const string &name, int n)
99 printf(" try:\n");
100 printf(" if not arg%d.__class__ is %s:\n",
101 pos, type.c_str());
102 printf(" arg%d = %s(arg%d)\n",
103 pos, type.c_str(), pos);
104 printf(" except:\n");
105 if (upcast) {
106 printf(" return %s(arg0).%s(",
107 type2python(super).c_str(), name.c_str());
108 for (int i = 1; i < n; ++i) {
109 if (i != 1)
110 printf(", ");
111 printf("arg%d", i);
113 printf(")\n");
114 } else
115 printf(" raise\n");
118 /* For each of the "n" initial arguments of the function "method"
119 * that refer to an isl structure,
120 * including the object on which the method is called,
121 * check if the corresponding actual argument is of the right type.
122 * If not, try and convert it to the right type.
123 * If that doesn't work and if "super" contains at least one element,
124 * try and convert self to the type of the first superclass in "super" and
125 * call the corresponding method.
126 * If "first_is_ctx" is set, then the first argument is skipped.
128 void python_generator::print_type_checks(const string &cname,
129 FunctionDecl *method, bool first_is_ctx, int n,
130 const vector<string> &super)
132 for (int i = first_is_ctx; i < n; ++i) {
133 ParmVarDecl *param = method->getParamDecl(i);
134 string type;
136 if (!is_isl_type(param->getOriginalType()))
137 continue;
138 type = type2python(extract_type(param->getOriginalType()));
139 if (!first_is_ctx && i > 0 && super.size() > 0)
140 print_type_check(type, i - first_is_ctx, true, super[0],
141 cname, n);
142 else
143 print_type_check(type, i - first_is_ctx, false, "",
144 cname, -1);
148 /* Print a call to the *_copy function corresponding to "type".
150 void python_generator::print_copy(QualType type)
152 string type_s = extract_type(type);
154 printf("isl.%s_copy", type_s.c_str());
157 /* Construct a wrapper for callback argument "param" (at position "arg").
158 * Assign the wrapper to "cb". We assume here that a function call
159 * has at most one callback argument.
161 * The wrapper converts the arguments of the callback to python types,
162 * taking a copy if the C callback does not take its arguments.
163 * If any exception is thrown, the wrapper keeps track of it in exc_info[0]
164 * and returns a value indicating an error. Otherwise the wrapper
165 * returns a value indicating success.
166 * In case the C callback is expected to return an isl_stat,
167 * the error value is -1 and the success value is 0.
168 * In case the C callback is expected to return an isl_bool,
169 * the error value is -1 and the success value is 1 or 0 depending
170 * on the result of the Python callback.
171 * Otherwise, None is returned to indicate an error and
172 * a copy of the object in case of success.
174 void python_generator::print_callback(ParmVarDecl *param, int arg)
176 QualType type = param->getOriginalType();
177 const FunctionProtoType *fn = extract_prototype(type);
178 QualType return_type = fn->getReturnType();
179 unsigned n_arg = fn->getNumArgs();
181 printf(" exc_info = [None]\n");
182 printf(" fn = CFUNCTYPE(");
183 if (is_isl_stat(return_type) || is_isl_bool(return_type))
184 printf("c_int");
185 else
186 printf("c_void_p");
187 for (unsigned i = 0; i < n_arg - 1; ++i) {
188 if (!is_isl_type(fn->getArgType(i)))
189 die("Argument has non-isl type");
190 printf(", c_void_p");
192 printf(", c_void_p)\n");
193 printf(" def cb_func(");
194 for (unsigned i = 0; i < n_arg; ++i) {
195 if (i)
196 printf(", ");
197 printf("cb_arg%d", i);
199 printf("):\n");
200 for (unsigned i = 0; i < n_arg - 1; ++i) {
201 string arg_type;
202 arg_type = type2python(extract_type(fn->getArgType(i)));
203 printf(" cb_arg%d = %s(ctx=arg0.ctx, ptr=",
204 i, arg_type.c_str());
205 if (!callback_takes_argument(param, i))
206 print_copy(fn->getArgType(i));
207 printf("(cb_arg%d))\n", i);
209 printf(" try:\n");
210 if (is_isl_stat(return_type))
211 printf(" arg%d(", arg);
212 else
213 printf(" res = arg%d(", arg);
214 for (unsigned i = 0; i < n_arg - 1; ++i) {
215 if (i)
216 printf(", ");
217 printf("cb_arg%d", i);
219 printf(")\n");
220 printf(" except:\n");
221 printf(" import sys\n");
222 printf(" exc_info[0] = sys.exc_info()\n");
223 if (is_isl_stat(return_type) || is_isl_bool(return_type))
224 printf(" return -1\n");
225 else
226 printf(" return None\n");
227 if (is_isl_stat(return_type)) {
228 printf(" return 0\n");
229 } else if (is_isl_bool(return_type)) {
230 printf(" return 1 if res else 0\n");
231 } else {
232 printf(" return ");
233 print_copy(return_type);
234 printf("(res.ptr)\n");
236 printf(" cb = fn(cb_func)\n");
239 /* Print the argument at position "arg" in call to "fd".
240 * "skip" is the number of initial arguments of "fd" that are
241 * skipped in the Python method.
243 * If the argument is a callback, then print a reference to
244 * the callback wrapper "cb".
245 * Otherwise, if the argument is marked as consuming a reference,
246 * then pass a copy of the pointer stored in the corresponding
247 * argument passed to the Python method.
248 * Otherwise, if the argument is a pointer, then pass this pointer itself.
249 * Otherwise, pass the argument directly.
251 void python_generator::print_arg_in_call(FunctionDecl *fd, int arg, int skip)
253 ParmVarDecl *param = fd->getParamDecl(arg);
254 QualType type = param->getOriginalType();
255 if (is_callback(type)) {
256 printf("cb");
257 } else if (takes(param)) {
258 print_copy(type);
259 printf("(arg%d.ptr)", arg - skip);
260 } else if (type->isPointerType()) {
261 printf("arg%d.ptr", arg - skip);
262 } else {
263 printf("arg%d", arg - skip);
267 /* Print formatted output with the given indentation.
269 static void print_indent(int indent, const char *format, ...)
271 va_list args;
273 printf("%*s", indent, " ");
274 va_start(args, format);
275 vprintf(format, args);
276 va_end(args);
279 /* Generate code that raises the exception captured in "exc_info", if any,
280 * with the given indentation.
282 static void print_rethrow(int indent, const char *exc_info)
284 print_indent(indent, "if %s != None:\n", exc_info);
285 print_indent(indent, " raise (%s[0], %s[1], %s[2])\n",
286 exc_info, exc_info, exc_info);
289 /* Print code with the given indentation that checks
290 * whether any of the persistent callbacks of "clazz"
291 * is set and if it failed with an exception. If so, the 'exc_info'
292 * field contains the exception and is raised again.
293 * The field is cleared because the callback and its data may get reused.
295 static void print_persistent_callback_failure_check(int indent,
296 const isl_class &clazz)
298 const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
299 set<FunctionDecl *>::const_iterator in;
301 for (in = callbacks.begin(); in != callbacks.end(); ++in) {
302 string callback_name = clazz.persistent_callback_name(*in);
304 print_indent(indent, "if hasattr(arg0, '%s') and "
305 "arg0.%s['exc_info'] != None:\n",
306 callback_name.c_str(), callback_name.c_str());
307 print_indent(indent, " exc_info = arg0.%s['exc_info'][0]\n",
308 callback_name.c_str());
309 print_indent(indent, " arg0.%s['exc_info'][0] = None\n",
310 callback_name.c_str());
311 print_rethrow(indent + 4, "exc_info");
315 /* Print the return statement of the python method corresponding
316 * to the C function "method" with the given indentation.
317 * If the object on which the method was called
318 * may have a persistent callback, then first check if any of those failed.
320 * If the method returns a new instance of the same object type and
321 * if the class has any persistent callbacks, then the data
322 * for these callbacks are copied from the original to the new object.
323 * If the method it itself setting a persistent callback,
324 * then keep track of the constructed C callback (such that it doesn't
325 * get destroyed) and the data structure that holds the captured exception
326 * (such that it can be raised again).
328 * If the return type is a (const) char *, then convert the result
329 * to a Python string, raising an error on NULL and freeing
330 * the C string if needed. For python 3 compatibility, the string returned
331 * by isl is explicitly decoded as an 'ascii' string. This is correct
332 * as all strings returned by isl are expected to be 'ascii'.
334 * If the return type is isl_stat, isl_bool or isl_size, then
335 * raise an error on isl_stat_error, isl_bool_error or isl_size_error.
336 * In case of isl_bool, the result is converted to
337 * a Python boolean.
338 * In case of isl_size, the result is converted to a Python int.
340 void python_generator::print_method_return(int indent, const isl_class &clazz,
341 FunctionDecl *method)
343 QualType return_type = method->getReturnType();
345 if (!is_static(clazz, method))
346 print_persistent_callback_failure_check(indent, clazz);
348 if (is_isl_type(return_type)) {
349 string type;
351 type = type2python(extract_type(return_type));
352 print_indent(indent,
353 "obj = %s(ctx=ctx, ptr=res)\n", type.c_str());
354 if (is_mutator(clazz, method) &&
355 clazz.has_persistent_callbacks())
356 print_indent(indent, "obj.copy_callbacks(arg0)\n");
357 if (clazz.persistent_callbacks.count(method)) {
358 string callback_name;
360 callback_name = clazz.persistent_callback_name(method);
361 print_indent(indent, "obj.%s = { 'func': cb, "
362 "'exc_info': exc_info }\n",
363 callback_name.c_str());
365 print_indent(indent, "return obj\n");
366 } else if (is_string(return_type)) {
367 print_indent(indent, "if res == 0:\n");
368 print_indent(indent, " raise\n");
369 print_indent(indent, "string = "
370 "cast(res, c_char_p).value.decode('ascii')\n");
372 if (gives(method))
373 print_indent(indent, "libc.free(res)\n");
375 print_indent(indent, "return string\n");
376 } else if (is_isl_neg_error(return_type)) {
377 print_indent(indent, "if res < 0:\n");
378 print_indent(indent, " raise\n");
379 if (is_isl_bool(return_type))
380 print_indent(indent, "return bool(res)\n");
381 else if (is_isl_size(return_type))
382 print_indent(indent, "return int(res)\n");
383 } else {
384 print_indent(indent, "return res\n");
388 /* Print a python "get" method corresponding to the C function "fd"
389 * in class "clazz" using a name that includes the "get_" prefix.
391 * This method simply calls the variant without the "get_" prefix and
392 * returns its result.
393 * Note that static methods are not considered to be "get" methods.
395 void python_generator::print_get_method(const isl_class &clazz,
396 FunctionDecl *fd)
398 string get_name = clazz.base_method_name(fd);
399 string name = clazz.method_name(fd);
400 int num_params = fd->getNumParams();
402 print_method_header(false, get_name, num_params);
403 printf(" return arg0.%s(", name.c_str());
404 print_method_arguments(1, num_params);
405 printf(")\n");
408 /* Print a python method corresponding to the C function "method".
409 * "super" contains the superclasses of the class to which the method belongs,
410 * with the first element corresponding to the annotation that appears
411 * closest to the annotated type. This superclass is the least
412 * general extension of the annotated type in the linearization
413 * of the class hierarchy.
415 * If the first argument of "method" is something other than an instance
416 * of the class, then mark the python method as static.
417 * If, moreover, this first argument is an isl_ctx, then remove
418 * it from the arguments of the Python method.
420 * If the function has a callback argument, then it also has a "user"
421 * argument. Since Python has closures, there is no need for such
422 * a user argument in the Python interface, so we simply drop it.
423 * We also create a wrapper ("cb") for the callback.
425 * If the function consumes a reference, then we pass it a copy of
426 * the actual argument.
428 * For methods that are identified as "get" methods, also
429 * print a variant of the method using a name that includes
430 * the "get_" prefix.
432 void python_generator::print_method(const isl_class &clazz,
433 FunctionDecl *method, vector<string> super)
435 string fullname = method->getName();
436 string cname = clazz.method_name(method);
437 int num_params = method->getNumParams();
438 int drop_user = 0;
439 int drop_ctx = first_arg_is_isl_ctx(method);
441 for (int i = 1; i < num_params; ++i) {
442 ParmVarDecl *param = method->getParamDecl(i);
443 QualType type = param->getOriginalType();
444 if (is_callback(type))
445 drop_user = 1;
448 print_method_header(is_static(clazz, method), cname,
449 num_params - drop_ctx - drop_user);
451 print_type_checks(cname, method, drop_ctx,
452 num_params - drop_user, super);
453 for (int i = 1; i < num_params; ++i) {
454 ParmVarDecl *param = method->getParamDecl(i);
455 QualType type = param->getOriginalType();
456 if (!is_callback(type))
457 continue;
458 print_callback(param, i - drop_ctx);
460 if (drop_ctx)
461 printf(" ctx = Context.getDefaultInstance()\n");
462 else
463 printf(" ctx = arg0.ctx\n");
464 printf(" res = isl.%s(", fullname.c_str());
465 if (drop_ctx)
466 printf("ctx");
467 else
468 print_arg_in_call(method, 0, 0);
469 for (int i = 1; i < num_params - drop_user; ++i) {
470 printf(", ");
471 print_arg_in_call(method, i, drop_ctx);
473 if (drop_user)
474 printf(", None");
475 printf(")\n");
477 if (drop_user)
478 print_rethrow(8, "exc_info[0]");
480 print_method_return(8, clazz, method);
482 if (clazz.is_get_method(method))
483 print_get_method(clazz, method);
486 /* Print part of an overloaded python method corresponding to the C function
487 * "method".
489 * In particular, print code to test whether the arguments passed to
490 * the python method correspond to the arguments expected by "method"
491 * and to call "method" if they do.
493 void python_generator::print_method_overload(const isl_class &clazz,
494 FunctionDecl *method)
496 string fullname = method->getName();
497 int num_params = method->getNumParams();
498 int first;
500 first = is_static(clazz, method) ? 0 : 1;
502 printf(" if ");
503 for (int i = first; i < num_params; ++i) {
504 if (i > first)
505 printf(" and ");
506 ParmVarDecl *param = method->getParamDecl(i);
507 if (is_isl_type(param->getOriginalType())) {
508 string type;
509 type = extract_type(param->getOriginalType());
510 type = type2python(type);
511 printf("arg%d.__class__ is %s", i, type.c_str());
512 } else
513 printf("type(arg%d) == str", i);
515 printf(":\n");
516 printf(" res = isl.%s(", fullname.c_str());
517 print_arg_in_call(method, 0, 0);
518 for (int i = 1; i < num_params; ++i) {
519 printf(", ");
520 print_arg_in_call(method, i, 0);
522 printf(")\n");
523 printf(" ctx = arg0.ctx\n");
524 print_method_return(12, clazz, method);
527 /* Print a python method with a name derived from "fullname"
528 * corresponding to the C functions "methods".
529 * "super" contains the superclasses of the class to which the method belongs.
531 * If "methods" consists of a single element that is not marked overloaded,
532 * the use print_method to print the method.
533 * Otherwise, print an overloaded method with pieces corresponding
534 * to each function in "methods".
536 void python_generator::print_method(const isl_class &clazz,
537 const string &fullname, const set<FunctionDecl *> &methods,
538 vector<string> super)
540 string cname;
541 set<FunctionDecl *>::const_iterator it;
542 int num_params;
543 FunctionDecl *any_method;
545 any_method = *methods.begin();
546 if (methods.size() == 1 && !is_overload(any_method)) {
547 print_method(clazz, any_method, super);
548 return;
551 cname = clazz.method_name(any_method);
552 num_params = any_method->getNumParams();
554 print_method_header(is_static(clazz, any_method), cname, num_params);
556 for (it = methods.begin(); it != methods.end(); ++it)
557 print_method_overload(clazz, *it);
560 /* Print a python method "name" corresponding to "fd" setting
561 * the enum value "value".
562 * "super" contains the superclasses of the class to which the method belongs,
563 * with the first element corresponding to the annotation that appears
564 * closest to the annotated type.
566 * The last argument of the C function does not appear in the method call,
567 * but is fixed to "value" instead.
568 * Other than that, the method printed here is similar to one
569 * printed by python_generator::print_method, except that
570 * some of the special cases do not occur.
572 void python_generator::print_set_enum(const isl_class &clazz,
573 FunctionDecl *fd, int value, const string &name,
574 const vector<string> &super)
576 string fullname = fd->getName();
577 int num_params = fd->getNumParams();
579 print_method_header(is_static(clazz, fd), name, num_params - 1);
581 print_type_checks(name, fd, false, num_params - 1, super);
582 printf(" ctx = arg0.ctx\n");
583 printf(" res = isl.%s(", fullname.c_str());
584 for (int i = 0; i < num_params - 1; ++i) {
585 if (i)
586 printf(", ");
587 print_arg_in_call(fd, i, 0);
589 printf(", %d", value);
590 printf(")\n");
591 print_method_return(8, clazz, fd);
594 /* Print python methods corresponding to "fd", which sets an enum.
595 * "super" contains the superclasses of the class to which the method belongs,
596 * with the first element corresponding to the annotation that appears
597 * closest to the annotated type.
599 * A method is generated for each value in the enum, setting
600 * the enum to that value.
602 void python_generator::print_set_enum(const isl_class &clazz,
603 FunctionDecl *fd, const vector<string> &super)
605 vector<set_enum>::const_iterator it;
606 const vector<set_enum> &set_enums = clazz.set_enums.at(fd);
608 for (it = set_enums.begin(); it != set_enums.end(); ++it)
609 print_set_enum(clazz, fd, it->value, it->method_name, super);
612 /* Print part of the constructor for this isl_class.
614 * In particular, check if the actual arguments correspond to the
615 * formal arguments of "cons" and if so call "cons" and put the
616 * result in self.ptr and a reference to the default context in self.ctx.
618 * If the function consumes a reference, then we pass it a copy of
619 * the actual argument.
621 * If the function takes a string argument, the python string is first
622 * encoded as a byte sequence, using 'ascii' as encoding. This assumes
623 * that all strings passed to isl can be converted to 'ascii'.
625 void python_generator::print_constructor(const isl_class &clazz,
626 FunctionDecl *cons)
628 string fullname = cons->getName();
629 string cname = clazz.method_name(cons);
630 int num_params = cons->getNumParams();
631 int drop_ctx = first_arg_is_isl_ctx(cons);
633 printf(" if len(args) == %d", num_params - drop_ctx);
634 for (int i = drop_ctx; i < num_params; ++i) {
635 ParmVarDecl *param = cons->getParamDecl(i);
636 QualType type = param->getOriginalType();
637 if (is_isl_type(type)) {
638 string s;
639 s = type2python(extract_type(type));
640 printf(" and args[%d].__class__ is %s",
641 i - drop_ctx, s.c_str());
642 } else if (type->isPointerType()) {
643 printf(" and type(args[%d]) == str", i - drop_ctx);
644 } else {
645 printf(" and type(args[%d]) == int", i - drop_ctx);
648 printf(":\n");
649 printf(" self.ctx = Context.getDefaultInstance()\n");
650 printf(" self.ptr = isl.%s(", fullname.c_str());
651 if (drop_ctx)
652 printf("self.ctx");
653 for (int i = drop_ctx; i < num_params; ++i) {
654 ParmVarDecl *param = cons->getParamDecl(i);
655 QualType type = param->getOriginalType();
656 if (i)
657 printf(", ");
658 if (is_isl_type(type)) {
659 if (takes(param))
660 print_copy(param->getOriginalType());
661 printf("(args[%d].ptr)", i - drop_ctx);
662 } else if (is_string(type)) {
663 printf("args[%d].encode('ascii')", i - drop_ctx);
664 } else {
665 printf("args[%d]", i - drop_ctx);
668 printf(")\n");
669 printf(" return\n");
672 /* If "clazz" has a type function describing subclasses,
673 * then add constructors that allow each of these subclasses
674 * to be treated as an object to the superclass.
676 void python_generator::print_upcast_constructors(const isl_class &clazz)
678 map<int, string>::const_iterator i;
680 if (!clazz.fn_type)
681 return;
683 for (i = clazz.type_subclasses.begin();
684 i != clazz.type_subclasses.end(); ++i) {
685 printf(" if len(args) == 1 and "
686 "isinstance(args[0], %s):\n",
687 type2python(i->second).c_str());
688 printf(" self.ctx = args[0].ctx\n");
689 printf(" self.ptr = isl.%s_copy(args[0].ptr)\n",
690 clazz.name.c_str());
691 printf(" return\n");
695 /* Print the header of the class "name" with superclasses "super".
696 * The order of the superclasses is the opposite of the order
697 * in which the corresponding annotations appear in the source code.
698 * If "clazz" is a subclass derived from a type function,
699 * then the immediate superclass is recorded in "clazz" itself.
701 void python_generator::print_class_header(const isl_class &clazz,
702 const string &name, const vector<string> &super)
704 printf("class %s", name.c_str());
705 if (super.size() > 0) {
706 printf("(");
707 for (unsigned i = 0; i < super.size(); ++i) {
708 if (i > 0)
709 printf(", ");
710 printf("%s", type2python(super[i]).c_str());
712 printf(")");
713 } else if (clazz.is_type_subclass()) {
714 printf("(%s)", type2python(clazz.superclass_name).c_str());
715 } else {
716 printf("(object)");
718 printf(":\n");
721 /* Tell ctypes about the return type of "fd".
722 * In particular, if "fd" returns a pointer to an isl object,
723 * then tell ctypes it returns a "c_void_p".
724 * If "fd" returns a char *, then simply tell ctypes.
726 * Nothing needs to be done for functions returning
727 * isl_bool, isl_stat or isl_size since they are represented by an int and
728 * ctypes assumes that a function returns int by default.
730 void python_generator::print_restype(FunctionDecl *fd)
732 string fullname = fd->getName();
733 QualType type = fd->getReturnType();
734 if (is_isl_type(type))
735 printf("isl.%s.restype = c_void_p\n", fullname.c_str());
736 else if (is_string(type))
737 printf("isl.%s.restype = POINTER(c_char)\n", fullname.c_str());
740 /* Tell ctypes about the types of the arguments of the function "fd".
742 void python_generator::print_argtypes(FunctionDecl *fd)
744 string fullname = fd->getName();
745 int n = fd->getNumParams();
746 int drop_user = 0;
748 printf("isl.%s.argtypes = [", fullname.c_str());
749 for (int i = 0; i < n - drop_user; ++i) {
750 ParmVarDecl *param = fd->getParamDecl(i);
751 QualType type = param->getOriginalType();
752 if (is_callback(type))
753 drop_user = 1;
754 if (i)
755 printf(", ");
756 if (is_isl_ctx(type))
757 printf("Context");
758 else if (is_isl_type(type) || is_callback(type))
759 printf("c_void_p");
760 else if (is_string(type))
761 printf("c_char_p");
762 else if (is_long(type))
763 printf("c_long");
764 else
765 printf("c_int");
767 if (drop_user)
768 printf(", c_void_p");
769 printf("]\n");
772 /* Print type definitions for the method 'fd'.
774 void python_generator::print_method_type(FunctionDecl *fd)
776 print_restype(fd);
777 print_argtypes(fd);
780 /* If "clazz" has a type function describing subclasses or
781 * if it is one of those type subclasses, then print a __new__ method.
783 * In the superclass, the __new__ method constructs an object
784 * of the subclass type specified by the type function.
785 * In the subclass, the __new__ method reverts to the original behavior.
787 void python_generator::print_new(const isl_class &clazz,
788 const string &python_name)
790 if (!clazz.fn_type && !clazz.is_type_subclass())
791 return;
793 printf(" def __new__(cls, *args, **keywords):\n");
795 if (clazz.fn_type) {
796 map<int, string>::const_iterator i;
798 printf(" if \"ptr\" in keywords:\n");
799 printf(" type = isl.%s(keywords[\"ptr\"])\n",
800 clazz.fn_type->getNameAsString().c_str());
802 for (i = clazz.type_subclasses.begin();
803 i != clazz.type_subclasses.end(); ++i) {
804 printf(" if type == %d:\n", i->first);
805 printf(" return %s(**keywords)\n",
806 type2python(i->second).c_str());
808 printf(" raise\n");
811 printf(" return super(%s, cls).__new__(cls)\n",
812 python_name.c_str());
815 /* Print declarations for methods printing the class representation,
816 * provided there is a corresponding *_to_str function.
818 * In particular, provide an implementation of __str__ and __repr__ methods to
819 * override the default representation used by python. Python uses __str__ to
820 * pretty print the class (e.g., when calling print(obj)) and uses __repr__
821 * when printing a precise representation of an object (e.g., when dumping it
822 * in the REPL console).
824 * Check the type of the argument before calling the *_to_str function
825 * on it in case the method was called on an object from a subclass.
827 * The return value of the *_to_str function is decoded to a python string
828 * assuming an 'ascii' encoding. This is necessary for python 3 compatibility.
830 void python_generator::print_representation(const isl_class &clazz,
831 const string &python_name)
833 if (!clazz.fn_to_str)
834 return;
836 printf(" def __str__(arg0):\n");
837 print_type_check(python_name, 0, false, "", "", -1);
838 printf(" ptr = isl.%s(arg0.ptr)\n",
839 string(clazz.fn_to_str->getName()).c_str());
840 printf(" res = cast(ptr, c_char_p).value.decode('ascii')\n");
841 printf(" libc.free(ptr)\n");
842 printf(" return res\n");
843 printf(" def __repr__(self):\n");
844 printf(" s = str(self)\n");
845 printf(" if '\"' in s:\n");
846 printf(" return 'isl.%s(\"\"\"%%s\"\"\")' %% s\n",
847 python_name.c_str());
848 printf(" else:\n");
849 printf(" return 'isl.%s(\"%%s\")' %% s\n",
850 python_name.c_str());
853 /* If "clazz" has any persistent callbacks, then print the definition
854 * of a "copy_callbacks" function that copies the persistent callbacks
855 * from one object to another.
857 void python_generator::print_copy_callbacks(const isl_class &clazz)
859 const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
860 set<FunctionDecl *>::const_iterator in;
862 if (!clazz.has_persistent_callbacks())
863 return;
865 printf(" def copy_callbacks(self, obj):\n");
866 for (in = callbacks.begin(); in != callbacks.end(); ++in) {
867 string callback_name = clazz.persistent_callback_name(*in);
869 printf(" if hasattr(obj, '%s'):\n",
870 callback_name.c_str());
871 printf(" self.%s = obj.%s\n",
872 callback_name.c_str(), callback_name.c_str());
876 /* Print code to set method type signatures.
878 * To be able to call C functions it is necessary to explicitly set their
879 * argument and result types. Do this for all exported constructors and
880 * methods (including those that set a persistent callback and
881 * those that set an enum value),
882 * as well as for the *_to_str and the type function, if they exist.
883 * Assuming each exported class has a *_copy and a *_free method,
884 * also unconditionally set the type of such methods.
886 void python_generator::print_method_types(const isl_class &clazz)
888 set<FunctionDecl *>::const_iterator in;
889 map<string, set<FunctionDecl *> >::const_iterator it;
890 map<FunctionDecl *, vector<set_enum> >::const_iterator ie;
891 const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
893 for (in = clazz.constructors.begin(); in != clazz.constructors.end();
894 ++in)
895 print_method_type(*in);
897 for (in = callbacks.begin(); in != callbacks.end(); ++in)
898 print_method_type(*in);
899 for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
900 for (in = it->second.begin(); in != it->second.end(); ++in)
901 print_method_type(*in);
902 for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie)
903 print_method_type(ie->first);
905 print_method_type(clazz.fn_copy);
906 print_method_type(clazz.fn_free);
907 if (clazz.fn_to_str)
908 print_method_type(clazz.fn_to_str);
909 if (clazz.fn_type)
910 print_method_type(clazz.fn_type);
913 /* Print out the definition of this isl_class.
915 * We first check if this isl_class is a subclass of one or more other classes.
916 * If it is, we make sure those superclasses are printed out first.
918 * Then we print a constructor with several cases, one for constructing
919 * a Python object from a return value, one for each function that
920 * was marked as a constructor and for each type based subclass.
922 * Next, we print out some common methods and the methods corresponding
923 * to functions that are not marked as constructors, including those
924 * that set a persistent callback and those that set an enum value.
926 * Finally, we tell ctypes about the types of the arguments of the
927 * constructor functions and the return types of those function returning
928 * an isl object.
930 void python_generator::print(const isl_class &clazz)
932 string p_name = type2python(clazz.subclass_name);
933 set<FunctionDecl *>::const_iterator in;
934 map<string, set<FunctionDecl *> >::const_iterator it;
935 map<FunctionDecl *, vector<set_enum> >::const_iterator ie;
936 vector<string> super = find_superclasses(clazz.type);
937 const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
939 for (unsigned i = 0; i < super.size(); ++i)
940 if (done.find(super[i]) == done.end())
941 print(classes[super[i]]);
942 if (clazz.is_type_subclass() && done.find(clazz.name) == done.end())
943 print(classes[clazz.name]);
944 done.insert(clazz.subclass_name);
946 printf("\n");
947 print_class_header(clazz, p_name, super);
948 printf(" def __init__(self, *args, **keywords):\n");
950 printf(" if \"ptr\" in keywords:\n");
951 printf(" self.ctx = keywords[\"ctx\"]\n");
952 printf(" self.ptr = keywords[\"ptr\"]\n");
953 printf(" return\n");
955 for (in = clazz.constructors.begin(); in != clazz.constructors.end();
956 ++in)
957 print_constructor(clazz, *in);
958 print_upcast_constructors(clazz);
959 printf(" raise Error\n");
960 printf(" def __del__(self):\n");
961 printf(" if hasattr(self, 'ptr'):\n");
962 printf(" isl.%s_free(self.ptr)\n", clazz.name.c_str());
964 print_new(clazz, p_name);
965 print_representation(clazz, p_name);
966 print_copy_callbacks(clazz);
968 for (in = callbacks.begin(); in != callbacks.end(); ++in)
969 print_method(clazz, *in, super);
970 for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
971 print_method(clazz, it->first, it->second, super);
972 for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie)
973 print_set_enum(clazz, ie->first, super);
975 printf("\n");
977 print_method_types(clazz);
980 /* Generate a python interface based on the extracted types and
981 * functions.
983 * Print out each class in turn. If one of these is a subclass of some
984 * other class, make sure the superclass is printed out first.
985 * functions.
987 void python_generator::generate()
989 map<string, isl_class>::iterator ci;
991 for (ci = classes.begin(); ci != classes.end(); ++ci) {
992 if (done.find(ci->first) == done.end())
993 print(ci->second);