1 1.1 mrg /* 2 1.1 mrg * Copyright 2011,2015 Sven Verdoolaege. All rights reserved. 3 1.1 mrg * 4 1.1 mrg * Redistribution and use in source and binary forms, with or without 5 1.1 mrg * modification, are permitted provided that the following conditions 6 1.1 mrg * are met: 7 1.1 mrg * 8 1.1 mrg * 1. Redistributions of source code must retain the above copyright 9 1.1 mrg * notice, this list of conditions and the following disclaimer. 10 1.1 mrg * 11 1.1 mrg * 2. Redistributions in binary form must reproduce the above 12 1.1 mrg * copyright notice, this list of conditions and the following 13 1.1 mrg * disclaimer in the documentation and/or other materials provided 14 1.1 mrg * with the distribution. 15 1.1 mrg * 16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY 17 1.1 mrg * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 mrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 mrg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR 20 1.1 mrg * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 1.1 mrg * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 1.1 mrg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 23 1.1 mrg * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.1 mrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.1 mrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 1.1 mrg * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 mrg * 28 1.1 mrg * The views and conclusions contained in the software and documentation 29 1.1 mrg * are those of the authors and should not be interpreted as 30 1.1 mrg * representing official policies, either expressed or implied, of 31 1.1 mrg * Sven Verdoolaege. 32 1.1 mrg */ 33 1.1 mrg 34 1.1 mrg #include "isl_config.h" 35 1.1 mrg 36 1.1 mrg #include <stdarg.h> 37 1.1 mrg #include <stdio.h> 38 1.1 mrg 39 1.1 mrg #include <algorithm> 40 1.1 mrg #include <iostream> 41 1.1 mrg #include <map> 42 1.1 mrg #include <vector> 43 1.1 mrg 44 1.1 mrg #include "python.h" 45 1.1 mrg #include "generator.h" 46 1.1 mrg 47 1.1 mrg /* Argument format for Python methods with a fixed number of arguments. 48 1.1 mrg */ 49 1.1 mrg static const char *fixed_arg_fmt = "arg%d"; 50 1.1 mrg /* Argument format for Python methods with a variable number of arguments. 51 1.1 mrg */ 52 1.1 mrg static const char *var_arg_fmt = "args[%d]"; 53 1.1 mrg 54 1.1 mrg /* Drop the "isl_" initial part of the type name "name". 55 1.1 mrg */ 56 1.1 mrg static string type2python(string name) 57 1.1 mrg { 58 1.1 mrg return name.substr(4); 59 1.1 mrg } 60 1.1 mrg 61 1.1 mrg /* Print the arguments of a method with "n_arg" arguments, starting at "first". 62 1.1 mrg */ 63 1.1 mrg void python_generator::print_method_arguments(int first, int n_arg) 64 1.1 mrg { 65 1.1 mrg for (int i = first; i < n_arg; ++i) { 66 1.1 mrg if (i > first) 67 1.1 mrg printf(", "); 68 1.1 mrg printf("arg%d", i); 69 1.1 mrg } 70 1.1 mrg } 71 1.1 mrg 72 1.1 mrg /* Print the start of a definition for method "name" 73 1.1 mrg * (without specifying the arguments). 74 1.1 mrg * If "is_static" is set, then mark the python method as static. 75 1.1 mrg * 76 1.1 mrg * If the method is called "from", then rename it to "convert_from" 77 1.1 mrg * because "from" is a python keyword. 78 1.1 mrg */ 79 1.1 mrg static void print_method_def(bool is_static, const string &name) 80 1.1 mrg { 81 1.1 mrg const char *s; 82 1.1 mrg 83 1.1 mrg if (is_static) 84 1.1 mrg printf(" @staticmethod\n"); 85 1.1 mrg 86 1.1 mrg s = name.c_str(); 87 1.1 mrg if (name == "from") 88 1.1 mrg s = "convert_from"; 89 1.1 mrg 90 1.1 mrg printf(" def %s", s); 91 1.1 mrg } 92 1.1 mrg 93 1.1 mrg /* Print the header of the method "name" with "n_arg" arguments. 94 1.1 mrg * If "is_static" is set, then mark the python method as static. 95 1.1 mrg */ 96 1.1 mrg void python_generator::print_method_header(bool is_static, const string &name, 97 1.1 mrg int n_arg) 98 1.1 mrg { 99 1.1 mrg print_method_def(is_static, name); 100 1.1 mrg printf("("); 101 1.1 mrg print_method_arguments(0, n_arg); 102 1.1 mrg printf("):\n"); 103 1.1 mrg } 104 1.1 mrg 105 1.1 mrg /* Print formatted output with the given indentation. 106 1.1 mrg */ 107 1.1 mrg static void print_indent(int indent, const char *format, ...) 108 1.1 mrg { 109 1.1 mrg va_list args; 110 1.1 mrg 111 1.1 mrg printf("%*s", indent, " "); 112 1.1 mrg va_start(args, format); 113 1.1 mrg vprintf(format, args); 114 1.1 mrg va_end(args); 115 1.1 mrg } 116 1.1 mrg 117 1.1 mrg /* Print a check that the argument in position "pos" is of type "type" 118 1.1 mrg * with the given indentation. 119 1.1 mrg * If this fails and if "upcast" is set, then convert the first 120 1.1 mrg * argument to "super" and call the method "name" on it, passing 121 1.1 mrg * the remaining of the "n" arguments. 122 1.1 mrg * If the check fails and "upcast" is not set, then simply raise 123 1.1 mrg * an exception. 124 1.1 mrg * If "upcast" is not set, then the "super", "name" and "n" arguments 125 1.1 mrg * to this function are ignored. 126 1.1 mrg * "fmt" is the format for printing Python method arguments. 127 1.1 mrg */ 128 1.1 mrg void python_generator::print_type_check(int indent, const string &type, 129 1.1 mrg const char *fmt, int pos, bool upcast, const string &super, 130 1.1 mrg const string &name, int n) 131 1.1 mrg { 132 1.1 mrg print_indent(indent, "try:\n"); 133 1.1 mrg print_indent(indent, " if not "); 134 1.1 mrg printf(fmt, pos); 135 1.1 mrg printf(".__class__ is %s:\n", type.c_str()); 136 1.1 mrg print_indent(indent, " "); 137 1.1 mrg printf(fmt, pos); 138 1.1 mrg printf(" = %s(", type.c_str()); 139 1.1 mrg printf(fmt, pos); 140 1.1 mrg printf(")\n"); 141 1.1 mrg print_indent(indent, "except:\n"); 142 1.1 mrg if (upcast) { 143 1.1 mrg print_indent(indent, " return %s(", 144 1.1 mrg type2python(super).c_str()); 145 1.1 mrg printf(fmt, 0); 146 1.1 mrg printf(").%s(", name.c_str()); 147 1.1 mrg for (int i = 1; i < n; ++i) { 148 1.1 mrg if (i != 1) 149 1.1 mrg printf(", "); 150 1.1 mrg printf(fmt, i); 151 1.1 mrg } 152 1.1 mrg printf(")\n"); 153 1.1 mrg } else 154 1.1 mrg print_indent(indent, " raise\n"); 155 1.1 mrg } 156 1.1 mrg 157 1.1 mrg /* For each of the "n" initial arguments of the function "method" 158 1.1 mrg * that refer to an isl structure, 159 1.1 mrg * including the object on which the method is called, 160 1.1 mrg * check if the corresponding actual argument is of the right type. 161 1.1 mrg * If not, try and convert it to the right type. 162 1.1 mrg * If that doesn't work and if "super" contains at least one element, 163 1.1 mrg * try and convert self to the type of the first superclass in "super" and 164 1.1 mrg * call the corresponding method. 165 1.1 mrg * If "first_is_ctx" is set, then the first argument is skipped. 166 1.1 mrg */ 167 1.1 mrg void python_generator::print_type_checks(const string &cname, 168 1.1 mrg FunctionDecl *method, bool first_is_ctx, int n, 169 1.1 mrg const vector<string> &super) 170 1.1 mrg { 171 1.1 mrg for (int i = first_is_ctx; i < n; ++i) { 172 1.1 mrg ParmVarDecl *param = method->getParamDecl(i); 173 1.1 mrg string type; 174 1.1 mrg 175 1.1 mrg if (!is_isl_type(param->getOriginalType())) 176 1.1 mrg continue; 177 1.1 mrg type = type2python(extract_type(param->getOriginalType())); 178 1.1 mrg if (!first_is_ctx && i > 0 && super.size() > 0) 179 1.1 mrg print_type_check(8, type, fixed_arg_fmt, 180 1.1 mrg i - first_is_ctx, true, 181 1.1 mrg super[0], cname, n); 182 1.1 mrg else 183 1.1 mrg print_type_check(8, type, fixed_arg_fmt, 184 1.1 mrg i - first_is_ctx, false, "", cname, -1); 185 1.1 mrg } 186 1.1 mrg } 187 1.1 mrg 188 1.1 mrg /* Print a call to the *_copy function corresponding to "type". 189 1.1 mrg */ 190 1.1 mrg void python_generator::print_copy(QualType type) 191 1.1 mrg { 192 1.1 mrg string type_s = extract_type(type); 193 1.1 mrg 194 1.1 mrg printf("isl.%s_copy", type_s.c_str()); 195 1.1 mrg } 196 1.1 mrg 197 1.1 mrg /* Construct a wrapper for callback argument "param" (at position "arg"). 198 1.1 mrg * Assign the wrapper to "cb{arg}". 199 1.1 mrg * 200 1.1 mrg * The wrapper converts the arguments of the callback to python types, 201 1.1 mrg * taking a copy if the C callback does not take its arguments. 202 1.1 mrg * If any exception is thrown, the wrapper keeps track of it in exc_info[0] 203 1.1 mrg * and returns a value indicating an error. Otherwise the wrapper 204 1.1 mrg * returns a value indicating success. 205 1.1 mrg * In case the C callback is expected to return an isl_stat, 206 1.1 mrg * the error value is -1 and the success value is 0. 207 1.1 mrg * In case the C callback is expected to return an isl_bool, 208 1.1 mrg * the error value is -1 and the success value is 1 or 0 depending 209 1.1 mrg * on the result of the Python callback. 210 1.1 mrg * Otherwise, None is returned to indicate an error and 211 1.1 mrg * a copy of the object in case of success. 212 1.1 mrg */ 213 1.1 mrg void python_generator::print_callback(ParmVarDecl *param, int arg) 214 1.1 mrg { 215 1.1 mrg QualType type = param->getOriginalType(); 216 1.1 mrg const FunctionProtoType *fn = extract_prototype(type); 217 1.1 mrg QualType return_type = fn->getReturnType(); 218 1.1 mrg unsigned n_arg = fn->getNumArgs(); 219 1.1 mrg 220 1.1 mrg printf(" exc_info = [None]\n"); 221 1.1 mrg printf(" fn = CFUNCTYPE("); 222 1.1 mrg if (is_isl_stat(return_type) || is_isl_bool(return_type)) 223 1.1 mrg printf("c_int"); 224 1.1 mrg else 225 1.1 mrg printf("c_void_p"); 226 1.1 mrg for (unsigned i = 0; i < n_arg - 1; ++i) { 227 1.1 mrg if (!is_isl_type(fn->getArgType(i))) 228 1.1 mrg die("Argument has non-isl type"); 229 1.1 mrg printf(", c_void_p"); 230 1.1 mrg } 231 1.1 mrg printf(", c_void_p)\n"); 232 1.1 mrg printf(" def cb_func("); 233 1.1 mrg for (unsigned i = 0; i < n_arg; ++i) { 234 1.1 mrg if (i) 235 1.1 mrg printf(", "); 236 1.1 mrg printf("cb_arg%d", i); 237 1.1 mrg } 238 1.1 mrg printf("):\n"); 239 1.1 mrg for (unsigned i = 0; i < n_arg - 1; ++i) { 240 1.1 mrg string arg_type; 241 1.1 mrg arg_type = type2python(extract_type(fn->getArgType(i))); 242 1.1 mrg printf(" cb_arg%d = %s(ctx=arg0.ctx, ptr=", 243 1.1 mrg i, arg_type.c_str()); 244 1.1 mrg if (!callback_takes_argument(param, i)) 245 1.1 mrg print_copy(fn->getArgType(i)); 246 1.1 mrg printf("(cb_arg%d))\n", i); 247 1.1 mrg } 248 1.1 mrg printf(" try:\n"); 249 1.1 mrg if (is_isl_stat(return_type)) 250 1.1 mrg printf(" arg%d(", arg); 251 1.1 mrg else 252 1.1 mrg printf(" res = arg%d(", arg); 253 1.1 mrg for (unsigned i = 0; i < n_arg - 1; ++i) { 254 1.1 mrg if (i) 255 1.1 mrg printf(", "); 256 1.1 mrg printf("cb_arg%d", i); 257 1.1 mrg } 258 1.1 mrg printf(")\n"); 259 1.1 mrg printf(" except BaseException as e:\n"); 260 1.1 mrg printf(" exc_info[0] = e\n"); 261 1.1 mrg if (is_isl_stat(return_type) || is_isl_bool(return_type)) 262 1.1 mrg printf(" return -1\n"); 263 1.1 mrg else 264 1.1 mrg printf(" return None\n"); 265 1.1 mrg if (is_isl_stat(return_type)) { 266 1.1 mrg printf(" return 0\n"); 267 1.1 mrg } else if (is_isl_bool(return_type)) { 268 1.1 mrg printf(" return 1 if res else 0\n"); 269 1.1 mrg } else { 270 1.1 mrg printf(" return "); 271 1.1 mrg print_copy(return_type); 272 1.1 mrg printf("(res.ptr)\n"); 273 1.1 mrg } 274 1.1 mrg printf(" cb%d = fn(cb_func)\n", arg); 275 1.1 mrg } 276 1.1 mrg 277 1.1 mrg /* Print the argument at position "arg" in call to "fd". 278 1.1 mrg * "fmt" is the format for printing Python method arguments. 279 1.1 mrg * "skip" is the number of initial arguments of "fd" that are 280 1.1 mrg * skipped in the Python method. 281 1.1 mrg * 282 1.1 mrg * If the (first) argument is an isl_ctx, then print "ctx", 283 1.1 mrg * assuming that the caller has made the context available 284 1.1 mrg * in a "ctx" variable. 285 1.1 mrg * Otherwise, if the argument is a callback, then print a reference to 286 1.1 mrg * the corresponding callback wrapper. 287 1.1 mrg * Otherwise, if the argument is marked as consuming a reference, 288 1.1 mrg * then pass a copy of the pointer stored in the corresponding 289 1.1 mrg * argument passed to the Python method. 290 1.1 mrg * Otherwise, if the argument is a string, then the python string is first 291 1.1 mrg * encoded as a byte sequence, using 'ascii' as encoding. This assumes 292 1.1 mrg * that all strings passed to isl can be converted to 'ascii'. 293 1.1 mrg * Otherwise, if the argument is a pointer, then pass this pointer itself. 294 1.1 mrg * Otherwise, pass the argument directly. 295 1.1 mrg */ 296 1.1 mrg void python_generator::print_arg_in_call(FunctionDecl *fd, const char *fmt, 297 1.1 mrg int arg, int skip) 298 1.1 mrg { 299 1.1 mrg ParmVarDecl *param = fd->getParamDecl(arg); 300 1.1 mrg QualType type = param->getOriginalType(); 301 1.1 mrg if (is_isl_ctx(type)) { 302 1.1 mrg printf("ctx"); 303 1.1 mrg } else if (is_callback(type)) { 304 1.1 mrg printf("cb%d", arg - skip); 305 1.1 mrg } else if (takes(param)) { 306 1.1 mrg print_copy(type); 307 1.1 mrg printf("("); 308 1.1 mrg printf(fmt, arg - skip); 309 1.1 mrg printf(".ptr)"); 310 1.1 mrg } else if (is_string(type)) { 311 1.1 mrg printf(fmt, arg - skip); 312 1.1 mrg printf(".encode('ascii')"); 313 1.1 mrg } else if (type->isPointerType()) { 314 1.1 mrg printf(fmt, arg - skip); 315 1.1 mrg printf(".ptr"); 316 1.1 mrg } else { 317 1.1 mrg printf(fmt, arg - skip); 318 1.1 mrg } 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg /* Generate code that raises the exception captured in "exc_info", if any, 322 1.1 mrg * with the given indentation. 323 1.1 mrg */ 324 1.1 mrg static void print_rethrow(int indent, const char *exc_info) 325 1.1 mrg { 326 1.1 mrg print_indent(indent, "if %s is not None:\n", exc_info); 327 1.1 mrg print_indent(indent, " raise %s\n", exc_info); 328 1.1 mrg } 329 1.1 mrg 330 1.1 mrg /* Print code with the given indentation that checks 331 1.1 mrg * whether any of the persistent callbacks of "clazz" 332 1.1 mrg * is set and if it failed with an exception. If so, the 'exc_info' 333 1.1 mrg * field contains the exception and is raised again. 334 1.1 mrg * The field is cleared because the callback and its data may get reused. 335 1.1 mrg * "fmt" is the format for printing Python method arguments. 336 1.1 mrg */ 337 1.1 mrg static void print_persistent_callback_failure_check(int indent, 338 1.1 mrg const isl_class &clazz, const char *fmt) 339 1.1 mrg { 340 1.1 mrg const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks; 341 1.1 mrg set<FunctionDecl *>::const_iterator in; 342 1.1 mrg 343 1.1 mrg for (in = callbacks.begin(); in != callbacks.end(); ++in) { 344 1.1 mrg string callback_name = clazz.persistent_callback_name(*in); 345 1.1 mrg 346 1.1 mrg print_indent(indent, "if hasattr("); 347 1.1 mrg printf(fmt, 0); 348 1.1 mrg printf(", '%s') and ", callback_name.c_str()); 349 1.1 mrg printf(fmt, 0); 350 1.1 mrg printf(".%s['exc_info'] != None:\n", callback_name.c_str()); 351 1.1 mrg print_indent(indent, " exc_info = "); 352 1.1 mrg printf(fmt, 0); 353 1.1 mrg printf(".%s['exc_info'][0]\n", callback_name.c_str()); 354 1.1 mrg print_indent(indent, " "); 355 1.1 mrg printf(fmt, 0); 356 1.1 mrg printf(".%s['exc_info'][0] = None\n", callback_name.c_str()); 357 1.1 mrg print_rethrow(indent + 4, "exc_info"); 358 1.1 mrg } 359 1.1 mrg } 360 1.1 mrg 361 1.1 mrg /* Print the return statement of the python method corresponding 362 1.1 mrg * to the C function "method" with the given indentation. 363 1.1 mrg * If the object on which the method was called 364 1.1 mrg * may have a persistent callback, then first check if any of those failed. 365 1.1 mrg * "fmt" is the format for printing Python method arguments. 366 1.1 mrg * 367 1.1 mrg * If the method returns a new instance of the same object type and 368 1.1 mrg * if the class has any persistent callbacks, then the data 369 1.1 mrg * for these callbacks are copied from the original to the new object. 370 1.1 mrg * If the method it itself setting a persistent callback, 371 1.1 mrg * then keep track of the constructed C callback (such that it doesn't 372 1.1 mrg * get destroyed) and the data structure that holds the captured exception 373 1.1 mrg * (such that it can be raised again). 374 1.1 mrg * The callback appears in position 1 and the C callback is therefore 375 1.1 mrg * called "cb1". 376 1.1 mrg * 377 1.1 mrg * If the return type is a (const) char *, then convert the result 378 1.1 mrg * to a Python string, raising an error on NULL and freeing 379 1.1 mrg * the C string if needed. For python 3 compatibility, the string returned 380 1.1 mrg * by isl is explicitly decoded as an 'ascii' string. This is correct 381 1.1 mrg * as all strings returned by isl are expected to be 'ascii'. 382 1.1 mrg * 383 1.1 mrg * If the return type is isl_stat, isl_bool or isl_size, then 384 1.1 mrg * raise an error on isl_stat_error, isl_bool_error or isl_size_error. 385 1.1 mrg * In case of isl_bool, the result is converted to 386 1.1 mrg * a Python boolean. 387 1.1 mrg * In case of isl_size, the result is converted to a Python int. 388 1.1 mrg */ 389 1.1 mrg void python_generator::print_method_return(int indent, const isl_class &clazz, 390 1.1 mrg FunctionDecl *method, const char *fmt) 391 1.1 mrg { 392 1.1 mrg QualType return_type = method->getReturnType(); 393 1.1 mrg 394 1.1 mrg if (!is_static(clazz, method)) 395 1.1 mrg print_persistent_callback_failure_check(indent, clazz, fmt); 396 1.1 mrg 397 1.1 mrg if (is_isl_type(return_type)) { 398 1.1 mrg string type; 399 1.1 mrg 400 1.1 mrg type = type2python(extract_type(return_type)); 401 1.1 mrg print_indent(indent, 402 1.1 mrg "obj = %s(ctx=ctx, ptr=res)\n", type.c_str()); 403 1.1 mrg if (is_mutator(clazz, method) && 404 1.1 mrg clazz.has_persistent_callbacks()) 405 1.1 mrg print_indent(indent, "obj.copy_callbacks(arg0)\n"); 406 1.1 mrg if (clazz.persistent_callbacks.count(method)) { 407 1.1 mrg string callback_name; 408 1.1 mrg 409 1.1 mrg callback_name = clazz.persistent_callback_name(method); 410 1.1 mrg print_indent(indent, "obj.%s = { 'func': cb1, " 411 1.1 mrg "'exc_info': exc_info }\n", 412 1.1 mrg callback_name.c_str()); 413 1.1 mrg } 414 1.1 mrg print_indent(indent, "return obj\n"); 415 1.1 mrg } else if (is_string(return_type)) { 416 1.1 mrg print_indent(indent, "if res == 0:\n"); 417 1.1 mrg print_indent(indent, " raise Error\n"); 418 1.1 mrg print_indent(indent, "string = " 419 1.1 mrg "cast(res, c_char_p).value.decode('ascii')\n"); 420 1.1 mrg 421 1.1 mrg if (gives(method)) 422 1.1 mrg print_indent(indent, "libc.free(res)\n"); 423 1.1 mrg 424 1.1 mrg print_indent(indent, "return string\n"); 425 1.1 mrg } else if (is_isl_neg_error(return_type)) { 426 1.1 mrg print_indent(indent, "if res < 0:\n"); 427 1.1 mrg print_indent(indent, " raise Error\n"); 428 1.1 mrg if (is_isl_bool(return_type)) 429 1.1 mrg print_indent(indent, "return bool(res)\n"); 430 1.1 mrg else if (is_isl_size(return_type)) 431 1.1 mrg print_indent(indent, "return int(res)\n"); 432 1.1 mrg } else { 433 1.1 mrg print_indent(indent, "return res\n"); 434 1.1 mrg } 435 1.1 mrg } 436 1.1 mrg 437 1.1 mrg /* Print a python "get" method corresponding to the C function "fd" 438 1.1 mrg * in class "clazz" using a name that includes the "get_" prefix. 439 1.1 mrg * 440 1.1 mrg * This method simply calls the variant without the "get_" prefix and 441 1.1 mrg * returns its result. 442 1.1 mrg * Note that static methods are not considered to be "get" methods. 443 1.1 mrg */ 444 1.1 mrg void python_generator::print_get_method(const isl_class &clazz, 445 1.1 mrg FunctionDecl *fd) 446 1.1 mrg { 447 1.1 mrg string get_name = clazz.base_method_name(fd); 448 1.1 mrg string name = clazz.method_name(fd); 449 1.1 mrg int num_params = fd->getNumParams(); 450 1.1 mrg 451 1.1 mrg print_method_header(false, get_name, num_params); 452 1.1 mrg printf(" return arg0.%s(", name.c_str()); 453 1.1 mrg print_method_arguments(1, num_params); 454 1.1 mrg printf(")\n"); 455 1.1 mrg } 456 1.1 mrg 457 1.1 mrg /* Print a call to "method", along with the corresponding 458 1.1 mrg * return statement, with the given indentation. 459 1.1 mrg * "drop_ctx" is set if the first argument is an isl_ctx. 460 1.1 mrg * 461 1.1 mrg * A "ctx" variable is first initialized as it may be needed 462 1.1 mrg * in the first call to print_arg_in_call and in print_method_return. 463 1.1 mrg * 464 1.1 mrg * If the method has any callback function, then any exception 465 1.1 mrg * thrown in any callback also need to be rethrown. 466 1.1 mrg */ 467 1.1 mrg void python_generator::print_method_call(int indent, const isl_class &clazz, 468 1.1 mrg FunctionDecl *method, const char *fmt, int drop_ctx) 469 1.1 mrg { 470 1.1 mrg string fullname = method->getName().str(); 471 1.1 mrg int num_params = method->getNumParams(); 472 1.1 mrg int drop_user = 0; 473 1.1 mrg 474 1.1 mrg if (drop_ctx) { 475 1.1 mrg print_indent(indent, "ctx = Context.getDefaultInstance()\n"); 476 1.1 mrg } else { 477 1.1 mrg print_indent(indent, "ctx = "); 478 1.1 mrg printf(fmt, 0); 479 1.1 mrg printf(".ctx\n"); 480 1.1 mrg } 481 1.1 mrg print_indent(indent, "res = isl.%s(", fullname.c_str()); 482 1.1 mrg for (int i = 0; i < num_params; ++i) { 483 1.1 mrg if (i > 0) 484 1.1 mrg printf(", "); 485 1.1 mrg print_arg_in_call(method, fmt, i, drop_ctx + drop_user); 486 1.1 mrg if (!is_callback_arg(method, i)) 487 1.1 mrg continue; 488 1.1 mrg ++drop_user; 489 1.1 mrg ++i; 490 1.1 mrg printf(", None"); 491 1.1 mrg } 492 1.1 mrg printf(")\n"); 493 1.1 mrg 494 1.1 mrg if (drop_user > 0) 495 1.1 mrg print_rethrow(indent, "exc_info[0]"); 496 1.1 mrg 497 1.1 mrg print_method_return(indent, clazz, method, fmt); 498 1.1 mrg } 499 1.1 mrg 500 1.1 mrg /* Print a python method corresponding to the C function "method". 501 1.1 mrg * "super" contains the superclasses of the class to which the method belongs, 502 1.1 mrg * with the first element corresponding to the annotation that appears 503 1.1 mrg * closest to the annotated type. This superclass is the least 504 1.1 mrg * general extension of the annotated type in the linearization 505 1.1 mrg * of the class hierarchy. 506 1.1 mrg * 507 1.1 mrg * If the first argument of "method" is something other than an instance 508 1.1 mrg * of the class, then mark the python method as static. 509 1.1 mrg * If, moreover, this first argument is an isl_ctx, then remove 510 1.1 mrg * it from the arguments of the Python method. 511 1.1 mrg * 512 1.1 mrg * If the function has any callback arguments, then it also has corresponding 513 1.1 mrg * "user" arguments. Since Python has closures, there is no need for such 514 1.1 mrg * user arguments in the Python interface, so we simply drop them. 515 1.1 mrg * We also create a wrapper ("cb{arg}") for each callback. 516 1.1 mrg * 517 1.1 mrg * If the function consumes a reference, then we pass it a copy of 518 1.1 mrg * the actual argument. 519 1.1 mrg * 520 1.1 mrg * For methods that are identified as "get" methods, also 521 1.1 mrg * print a variant of the method using a name that includes 522 1.1 mrg * the "get_" prefix. 523 1.1 mrg */ 524 1.1 mrg void python_generator::print_method(const isl_class &clazz, 525 1.1 mrg FunctionDecl *method, vector<string> super) 526 1.1 mrg { 527 1.1 mrg string cname = clazz.method_name(method); 528 1.1 mrg int num_params = method->getNumParams(); 529 1.1 mrg int drop_user = 0; 530 1.1 mrg int drop_ctx = first_arg_is_isl_ctx(method); 531 1.1 mrg 532 1.1 mrg for (int i = 1; i < num_params; ++i) { 533 1.1 mrg if (is_callback_arg(method, i)) 534 1.1 mrg drop_user += 1; 535 1.1 mrg } 536 1.1 mrg 537 1.1 mrg print_method_header(is_static(clazz, method), cname, 538 1.1 mrg num_params - drop_ctx - drop_user); 539 1.1 mrg 540 1.1 mrg print_type_checks(cname, method, drop_ctx, 541 1.1 mrg num_params, super); 542 1.1 mrg drop_user = 0; 543 1.1 mrg for (int i = 1; i < num_params; ++i) { 544 1.1 mrg ParmVarDecl *param = method->getParamDecl(i); 545 1.1 mrg QualType type = param->getOriginalType(); 546 1.1 mrg if (!is_callback(type)) 547 1.1 mrg continue; 548 1.1 mrg print_callback(param, i - drop_ctx - drop_user); 549 1.1 mrg drop_user += 1; 550 1.1 mrg } 551 1.1 mrg print_method_call(8, clazz, method, fixed_arg_fmt, drop_ctx); 552 1.1 mrg 553 1.1 mrg if (clazz.is_get_method(method)) 554 1.1 mrg print_get_method(clazz, method); 555 1.1 mrg } 556 1.1 mrg 557 1.1 mrg /* Print a condition that checks whether Python method argument "i" 558 1.1 mrg * corresponds to the C function argument type "type". 559 1.1 mrg */ 560 1.1 mrg static void print_argument_check(QualType type, int i) 561 1.1 mrg { 562 1.1 mrg if (generator::is_isl_type(type)) { 563 1.1 mrg string type_str; 564 1.1 mrg type_str = generator::extract_type(type); 565 1.1 mrg type_str = type2python(type_str); 566 1.1 mrg printf("args[%d].__class__ is %s", i, type_str.c_str()); 567 1.1 mrg } else if (type->isPointerType()) { 568 1.1 mrg printf("type(args[%d]) == str", i); 569 1.1 mrg } else { 570 1.1 mrg printf("type(args[%d]) == int", i); 571 1.1 mrg } 572 1.1 mrg } 573 1.1 mrg 574 1.1 mrg /* Is any element of "vector" set? 575 1.1 mrg */ 576 1.1 mrg static bool any(const std::vector<bool> &vector) 577 1.1 mrg { 578 1.1 mrg return std::find(vector.begin(), vector.end(), true) != vector.end(); 579 1.1 mrg } 580 1.1 mrg 581 1.1 mrg /* Print a test that checks whether the arguments passed 582 1.1 mrg * to the Python method correspond to the arguments 583 1.1 mrg * expected by "fd" and 584 1.1 mrg * check if the object on which the method is called, if any, 585 1.1 mrg * is of the right type. 586 1.1 mrg * "drop_ctx" is set if the first argument of "fd" is an isl_ctx, 587 1.1 mrg * which does not appear as an argument to the Python method. 588 1.1 mrg * 589 1.1 mrg * If an automatic conversion function is available for any 590 1.1 mrg * of the argument types, then also allow the argument 591 1.1 mrg * to be of the type as prescribed by the second input argument 592 1.1 mrg * of the conversion function. 593 1.1 mrg * The corresponding arguments are then converted to the expected types 594 1.1 mrg * if needed. 595 1.1 mrg * The object on which the method is called is also converted if needed. 596 1.1 mrg * The argument tuple first needs to be converted to a list 597 1.1 mrg * in order to be able to modify the entries. 598 1.1 mrg */ 599 1.1 mrg void python_generator::print_argument_checks(const isl_class &clazz, 600 1.1 mrg FunctionDecl *fd, int drop_ctx) 601 1.1 mrg { 602 1.1 mrg int num_params = fd->getNumParams(); 603 1.1 mrg bool is_static = generator::is_static(clazz, fd); 604 1.1 mrg int first = is_static ? drop_ctx : 1; 605 1.1 mrg std::vector<bool> convert(num_params); 606 1.1 mrg 607 1.1 mrg printf(" if len(args) == %d", num_params - drop_ctx); 608 1.1 mrg for (int i = first; i < num_params; ++i) { 609 1.1 mrg ParmVarDecl *param = fd->getParamDecl(i); 610 1.1 mrg QualType type = param->getOriginalType(); 611 1.1 mrg const Type *ptr = type.getTypePtr(); 612 1.1 mrg 613 1.1 mrg printf(" and "); 614 1.1 mrg if (conversions.count(ptr) == 0) { 615 1.1 mrg print_argument_check(type, i - drop_ctx); 616 1.1 mrg } else { 617 1.1 mrg QualType type2 = conversions.at(ptr)->getOriginalType(); 618 1.1 mrg convert[i] = true; 619 1.1 mrg printf("("); 620 1.1 mrg print_argument_check(type, i - drop_ctx); 621 1.1 mrg printf(" or "); 622 1.1 mrg print_argument_check(type2, i - drop_ctx); 623 1.1 mrg printf(")"); 624 1.1 mrg } 625 1.1 mrg } 626 1.1 mrg printf(":\n"); 627 1.1 mrg 628 1.1 mrg if (is_static && !any(convert)) 629 1.1 mrg return; 630 1.1 mrg print_indent(12, "args = list(args)\n"); 631 1.1 mrg first = is_static ? drop_ctx : 0; 632 1.1 mrg for (int i = first; i < num_params; ++i) { 633 1.1 mrg bool is_self = !is_static && i == 0; 634 1.1 mrg ParmVarDecl *param = fd->getParamDecl(i); 635 1.1 mrg string type; 636 1.1 mrg 637 1.1 mrg if (!is_self && !convert[i]) 638 1.1 mrg continue; 639 1.1 mrg type = type2python(extract_type(param->getOriginalType())); 640 1.1 mrg print_type_check(12, type, var_arg_fmt, 641 1.1 mrg i - drop_ctx, false, "", "", -1); 642 1.1 mrg } 643 1.1 mrg } 644 1.1 mrg 645 1.1 mrg /* Print part of an overloaded python method corresponding to the C function 646 1.1 mrg * "method". 647 1.1 mrg * "drop_ctx" is set if the first argument of "method" is an isl_ctx. 648 1.1 mrg * 649 1.1 mrg * In particular, print code to test whether the arguments passed to 650 1.1 mrg * the python method correspond to the arguments expected by "method" 651 1.1 mrg * and to call "method" if they do. 652 1.1 mrg */ 653 1.1 mrg void python_generator::print_method_overload(const isl_class &clazz, 654 1.1 mrg FunctionDecl *method) 655 1.1 mrg { 656 1.1 mrg int drop_ctx = first_arg_is_isl_ctx(method); 657 1.1 mrg 658 1.1 mrg print_argument_checks(clazz, method, drop_ctx); 659 1.1 mrg print_method_call(12, clazz, method, var_arg_fmt, drop_ctx); 660 1.1 mrg } 661 1.1 mrg 662 1.1 mrg /* Print a python method with a name derived from "fullname" 663 1.1 mrg * corresponding to the C functions "methods". 664 1.1 mrg * "super" contains the superclasses of the class to which the method belongs. 665 1.1 mrg * 666 1.1 mrg * If "methods" consists of a single element that is not marked overloaded, 667 1.1 mrg * the use print_method to print the method. 668 1.1 mrg * Otherwise, print an overloaded method with pieces corresponding 669 1.1 mrg * to each function in "methods". 670 1.1 mrg */ 671 1.1 mrg void python_generator::print_method(const isl_class &clazz, 672 1.1 mrg const string &fullname, const function_set &methods, 673 1.1 mrg vector<string> super) 674 1.1 mrg { 675 1.1 mrg string cname; 676 1.1 mrg function_set::const_iterator it; 677 1.1 mrg FunctionDecl *any_method; 678 1.1 mrg 679 1.1 mrg any_method = *methods.begin(); 680 1.1 mrg if (methods.size() == 1 && !is_overload(any_method)) { 681 1.1 mrg print_method(clazz, any_method, super); 682 1.1 mrg return; 683 1.1 mrg } 684 1.1 mrg 685 1.1 mrg cname = clazz.method_name(any_method); 686 1.1 mrg 687 1.1 mrg print_method_def(is_static(clazz, any_method), cname); 688 1.1 mrg printf("(*args):\n"); 689 1.1 mrg 690 1.1 mrg for (it = methods.begin(); it != methods.end(); ++it) 691 1.1 mrg print_method_overload(clazz, *it); 692 1.1 mrg printf(" raise Error\n"); 693 1.1 mrg } 694 1.1 mrg 695 1.1 mrg /* Print a python method "name" corresponding to "fd" setting 696 1.1 mrg * the enum value "value". 697 1.1 mrg * "super" contains the superclasses of the class to which the method belongs, 698 1.1 mrg * with the first element corresponding to the annotation that appears 699 1.1 mrg * closest to the annotated type. 700 1.1 mrg * 701 1.1 mrg * The last argument of the C function does not appear in the method call, 702 1.1 mrg * but is fixed to "value" instead. 703 1.1 mrg * Other than that, the method printed here is similar to one 704 1.1 mrg * printed by python_generator::print_method, except that 705 1.1 mrg * some of the special cases do not occur. 706 1.1 mrg */ 707 1.1 mrg void python_generator::print_set_enum(const isl_class &clazz, 708 1.1 mrg FunctionDecl *fd, int value, const string &name, 709 1.1 mrg const vector<string> &super) 710 1.1 mrg { 711 1.1 mrg string fullname = fd->getName().str(); 712 1.1 mrg int num_params = fd->getNumParams(); 713 1.1 mrg 714 1.1 mrg print_method_header(is_static(clazz, fd), name, num_params - 1); 715 1.1 mrg 716 1.1 mrg print_type_checks(name, fd, false, num_params - 1, super); 717 1.1 mrg printf(" ctx = arg0.ctx\n"); 718 1.1 mrg printf(" res = isl.%s(", fullname.c_str()); 719 1.1 mrg for (int i = 0; i < num_params - 1; ++i) { 720 1.1 mrg if (i) 721 1.1 mrg printf(", "); 722 1.1 mrg print_arg_in_call(fd, fixed_arg_fmt, i, 0); 723 1.1 mrg } 724 1.1 mrg printf(", %d", value); 725 1.1 mrg printf(")\n"); 726 1.1 mrg print_method_return(8, clazz, fd, fixed_arg_fmt); 727 1.1 mrg } 728 1.1 mrg 729 1.1 mrg /* Print python methods corresponding to "fd", which sets an enum. 730 1.1 mrg * "super" contains the superclasses of the class to which the method belongs, 731 1.1 mrg * with the first element corresponding to the annotation that appears 732 1.1 mrg * closest to the annotated type. 733 1.1 mrg * 734 1.1 mrg * A method is generated for each value in the enum, setting 735 1.1 mrg * the enum to that value. 736 1.1 mrg */ 737 1.1 mrg void python_generator::print_set_enum(const isl_class &clazz, 738 1.1 mrg FunctionDecl *fd, const vector<string> &super) 739 1.1 mrg { 740 1.1 mrg vector<set_enum>::const_iterator it; 741 1.1 mrg const vector<set_enum> &set_enums = clazz.set_enums.at(fd); 742 1.1 mrg 743 1.1 mrg for (it = set_enums.begin(); it != set_enums.end(); ++it) 744 1.1 mrg print_set_enum(clazz, fd, it->value, it->method_name, super); 745 1.1 mrg } 746 1.1 mrg 747 1.1 mrg /* Print part of the constructor for this isl_class. 748 1.1 mrg * 749 1.1 mrg * In particular, check if the actual arguments correspond to the 750 1.1 mrg * formal arguments of "cons" and if so call "cons" and put the 751 1.1 mrg * result in self.ptr and a reference to the default context in self.ctx. 752 1.1 mrg */ 753 1.1 mrg void python_generator::print_constructor(const isl_class &clazz, 754 1.1 mrg FunctionDecl *cons) 755 1.1 mrg { 756 1.1 mrg string fullname = cons->getName().str(); 757 1.1 mrg string cname = clazz.method_name(cons); 758 1.1 mrg int num_params = cons->getNumParams(); 759 1.1 mrg int drop_ctx = first_arg_is_isl_ctx(cons); 760 1.1 mrg 761 1.1 mrg print_argument_checks(clazz, cons, drop_ctx); 762 1.1 mrg printf(" self.ctx = Context.getDefaultInstance()\n"); 763 1.1 mrg printf(" self.ptr = isl.%s(", fullname.c_str()); 764 1.1 mrg if (drop_ctx) 765 1.1 mrg printf("self.ctx"); 766 1.1 mrg for (int i = drop_ctx; i < num_params; ++i) { 767 1.1 mrg if (i) 768 1.1 mrg printf(", "); 769 1.1 mrg print_arg_in_call(cons, var_arg_fmt, i, drop_ctx); 770 1.1 mrg } 771 1.1 mrg printf(")\n"); 772 1.1 mrg printf(" return\n"); 773 1.1 mrg } 774 1.1 mrg 775 1.1 mrg /* The definition of the part of constructor for the "id" class 776 1.1 mrg * that construct an object from a name and a user object, 777 1.1 mrg * without the initial newline. 778 1.1 mrg * 779 1.1 mrg * Just like the parts generated by python_generator::print_constructor, 780 1.1 mrg * the result of the isl_id_alloc call is stored in self.ptr and 781 1.1 mrg * a reference to the default context is stored in self.ctx. 782 1.1 mrg * Also, just like any other constructor or method with a string argument, 783 1.1 mrg * the python string is first encoded as a byte sequence, 784 1.1 mrg * using 'ascii' as encoding. 785 1.1 mrg * 786 1.1 mrg * Since the isl_id keeps a reference to the Python user object, 787 1.1 mrg * the reference count of the Python object needs to be incremented, 788 1.1 mrg * but only if the construction of the isl_id is successful. 789 1.1 mrg * The reference count of the Python object is decremented again 790 1.1 mrg * by Context.free_user when the reference count of the isl_id 791 1.1 mrg * drops to zero. 792 1.1 mrg */ 793 1.1 mrg static const char *const id_constructor_user = &R"( 794 1.1 mrg if len(args) == 2 and type(args[0]) == str: 795 1.1 mrg self.ctx = Context.getDefaultInstance() 796 1.1 mrg name = args[0].encode('ascii') 797 1.1 mrg self.ptr = isl.isl_id_alloc(self.ctx, name, args[1]) 798 1.1 mrg self.ptr = isl.isl_id_set_free_user(self.ptr, Context.free_user) 799 1.1 mrg if self.ptr is not None: 800 1.1 mrg pythonapi.Py_IncRef(py_object(args[1])) 801 1.1 mrg return 802 1.1 mrg )"[1]; 803 1.1 mrg 804 1.1 mrg /* Print any special constructor parts of this class that are not 805 1.1 mrg * automatically derived from the C interface. 806 1.1 mrg * 807 1.1 mrg * In particular, print a special constructor part for the "id" class. 808 1.1 mrg */ 809 1.1 mrg void python_generator::print_special_constructors(const isl_class &clazz) 810 1.1 mrg { 811 1.1 mrg if (clazz.name != "isl_id") 812 1.1 mrg return; 813 1.1 mrg 814 1.1 mrg printf("%s", id_constructor_user); 815 1.1 mrg } 816 1.1 mrg 817 1.1 mrg /* The definition of an "id" method 818 1.1 mrg * for retrieving the user object associated to the identifier, 819 1.1 mrg * without the initial newline. 820 1.1 mrg * 821 1.1 mrg * The isl_id needs to have been created by the constructor 822 1.1 mrg * in id_constructor_user. That is, it needs to have a user pointer and 823 1.1 mrg * it needs to have its free_user callback set to Context.free_user. 824 1.1 mrg * The functions need to be cast to c_void_p to be able to compare 825 1.1 mrg * the addresses. 826 1.1 mrg * 827 1.1 mrg * Return None if any of the checks fail. 828 1.1 mrg * Note that isl_id_get_user returning NULL automatically results in None. 829 1.1 mrg */ 830 1.1 mrg static const char *const id_user = &R"( 831 1.1 mrg def user(self): 832 1.1 mrg free_user = cast(Context.free_user, c_void_p) 833 1.1 mrg id_free_user = cast(isl.isl_id_get_free_user(self.ptr), c_void_p) 834 1.1 mrg if id_free_user.value != free_user.value: 835 1.1 mrg return None 836 1.1 mrg return isl.isl_id_get_user(self.ptr) 837 1.1 mrg )"[1]; 838 1.1 mrg 839 1.1 mrg /* Print any special methods of this class that are not 840 1.1 mrg * automatically derived from the C interface. 841 1.1 mrg * 842 1.1 mrg * In particular, print a special method for the "id" class. 843 1.1 mrg */ 844 1.1 mrg void python_generator::print_special_methods(const isl_class &clazz) 845 1.1 mrg { 846 1.1 mrg if (clazz.name != "isl_id") 847 1.1 mrg return; 848 1.1 mrg 849 1.1 mrg printf("%s", id_user); 850 1.1 mrg } 851 1.1 mrg 852 1.1 mrg /* If "clazz" has a type function describing subclasses, 853 1.1 mrg * then add constructors that allow each of these subclasses 854 1.1 mrg * to be treated as an object to the superclass. 855 1.1 mrg */ 856 1.1 mrg void python_generator::print_upcast_constructors(const isl_class &clazz) 857 1.1 mrg { 858 1.1 mrg map<int, string>::const_iterator i; 859 1.1 mrg 860 1.1 mrg if (!clazz.fn_type) 861 1.1 mrg return; 862 1.1 mrg 863 1.1 mrg for (i = clazz.type_subclasses.begin(); 864 1.1 mrg i != clazz.type_subclasses.end(); ++i) { 865 1.1 mrg printf(" if len(args) == 1 and " 866 1.1 mrg "isinstance(args[0], %s):\n", 867 1.1 mrg type2python(i->second).c_str()); 868 1.1 mrg printf(" self.ctx = args[0].ctx\n"); 869 1.1 mrg printf(" self.ptr = isl.%s_copy(args[0].ptr)\n", 870 1.1 mrg clazz.name.c_str()); 871 1.1 mrg printf(" return\n"); 872 1.1 mrg } 873 1.1 mrg } 874 1.1 mrg 875 1.1 mrg /* Print the header of the class "name" with superclasses "super". 876 1.1 mrg * The order of the superclasses is the opposite of the order 877 1.1 mrg * in which the corresponding annotations appear in the source code. 878 1.1 mrg * If "clazz" is a subclass derived from a type function, 879 1.1 mrg * then the immediate superclass is recorded in "clazz" itself. 880 1.1 mrg */ 881 1.1 mrg void python_generator::print_class_header(const isl_class &clazz, 882 1.1 mrg const string &name, const vector<string> &super) 883 1.1 mrg { 884 1.1 mrg printf("class %s", name.c_str()); 885 1.1 mrg if (super.size() > 0) { 886 1.1 mrg printf("("); 887 1.1 mrg for (unsigned i = 0; i < super.size(); ++i) { 888 1.1 mrg if (i > 0) 889 1.1 mrg printf(", "); 890 1.1 mrg printf("%s", type2python(super[i]).c_str()); 891 1.1 mrg } 892 1.1 mrg printf(")"); 893 1.1 mrg } else if (clazz.is_type_subclass()) { 894 1.1 mrg printf("(%s)", type2python(clazz.superclass_name).c_str()); 895 1.1 mrg } else { 896 1.1 mrg printf("(object)"); 897 1.1 mrg } 898 1.1 mrg printf(":\n"); 899 1.1 mrg } 900 1.1 mrg 901 1.1 mrg /* Tell ctypes about the return type of "fd". 902 1.1 mrg * In particular, if "fd" returns a pointer to an isl object, 903 1.1 mrg * then tell ctypes it returns a "c_void_p". 904 1.1 mrg * If "fd" returns a char *, then simply tell ctypes. 905 1.1 mrg * 906 1.1 mrg * Nothing needs to be done for functions returning 907 1.1 mrg * isl_bool, isl_stat or isl_size since they are represented by an int and 908 1.1 mrg * ctypes assumes that a function returns int by default. 909 1.1 mrg */ 910 1.1 mrg void python_generator::print_restype(FunctionDecl *fd) 911 1.1 mrg { 912 1.1 mrg string fullname = fd->getName().str(); 913 1.1 mrg QualType type = fd->getReturnType(); 914 1.1 mrg if (is_isl_type(type)) 915 1.1 mrg printf("isl.%s.restype = c_void_p\n", fullname.c_str()); 916 1.1 mrg else if (is_string(type)) 917 1.1 mrg printf("isl.%s.restype = POINTER(c_char)\n", fullname.c_str()); 918 1.1 mrg } 919 1.1 mrg 920 1.1 mrg /* Tell ctypes about the types of the arguments of the function "fd". 921 1.1 mrg * 922 1.1 mrg * Any callback argument is followed by a user pointer argument. 923 1.1 mrg * Each such pair or arguments is handled together. 924 1.1 mrg */ 925 1.1 mrg void python_generator::print_argtypes(FunctionDecl *fd) 926 1.1 mrg { 927 1.1 mrg string fullname = fd->getName().str(); 928 1.1 mrg int n = fd->getNumParams(); 929 1.1 mrg 930 1.1 mrg printf("isl.%s.argtypes = [", fullname.c_str()); 931 1.1 mrg for (int i = 0; i < n; ++i) { 932 1.1 mrg ParmVarDecl *param = fd->getParamDecl(i); 933 1.1 mrg QualType type = param->getOriginalType(); 934 1.1 mrg if (i) 935 1.1 mrg printf(", "); 936 1.1 mrg if (is_isl_ctx(type)) 937 1.1 mrg printf("Context"); 938 1.1 mrg else if (is_isl_type(type)) 939 1.1 mrg printf("c_void_p"); 940 1.1 mrg else if (is_callback(type)) 941 1.1 mrg printf("c_void_p, c_void_p"); 942 1.1 mrg else if (is_string(type)) 943 1.1 mrg printf("c_char_p"); 944 1.1 mrg else if (is_long(type)) 945 1.1 mrg printf("c_long"); 946 1.1 mrg else 947 1.1 mrg printf("c_int"); 948 1.1 mrg 949 1.1 mrg if (is_callback(type)) 950 1.1 mrg ++i; 951 1.1 mrg } 952 1.1 mrg printf("]\n"); 953 1.1 mrg } 954 1.1 mrg 955 1.1 mrg /* Print type definitions for the method 'fd'. 956 1.1 mrg */ 957 1.1 mrg void python_generator::print_method_type(FunctionDecl *fd) 958 1.1 mrg { 959 1.1 mrg print_restype(fd); 960 1.1 mrg print_argtypes(fd); 961 1.1 mrg } 962 1.1 mrg 963 1.1 mrg /* If "clazz" has a type function describing subclasses or 964 1.1 mrg * if it is one of those type subclasses, then print a __new__ method. 965 1.1 mrg * 966 1.1 mrg * In the superclass, the __new__ method constructs an object 967 1.1 mrg * of the subclass type specified by the type function, 968 1.1 mrg * raising an error on an error type. 969 1.1 mrg * In the subclass, the __new__ method reverts to the original behavior. 970 1.1 mrg */ 971 1.1 mrg void python_generator::print_new(const isl_class &clazz, 972 1.1 mrg const string &python_name) 973 1.1 mrg { 974 1.1 mrg if (!clazz.fn_type && !clazz.is_type_subclass()) 975 1.1 mrg return; 976 1.1 mrg 977 1.1 mrg printf(" def __new__(cls, *args, **keywords):\n"); 978 1.1 mrg 979 1.1 mrg if (clazz.fn_type) { 980 1.1 mrg map<int, string>::const_iterator i; 981 1.1 mrg 982 1.1 mrg printf(" if \"ptr\" in keywords:\n"); 983 1.1 mrg printf(" type = isl.%s(keywords[\"ptr\"])\n", 984 1.1 mrg clazz.fn_type->getNameAsString().c_str()); 985 1.1 mrg 986 1.1 mrg for (i = clazz.type_subclasses.begin(); 987 1.1 mrg i != clazz.type_subclasses.end(); ++i) { 988 1.1 mrg printf(" if type == %d:\n", i->first); 989 1.1 mrg printf(" return %s(**keywords)\n", 990 1.1 mrg type2python(i->second).c_str()); 991 1.1 mrg } 992 1.1 mrg printf(" raise Error\n"); 993 1.1 mrg } 994 1.1 mrg 995 1.1 mrg printf(" return super(%s, cls).__new__(cls)\n", 996 1.1 mrg python_name.c_str()); 997 1.1 mrg } 998 1.1 mrg 999 1.1 mrg /* Print declarations for methods printing the class representation, 1000 1.1 mrg * provided there is a corresponding *_to_str function. 1001 1.1 mrg * 1002 1.1 mrg * In particular, provide an implementation of __str__ and __repr__ methods to 1003 1.1 mrg * override the default representation used by python. Python uses __str__ to 1004 1.1 mrg * pretty print the class (e.g., when calling print(obj)) and uses __repr__ 1005 1.1 mrg * when printing a precise representation of an object (e.g., when dumping it 1006 1.1 mrg * in the REPL console). 1007 1.1 mrg * 1008 1.1 mrg * Check the type of the argument before calling the *_to_str function 1009 1.1 mrg * on it in case the method was called on an object from a subclass. 1010 1.1 mrg * 1011 1.1 mrg * The return value of the *_to_str function is decoded to a python string 1012 1.1 mrg * assuming an 'ascii' encoding. This is necessary for python 3 compatibility. 1013 1.1 mrg */ 1014 1.1 mrg void python_generator::print_representation(const isl_class &clazz, 1015 1.1 mrg const string &python_name) 1016 1.1 mrg { 1017 1.1 mrg if (!clazz.fn_to_str) 1018 1.1 mrg return; 1019 1.1 mrg 1020 1.1 mrg printf(" def __str__(arg0):\n"); 1021 1.1 mrg print_type_check(8, python_name, fixed_arg_fmt, 0, false, "", "", -1); 1022 1.1 mrg printf(" ptr = isl.%s(arg0.ptr)\n", 1023 1.1 mrg string(clazz.fn_to_str->getName()).c_str()); 1024 1.1 mrg printf(" res = cast(ptr, c_char_p).value.decode('ascii')\n"); 1025 1.1 mrg printf(" libc.free(ptr)\n"); 1026 1.1 mrg printf(" return res\n"); 1027 1.1 mrg printf(" def __repr__(self):\n"); 1028 1.1 mrg printf(" s = str(self)\n"); 1029 1.1 mrg printf(" if '\"' in s:\n"); 1030 1.1 mrg printf(" return 'isl.%s(\"\"\"%%s\"\"\")' %% s\n", 1031 1.1 mrg python_name.c_str()); 1032 1.1 mrg printf(" else:\n"); 1033 1.1 mrg printf(" return 'isl.%s(\"%%s\")' %% s\n", 1034 1.1 mrg python_name.c_str()); 1035 1.1 mrg } 1036 1.1 mrg 1037 1.1 mrg /* If "clazz" has any persistent callbacks, then print the definition 1038 1.1 mrg * of a "copy_callbacks" function that copies the persistent callbacks 1039 1.1 mrg * from one object to another. 1040 1.1 mrg */ 1041 1.1 mrg void python_generator::print_copy_callbacks(const isl_class &clazz) 1042 1.1 mrg { 1043 1.1 mrg const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks; 1044 1.1 mrg set<FunctionDecl *>::const_iterator in; 1045 1.1 mrg 1046 1.1 mrg if (!clazz.has_persistent_callbacks()) 1047 1.1 mrg return; 1048 1.1 mrg 1049 1.1 mrg printf(" def copy_callbacks(self, obj):\n"); 1050 1.1 mrg for (in = callbacks.begin(); in != callbacks.end(); ++in) { 1051 1.1 mrg string callback_name = clazz.persistent_callback_name(*in); 1052 1.1 mrg 1053 1.1 mrg printf(" if hasattr(obj, '%s'):\n", 1054 1.1 mrg callback_name.c_str()); 1055 1.1 mrg printf(" self.%s = obj.%s\n", 1056 1.1 mrg callback_name.c_str(), callback_name.c_str()); 1057 1.1 mrg } 1058 1.1 mrg } 1059 1.1 mrg 1060 1.1 mrg /* Print code to set method type signatures. 1061 1.1 mrg * 1062 1.1 mrg * To be able to call C functions it is necessary to explicitly set their 1063 1.1 mrg * argument and result types. Do this for all exported constructors and 1064 1.1 mrg * methods (including those that set a persistent callback and 1065 1.1 mrg * those that set an enum value), 1066 1.1 mrg * as well as for the *_to_str and the type function, if they exist. 1067 1.1 mrg * Assuming each exported class has a *_copy and a *_free method, 1068 1.1 mrg * also unconditionally set the type of such methods. 1069 1.1 mrg */ 1070 1.1 mrg void python_generator::print_method_types(const isl_class &clazz) 1071 1.1 mrg { 1072 1.1 mrg function_set::const_iterator in; 1073 1.1 mrg map<string, function_set>::const_iterator it; 1074 1.1 mrg map<FunctionDecl *, vector<set_enum> >::const_iterator ie; 1075 1.1 mrg const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks; 1076 1.1 mrg 1077 1.1 mrg for (in = clazz.constructors.begin(); in != clazz.constructors.end(); 1078 1.1 mrg ++in) 1079 1.1 mrg print_method_type(*in); 1080 1.1 mrg 1081 1.1 mrg for (in = callbacks.begin(); in != callbacks.end(); ++in) 1082 1.1 mrg print_method_type(*in); 1083 1.1 mrg for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it) 1084 1.1 mrg for (in = it->second.begin(); in != it->second.end(); ++in) 1085 1.1 mrg print_method_type(*in); 1086 1.1 mrg for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie) 1087 1.1 mrg print_method_type(ie->first); 1088 1.1 mrg 1089 1.1 mrg print_method_type(clazz.fn_copy); 1090 1.1 mrg print_method_type(clazz.fn_free); 1091 1.1 mrg if (clazz.fn_to_str) 1092 1.1 mrg print_method_type(clazz.fn_to_str); 1093 1.1 mrg if (clazz.fn_type) 1094 1.1 mrg print_method_type(clazz.fn_type); 1095 1.1 mrg } 1096 1.1 mrg 1097 1.1 mrg /* Print out the definition of this isl_class. 1098 1.1 mrg * 1099 1.1 mrg * We first check if this isl_class is a subclass of one or more other classes. 1100 1.1 mrg * If it is, we make sure those superclasses are printed out first. 1101 1.1 mrg * 1102 1.1 mrg * Then we print a constructor with several cases, one for constructing 1103 1.1 mrg * a Python object from a return value, one for each function that 1104 1.1 mrg * was marked as a constructor, a class specific constructor, if any, and 1105 1.1 mrg * one for each type based subclass. 1106 1.1 mrg * 1107 1.1 mrg * Next, we print out some common methods, class specific methods and 1108 1.1 mrg * the methods corresponding 1109 1.1 mrg * to functions that are not marked as constructors, including those 1110 1.1 mrg * that set a persistent callback and those that set an enum value. 1111 1.1 mrg * 1112 1.1 mrg * Finally, we tell ctypes about the types of the arguments of the 1113 1.1 mrg * constructor functions and the return types of those function returning 1114 1.1 mrg * an isl object. 1115 1.1 mrg */ 1116 1.1 mrg void python_generator::print(const isl_class &clazz) 1117 1.1 mrg { 1118 1.1 mrg string p_name = type2python(clazz.subclass_name); 1119 1.1 mrg vector<string> super = find_superclasses(clazz.type); 1120 1.1 mrg const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks; 1121 1.1 mrg 1122 1.1 mrg for (unsigned i = 0; i < super.size(); ++i) 1123 1.1 mrg if (done.find(super[i]) == done.end()) 1124 1.1 mrg print(classes[super[i]]); 1125 1.1 mrg if (clazz.is_type_subclass() && done.find(clazz.name) == done.end()) 1126 1.1 mrg print(classes[clazz.name]); 1127 1.1 mrg done.insert(clazz.subclass_name); 1128 1.1 mrg 1129 1.1 mrg printf("\n"); 1130 1.1 mrg print_class_header(clazz, p_name, super); 1131 1.1 mrg printf(" def __init__(self, *args, **keywords):\n"); 1132 1.1 mrg 1133 1.1 mrg printf(" if \"ptr\" in keywords:\n"); 1134 1.1 mrg printf(" self.ctx = keywords[\"ctx\"]\n"); 1135 1.1 mrg printf(" self.ptr = keywords[\"ptr\"]\n"); 1136 1.1 mrg printf(" return\n"); 1137 1.1 mrg 1138 1.1 mrg for (const auto &cons : clazz.constructors) 1139 1.1 mrg print_constructor(clazz, cons); 1140 1.1 mrg print_special_constructors(clazz); 1141 1.1 mrg print_upcast_constructors(clazz); 1142 1.1 mrg printf(" raise Error\n"); 1143 1.1 mrg printf(" def __del__(self):\n"); 1144 1.1 mrg printf(" if hasattr(self, 'ptr'):\n"); 1145 1.1 mrg printf(" isl.%s_free(self.ptr)\n", clazz.name.c_str()); 1146 1.1 mrg 1147 1.1 mrg print_new(clazz, p_name); 1148 1.1 mrg print_representation(clazz, p_name); 1149 1.1 mrg print_copy_callbacks(clazz); 1150 1.1 mrg 1151 1.1 mrg print_special_methods(clazz); 1152 1.1 mrg for (const auto &callback : callbacks) 1153 1.1 mrg print_method(clazz, callback, super); 1154 1.1 mrg for (const auto &kvp : clazz.methods) 1155 1.1 mrg print_method(clazz, kvp.first, kvp.second, super); 1156 1.1 mrg for (const auto &kvp : clazz.set_enums) 1157 1.1 mrg print_set_enum(clazz, kvp.first, super); 1158 1.1 mrg 1159 1.1 mrg printf("\n"); 1160 1.1 mrg 1161 1.1 mrg print_method_types(clazz); 1162 1.1 mrg } 1163 1.1 mrg 1164 1.1 mrg /* Generate a python interface based on the extracted types and 1165 1.1 mrg * functions. 1166 1.1 mrg * 1167 1.1 mrg * Print out each class in turn. If one of these is a subclass of some 1168 1.1 mrg * other class, make sure the superclass is printed out first. 1169 1.1 mrg * functions. 1170 1.1 mrg */ 1171 1.1 mrg void python_generator::generate() 1172 1.1 mrg { 1173 1.1 mrg map<string, isl_class>::iterator ci; 1174 1.1 mrg 1175 1.1 mrg for (ci = classes.begin(); ci != classes.end(); ++ci) { 1176 1.1 mrg if (done.find(ci->first) == done.end()) 1177 1.1 mrg print(ci->second); 1178 1.1 mrg } 1179 1.1 mrg } 1180