diff --git a/doc/misc.rst b/doc/misc.rst index c6b204d88424e3fa49cc30f5eac0d2b0f58f186e..3eb96aa9517534189e7f36397517dbdbdb1f4255 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -85,6 +85,11 @@ Version 2011.3 * :class:`islpy.Dim` was renamed to :class:`islpy.Space` in isl. * :class:`islpy.Div` was removed and replaced by :class:`islpy.Aff` wherever it was used previously. +* :meth:`islpy.BasicSet.as_set` + and + :meth:`islpy.BasicMap.as_map` + were removed. +* :ref:`automatic-casts` were added. Version 2011.2 -------------- diff --git a/doc/reference.rst b/doc/reference.rst index 1f0657f79740ab148cbebc5d16fe796e8d9cd052..3bcca93b32e4ed8717876354475e5ef9f8f563b2 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -46,6 +46,27 @@ Whenever an integer argument is required, :mod:`islpy` supports regular Python integers, Python long integers, and :mod:`gmpy` integers. It will return :mod:`gmpy` integers. +.. _automatic casts: + +Automatic Casts +--------------- + +:mod:`islpy` will automatically perform the following upward casts in argument +lists: + +==================== ========================== +Called with Argument Type +==================== ========================== +:class:`BasicSet` :class:`Set` +:class:`BasicMap` :class:`Map` +:class:`Set` :class:`UnionSet` +:class:`Map` :class:`UnionMap` +:class:`Space` :class:`LocalSpace` +:class:`Aff` :class:`PwAff` +==================== ========================== + +as well as casts contained in the transitive closure of this 'casting graph'. + Symbolic Constants ^^^^^^^^^^^^^^^^^^ diff --git a/gen_wrap.py b/gen_wrap.py index d0bd42939d59fb554580d5b826696cf75893c603..ab101ad4dc4659a97353324ad434d4374b94d688 100644 --- a/gen_wrap.py +++ b/gen_wrap.py @@ -551,6 +551,8 @@ def write_wrapper(outf, meth): docs.append(":param %s: integer" % arg.name) elif arg.base_type.startswith("isl_") and arg.ptr == "*": + need_nonconst = False + arg_cls = arg.base_type[4:] arg_descr = ":param %s: :class:`%s`" % (arg.name, to_py_class(arg_cls)) @@ -558,7 +560,7 @@ def write_wrapper(outf, meth): raise Undocumented(meth) checks.append(""" - if (!arg_%(name)s || !arg_%(name)s->is_valid()) + if (!arg_%(name)s.is_valid()) PYTHON_ERROR(ValueError, "passed invalid arg to isl_%(meth)s for %(name)s"); """ % dict(name=arg.name, meth="%s_%s" % (meth.cls, meth.name))) @@ -566,11 +568,11 @@ def write_wrapper(outf, meth): if arg.semantics is SEM_TAKE: if copyable: checks.append(""" - if (!arg_%(name)s || !arg_%(name)s->is_valid()) + if (!arg_%(name)s.is_valid()) PYTHON_ERROR(ValueError, "passed invalid arg to isl_%(meth)s for %(name)s"); std::auto_ptr<%(cls)s> auto_arg_%(name)s; { - isl_%(cls)s *tmp_ptr = isl_%(cls)s_copy(arg_%(name)s->m_data); + isl_%(cls)s *tmp_ptr = isl_%(cls)s_copy(arg_%(name)s.m_data); if (!tmp_ptr) throw std::runtime_error("failed to copy arg %(name)s on entry to %(meth)s"); auto_arg_%(name)s = std::auto_ptr<%(cls)s>(new %(cls)s(tmp_ptr)); @@ -584,19 +586,24 @@ def write_wrapper(outf, meth): passed_args.append("auto_arg_%s->m_data" % arg.name) else: + need_nonconst = True + if not (arg_idx == 0 and meth.is_mutator): - post_call.append("arg_%s->invalidate();" % arg.name) + post_call.append("arg_%s.invalidate();" % arg.name) - passed_args.append("arg_%s->m_data" % arg.name) + passed_args.append("arg_%s.m_data" % arg.name) if arg_idx == 0 and meth.is_mutator: arg_descr += " (mutated in-place)" else: arg_descr += " (:ref:`becomes invalid `)" else: - passed_args.append("arg_%s->m_data" % arg.name) + passed_args.append("arg_%s.m_data" % arg.name) - input_args.append("%s *%s" % (arg_cls, "arg_"+arg.name)) + if need_nonconst: + input_args.append("%s &%s" % (arg_cls, "arg_"+arg.name)) + else: + input_args.append("%s const &%s" % (arg_cls, "arg_"+arg.name)) docs.append(arg_descr) @@ -688,8 +695,8 @@ def write_wrapper(outf, meth): meth.mutator_veto = True raise Retry() - processed_return_type = "isl::%s *" % ret_cls - body.append("arg_%s->m_data = result;" % meth.args[0].name) + processed_return_type = "isl::%s &" % ret_cls + body.append("arg_%s.m_data = result;" % meth.args[0].name) body.append("return arg_%s;" % meth.args[0].name) ret_descr = ":class:`%s` (self)" % to_py_class(ret_cls) diff --git a/islpy/__init__.py b/islpy/__init__.py index 856284eb1baa45cea7ada0ae1a1dc910b81f9503..0998c82a2cd575e706a784cb5a7b4b58efb75236 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -275,7 +275,7 @@ def _add_functionality(): # {{{ aff arithmetic def _number_to_aff(template, num): - result = Aff.zero_on_domain(LocalSpace.from_space(template.get_domain_space())) + result = Aff.zero_on_domain(template.get_domain_space()) result = result.set_constant(num) if isinstance(template, PwAff): return PwAff.from_aff(result) @@ -318,7 +318,10 @@ def _add_functionality(): # }}} - # {{{ add automatic upcasts + # {{{ add automatic 'self' upcasts + + # note: automatic upcasts for method arguments are provided through + # 'implicitly_convertible' on the C++ side of the wrapper. class UpcastWrapper(object): def __init__(self, method, upcast): @@ -350,9 +353,16 @@ def _add_functionality(): setattr(basic_class, method_name, update_wrapper(wrapper, method)) for args_triple in [ - (BasicSet, Set, BasicSet.as_set), - (BasicMap, Map, BasicMap.as_map), + (BasicSet, Set, Set.from_basic_set), + (BasicMap, Map, Map.from_basic_map), + (Set, UnionSet, UnionSet.from_set), + (Map, UnionMap, UnionMap.from_map), + + (BasicSet, UnionSet, lambda x: UnionSet.from_set(Set.from_basic_set(x))), + (BasicMap, UnionMap, lambda x: UnionMap.from_map(Map.from_basic_map(x))), + (Aff, PwAff, PwAff.from_aff), + (Space, LocalSpace, LocalSpace.from_space), ]: add_upcasts(*args_triple) diff --git a/setup.py b/setup.py index 11d6c7c1b3176ce0058aba2c517592a7ea3f3d8c..ee54cddf5d6402724b1f13b8367c7ccf428a6124 100644 --- a/setup.py +++ b/setup.py @@ -156,7 +156,7 @@ def main(): ext_modules = [ Extension( "islpy._isl", - EXTRA_OBJECTS + ["src/wrapper/wrap_isl.cpp"], + ["src/wrapper/wrap_isl.cpp"] + EXTRA_OBJECTS, include_dirs=INCLUDE_DIRS, library_dirs=LIBRARY_DIRS, libraries=LIBRARIES, diff --git a/src/wrapper/wrap_isl.cpp b/src/wrapper/wrap_isl.cpp index bd79ebed57f7249152af2f4b4881af9d6440de37..e5ba172fba35ae84ff4227a3b6c275d9c5af7a81 100644 --- a/src/wrapper/wrap_isl.cpp +++ b/src/wrapper/wrap_isl.cpp @@ -54,8 +54,26 @@ namespace isl } #define WRAP_CLASS(name) \ - struct name \ - { \ + struct name { WRAP_CLASS_CONTENT(name) } + +#define MAKE_CAST_CTOR(name, from_type, cast_func) \ + name(from_type &data) \ + : m_valid(false) \ + { \ + m_ctx = isl_##from_type##_get_ctx(data.m_data); \ + \ + isl_##from_type *copy = isl_##from_type##_copy(data.m_data); \ + if (!copy) \ + throw std::runtime_error("isl_" #from_type "_copy failed"); \ + m_data = cast_func(copy); \ + if (!m_data) \ + throw std::runtime_error(#cast_func " failed"); \ + \ + m_valid = true; \ + ctx_use_map[m_ctx] += 1; \ + } + +#define WRAP_CLASS_CONTENT(name) \ private: \ bool m_valid; \ isl_ctx *m_ctx; \ @@ -87,8 +105,7 @@ namespace isl isl_##name##_free(m_data); \ deref_ctx(m_ctx); \ } \ - } \ - }; + } struct ctx \ { @@ -105,7 +122,7 @@ namespace isl ctx_use_map[m_data] += 1; } - bool is_valid() + bool is_valid() const { return true; } @@ -121,18 +138,47 @@ namespace isl WRAP_CLASS(id); WRAP_CLASS(aff); - WRAP_CLASS(pw_aff); + + struct pw_aff + { + WRAP_CLASS_CONTENT(pw_aff); + MAKE_CAST_CTOR(pw_aff, aff, isl_pw_aff_from_aff); + }; WRAP_CLASS(constraint); WRAP_CLASS(space); - WRAP_CLASS(local_space); + + struct local_space + { + WRAP_CLASS_CONTENT(local_space); + MAKE_CAST_CTOR(local_space, space, isl_local_space_from_space); + }; WRAP_CLASS(basic_set); WRAP_CLASS(basic_map); - WRAP_CLASS(set); - WRAP_CLASS(map); - WRAP_CLASS(union_set); - WRAP_CLASS(union_map); + + struct set + { + WRAP_CLASS_CONTENT(set); + MAKE_CAST_CTOR(set, basic_set, isl_set_from_basic_set); + }; + + struct map + { + WRAP_CLASS_CONTENT(map); + MAKE_CAST_CTOR(map, basic_map, isl_map_from_basic_map); + }; + + struct union_set + { + WRAP_CLASS_CONTENT(union_set); + MAKE_CAST_CTOR(union_set, set, isl_union_set_from_set); + }; + struct union_map + { + WRAP_CLASS_CONTENT(union_map); + MAKE_CAST_CTOR(union_map, map, isl_union_map_from_map); + }; WRAP_CLASS(point); WRAP_CLASS(vertex); @@ -307,5 +353,12 @@ BOOST_PYTHON_MODULE(_isl) FORMAT_ATTR(LATEX); FORMAT_ATTR(EXT_POLYLIB); + py::implicitly_convertible(); + py::implicitly_convertible(); + py::implicitly_convertible(); + py::implicitly_convertible(); + py::implicitly_convertible(); + py::implicitly_convertible(); + #include "gen-expose.inc" }