2 * Copyright 2011,2015 Sven Verdoolaege. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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
34 #include "isl_config.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
) {
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
,
76 printf(" @staticmethod\n");
82 printf(" def %s(", s
);
83 print_method_arguments(0, n_arg
);
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
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
)
100 printf(" if not arg%d.__class__ is %s:\n",
102 printf(" arg%d = %s(arg%d)\n",
103 pos
, type
.c_str(), pos
);
104 printf(" except:\n");
106 printf(" return %s(arg0).%s(",
107 type2python(super
).c_str(), name
.c_str());
108 for (int i
= 1; i
< n
; ++i
) {
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
);
136 if (!is_isl_type(param
->getOriginalType()))
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],
143 print_type_check(type
, i
- first_is_ctx
, false, "",
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
))
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
) {
197 printf("cb_arg%d", i
);
200 for (unsigned i
= 0; i
< n_arg
- 1; ++i
) {
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
);
210 if (is_isl_stat(return_type
))
211 printf(" arg%d(", arg
);
213 printf(" res = arg%d(", arg
);
214 for (unsigned i
= 0; i
< n_arg
- 1; ++i
) {
217 printf("cb_arg%d", i
);
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");
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");
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
)) {
257 } else if (takes(param
)) {
259 printf("(arg%d.ptr)", arg
- skip
);
260 } else if (type
->isPointerType()) {
261 printf("arg%d.ptr", arg
- skip
);
263 printf("arg%d", arg
- skip
);
267 /* Print formatted output with the given indentation.
269 static void print_indent(int indent
, const char *format
, ...)
273 printf("%*s", indent
, " ");
274 va_start(args
, format
);
275 vprintf(format
, 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
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
)) {
351 type
= type2python(extract_type(return_type
));
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");
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");
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
,
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
);
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
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();
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
))
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
))
458 print_callback(param
, i
- drop_ctx
);
461 printf(" ctx = Context.getDefaultInstance()\n");
463 printf(" ctx = arg0.ctx\n");
464 printf(" res = isl.%s(", fullname
.c_str());
468 print_arg_in_call(method
, 0, 0);
469 for (int i
= 1; i
< num_params
- drop_user
; ++i
) {
471 print_arg_in_call(method
, i
, drop_ctx
);
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
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();
500 first
= is_static(clazz
, method
) ? 0 : 1;
503 for (int i
= first
; i
< num_params
; ++i
) {
506 ParmVarDecl
*param
= method
->getParamDecl(i
);
507 if (is_isl_type(param
->getOriginalType())) {
509 type
= extract_type(param
->getOriginalType());
510 type
= type2python(type
);
511 printf("arg%d.__class__ is %s", i
, type
.c_str());
513 printf("type(arg%d) == str", i
);
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
) {
520 print_arg_in_call(method
, i
, 0);
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
)
541 set
<FunctionDecl
*>::const_iterator it
;
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
);
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
) {
587 print_arg_in_call(fd
, i
, 0);
589 printf(", %d", value
);
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
,
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
)) {
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
);
645 printf(" and type(args[%d]) == int", i
- drop_ctx
);
649 printf(" self.ctx = Context.getDefaultInstance()\n");
650 printf(" self.ptr = isl.%s(", fullname
.c_str());
653 for (int i
= drop_ctx
; i
< num_params
; ++i
) {
654 ParmVarDecl
*param
= cons
->getParamDecl(i
);
655 QualType type
= param
->getOriginalType();
658 if (is_isl_type(type
)) {
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
);
665 printf("args[%d]", i
- drop_ctx
);
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
;
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",
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) {
707 for (unsigned i
= 0; i
< super
.size(); ++i
) {
710 printf("%s", type2python(super
[i
]).c_str());
713 } else if (clazz
.is_type_subclass()) {
714 printf("(%s)", type2python(clazz
.superclass_name
).c_str());
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();
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
))
756 if (is_isl_ctx(type
))
758 else if (is_isl_type(type
) || is_callback(type
))
760 else if (is_string(type
))
762 else if (is_long(type
))
768 printf(", c_void_p");
772 /* Print type definitions for the method 'fd'.
774 void python_generator::print_method_type(FunctionDecl
*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())
793 printf(" def __new__(cls, *args, **keywords):\n");
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());
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
)
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());
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())
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();
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
);
908 print_method_type(clazz
.fn_to_str
);
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
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
);
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");
955 for (in
= clazz
.constructors
.begin(); in
!= clazz
.constructors
.end();
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
);
977 print_method_types(clazz
);
980 /* Generate a python interface based on the extracted types and
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.
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())