2 * Copyright 2016, 2017 Tobias Grosser. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY TOBIAS GROSSER ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
41 #include "isl_config.h"
43 /* Print string formatted according to "fmt" to ostream "os".
45 * This osprintf method allows us to use printf style formatting constructs when
46 * writing to an ostream.
48 static void osprintf(ostream
&os
, const char *format
, ...)
55 va_start(arguments
, format
);
57 string_stream
= open_memstream(&string_pointer
, &size
);
60 fprintf(stderr
, "open_memstream failed -- aborting!\n");
64 vfprintf(string_stream
, format
, arguments
);
65 fclose(string_stream
);
70 /* Generate a cpp interface based on the extracted types and functions.
72 * Print first a set of forward declarations for all isl wrapper
73 * classes, then the declarations of the classes, and at the end all
76 void cpp_generator::generate()
81 osprintf(os
, "namespace isl {\n\n");
82 osprintf(os
, "inline namespace noexceptions {\n\n");
84 print_forward_declarations(os
);
86 print_declarations(os
);
88 print_implementations(os
);
90 osprintf(os
, "} // namespace noexceptions\n");
91 osprintf(os
, "} // namespace isl\n\n");
92 osprintf(os
, "#endif /* ISL_CPP_NOEXCEPTIONS */\n");
95 /* Print forward declarations for all classes to "os".
97 void cpp_generator::print_forward_declarations(ostream
&os
)
99 map
<string
, isl_class
>::iterator ci
;
101 osprintf(os
, "// forward declarations\n");
103 for (ci
= classes
.begin(); ci
!= classes
.end(); ++ci
)
104 print_class_forward_decl(os
, ci
->second
);
107 /* Print all declarations to "os".
109 void cpp_generator::print_declarations(ostream
&os
)
111 map
<string
, isl_class
>::iterator ci
;
114 for (ci
= classes
.begin(); ci
!= classes
.end(); ++ci
) {
120 print_class(os
, ci
->second
);
124 /* Print all implementations to "os".
126 void cpp_generator::print_implementations(ostream
&os
)
128 map
<string
, isl_class
>::iterator ci
;
131 for (ci
= classes
.begin(); ci
!= classes
.end(); ++ci
) {
137 print_class_impl(os
, ci
->second
);
141 /* Print declarations for class "clazz" to "os".
143 void cpp_generator::print_class(ostream
&os
, const isl_class
&clazz
)
145 const char *name
= clazz
.name
.c_str();
146 std::string cppstring
= type2cpp(clazz
);
147 const char *cppname
= cppstring
.c_str();
149 osprintf(os
, "// declarations for isl::%s\n", cppname
);
151 print_class_factory_decl(os
, clazz
);
153 osprintf(os
, "class %s {\n", cppname
);
154 osprintf(os
, " friend ");
155 print_class_factory_decl(os
, clazz
);
157 osprintf(os
, " %s *ptr = nullptr;\n", name
);
159 print_private_constructors_decl(os
, clazz
);
161 osprintf(os
, "public:\n");
162 print_public_constructors_decl(os
, clazz
);
163 print_copy_assignment_decl(os
, clazz
);
164 print_destructor_decl(os
, clazz
);
165 print_ptr_decl(os
, clazz
);
167 osprintf(os
, "};\n");
170 /* Print forward declaration of class "clazz" to "os".
172 void cpp_generator::print_class_forward_decl(ostream
&os
,
173 const isl_class
&clazz
)
175 std::string cppstring
= type2cpp(clazz
);
176 const char *cppname
= cppstring
.c_str();
178 osprintf(os
, "class %s;\n", cppname
);
181 /* Print global factory function to "os".
183 * Each class has one global factory function:
185 * isl::set manage(__isl_take isl_set *ptr);
187 * The only public way to construct isl C++ objects from a raw pointer is
188 * through this global factory function. This ensures isl object creation
189 * is very explicit and pointers are not converted by accident. Due to
190 * overloading, manage() can be called on any isl raw pointer and the
191 * corresponding object is automatically created, without the user having
192 * to choose the right isl object type.
194 void cpp_generator::print_class_factory_decl(ostream
&os
,
195 const isl_class
&clazz
)
197 const char *name
= clazz
.name
.c_str();
198 std::string cppstring
= type2cpp(clazz
);
199 const char *cppname
= cppstring
.c_str();
201 osprintf(os
, "inline isl::%s manage(__isl_take %s *ptr);\n", cppname
,
205 /* Print declarations of private constructors for class "clazz" to "os".
207 * Each class has currently one private constructor:
209 * 1) Constructor from a plain isl_* C pointer
213 * set(__isl_take isl_set *ptr);
215 * The raw pointer constructor is kept private. Object creation is only
216 * possible through isl::manage().
218 void cpp_generator::print_private_constructors_decl(ostream
&os
,
219 const isl_class
&clazz
)
221 const char *name
= clazz
.name
.c_str();
222 std::string cppstring
= type2cpp(clazz
);
223 const char *cppname
= cppstring
.c_str();
225 osprintf(os
, " inline explicit %s(__isl_take %s *ptr);\n", cppname
,
229 /* Print declarations of public constructors for class "clazz" to "os".
231 * Each class currently has two public constructors:
233 * 1) A default constructor
234 * 2) A copy constructor
239 * set(const isl::set &set);
241 void cpp_generator::print_public_constructors_decl(ostream
&os
,
242 const isl_class
&clazz
)
244 std::string cppstring
= type2cpp(clazz
);
245 const char *cppname
= cppstring
.c_str();
246 osprintf(os
, " inline /* implicit */ %s();\n", cppname
);
248 osprintf(os
, " inline /* implicit */ %s(const isl::%s &obj);\n",
252 /* Print declarations of copy assignment operator for class "clazz"
255 * Each class has one assignment operator.
257 * isl:set &set::operator=(isl::set obj)
260 void cpp_generator::print_copy_assignment_decl(ostream
&os
,
261 const isl_class
&clazz
)
263 std::string cppstring
= type2cpp(clazz
);
264 const char *cppname
= cppstring
.c_str();
266 osprintf(os
, " inline isl::%s &operator=(isl::%s obj);\n", cppname
,
270 /* Print declaration of destructor for class "clazz" to "os".
272 void cpp_generator::print_destructor_decl(ostream
&os
, const isl_class
&clazz
)
274 std::string cppstring
= type2cpp(clazz
);
275 const char *cppname
= cppstring
.c_str();
277 osprintf(os
, " inline ~%s();\n", cppname
);
280 /* Print declaration of pointer functions for class "clazz" to "os".
282 * To obtain a raw pointer three functions are provided:
284 * 1) __isl_give isl_set *copy()
286 * Returns a pointer to a _copy_ of the internal object
288 * 2) __isl_keep isl_set *get()
290 * Returns a pointer to the internal object
292 * 3) __isl_give isl_set *release()
294 * Returns a pointer to the internal object and resets the
295 * internal pointer to nullptr.
297 * We also provide functionality to explicitly check if a pointer is
298 * currently managed by this object.
302 * Check if the current object is a null pointer.
304 * The functions get() and release() model the value_ptr proposed in
305 * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3339.pdf.
306 * The copy() function is an extension to allow the user to explicitly
307 * copy the underlying object.
309 * Also generate a declaration to delete copy() for r-values, for
310 * r-values release() should be used to avoid unnecessary copies.
312 void cpp_generator::print_ptr_decl(ostream
&os
, const isl_class
&clazz
)
314 const char *name
= clazz
.name
.c_str();
316 osprintf(os
, " inline __isl_give %s *copy() const &;\n", name
);
317 osprintf(os
, " inline __isl_give %s *copy() && = delete;\n", name
);
318 osprintf(os
, " inline __isl_keep %s *get() const;\n", name
);
319 osprintf(os
, " inline __isl_give %s *release();\n", name
);
320 osprintf(os
, " inline bool is_null() const;\n");
323 /* Print implementations for class "clazz" to "os".
325 void cpp_generator::print_class_impl(ostream
&os
, const isl_class
&clazz
)
327 std::string cppstring
= type2cpp(clazz
);
328 const char *cppname
= cppstring
.c_str();
330 osprintf(os
, "// implementations for isl::%s\n", cppname
);
332 print_class_factory_impl(os
, clazz
);
334 print_public_constructors_impl(os
, clazz
);
336 print_private_constructors_impl(os
, clazz
);
338 print_copy_assignment_impl(os
, clazz
);
340 print_destructor_impl(os
, clazz
);
342 print_ptr_impl(os
, clazz
);
345 /* Print implementation of global factory function to "os".
347 void cpp_generator::print_class_factory_impl(ostream
&os
,
348 const isl_class
&clazz
)
350 const char *name
= clazz
.name
.c_str();
351 std::string cppstring
= type2cpp(clazz
);
352 const char *cppname
= cppstring
.c_str();
354 osprintf(os
, "isl::%s manage(__isl_take %s *ptr) {\n", cppname
, name
);
355 osprintf(os
, " return %s(ptr);\n", cppname
);
359 /* Print implementations of private constructors for class "clazz" to "os".
361 void cpp_generator::print_private_constructors_impl(ostream
&os
,
362 const isl_class
&clazz
)
364 const char *name
= clazz
.name
.c_str();
365 std::string cppstring
= type2cpp(clazz
);
366 const char *cppname
= cppstring
.c_str();
368 osprintf(os
, "%s::%s(__isl_take %s *ptr)\n : ptr(ptr) {}\n",
369 cppname
, cppname
, name
);
372 /* Print implementations of public constructors for class "clazz" to "os".
374 void cpp_generator::print_public_constructors_impl(ostream
&os
,
375 const isl_class
&clazz
)
377 const char *name
= clazz
.name
.c_str();
378 std::string cppstring
= type2cpp(clazz
);
379 const char *cppname
= cppstring
.c_str();
381 osprintf(os
, "%s::%s()\n : ptr(nullptr) {}\n\n", cppname
, cppname
);
382 osprintf(os
, "%s::%s(const isl::%s &obj)\n : ptr(obj.copy()) {}\n",
383 cppname
, cppname
, cppname
, name
);
386 /* Print implementation of copy assignment operator for class "clazz" to "os".
388 void cpp_generator::print_copy_assignment_impl(ostream
&os
,
389 const isl_class
&clazz
)
391 const char *name
= clazz
.name
.c_str();
392 std::string cppstring
= type2cpp(clazz
);
393 const char *cppname
= cppstring
.c_str();
395 osprintf(os
, "%s &%s::operator=(isl::%s obj) {\n", cppname
,
397 osprintf(os
, " std::swap(this->ptr, obj.ptr);\n", name
);
398 osprintf(os
, " return *this;\n");
402 /* Print implementation of destructor for class "clazz" to "os".
404 void cpp_generator::print_destructor_impl(ostream
&os
,
405 const isl_class
&clazz
)
407 const char *name
= clazz
.name
.c_str();
408 std::string cppstring
= type2cpp(clazz
);
409 const char *cppname
= cppstring
.c_str();
411 osprintf(os
, "%s::~%s() {\n", cppname
, cppname
);
412 osprintf(os
, " if (ptr)\n");
413 osprintf(os
, " %s_free(ptr);\n", name
);
417 /* Print implementation of ptr() functions for class "clazz" to "os".
419 void cpp_generator::print_ptr_impl(ostream
&os
, const isl_class
&clazz
)
421 const char *name
= clazz
.name
.c_str();
422 std::string cppstring
= type2cpp(clazz
);
423 const char *cppname
= cppstring
.c_str();
425 osprintf(os
, "__isl_give %s *%s::copy() const & {\n", name
, cppname
);
426 osprintf(os
, " return %s_copy(ptr);\n", name
);
427 osprintf(os
, "}\n\n");
428 osprintf(os
, "__isl_keep %s *%s::get() const {\n", name
, cppname
);
429 osprintf(os
, " return ptr;\n");
430 osprintf(os
, "}\n\n");
431 osprintf(os
, "__isl_give %s *%s::release() {\n", name
, cppname
);
432 osprintf(os
, " %s *tmp = ptr;\n", name
);
433 osprintf(os
, " ptr = nullptr;\n");
434 osprintf(os
, " return tmp;\n");
435 osprintf(os
, "}\n\n");
436 osprintf(os
, "bool %s::is_null() const {\n", cppname
);
437 osprintf(os
, " return ptr == nullptr;\n");
441 /* Translate isl class "clazz" to its corresponding C++ type.
443 string
cpp_generator::type2cpp(const isl_class
&clazz
)
445 return type2cpp(clazz
.name
);
448 /* Translate type string "type_str" to its C++ name counterpart.
450 string
cpp_generator::type2cpp(string type_str
)
452 return type_str
.substr(4);