Advertisement
Guest User

Untitled

a guest
Dec 3rd, 2016
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 45.79 KB | None | 0 0
  1. from __future__ import print_function
  2.  
  3. __copyright__ = """
  4. Copyright (C) 2016 The MathWorks, Inc.
  5. Copyright (C) 2011-15 Andreas Kloeckner
  6. """
  7.  
  8. __license__ = """
  9. Permission is hereby granted, free of charge, to any person obtaining a copy
  10. of this software and associated documentation files (the "Software"), to deal
  11. in the Software without restriction, including without limitation the rights
  12. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. copies of the Software, and to permit persons to whom the Software is
  14. furnished to do so, subject to the following conditions:
  15.  
  16. The above copyright notice and this permission notice shall be included in
  17. all copies or substantial portions of the Software.
  18.  
  19. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. THE SOFTWARE.
  26. """
  27.  
  28. import re
  29. import sys
  30. import copy
  31. from py_codegen import PythonCodeGenerator, Indentation
  32.  
  33. SEM_TAKE = "take"
  34. SEM_GIVE = "give"
  35. SEM_KEEP = "keep"
  36. SEM_NULL = "null"
  37.  
  38. ISL_SEM_TO_SEM = {
  39. "__isl_take": SEM_TAKE,
  40. "__isl_give": SEM_GIVE,
  41. "__isl_keep": SEM_KEEP,
  42. "__isl_null": SEM_NULL,
  43. }
  44.  
  45. NON_COPYABLE = ["ctx", "printer", "access_info", "vertex", "vertices", "cell",
  46. "flow", "restriction", "union_flow"]
  47. NON_COPYABLE_WITH_ISL_PREFIX = ["isl_"+i for i in NON_COPYABLE]
  48.  
  49. CPP_RESERVED_WORDS = """
  50. and and_eq asm auto bitand
  51. bitor bool break case catch
  52. char class const const_cast continue
  53. default delete do double dynamic_cast
  54. else enum explicit export extern
  55. false float for friend goto
  56. if inline int long mutable
  57. namespace new not not_eq operator
  58. or or_eq private protected public
  59. register reinterpret_cast return short signed
  60. sizeof static static_cast struct switch
  61. template this throw true try
  62. typedef typeid typename union unsigned
  63. using virtual void volatile wchar_t
  64. while xor xor_eq
  65. """.split()
  66.  
  67.  
  68. # {{{ data model
  69.  
  70. def type_cdecl(base_type, type_ptr, decl_words):
  71. return "{decl_words}{optional_space}{base_type}{optional_space2}{ptr}".format(
  72. decl_words=" ".join(decl_words),
  73. optional_space=" " if len(decl_words) > 0 else "",
  74. base_type=base_type,
  75. optional_space2=" " if len(type_ptr) > 0 else "",
  76. ptr=type_ptr)
  77.  
  78. def type_cpp_cls(base_type, type_ptr, decl_words):
  79. # whether it's isl_set* or isl_set**, we return the same `Set` since we're passing by reference
  80. if base_type.startswith("isl_") and (type_ptr == "*" or type_ptr == "**"):
  81. return isl_class_to_cpp_class(base_type)
  82. # there are no char** things in isl, except some obscure argv thing we won't consider
  83. elif base_type in ["const char", "char"] and type_ptr == "*":
  84. return "std::string"
  85. # fallback c_declarator option
  86. return type_cdecl(base_type, type_ptr, decl_words)
  87.  
  88. class Argument:
  89. def __init__(self, name, semantics, decl_words, base_type, ptr):
  90. self.name = name
  91. self.semantics = semantics
  92. assert isinstance(decl_words, list)
  93. self.decl_words = decl_words
  94. self.base_type = base_type
  95. self.ptr = ptr
  96.  
  97. def c_declarator(self):
  98. return "{cdecl}{name}".format(
  99. cdecl=type_cdecl(self.base_type, self.ptr, self.decl_words),
  100. name=self.name)
  101.  
  102. def cpp_cls(self):
  103. ty = type_cpp_cls(self.base_type, self.ptr, self.decl_words)
  104. # whether it's isl_set* or isl_set**, it makes no difference to us
  105. if self.base_type.startswith("isl_"):
  106. if self.base_type[4:] in NON_COPYABLE:
  107. return "{type} &{name}".format(type=ty, name=self.name)
  108. elif self.semantics == SEM_TAKE:
  109. return "{type} &&{name}".format(type=ty, name=self.name)
  110. return "{type} {name}".format(type=ty, name=self.name)
  111.  
  112. class CallbackArgument:
  113. def __init__(self, name,
  114. return_semantics, return_decl_words, return_base_type, return_ptr, args):
  115. self.name = name
  116. self.return_semantics = return_semantics
  117. self.semantics = SEM_KEEP
  118. assert isinstance(return_decl_words, list)
  119. self.return_decl_words = return_decl_words
  120. self.return_base_type = return_base_type
  121. self.base_type = return_base_type
  122. self.return_ptr = return_ptr
  123. self.ptr = return_ptr
  124. self.args = args
  125.  
  126. def c_declarator(self):
  127. return "{cdecl} (*{name})({args})".format(
  128. cdecl=type_cdecl(self.return_base_type, self.return_ptr, self.return_decl_words),
  129. name=self.name,
  130. args=", ".join([arg.c_declarator() for arg in self.args]))
  131.  
  132. def c_declarator_type(self):
  133. return "{cdecl} (*)({args})".format(
  134. cdecl=type_cdecl(self.return_base_type, self.return_ptr, self.return_decl_words),
  135. name=self.name,
  136. args=", ".join([arg.c_declarator() for arg in self.args]))
  137.  
  138. def cpp_cls(self):
  139. return "{type_cpp_cls} (*{name})({args_cpp_cls})".format(
  140. type_cpp_cls=type_cpp_cls(self.return_base_type, self.return_ptr, self.return_decl_words),
  141. name=self.name,
  142. args_cpp_cls=self.args_cpp_cls())
  143.  
  144. def args_cpp_cls(self):
  145. return ", ".join([arg.cpp_cls() for arg in self.args])
  146.  
  147. def ret_cpp_cls(self):
  148. return type_cpp_cls(self.return_base_type, self.return_ptr, self.return_decl_words)
  149.  
  150. class Method:
  151. def __init__(self, cls, name, c_name,
  152. return_semantics, return_decl_words, return_base_type, return_ptr,
  153. args, is_exported, is_constructor):
  154. self.cls = cls
  155. self.name = name
  156. self.c_name = c_name
  157. self.return_semantics = return_semantics
  158. self.return_decl_words = return_decl_words
  159. self.return_base_type = return_base_type
  160. self.return_ptr = return_ptr
  161. self.args = args
  162. self.mutator_veto = False
  163. self.is_exported = is_exported
  164. self.is_constructor = is_constructor
  165.  
  166. if not self.is_static:
  167. self.args[0].name = "*this"
  168.  
  169. @property
  170. def is_static(self):
  171. return not (self.args and self.args[0].base_type.startswith("isl_"+self.cls))
  172.  
  173. @property
  174. def is_mutator(self):
  175. return (not self.is_static
  176. and self.args[0].semantics is SEM_TAKE
  177. and self.return_ptr == "*" == self.args[0].ptr
  178. and self.return_base_type == self.args[0].base_type
  179. and self.return_semantics is SEM_GIVE
  180. and not self.mutator_veto
  181. and self.args[0].base_type in NON_COPYABLE_WITH_ISL_PREFIX)
  182.  
  183. def ret_cpp_cls(self):
  184. ty = type_cpp_cls(self.return_base_type, self.return_ptr, self.return_decl_words)
  185. return ty
  186.  
  187. def args_cpp_cls(self):
  188. return ", ".join([arg.cpp_cls() for arg in self.args])
  189.  
  190. def prune_this(self):
  191. meth = copy.copy(self)
  192. if len(meth.args) > 0 and meth.args[0].base_type == "isl_"+meth.cls:
  193. # The first argument is the implicit "this", which is useful while calling the isl version
  194. # of the function, but not useful when declaring or defining the cpp version.
  195. meth.args = meth.args[1:]
  196. return meth
  197. return self
  198.  
  199. def cpp_cls(self):
  200. static_spec = "static " if self.is_static else ""
  201. return "{static_spec}{ret_cpp_cls} {name}({args});".format(
  202. static_spec=static_spec,
  203. ret_cpp_cls=self.ret_cpp_cls(),
  204. name=self.name, # cpp name, not c_name
  205. args=self.prune_this().args_cpp_cls())
  206.  
  207. def __repr__(self):
  208. return "<method %s>" % self.c_name
  209.  
  210. # }}}
  211.  
  212.  
  213. CLASSES = [
  214. # /!\ Order matters, class names that are prefixes of others should go last.
  215.  
  216. "ctx",
  217.  
  218. # lists
  219. "id_list", "val_list",
  220. "basic_set_list", "basic_map_list", "set_list", "map_list",
  221. "union_set_list",
  222. "constraint_list",
  223. "aff_list", "pw_aff_list", "band_list",
  224. "ast_expr_list", "ast_node_list",
  225.  
  226. # maps
  227. "id_to_ast_expr",
  228.  
  229. # others
  230. "printer", "val", "multi_val", "vec", "mat",
  231. "aff", "pw_aff", "union_pw_aff",
  232. "multi_aff", "multi_pw_aff", "pw_multi_aff", "union_pw_multi_aff",
  233. "union_pw_aff_list",
  234. "multi_union_pw_aff",
  235.  
  236. "id",
  237. "constraint", "space", "local_space",
  238.  
  239. "basic_set", "basic_map",
  240. "set", "map",
  241. "union_map", "union_set",
  242. "point", "vertex", "cell", "vertices",
  243.  
  244. "qpolynomial_fold", "pw_qpolynomial_fold",
  245. "union_pw_qpolynomial_fold",
  246. "union_pw_qpolynomial",
  247. "qpolynomial", "pw_qpolynomial",
  248. "term",
  249.  
  250. "band", "schedule_constraints", "schedule_node", "schedule",
  251.  
  252. "access_info", "flow", "restriction",
  253. "union_access_info", "union_flow",
  254.  
  255. "ast_expr", "ast_node", "ast_print_options",
  256. "ast_build",
  257. ]
  258.  
  259. UNTYPEDEFD_CLASSES = ["options"]
  260.  
  261.  
  262. IMPLICIT_CONVERSIONS = {
  263. "isl_set": [("isl_basic_set", "from_basic_set")],
  264. "isl_map": [("isl_basic_map", "from_basic_map")],
  265. "isl_union_set": [("isl_set", "from_set")],
  266. "isl_union_map": [("isl_map", "from_map")],
  267. "isl_local_space": [("isl_space", "from_space")],
  268. "isl_pw_aff": [("isl_aff", "from_aff")],
  269. }
  270.  
  271.  
  272. ENUMS = {
  273. # ctx.h
  274. "isl_error": """
  275. isl_error_none,
  276. isl_error_abort,
  277. isl_error_alloc,
  278. isl_error_unknown,
  279. isl_error_internal,
  280. isl_error_invalid,
  281. isl_error_quota,
  282. isl_error_unsupported,
  283. """,
  284. "isl_stat": """
  285. isl_stat_error,
  286. isl_stat_ok,
  287. """,
  288. "isl_bool": """
  289. isl_bool_error,
  290. isl_bool_false,
  291. isl_bool_true,
  292. """,
  293. # space.h
  294. "isl_dim_type": """
  295. isl_dim_cst,
  296. isl_dim_param,
  297. isl_dim_in,
  298. isl_dim_out,
  299. isl_dim_set,
  300. isl_dim_div,
  301. isl_dim_all,
  302. """,
  303.  
  304. # schedule_type.h
  305. "isl_schedule_node_type": """
  306. isl_schedule_node_error,
  307. isl_schedule_node_band,
  308. isl_schedule_node_context,
  309. isl_schedule_node_domain,
  310. isl_schedule_node_expansion,
  311. isl_schedule_node_extension,
  312. isl_schedule_node_filter,
  313. isl_schedule_node_leaf,
  314. isl_schedule_node_guard,
  315. isl_schedule_node_mark,
  316. isl_schedule_node_sequence,
  317. isl_schedule_node_set,
  318. """,
  319.  
  320. # ast_type.h
  321. "isl_ast_op_type": """
  322. isl_ast_op_error,
  323. isl_ast_op_and,
  324. isl_ast_op_and_then,
  325. isl_ast_op_or,
  326. isl_ast_op_or_else,
  327. isl_ast_op_max,
  328. isl_ast_op_min,
  329. isl_ast_op_minus,
  330. isl_ast_op_add,
  331. isl_ast_op_sub,
  332. isl_ast_op_mul,
  333. isl_ast_op_div,
  334. isl_ast_op_fdiv_q,
  335. isl_ast_op_pdiv_q,
  336. isl_ast_op_pdiv_r,
  337. isl_ast_op_zdiv_r,
  338. isl_ast_op_cond,
  339. isl_ast_op_select,
  340. isl_ast_op_eq,
  341. isl_ast_op_le,
  342. isl_ast_op_lt,
  343. isl_ast_op_ge,
  344. isl_ast_op_gt,
  345. isl_ast_op_call,
  346. isl_ast_op_access,
  347. isl_ast_op_member,
  348. isl_ast_op_address_of,
  349. """,
  350. "isl_ast_expr_type": """
  351. isl_ast_expr_error,
  352. isl_ast_expr_op,
  353. isl_ast_expr_id,
  354. isl_ast_expr_int,
  355. """,
  356. "isl_ast_node_type": """
  357. isl_ast_node_error,
  358. isl_ast_node_for,
  359. isl_ast_node_if,
  360. isl_ast_node_block,
  361. isl_ast_node_mark,
  362. isl_ast_node_user,
  363. """,
  364. "isl_ast_loop_type": """
  365. isl_ast_loop_error,
  366. isl_ast_loop_default,
  367. isl_ast_loop_atomic,
  368. isl_ast_loop_unroll,
  369. isl_ast_loop_separate,
  370. """,
  371.  
  372. # polynomial_type.h
  373. "isl_fold": """
  374. isl_fold_min,
  375. isl_fold_max,
  376. isl_fold_list,
  377. """,
  378.  
  379. # printer.h
  380. "isl_format": """
  381. ISL_FORMAT_ISL,
  382. ISL_FORMAT_POLYLIB,
  383. ISL_FORMAT_POLYLIB_CONSTRAINTS,
  384. ISL_FORMAT_OMEGA,
  385. ISL_FORMAT_C,
  386. ISL_FORMAT_LATEX,
  387. ISL_FORMAT_EXT_POLYLIB,
  388. """,
  389.  
  390. "isl_yaml_style": """
  391. ISL_YAML_STYLE_BLOCK,
  392. ISL_YAML_STYLE_FLOW,
  393. """,
  394.  
  395. # options.h
  396.  
  397. "isl_bound": """
  398. ISL_BOUND_BERNSTEIN,
  399. ISL_BOUND_RANGE,
  400. """,
  401.  
  402. "isl_on_error": """
  403. ISL_ON_ERROR_WARN,
  404. ISL_ON_ERROR_CONTINUE,
  405. ISL_ON_ERROR_ABORT,
  406. """,
  407.  
  408. "isl_schedule_algorithm": """
  409. ISL_SCHEDULE_ALGORITHM_ISL,
  410. ISL_SCHEDULE_ALGORITHM_FEAUTRIER,
  411. """
  412. }
  413.  
  414. # isl_basic_set_multiplicative_call is actually blacklisted due to
  415. # absence of "user" pointer in callback
  416. DEPRECATED_METHODS = [ "isl_space_tuple_match",
  417. "isl_basic_set_add",
  418. "isl_basic_set_multiplicative_call" ]
  419.  
  420. MACRO_ENUMS = [
  421. "isl_format", "isl_yaml_style",
  422. "isl_bound", "isl_on_error", "isl_schedule_algorithm",
  423. ]
  424.  
  425. SPECIAL_CLASS_NAME_MAP = {
  426. "ctx": "Context"
  427. }
  428.  
  429. def isl_class_to_cpp_class(cls_name):
  430. if cls_name.startswith("isl_"):
  431. cls_name = cls_name[4:]
  432. try:
  433. return SPECIAL_CLASS_NAME_MAP[cls_name]
  434. except KeyError:
  435. return ''.join(piece.capitalize() for piece in cls_name.split('_'))
  436.  
  437. HEADER_PREAMBLE = """
  438. #pragma once
  439.  
  440. #include "isl/ctx.h"
  441. #include "isl/id.h"
  442. #include "isl/space.h"
  443. #include "isl/set.h"
  444. #include "isl/map.h"
  445. #include "isl/local_space.h"
  446. #include "isl/aff.h"
  447. #include "isl/polynomial.h"
  448. #include "isl/union_map.h"
  449. #include "isl/union_set.h"
  450. #include "isl/printer.h"
  451. #include "isl/vertices.h"
  452. #include "isl/point.h"
  453. #include "isl/constraint.h"
  454. #include "isl/val.h"
  455. #include "isl/vec.h"
  456. #include "isl/mat.h"
  457. #include "isl/band.h"
  458. #include "isl/schedule.h"
  459. #include "isl/schedule_node.h"
  460. #include "isl/flow.h"
  461. #include "isl/options.h"
  462. #include "isl/ast.h"
  463. #include "isl/ast_build.h"
  464. #include "isl/ilp.h"
  465.  
  466. #include <unordered_map>
  467. #include <string>
  468. #include <cassert>
  469.  
  470. namespace isl {
  471.  
  472. // Forward declares
  473. void lowerCtxRefCount(isl_ctx* aCtx);
  474. void increaseCtxRefCount(isl_ctx* aCtx);
  475.  
  476. // Forward declares to resolve dependency cycles
  477. """ + "\n".join(["class %s;" % isl_class_to_cpp_class(cls) for cls in CLASSES]) + """
  478.  
  479. // We have to reference count isl_ctx objects; free it when all objects of the context are freed.
  480. extern std::unordered_map<void*, unsigned> contextUseMap;
  481.  
  482. template <typename IslObjT>
  483. class IslObjectBase {
  484. protected:
  485. IslObjT *fData;
  486. isl_ctx *fCtx;
  487. public:
  488. // called from copy constructor or plainly
  489. IslObjectBase(const IslObjT* aData, isl_ctx* aCtx)
  490. : fData(const_cast<IslObjT*>(aData)) // necessary due to fine constructor matching
  491. , fCtx(aCtx)
  492. {
  493. increaseCtxRefCount(fCtx);
  494. }
  495.  
  496. // called from move constructor
  497. IslObjectBase(IslObjT* &&aData, isl_ctx* aCtx)
  498. : fData(aData)
  499. , fCtx(aCtx)
  500. {
  501. aData = nullptr;
  502. }
  503.  
  504. // the derived class destructor has already done its thing
  505. virtual ~IslObjectBase() = default;
  506.  
  507. // don't work with base-class objects
  508. IslObjectBase(const IslObjectBase<IslObjT> &aOther) = delete;
  509. IslObjectBase<IslObjT> &operator=(const IslObjectBase<IslObjT> &aOther) = delete;
  510.  
  511. IslObjT *release() {
  512. assert(fData && "cannot release already-released object");
  513. lowerCtxRefCount(fCtx);
  514. auto data = fData;
  515. fData = nullptr;
  516. return data;
  517. }
  518.  
  519. bool operator==(IslObjectBase<IslObjT> &aOther) {
  520. return fData == aOther.fData;
  521. }
  522.  
  523. bool operator!=(IslObjectBase<IslObjT> &aOther) {
  524. return !(this == aOther);
  525. }
  526. };
  527. """
  528.  
  529. CPP_PREAMBLE = """
  530. #include "{header_location}"
  531.  
  532. namespace isl {{
  533.  
  534. // Concrete realization of the context map
  535. std::unordered_map<void*, unsigned> contextUseMap;
  536.  
  537. void lowerCtxRefCount(isl_ctx* aCtx) {{
  538. contextUseMap[aCtx] -= 1;
  539. if (!contextUseMap[aCtx]) {{
  540. contextUseMap.erase(aCtx);
  541. isl_ctx_free(aCtx);
  542. }}
  543. }}
  544.  
  545. void increaseCtxRefCount(isl_ctx* aCtx) {{
  546. auto it = contextUseMap.find(aCtx);
  547. contextUseMap[aCtx] = it == contextUseMap.end() ? 1 : it->second + 1;
  548. }}
  549.  
  550. """
  551.  
  552. SAFE_TYPES = list(ENUMS) + ["int", "unsigned", "uint32_t", "size_t", "double",
  553. "long", "unsigned long"]
  554. SAFE_IN_TYPES = SAFE_TYPES + ["const char *", "char *"]
  555.  
  556. # {{{ parser
  557.  
  558. DECL_RE = re.compile(r"""
  559. (?:__isl_overload\s*)?
  560. ((?:\w+\s+)*) (\**) \s* (?# return type)
  561. (\w+) (?# func name)
  562. \(
  563. (.*) (?# args)
  564. \)
  565. """,
  566. re.VERBOSE)
  567. FUNC_PTR_RE = re.compile(r"""
  568. ((?:\w+\s+)*) (\**) \s* (?# return type)
  569. \(\*(\w+)\) (?# func name)
  570. \(
  571. (.*) (?# args)
  572. \)
  573. """,
  574. re.VERBOSE)
  575. STRUCT_DECL_RE = re.compile(
  576. r"(__isl_export\s+)?"
  577. "struct\s+"
  578. "(__isl_subclass\([a-z_ ]+\)\s+)?"
  579. "([a-z_A-Z0-9]+)\s*;")
  580. ARG_RE = re.compile(r"^((?:\w+)\s+)+(\**)\s*(\w+)$")
  581. INLINE_SEMICOLON_RE = re.compile(r"\;[ \t]*(?=\w)")
  582.  
  583.  
  584. def filter_semantics(words):
  585. semantics = []
  586. other_words = []
  587. for w in words:
  588. if w in ISL_SEM_TO_SEM:
  589. semantics.append(ISL_SEM_TO_SEM[w])
  590. else:
  591. other_words.append(w)
  592.  
  593. if semantics:
  594. assert len(semantics) == 1
  595. return semantics[0], other_words
  596. else:
  597. return None, other_words
  598.  
  599.  
  600. def split_at_unparenthesized_commas(s):
  601. paren_level = 0
  602. i = 0
  603. last_start = 0
  604.  
  605. while i < len(s):
  606. c = s[i]
  607. if c == "(":
  608. paren_level += 1
  609. elif c == ")":
  610. paren_level -= 1
  611. elif c == "," and paren_level == 0:
  612. yield s[last_start:i]
  613. last_start = i+1
  614.  
  615. i += 1
  616.  
  617. yield s[last_start:i]
  618.  
  619.  
  620. class BadArg(ValueError):
  621. pass
  622.  
  623.  
  624. class Retry(ValueError):
  625. pass
  626.  
  627.  
  628. class Undocumented(ValueError):
  629. pass
  630.  
  631.  
  632. class SignatureNotSupported(ValueError):
  633. pass
  634.  
  635.  
  636. def parse_arg(arg):
  637. if "(*" in arg:
  638. arg_match = FUNC_PTR_RE.match(arg)
  639. assert arg_match is not None, "fptr: %s" % arg
  640.  
  641. return_semantics, ret_words = filter_semantics(
  642. arg_match.group(1).split())
  643. return_decl_words = ret_words[:-1]
  644. return_base_type = ret_words[-1]
  645.  
  646. return_ptr = arg_match.group(2)
  647. name = arg_match.group(3)
  648. args = [parse_arg(i.strip())
  649. for i in split_at_unparenthesized_commas(arg_match.group(4))]
  650.  
  651. return CallbackArgument(name.strip(),
  652. return_semantics,
  653. return_decl_words,
  654. return_base_type,
  655. return_ptr.strip(),
  656. args)
  657.  
  658. words = arg.split()
  659. semantics, words = filter_semantics(words)
  660.  
  661. decl_words = []
  662. if words[0] in ["struct", "enum"]:
  663. decl_words.append(words.pop(0))
  664.  
  665. rebuilt_arg = " ".join(words)
  666. arg_match = ARG_RE.match(rebuilt_arg)
  667.  
  668. base_type = arg_match.group(1).strip()
  669.  
  670. if base_type == "isl_args":
  671. raise BadArg("isl_args not supported")
  672.  
  673. assert arg_match is not None, rebuilt_arg
  674. return Argument(
  675. name=arg_match.group(3),
  676. semantics=semantics,
  677. decl_words=decl_words,
  678. base_type=base_type,
  679. ptr=arg_match.group(2).strip())
  680.  
  681.  
  682. class FunctionData:
  683. def __init__(self, include_dirs):
  684. self.classes_to_methods = {}
  685. self.include_dirs = include_dirs
  686. self.seen_c_names = set()
  687.  
  688. self.headers = []
  689.  
  690. def read_header(self, fname):
  691. self.headers.append(fname)
  692.  
  693. from os.path import join
  694. success = False
  695. for inc_dir in self.include_dirs:
  696. try:
  697. inf = open(join(inc_dir, fname), "rt")
  698. except IOError:
  699. pass
  700. else:
  701. success = True
  702. break
  703.  
  704. if not success:
  705. raise RuntimeError("header '%s' not found" % fname)
  706.  
  707. try:
  708. lines = inf.readlines()
  709. finally:
  710. inf.close()
  711.  
  712. # heed continuations, split at semicolons
  713. new_lines = []
  714. i = 0
  715. while i < len(lines):
  716. my_line = lines[i].strip()
  717. i += 1
  718.  
  719. while my_line.endswith("\\"):
  720. my_line = my_line[:-1] + lines[i].strip()
  721. i += 1
  722.  
  723. if not my_line.strip().startswith("#"):
  724. my_line = INLINE_SEMICOLON_RE.sub(";\n", my_line)
  725. new_lines.extend(my_line.split("\n"))
  726.  
  727. lines = new_lines
  728.  
  729. i = 0
  730.  
  731. while i < len(lines):
  732. l = lines[i].strip()
  733.  
  734. if (not l
  735. or l.startswith("extern")
  736. or STRUCT_DECL_RE.search(l)
  737. or l.startswith("typedef")
  738. or l == "}"):
  739. i += 1
  740. elif "/*" in l:
  741. while True:
  742. if "*/" in l:
  743. i += 1
  744. break
  745.  
  746. i += 1
  747.  
  748. l = lines[i].strip()
  749. elif l.endswith("{"):
  750. while True:
  751. if "}" in l:
  752. i += 1
  753. break
  754.  
  755. i += 1
  756.  
  757. l = lines[i].strip()
  758.  
  759. elif not l:
  760. i += 1
  761.  
  762. else:
  763. decl = ""
  764.  
  765. while True:
  766. decl = decl + l
  767. if decl:
  768. decl += " "
  769. i += 1
  770. if STRUCT_DECL_RE.search(decl):
  771. break
  772.  
  773. open_par_count = sum(1 for i in decl if i == "(")
  774. close_par_count = sum(1 for i in decl if i == ")")
  775. if open_par_count and open_par_count == close_par_count:
  776. break
  777. l = lines[i].strip()
  778.  
  779. if not STRUCT_DECL_RE.search(decl):
  780. self.parse_decl(decl)
  781.  
  782. def parse_decl(self, decl):
  783. decl_match = DECL_RE.match(decl)
  784. if decl_match is None:
  785. print("WARNING: func decl regexp not matched: %s" % decl)
  786. return
  787.  
  788. return_base_type = decl_match.group(1)
  789. return_base_type = return_base_type.replace("ISL_DEPRECATED", "").strip()
  790.  
  791. return_ptr = decl_match.group(2)
  792. c_name = decl_match.group(3)
  793. args = [i.strip()
  794. for i in split_at_unparenthesized_commas(decl_match.group(4))]
  795.  
  796. if args == ["void"]:
  797. args = []
  798.  
  799. if c_name in [
  800. "ISL_ARG_DECL",
  801. "ISL_DECLARE_LIST",
  802. "ISL_DECLARE_LIST_FN",
  803. "isl_ast_op_type_print_macro",
  804. "ISL_DECLARE_MULTI",
  805. "ISL_DECLARE_MULTI_NEG",
  806. "ISL_DECLARE_MULTI_DIMS",
  807. "ISL_DECLARE_MULTI_WITH_DOMAIN",
  808. "isl_malloc_or_die",
  809. "isl_calloc_or_die",
  810. "isl_realloc_or_die",
  811. "isl_handle_error",
  812. ]:
  813. return
  814.  
  815. assert c_name.startswith("isl_"), c_name
  816. name = c_name[4:]
  817.  
  818. found_class = False
  819. for cls in CLASSES:
  820. if name.startswith(cls):
  821. found_class = True
  822. name = name[len(cls)+1:]
  823. break
  824.  
  825. # Don't be tempted to chop off "_val"--the "_val" versions of
  826. # some methods are incompatible with the isl_int ones.
  827. #
  828. # (For example, isl_aff_get_constant() returns just the constant,
  829. # but isl_aff_get_constant_val() returns the constant divided by
  830. # the denominator.)
  831. #
  832. # To avoid breaking user code in non-obvious ways, the new
  833. # names are carried over to the Python level.
  834.  
  835. if not found_class:
  836. if name.startswith("options_"):
  837. found_class = True
  838. cls = "ctx"
  839. name = name[len("options_"):]
  840. elif name.startswith("equality_") or name.startswith("inequality_"):
  841. found_class = True
  842. cls = "constraint"
  843. elif name == "ast_op_type_set_print_name":
  844. found_class = True
  845. cls = "printer"
  846. name = "ast_op_type_set_print_name"
  847.  
  848. if name.startswith("2"):
  849. name = "two_"+name[1:]
  850.  
  851. assert found_class, name
  852.  
  853. try:
  854. args = [parse_arg(arg) for arg in args]
  855. except BadArg:
  856. print("SKIP: %s %s" % (cls, name))
  857. return
  858.  
  859. if name in CPP_RESERVED_WORDS:
  860. name = name + "_"
  861.  
  862. if cls == "options":
  863. assert name.startswith("set_") or name.startswith("get_"), (name, c_name)
  864. name = name[:4]+"option_"+name[4:]
  865.  
  866. words = return_base_type.split()
  867.  
  868. is_exported = "__isl_export" in words
  869. if is_exported:
  870. words.remove("__isl_export")
  871.  
  872. is_constructor = "__isl_constructor" in words
  873. if is_constructor:
  874. words.remove("__isl_constructor")
  875.  
  876. return_semantics, words = filter_semantics(words)
  877. return_decl_words = []
  878. if words[0] in ["struct", "enum"]:
  879. return_decl_words.append(words.pop(0))
  880. return_base_type = " ".join(words)
  881.  
  882. cls_meth_list = self.classes_to_methods.setdefault(cls, [])
  883.  
  884. if c_name in self.seen_c_names:
  885. return
  886.  
  887. cls_meth_list.append(Method(
  888. cls, name, c_name,
  889. return_semantics, return_decl_words, return_base_type, return_ptr,
  890. args, is_exported=is_exported, is_constructor=is_constructor))
  891.  
  892. self.seen_c_names.add(c_name)
  893.  
  894. # }}}
  895.  
  896.  
  897. # {{{ python wrapper writer
  898.  
  899. def write_method_prototype(gen, meth):
  900. if meth.name == "options": return
  901. gen(meth.cpp_cls())
  902.  
  903. def write_class(gen, cls_name, methods):
  904. cpp_cls = isl_class_to_cpp_class(cls_name)
  905. gen("class {cpp_cls} : public IslObjectBase<isl_{cls}> {{".format(cls=cls_name, cpp_cls=cpp_cls))
  906. gen("public:")
  907. with Indentation(gen):
  908. # Constructor
  909. gen("""
  910. {cpp_cls}(isl_{cls} *aData) : IslObjectBase(aData, ctx(aData)) {{}}
  911. """
  912. .format(cpp_cls=cpp_cls, cls=cls_name))
  913.  
  914. # Alternate constructors, auto-conversions
  915. gen_conversions(gen, cls_name)
  916. gen("")
  917.  
  918. if cls_name == "ctx":
  919. gen("""
  920. isl_ctx *ctx(isl_ctx *aData) {{
  921. return aData;
  922. }}
  923.  
  924. ~{cpp_cls}() {{
  925. if (fData) {{
  926. release();
  927. }}
  928. }}
  929. """
  930. .format(cpp_cls=cpp_cls))
  931. gen("")
  932.  
  933. else:
  934. gen("""
  935. isl_ctx *ctx(isl_{cls} *aData) {{
  936. return isl_{cls}_get_ctx(aData);
  937. }}
  938.  
  939. ~{cpp_cls}() {{
  940. if (fData) {{
  941. isl_{cls}_free(fData);
  942. lowerCtxRefCount(fCtx);
  943. }}
  944. }}
  945. """
  946. .format(cls=cls_name, cpp_cls=cpp_cls))
  947. gen("")
  948.  
  949. # Implicit conversion to underlying data type
  950. gen("""
  951. operator isl_{cls}*() {{
  952. return fData;
  953. }}
  954.  
  955. isl_{cls} **operator &() {{
  956. return &fData;
  957. }}
  958. """.format(cls=cls_name))
  959. gen("")
  960.  
  961. if cls_name in NON_COPYABLE:
  962. # copy constructor and move constructor
  963. gen("""
  964. // non-copyable
  965. {cpp_cls}(const {cpp_cls} &aOther) = delete;
  966.  
  967. // but movable
  968. {cpp_cls}({cpp_cls} &&aOther)
  969. : IslObjectBase(std::move(aOther.fData), ctx(aOther.fData)) {{}}
  970. """
  971. .format(cls=cls_name, cpp_cls=cpp_cls))
  972. gen("")
  973.  
  974. # copy assignment operator and move assignment operator
  975. gen("""
  976. {cpp_cls} &operator=(const {cpp_cls} &aOther) = delete;
  977.  
  978. {cpp_cls} &operator=({cpp_cls} &&aOther) {{
  979. fData = aOther.fData;
  980. aOther.fData = nullptr;
  981. fCtx = aOther.fCtx;
  982. return *this;
  983. }}
  984. """.format(cls=cls_name, cpp_cls=cpp_cls))
  985. gen("")
  986. else:
  987. # copy constructor and move constructor
  988. gen("""
  989. // copyable
  990. {cpp_cls}(const {cpp_cls} &aOther)
  991. : IslObjectBase(aOther.fData, ctx(aOther.fData)) // need to call
  992. // lvalue constructor
  993. {{
  994. fData = isl_{cls}_copy(aOther.fData); // do this separately to avoid
  995. // calling the rvalue constructor
  996. }}
  997.  
  998. // movable too
  999. {cpp_cls}({cpp_cls} &&aOther)
  1000. : IslObjectBase(std::move(aOther.fData), ctx(aOther.fData)) {{}}
  1001. """
  1002. .format(cls=cls_name, cpp_cls=cpp_cls))
  1003. gen("")
  1004.  
  1005. # copy assignment operator and move assignment operator
  1006. gen("""
  1007. {cpp_cls} &operator=(const {cpp_cls} &aOther) {{
  1008. fData = isl_{cls}_copy(aOther.fData);
  1009. fCtx = aOther.fCtx;
  1010. increaseCtxRefCount(fCtx);
  1011. return *this;
  1012. }}
  1013.  
  1014. {cpp_cls} &operator=({cpp_cls} &&aOther) {{
  1015. fData = aOther.fData;
  1016. aOther.fData = nullptr;
  1017. fCtx = aOther.fCtx;
  1018. return *this;
  1019. }}
  1020. """.format(cls=cls_name, cpp_cls=cpp_cls))
  1021. gen("")
  1022.  
  1023. # method prototypes
  1024. [write_method_prototype(gen, meth) for meth in methods]
  1025.  
  1026. # Closing brace of class
  1027. gen("};")
  1028.  
  1029. def gen_conversions(gen, tgt_cls):
  1030. conversions = IMPLICIT_CONVERSIONS.get(tgt_cls, [])
  1031. for src_cls, conversion_method in conversions:
  1032. gen_conversions(gen, src_cls, name)
  1033.  
  1034. gen("""
  1035. {cpp_tgt_cls}({cpp_src_cls} aEl)
  1036. : {cpp_tgt_cls}({cpp_src_cls}.{conversion_method}(aEl)) {{}}
  1037. """
  1038. .format(
  1039. cpp_tgt_cls=isl_class_to_cpp_class(tgt_cls),
  1040. cpp_src_cls=isl_class_to_cpp_class(src_cls),
  1041. conversion_method=conversion_method))
  1042.  
  1043.  
  1044. def gen_callback_wrapper(gen, cb, func_name, has_userptr):
  1045. passed_args = []
  1046. input_args = []
  1047.  
  1048. if has_userptr:
  1049. assert cb.args[-1].name == "user"
  1050.  
  1051. pre_call = PythonCodeGenerator()
  1052. post_call = PythonCodeGenerator()
  1053. result_name = "result"
  1054.  
  1055. for arg in cb.args[:-1]:
  1056. if arg.base_type.startswith("isl_") and arg.ptr == "*":
  1057. input_args.append(arg.name)
  1058. passed_args.append("cpp_%s" % arg.name)
  1059.  
  1060. pre_call(
  1061. "auto cpp_{name} = {cpp_cls}{{{name}}};"
  1062. .format(
  1063. name=arg.name,
  1064. cpp_cls=isl_class_to_cpp_class(arg.base_type)))
  1065.  
  1066. if arg.semantics is SEM_TAKE:
  1067. # We (the callback) are supposed to free the object, so
  1068. # just keep it attached to its wrapper until GC gets
  1069. # rid of it.
  1070. pass
  1071. elif arg.semantics is SEM_KEEP:
  1072. # The caller wants to keep this object, so we'll stop managing
  1073. # it.
  1074. post_call("cpp_{name}.release();".format(name=arg.name))
  1075. else:
  1076. raise SignatureNotSupported(
  1077. "callback arg semantics not understood: %s" % arg.semantics)
  1078.  
  1079. else:
  1080. raise SignatureNotSupported("unsupported callback arg: %s %s" % (
  1081. arg.base_type, arg.ptr))
  1082.  
  1083. if has_userptr:
  1084. input_args.append("user")
  1085. passed_args.append("nullptr")
  1086.  
  1087. if cb.return_base_type in SAFE_IN_TYPES and cb.return_ptr == "":
  1088. pass
  1089.  
  1090. elif cb.return_base_type.startswith("isl_") and cb.return_ptr == "*":
  1091. ret_cpp_cls = isl_class_to_cpp_class(cb.return_base_type)
  1092.  
  1093. if cb.return_semantics is None:
  1094. raise SignatureNotSupported("callback return with unspecified semantics")
  1095. elif cb.return_semantics is not SEM_GIVE:
  1096. raise SignatureNotSupported("callback return with non-GIVE semantics")
  1097.  
  1098. result_name = "result.release()"
  1099.  
  1100. else:
  1101. raise SignatureNotSupported("unsupported callback signature")
  1102.  
  1103. gen(
  1104. "auto {func_name} = []({input_args}) {{"
  1105. .format(
  1106. func_name=func_name,
  1107. input_args=", ".join([arg.c_declarator() for arg in cb.args])))
  1108.  
  1109. with Indentation(gen):
  1110. gen.extend(pre_call)
  1111. gen(
  1112. "{cpp_ret_type} result = reinterpret_cast<{cb_ctype}>({name})({passed_args});"
  1113. .format(cpp_ret_type=cb.ret_cpp_cls(),
  1114. cb_ctype=cb.c_declarator_type(), name="user",
  1115. passed_args=", ".join(passed_args)))
  1116.  
  1117. gen.extend(post_call)
  1118. gen("return {result_name};".format(result_name=result_name))
  1119.  
  1120. gen("};")
  1121.  
  1122.  
  1123. def write_method_wrapper(gen, cls_name, meth):
  1124. pre_call = PythonCodeGenerator()
  1125.  
  1126. # There are two post-call phases, "safety", and "check". The "safety"
  1127. # phase's job is to package up all the data returned by the function
  1128. # called. No exceptions may be raised before safety ends.
  1129. #
  1130. # Next, the "check" phase will perform error checking and may raise exceptions.
  1131. safety = PythonCodeGenerator()
  1132. check = PythonCodeGenerator()
  1133. docs = []
  1134.  
  1135. passed_args = []
  1136. input_args = []
  1137. doc_args = []
  1138. ret_val = None
  1139. ret_descr = None
  1140.  
  1141. arg_idx = 0
  1142. while arg_idx < len(meth.args):
  1143. arg = meth.args[arg_idx]
  1144.  
  1145. if isinstance(arg, CallbackArgument):
  1146. has_userptr = (
  1147. arg_idx + 1 < len(meth.args)
  1148. and meth.args[arg_idx+1].name == "user")
  1149. if has_userptr:
  1150. arg_idx += 1
  1151.  
  1152. cb_wrapper_name = "cb_wrapper_"+arg.name
  1153.  
  1154. gen_callback_wrapper(pre_call, arg, cb_wrapper_name, has_userptr)
  1155.  
  1156. input_args.append(arg.name)
  1157.  
  1158. passed_args.append(cb_wrapper_name)
  1159. if has_userptr:
  1160. passed_args.append("reinterpret_cast<void*>(%s)" % arg.name)
  1161.  
  1162. docs.append(":param %s: callback(%s) -> %s"
  1163. % (
  1164. arg.name,
  1165. ", ".join(
  1166. sub_arg.name
  1167. for sub_arg in arg.args
  1168. if sub_arg.name != "user"),
  1169. arg.return_base_type
  1170. ))
  1171.  
  1172. elif arg.base_type in SAFE_IN_TYPES and not arg.ptr:
  1173. passed_args.append(arg.name)
  1174. input_args.append(arg.name)
  1175. doc_args.append(arg.name)
  1176. doc_cls = arg.base_type
  1177. if doc_cls.startswith("isl_"):
  1178. doc_cls = doc_cls[4:]
  1179.  
  1180. docs.append(":param %s: :class:`%s`" % (arg.name, doc_cls))
  1181.  
  1182. elif arg.base_type in ["char", "const char"] and arg.ptr == "*":
  1183. c_name = "cstr_"+arg.name
  1184.  
  1185. pre_call("auto {c_name} = {arg_name}.c_str();"
  1186. .format(c_name=c_name, arg_name=arg.name))
  1187.  
  1188. if arg.semantics is SEM_TAKE:
  1189. raise SignatureNotSupported("__isl_take %s %s" % (arg.base_type, arg.ptr))
  1190. else:
  1191. passed_args.append(c_name)
  1192. input_args.append(arg.name)
  1193.  
  1194. docs.append(":param %s: string" % arg.name)
  1195.  
  1196. elif arg.base_type == "int" and arg.ptr == "*":
  1197. if arg.name in ["exact", "tight"]:
  1198. passed_args.append(arg.name)
  1199. docs.append(":param %s: int *" % arg.name)
  1200. else:
  1201. raise SignatureNotSupported("int *")
  1202.  
  1203. elif arg.base_type == "isl_val" and arg.ptr == "*" and arg_idx > 0:
  1204. # {{{ val input argument
  1205.  
  1206. val_name = "val_" + arg.name.replace("*", "")
  1207. fmt_args = dict(
  1208. arg0_name=meth.args[0].name,
  1209. name=arg.name,
  1210. val_name=val_name)
  1211.  
  1212. if arg.semantics is SEM_TAKE:
  1213. # we clone Val so we can release the clone
  1214. pre_call("auto {val_name} = {name};".format(**fmt_args))
  1215. passed_args.append(val_name + ".release()")
  1216. else:
  1217. passed_args.append(arg.name)
  1218. input_args.append(arg.name)
  1219.  
  1220. docs.append(":param %s: :class:`Val`" % arg.name)
  1221.  
  1222. # }}}
  1223.  
  1224. elif arg.base_type.startswith("isl_") and arg.ptr == "*":
  1225. # {{{ isl types input arguments
  1226.  
  1227. arg_cpp_cls = isl_class_to_cpp_class(arg.base_type)
  1228.  
  1229. arg_cls = arg.base_type[4:]
  1230. arg_descr = ":param %s: :class:`%s`" % (
  1231. arg.name, isl_class_to_cpp_class(arg_cls))
  1232.  
  1233. if arg.semantics is None and arg.base_type != "isl_ctx":
  1234. raise Undocumented(meth)
  1235.  
  1236. copyable = arg_cls not in NON_COPYABLE
  1237. if arg.semantics is SEM_TAKE:
  1238. if copyable:
  1239. new_name = "copy_"+arg.name.replace("*", "")
  1240. pre_call('auto {copy_name} = {name};'
  1241. .format(copy_name=new_name, name=arg.name))
  1242. arg_descr += " (copied)"
  1243. else:
  1244. new_name = "move_"+arg.name.replace("*", "")
  1245. pre_call('auto {move_name} = std::move({name});'
  1246. .format(move_name=new_name, name=arg.name))
  1247. arg_descr += " (moved)"
  1248.  
  1249. passed_args.append(new_name+".release()")
  1250.  
  1251. elif arg.semantics is SEM_KEEP or arg.semantics is None:
  1252. passed_args.append(arg.name)
  1253.  
  1254. else:
  1255. raise RuntimeError("unexpected semantics: %s" % arg.semantics)
  1256.  
  1257. input_args.append(arg.name)
  1258. docs.append(arg_descr)
  1259.  
  1260. # }}}
  1261.  
  1262. elif arg.base_type.startswith("isl_") and arg.ptr == "**":
  1263. # {{{ isl types output arguments
  1264.  
  1265. if arg.semantics is not SEM_GIVE:
  1266. raise SignatureNotSupported("non-give secondary ptr return value")
  1267.  
  1268. # Stuff is passed by reference anyway, so the ** is irrelevant to us.
  1269. passed_args.append("&{name}".format(name=arg.name))
  1270. # }}}
  1271.  
  1272. elif (arg.base_type == "void"
  1273. and arg.ptr == "*"
  1274. and arg.name == "user"):
  1275.  
  1276. passed_args.append("nullptr")
  1277. input_args.append(arg.name)
  1278.  
  1279. pre_call("""
  1280. assert(!{name} && "passing non-nullptr arguments for '{name}' is not supported");
  1281. """
  1282. .format(name=arg.name))
  1283.  
  1284. docs.append(":param %s: None" % arg.name)
  1285.  
  1286. else:
  1287. raise SignatureNotSupported("arg type %s %s" % (arg.base_type, arg.ptr))
  1288.  
  1289. arg_idx += 1
  1290. pre_call("")
  1291.  
  1292. # {{{ return value processing
  1293.  
  1294. if meth.return_base_type == "isl_stat" and not meth.return_ptr:
  1295. ret_val = "result"
  1296. ret_descr = "isl_stat"
  1297.  
  1298. elif meth.return_base_type == "isl_bool" and not meth.return_ptr:
  1299. ret_val = "result"
  1300. ret_descr = "isl_bool"
  1301.  
  1302. elif meth.return_base_type in SAFE_TYPES and not meth.return_ptr:
  1303. ret_val = "result"
  1304. ret_descr = meth.return_base_type
  1305.  
  1306. elif (meth.return_base_type.startswith("isl_")
  1307. and meth.return_semantics is SEM_NULL):
  1308. assert not meth.is_mutator
  1309.  
  1310. elif meth.return_base_type.startswith("isl_") and meth.return_ptr == "*":
  1311. ret_cls = meth.return_base_type[4:]
  1312.  
  1313. if meth.is_mutator:
  1314. if ret_val:
  1315. meth.mutator_veto = True
  1316. raise Retry()
  1317.  
  1318. # "this" is consumed, so let's put in a safety check so the destructor doesn't try to
  1319. # double-free us
  1320. safety("fData = nullptr;")
  1321. ret_val = "std::move(result)"
  1322. ret_descr = ":class:`%s` (self)" % isl_class_to_cpp_class(ret_cls)
  1323. else:
  1324. if meth.return_semantics is None and ret_cls != "ctx":
  1325. raise Undocumented(meth)
  1326.  
  1327. if meth.return_semantics is not SEM_GIVE and ret_cls != "ctx":
  1328. raise SignatureNotSupported("non-give return")
  1329.  
  1330. py_ret_cls = isl_class_to_cpp_class(ret_cls)
  1331. ret_val = "result"
  1332. ret_descr = ":class:`%s`" % py_ret_cls
  1333.  
  1334. elif meth.return_base_type in ["const char", "char"] and meth.return_ptr == "*":
  1335. # auto-constructs std::string at return time
  1336. ret_val = "result"
  1337. ret_descr = "string"
  1338.  
  1339. elif (meth.return_base_type == "void"
  1340. and meth.return_ptr == "*"
  1341. and meth.name == "get_user"):
  1342.  
  1343. raise SignatureNotSupported("get_user")
  1344.  
  1345. elif meth.return_base_type == "void" and not meth.return_ptr:
  1346. pass
  1347.  
  1348. else:
  1349. raise SignatureNotSupported("ret type: %s %s in %s" % (
  1350. meth.return_base_type, meth.return_ptr, meth))
  1351.  
  1352. # }}}
  1353.  
  1354. check("")
  1355. if not ret_val:
  1356. ret_descr = "(nothing)"
  1357.  
  1358. else:
  1359. check("return " + ret_val + ";")
  1360. ret_descr = ret_descr
  1361.  
  1362. docs = (["%s(%s)" % (meth.name, ", ".join(input_args)), ""]
  1363. + docs
  1364. + [":return: %s" % ret_descr])
  1365.  
  1366. cpp_cls = isl_class_to_cpp_class(cls_name)
  1367.  
  1368. # doxygen comments
  1369. gen('\n'.join(["/// " + doc for doc in [""] + docs]))
  1370. gen("{ret_cpp_cls} {cpp_cls}::{name}({input_args}) {{"
  1371. .format(ret_cpp_cls=meth.ret_cpp_cls(), cpp_cls=cpp_cls,
  1372. name=meth.name, input_args=meth.prune_this().args_cpp_cls()))
  1373.  
  1374. gen.indent()
  1375. gen("")
  1376. gen.extend(pre_call)
  1377. gen("")
  1378.  
  1379. if ret_val:
  1380. gen("{ret_cpp_cls} result = {c_name}({args});"
  1381. .format(ret_cpp_cls=meth.ret_cpp_cls(), c_name=meth.c_name, args=", ".join(passed_args)))
  1382. else:
  1383. gen("{c_name}({args});".format(c_name=meth.c_name, args=", ".join(passed_args)))
  1384.  
  1385. gen.extend(safety)
  1386. gen.extend(check)
  1387. gen.dedent()
  1388. gen("}")
  1389. gen("")
  1390.  
  1391. # }}}
  1392.  
  1393.  
  1394. ADD_VERSIONS = {
  1395. "union_pw_aff": 15,
  1396. "multi_union_pw_aff": 15,
  1397. "basic_map_list": 15,
  1398. "map_list": 15,
  1399. "union_set_list": 15,
  1400. }
  1401.  
  1402.  
  1403. def gen_wrapper(include_dirs, include_barvinok=False, isl_version=None,
  1404. wrapper_header_location="Isl.hpp"):
  1405. fdata = FunctionData(["."] + include_dirs)
  1406. fdata.read_header("isl/ctx.h")
  1407. fdata.read_header("isl/id.h")
  1408. fdata.read_header("isl/space.h")
  1409. fdata.read_header("isl/set.h")
  1410. fdata.read_header("isl/map.h")
  1411. fdata.read_header("isl/local_space.h")
  1412. fdata.read_header("isl/aff.h")
  1413. fdata.read_header("isl/polynomial.h")
  1414. fdata.read_header("isl/union_map.h")
  1415. fdata.read_header("isl/union_set.h")
  1416. fdata.read_header("isl/printer.h")
  1417. fdata.read_header("isl/vertices.h")
  1418. fdata.read_header("isl/point.h")
  1419. fdata.read_header("isl/constraint.h")
  1420. fdata.read_header("isl/val.h")
  1421. fdata.read_header("isl/vec.h")
  1422. fdata.read_header("isl/mat.h")
  1423. fdata.read_header("isl/band.h")
  1424. fdata.read_header("isl/schedule.h")
  1425. fdata.read_header("isl/schedule_node.h")
  1426. fdata.read_header("isl/flow.h")
  1427. fdata.read_header("isl/options.h")
  1428. fdata.read_header("isl/ast.h")
  1429. fdata.read_header("isl/ast_build.h")
  1430. fdata.read_header("isl/ilp.h")
  1431.  
  1432. if isl_version is None:
  1433. fdata.read_header("isl_declaration_macros_expanded.h")
  1434. else:
  1435. fdata.read_header("isl_declaration_macros_expanded_v%d.h"
  1436. % isl_version)
  1437. fdata.headers.pop()
  1438.  
  1439. undoc = []
  1440.  
  1441. with open("islpy/Isl.hpp", "wt") as wrapper_f:
  1442. wrapper_gen = PythonCodeGenerator()
  1443.  
  1444. wrapper_f.write(
  1445. "// AUTOMATICALLY GENERATED by gen_wrap.py -- do not edit\n")
  1446. wrapper_f.write(HEADER_PREAMBLE)
  1447.  
  1448. wrapper_gen("// {{{ classes")
  1449.  
  1450. for cls_name in CLASSES:
  1451. methods = fdata.classes_to_methods.get(cls_name, [])
  1452. methods = [meth for meth in methods if meth.c_name not in DEPRECATED_METHODS]
  1453.  
  1454. # First, write the class with prototypes of member functions.
  1455. write_class(wrapper_gen, cls_name, methods)
  1456. wrapper_gen("")
  1457.  
  1458. wrapper_gen("// }}}")
  1459. wrapper_gen("} // end namespace isl")
  1460. wrapper_gen("")
  1461.  
  1462. wrapper_f.write("\n" + wrapper_gen.get())
  1463.  
  1464. with open("islpy/Isl.cpp", "wt") as wrapper_f:
  1465. wrapper_gen = PythonCodeGenerator()
  1466.  
  1467. wrapper_f.write(
  1468. "// AUTOMATICALLY GENERATED by gen_wrap.py -- do not edit\n")
  1469. wrapper_f.write(CPP_PREAMBLE.format(header_location=wrapper_header_location))
  1470.  
  1471. for cls_name in CLASSES:
  1472. methods = fdata.classes_to_methods.get(cls_name, [])
  1473. methods = [meth for meth in methods if meth.c_name not in DEPRECATED_METHODS]
  1474.  
  1475. # Then define all the methods.
  1476. wrapper_gen("// {{{ methods of " + cls_name)
  1477. wrapper_gen("")
  1478.  
  1479. for meth in methods:
  1480. if meth.name in ["free", "set_free_user"]:
  1481. continue
  1482.  
  1483. try:
  1484. write_method_wrapper(wrapper_gen, cls_name, meth)
  1485. except Retry:
  1486. write_method_wrapper(wrapper_gen, cls_name, meth)
  1487. except Undocumented:
  1488. undoc.append(str(meth))
  1489. except SignatureNotSupported:
  1490. _, e, _ = sys.exc_info()
  1491. print("SKIP (sig not supported: %s): %s" % (e, meth))
  1492. else:
  1493. pass
  1494.  
  1495. wrapper_gen("// }}}")
  1496. wrapper_gen("")
  1497.  
  1498. wrapper_gen("// }}}")
  1499. wrapper_gen("} // end namespace isl")
  1500. wrapper_gen("")
  1501.  
  1502. wrapper_f.write("\n" + wrapper_gen.get())
  1503.  
  1504. print("SKIP (%d undocumented methods): %s" % (len(undoc), ", ".join(undoc)))
  1505.  
  1506. return fdata.headers
  1507.  
  1508. if __name__ == "__main__":
  1509. from os.path import expanduser
  1510. gen_wrapper([expanduser("isl/include")])
  1511.  
  1512. # vim: foldmethod=marker
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement