1 // {{{ MIT License
2 
3 // Copyright 2017 Roland Kaminski
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 // IN THE SOFTWARE.
22 
23 // }}}
24 
25 #if defined(__GNUC__) && !defined(__clang__)
26 #pragma GCC diagnostic push
27 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
28 #elif defined(_MSC_VER)
29 #pragma warning (disable : 4996) // 'strcpy' may be unsafe
30 #endif
31 
32 #include <clingo/clingo_app.hh>
33 #include <clingo/clingocontrol.hh>
34 #include <gringo/input/groundtermparser.hh>
35 #include <gringo/input/programbuilder.hh>
36 #include <gringo/input/nongroundparser.hh>
37 #include <clingo/astv2.hh>
38 #include <cstdarg>
39 
40 #if defined CLINGO_NO_THREAD_LOCAL && ! defined EMSCRIPTEN
41 #   include <thread>
42 #   include <mutex>
43 #endif
44 
45 // {{{1 error handling
46 
47 using namespace Gringo;
48 
49 namespace {
50 
51 // {{{1 declaration of ClingoError
52 
53 struct ClingoError : std::exception {
ClingoError__anonb1f002eb0111::ClingoError54     ClingoError()
55     : code(clingo_error_code()) {
56         try {
57             char const *msg = clingo_error_message();
58             message = msg ? msg : "no message";
59         }
60         catch (...) { }
61     }
what__anonb1f002eb0111::ClingoError62     char const *what() const noexcept {
63         return message.c_str();
64     }
65     std::string message;
66     clingo_error_t code;
67 };
68 
clingo_expect(bool expr)69 void inline clingo_expect(bool expr) {
70     if (!expr) { throw std::runtime_error("unexpected"); }
71 }
72 
73 void handleError();
74 
75 #define GRINGO_CLINGO_TRY try
76 #define GRINGO_CLINGO_CATCH catch (...) { handleError(); return false; } return true
77 
78 #define GRINGO_CALLBACK_TRY try
79 #define GRINGO_CALLBACK_CATCH(ref) catch (...){ (ref) = std::current_exception(); return false; } return true
80 
81 template <class F>
print_size(F f)82 size_t print_size(F f) {
83     CountStream cs;
84     f(cs);
85     cs.flush();
86     return cs.count() + 1;
87 }
88 
89 template <class F>
print(char * ret,size_t n,F f)90 void print(char *ret, size_t n, F f) {
91     ArrayStream as(ret, n);
92     f(as);
93     as << '\0';
94     as.flush();
95 }
96 
97 #ifdef EMSCRIPTEN
98     std::exception_ptr g_lastException;
99     std::string g_lastMessage;
100     clingo_error_t g_lastCode;
101 #elif ! defined CLINGO_NO_THREAD_LOCAL
102     thread_local std::exception_ptr g_lastException;
103     thread_local std::string g_lastMessage;
104     thread_local clingo_error_t g_lastCode;
105 #else
106     struct TLData {
107         std::exception_ptr lastException;
108         std::string lastMessage;
109         clingo_error_t lastCode;
110     };
111     std::mutex g_tLMut;
112     std::unordered_map<std::thread::id, TLData> g_tLData;
tLlastException()113     std::exception_ptr &tLlastException() {
114         std::lock_guard<std::mutex> lock(g_tLMut);
115         return g_tLData[std::this_thread::get_id()].lastException;
116     }
tLlastMessage()117     std::string &tLlastMessage() {
118         std::lock_guard<std::mutex> lock(g_tLMut);
119         return g_tLData[std::this_thread::get_id()].lastMessage;
120     }
tLlastCode()121     clingo_error_t &tLlastCode() {
122         std::lock_guard<std::mutex> lock(g_tLMut);
123         return g_tLData[std::this_thread::get_id()].lastCode;
124     }
125     #define g_lastException (tLlastException())
126     #define g_lastMessage (tLlastMessage())
127     #define g_lastCode (tLlastCode())
128 #endif
129 
forwardError(bool ret,std::exception_ptr * exc=nullptr)130 void forwardError(bool ret, std::exception_ptr *exc=nullptr) {
131     if (!ret) {
132         if (exc && *exc) { std::rethrow_exception(*exc); }
133         else             { throw ClingoError(); }
134     }
135 }
136 
handleError()137 void handleError() {
138     try { throw; }
139     // Note: a ClingoError is throw after an exception is set or a user error is thrown so either
140     //       - g_lastException is already set, or
141     //       - there was a user error (currently not associated to an error message)
142     catch (ClingoError const &e)        { g_lastException = std::current_exception(); g_lastCode = e.code; }
143     catch (std::bad_alloc const &)      { g_lastException = std::current_exception(); g_lastCode = clingo_error_bad_alloc; }
144     catch (std::logic_error)            { g_lastException = std::current_exception(); g_lastCode = clingo_error_logic; }
145     catch (...)                         { g_lastException = std::current_exception(); g_lastCode = clingo_error_runtime; }
146 }
147 
148 
clingo_terminate(char const * loc)149 void clingo_terminate(char const *loc) {
150     fprintf(stderr, "%s:\n %s\n", loc, clingo_error_message());
151     fflush(stderr);
152     std::_Exit(1);
153 }
154 
155 // }}}1
156 // {{{1
157 
conv(Location const & loc)158 clingo_location_t conv(Location const &loc) {
159     return {loc.beginFilename.c_str(), loc.endFilename.c_str(), loc.beginLine, loc.endLine, loc.beginColumn, loc.endColumn};
160 }
161 
conv(clingo_location_t const & loc)162 Location conv(clingo_location_t const &loc) {
163     return { loc.begin_file,
164              static_cast<unsigned int>(loc.begin_line),
165              static_cast<unsigned int>(loc.begin_column),
166              loc.end_file,
167              static_cast<unsigned int>(loc.end_line),
168              static_cast<unsigned int>(loc.end_column)};
169 }
170 
171 // 1}}}
172 } // namespace
173 
174 // c interface
175 
176 // {{{1 error handling
177 
clingo_set_error(clingo_error_t code,char const * message)178 extern "C" void clingo_set_error(clingo_error_t code, char const *message) {
179     g_lastCode = code;
180     try         { g_lastException = std::make_exception_ptr(std::runtime_error(message)); }
181     catch (...) { g_lastException = nullptr; }
182 }
clingo_error_message()183 extern "C" char const *clingo_error_message() {
184     if (g_lastException) {
185         try { std::rethrow_exception(g_lastException); }
186         catch (std::bad_alloc const &) { return "bad_alloc"; }
187         catch (std::exception const &e) {
188             g_lastMessage = e.what();
189             return g_lastMessage.c_str();
190         }
191     }
192     return nullptr;
193 }
194 
clingo_error_code()195 extern "C" clingo_error_t clingo_error_code() {
196     return g_lastCode;
197 }
198 
clingo_error_string(clingo_error_t code)199 extern "C" char const *clingo_error_string(clingo_error_t code) {
200     switch (static_cast<clingo_error_e>(code)) {
201         case clingo_error_success:               { return "success"; }
202         case clingo_error_runtime:               { return "runtime error"; }
203         case clingo_error_bad_alloc:             { return "bad allocation"; }
204         case clingo_error_logic:                 { return "logic error"; }
205         case clingo_error_unknown:               { return "unknown error"; }
206     }
207     return nullptr;
208 }
209 
clingo_warning_string(clingo_warning_t code)210 extern "C" char const *clingo_warning_string(clingo_warning_t code) {
211     switch (static_cast<clingo_warning_e>(code)) {
212         case clingo_warning_operation_undefined: { return "operation undefined"; }
213         case clingo_warning_runtime_error:       { return "runtime error"; }
214         case clingo_warning_atom_undefined:      { return "atom undefined"; }
215         case clingo_warning_file_included:       { return "file included"; }
216         case clingo_warning_variable_unbounded:  { return "variable unbounded"; }
217         case clingo_warning_global_variable:     { return "global variable"; }
218         case clingo_warning_other:               { return "other"; }
219     }
220     return "unknown message code";
221 }
222 
223 // {{{1 signature
224 
clingo_signature_create(char const * name,uint32_t arity,bool positive,clingo_signature_t * ret)225 extern "C" bool clingo_signature_create(char const *name, uint32_t arity, bool positive, clingo_signature_t *ret) {
226     GRINGO_CLINGO_TRY {
227         *ret = Sig(name, arity, !positive).rep();
228     } GRINGO_CLINGO_CATCH;
229 }
230 
clingo_signature_name(clingo_signature_t sig)231 extern "C" char const *clingo_signature_name(clingo_signature_t sig) {
232     return Sig(sig).name().c_str();
233 }
234 
clingo_signature_arity(clingo_signature_t sig)235 extern "C" uint32_t clingo_signature_arity(clingo_signature_t sig) {
236     return Sig(sig).arity();
237 }
238 
clingo_signature_is_negative(clingo_signature_t sig)239 extern "C" bool clingo_signature_is_negative(clingo_signature_t sig) {
240     return Sig(sig).sign();
241 }
242 
clingo_signature_is_positive(clingo_signature_t sig)243 extern "C" bool clingo_signature_is_positive(clingo_signature_t sig) {
244     return !Sig(sig).sign();
245 }
246 
clingo_signature_hash(clingo_signature_t sig)247 extern "C" size_t clingo_signature_hash(clingo_signature_t sig) {
248     return Sig(sig).hash();
249 }
250 
clingo_signature_is_equal_to(clingo_signature_t a,clingo_signature_t b)251 extern "C" bool clingo_signature_is_equal_to(clingo_signature_t a, clingo_signature_t b) {
252     return Sig(a) == Sig(b);
253 }
254 
clingo_signature_is_less_than(clingo_signature_t a,clingo_signature_t b)255 extern "C" bool clingo_signature_is_less_than(clingo_signature_t a, clingo_signature_t b) {
256     return Sig(a) < Sig(b);
257 }
258 
259 
260 // {{{1 value
261 
clingo_symbol_create_number(int num,clingo_symbol_t * val)262 extern "C" void clingo_symbol_create_number(int num, clingo_symbol_t *val) {
263     *val = Symbol::createNum(num).rep();
264 }
265 
clingo_symbol_create_supremum(clingo_symbol_t * val)266 extern "C" void clingo_symbol_create_supremum(clingo_symbol_t *val) {
267     *val = Symbol::createSup().rep();
268 }
269 
clingo_symbol_create_infimum(clingo_symbol_t * val)270 extern "C" void clingo_symbol_create_infimum(clingo_symbol_t *val) {
271     *val = Symbol::createInf().rep();
272 }
273 
clingo_symbol_create_string(char const * str,clingo_symbol_t * val)274 extern "C" bool clingo_symbol_create_string(char const *str, clingo_symbol_t *val) {
275     GRINGO_CLINGO_TRY {
276         *val = Symbol::createStr(str).rep();
277     } GRINGO_CLINGO_CATCH;
278 }
279 
clingo_symbol_create_id(char const * id,bool positive,clingo_symbol_t * val)280 extern "C" bool clingo_symbol_create_id(char const *id, bool positive, clingo_symbol_t *val) {
281     GRINGO_CLINGO_TRY {
282         *val = Symbol::createId(id, !positive).rep();
283     } GRINGO_CLINGO_CATCH;
284 }
285 
clingo_symbol_create_function(char const * name,clingo_symbol_t const * args,size_t n,bool positive,clingo_symbol_t * val)286 extern "C" bool clingo_symbol_create_function(char const *name, clingo_symbol_t const *args, size_t n, bool positive, clingo_symbol_t *val) {
287     GRINGO_CLINGO_TRY {
288         *val = Symbol::createFun(name, SymSpan{reinterpret_cast<Symbol const *>(args), n}, !positive).rep();
289     } GRINGO_CLINGO_CATCH;
290 }
291 
clingo_symbol_number(clingo_symbol_t val,int * num)292 extern "C" bool clingo_symbol_number(clingo_symbol_t val, int *num) {
293     GRINGO_CLINGO_TRY {
294         clingo_expect(Symbol(val).type() == SymbolType::Num);
295         *num = Symbol(val).num();
296     } GRINGO_CLINGO_CATCH;
297 }
298 
clingo_symbol_name(clingo_symbol_t val,char const ** name)299 extern "C" bool clingo_symbol_name(clingo_symbol_t val, char const **name) {
300     GRINGO_CLINGO_TRY {
301         clingo_expect(Symbol(val).type() == SymbolType::Fun);
302         *name = Symbol(val).name().c_str();
303     } GRINGO_CLINGO_CATCH;
304 }
305 
clingo_symbol_string(clingo_symbol_t val,char const ** str)306 extern "C" bool clingo_symbol_string(clingo_symbol_t val, char const **str) {
307     GRINGO_CLINGO_TRY {
308         clingo_expect(Symbol(val).type() == SymbolType::Str);
309         *str = Symbol(val).string().c_str();
310     } GRINGO_CLINGO_CATCH;
311 }
312 
clingo_symbol_is_negative(clingo_symbol_t val,bool * sign)313 extern "C" bool clingo_symbol_is_negative(clingo_symbol_t val, bool *sign) {
314     GRINGO_CLINGO_TRY {
315         clingo_expect(Symbol(val).type() == SymbolType::Fun);
316         *sign = Symbol(val).sign();
317     } GRINGO_CLINGO_CATCH;
318 }
319 
clingo_symbol_is_positive(clingo_symbol_t val,bool * sign)320 extern "C" bool clingo_symbol_is_positive(clingo_symbol_t val, bool *sign) {
321     GRINGO_CLINGO_TRY {
322         clingo_expect(Symbol(val).type() == SymbolType::Fun);
323         *sign = !Symbol(val).sign();
324     } GRINGO_CLINGO_CATCH;
325 }
326 
clingo_symbol_arguments(clingo_symbol_t val,clingo_symbol_t const ** args,size_t * n)327 extern "C" bool clingo_symbol_arguments(clingo_symbol_t val, clingo_symbol_t const **args, size_t *n) {
328     GRINGO_CLINGO_TRY {
329         clingo_expect(Symbol(val).type() == SymbolType::Fun);
330         auto ret = Symbol(val).args();
331         *args = reinterpret_cast<clingo_symbol_t const *>(ret.first);
332         *n = ret.size;
333     } GRINGO_CLINGO_CATCH;
334 }
335 
clingo_symbol_type(clingo_symbol_t val)336 extern "C" clingo_symbol_type_t clingo_symbol_type(clingo_symbol_t val) {
337     return static_cast<clingo_symbol_type_t>(Symbol(val).type());
338 }
339 
clingo_symbol_to_string_size(clingo_symbol_t val,size_t * n)340 extern "C" bool clingo_symbol_to_string_size(clingo_symbol_t val, size_t *n) {
341     GRINGO_CLINGO_TRY { *n = print_size([&val](std::ostream &out) { Symbol(val).print(out); }); }
342     GRINGO_CLINGO_CATCH;
343 }
344 
clingo_symbol_to_string(clingo_symbol_t val,char * ret,size_t n)345 extern "C" bool clingo_symbol_to_string(clingo_symbol_t val, char *ret, size_t n) {
346     GRINGO_CLINGO_TRY { print(ret, n, [&val](std::ostream &out) { Symbol(val).print(out); }); }
347     GRINGO_CLINGO_CATCH;
348 }
349 
clingo_symbol_is_equal_to(clingo_symbol_t a,clingo_symbol_t b)350 extern "C" bool clingo_symbol_is_equal_to(clingo_symbol_t a, clingo_symbol_t b) {
351     return Symbol(a) == Symbol(b);
352 }
353 
clingo_symbol_is_less_than(clingo_symbol_t a,clingo_symbol_t b)354 extern "C" bool clingo_symbol_is_less_than(clingo_symbol_t a, clingo_symbol_t b) {
355     return Symbol(a) < Symbol(b);
356 }
357 
clingo_symbol_hash(clingo_symbol_t sym)358 extern "C" size_t clingo_symbol_hash(clingo_symbol_t sym) {
359     return Symbol(sym).hash();
360 }
361 
362 // {{{1 symbolic atoms
363 
clingo_symbolic_atoms_begin(clingo_symbolic_atoms_t const * dom,clingo_signature_t const * sig,clingo_symbolic_atom_iterator_t * ret)364 extern "C" bool clingo_symbolic_atoms_begin(clingo_symbolic_atoms_t const *dom, clingo_signature_t const *sig, clingo_symbolic_atom_iterator_t *ret) {
365     GRINGO_CLINGO_TRY { *ret = sig ? dom->begin(Sig(*sig)) : dom->begin(); }
366     GRINGO_CLINGO_CATCH;
367 }
368 
clingo_symbolic_atoms_end(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t * ret)369 extern "C" bool clingo_symbolic_atoms_end(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t *ret) {
370     GRINGO_CLINGO_TRY { *ret = dom->end(); }
371     GRINGO_CLINGO_CATCH;
372 }
373 
clingo_symbolic_atoms_find(clingo_symbolic_atoms_t const * dom,clingo_symbol_t atom,clingo_symbolic_atom_iterator_t * ret)374 extern "C" bool clingo_symbolic_atoms_find(clingo_symbolic_atoms_t const *dom, clingo_symbol_t atom, clingo_symbolic_atom_iterator_t *ret) {
375     GRINGO_CLINGO_TRY { *ret = dom->lookup(Symbol(atom)); }
376     GRINGO_CLINGO_CATCH;
377 }
378 
clingo_symbolic_atoms_iterator_is_equal_to(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t it,clingo_symbolic_atom_iterator_t jt,bool * ret)379 extern "C" bool clingo_symbolic_atoms_iterator_is_equal_to(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t it, clingo_symbolic_atom_iterator_t jt, bool *ret) {
380     GRINGO_CLINGO_TRY { *ret = dom->eq(it, jt); }
381     GRINGO_CLINGO_CATCH;
382 }
383 
clingo_symbolic_atoms_signatures_size(clingo_symbolic_atoms_t const * dom,size_t * n)384 extern "C" bool clingo_symbolic_atoms_signatures_size(clingo_symbolic_atoms_t const *dom, size_t *n) {
385     GRINGO_CLINGO_TRY {
386         // TODO: implement matching C++ functions ...
387         auto sigs = dom->signatures();
388         *n = sigs.size();
389     }
390     GRINGO_CLINGO_CATCH;
391 }
392 
clingo_symbolic_atoms_signatures(clingo_symbolic_atoms_t const * dom,clingo_signature_t * ret,size_t n)393 extern "C" bool clingo_symbolic_atoms_signatures(clingo_symbolic_atoms_t const *dom, clingo_signature_t *ret, size_t n) {
394     GRINGO_CLINGO_TRY {
395         // TODO: implement matching C++ functions ...
396         auto sigs = dom->signatures();
397         if (n < sigs.size()) { throw std::length_error("not enough space"); }
398         for (auto &sig : sigs) { *ret++ = sig.rep(); }
399     }
400     GRINGO_CLINGO_CATCH;
401 }
402 
clingo_symbolic_atoms_size(clingo_symbolic_atoms_t const * dom,size_t * size)403 extern "C" bool clingo_symbolic_atoms_size(clingo_symbolic_atoms_t const *dom, size_t *size) {
404     GRINGO_CLINGO_TRY { *size = dom->length(); }
405     GRINGO_CLINGO_CATCH;
406 }
407 
clingo_symbolic_atoms_symbol(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,clingo_symbol_t * sym)408 extern "C" bool clingo_symbolic_atoms_symbol(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, clingo_symbol_t *sym) {
409     GRINGO_CLINGO_TRY { *sym = dom->atom(atm).rep(); }
410     GRINGO_CLINGO_CATCH;
411 }
412 
clingo_symbolic_atoms_literal(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,clingo_literal_t * lit)413 extern "C" bool clingo_symbolic_atoms_literal(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, clingo_literal_t *lit) {
414     GRINGO_CLINGO_TRY { *lit = dom->literal(atm); }
415     GRINGO_CLINGO_CATCH;
416 }
417 
clingo_symbolic_atoms_is_fact(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,bool * fact)418 extern "C" bool clingo_symbolic_atoms_is_fact(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, bool *fact) {
419     GRINGO_CLINGO_TRY { *fact = dom->fact(atm); }
420     GRINGO_CLINGO_CATCH;
421 }
422 
clingo_symbolic_atoms_is_external(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,bool * external)423 extern "C" bool clingo_symbolic_atoms_is_external(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, bool *external) {
424     GRINGO_CLINGO_TRY { *external = dom->external(atm); }
425     GRINGO_CLINGO_CATCH;
426 }
427 
clingo_symbolic_atoms_next(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,clingo_symbolic_atom_iterator_t * next)428 extern "C" bool clingo_symbolic_atoms_next(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, clingo_symbolic_atom_iterator_t *next) {
429     GRINGO_CLINGO_TRY { *next = dom->next(atm); }
430     GRINGO_CLINGO_CATCH;
431 }
432 
clingo_symbolic_atoms_is_valid(clingo_symbolic_atoms_t const * dom,clingo_symbolic_atom_iterator_t atm,bool * valid)433 extern "C" bool clingo_symbolic_atoms_is_valid(clingo_symbolic_atoms_t const *dom, clingo_symbolic_atom_iterator_t atm, bool *valid) {
434     GRINGO_CLINGO_TRY { *valid = dom->valid(atm); }
435     GRINGO_CLINGO_CATCH;
436 }
437 
438 // {{{1 theory atoms
439 
440 struct clingo_theory_atoms : Gringo::Output::DomainData { };
441 
clingo_theory_atoms_term_type(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_theory_term_type_t * ret)442 extern "C" bool clingo_theory_atoms_term_type(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_theory_term_type_t *ret) {
443     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_theory_term_type_t>(atoms->termType(value)); }
444     GRINGO_CLINGO_CATCH;
445 }
446 
clingo_theory_atoms_term_number(clingo_theory_atoms_t const * atoms,clingo_id_t value,int * ret)447 extern "C" bool clingo_theory_atoms_term_number(clingo_theory_atoms_t const *atoms, clingo_id_t value, int *ret) {
448     GRINGO_CLINGO_TRY { *ret = atoms->termNum(value); }
449     GRINGO_CLINGO_CATCH;
450 }
451 
clingo_theory_atoms_term_name(clingo_theory_atoms_t const * atoms,clingo_id_t value,char const ** ret)452 extern "C" bool clingo_theory_atoms_term_name(clingo_theory_atoms_t const *atoms, clingo_id_t value, char const **ret) {
453     GRINGO_CLINGO_TRY { *ret = atoms->termName(value); }
454     GRINGO_CLINGO_CATCH;
455 }
456 
clingo_theory_atoms_term_arguments(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_id_t const ** ret,size_t * n)457 extern "C" bool clingo_theory_atoms_term_arguments(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) {
458     GRINGO_CLINGO_TRY {
459         auto span = atoms->termArgs(value);
460         *ret = span.first;
461         *n = span.size;
462     }
463     GRINGO_CLINGO_CATCH;
464 }
465 
clingo_theory_atoms_element_tuple(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_id_t const ** ret,size_t * n)466 extern "C" bool clingo_theory_atoms_element_tuple(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) {
467     GRINGO_CLINGO_TRY {
468         auto span = atoms->elemTuple(value);
469         *ret = span.first;
470         *n = span.size;
471     }
472     GRINGO_CLINGO_CATCH;
473 }
474 
clingo_theory_atoms_element_condition(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_literal_t const ** ret,size_t * n)475 extern "C" bool clingo_theory_atoms_element_condition(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_literal_t const **ret, size_t *n) {
476     GRINGO_CLINGO_TRY {
477         auto span = atoms->elemCond(value);
478         *ret = span.first;
479         *n = span.size;
480     }
481     GRINGO_CLINGO_CATCH;
482 }
483 
clingo_theory_atoms_element_condition_id(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_literal_t * ret)484 extern "C" bool clingo_theory_atoms_element_condition_id(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_literal_t *ret) {
485     GRINGO_CLINGO_TRY { *ret = atoms->elemCondLit(value); }
486     GRINGO_CLINGO_CATCH;
487 }
488 
clingo_theory_atoms_atom_elements(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_id_t const ** ret,size_t * n)489 extern "C" bool clingo_theory_atoms_atom_elements(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) {
490     GRINGO_CLINGO_TRY {
491         auto span = atoms->atomElems(value);
492         *ret = span.first;
493         *n = span.size;
494     }
495     GRINGO_CLINGO_CATCH;
496 }
497 
clingo_theory_atoms_atom_term(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_id_t * ret)498 extern "C" bool clingo_theory_atoms_atom_term(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_id_t *ret) {
499     GRINGO_CLINGO_TRY { *ret = atoms->atomTerm(value); }
500     GRINGO_CLINGO_CATCH;
501 }
502 
clingo_theory_atoms_atom_has_guard(clingo_theory_atoms_t const * atoms,clingo_id_t value,bool * ret)503 extern "C" bool clingo_theory_atoms_atom_has_guard(clingo_theory_atoms_t const *atoms, clingo_id_t value, bool *ret) {
504     GRINGO_CLINGO_TRY { *ret = atoms->atomHasGuard(value); }
505     GRINGO_CLINGO_CATCH;
506 }
507 
clingo_theory_atoms_atom_literal(clingo_theory_atoms_t const * atoms,clingo_id_t value,clingo_literal_t * ret)508 extern "C" bool clingo_theory_atoms_atom_literal(clingo_theory_atoms_t const *atoms, clingo_id_t value, clingo_literal_t *ret) {
509     GRINGO_CLINGO_TRY { *ret = atoms->atomLit(value); }
510     GRINGO_CLINGO_CATCH;
511 }
512 
clingo_theory_atoms_atom_guard(clingo_theory_atoms_t const * atoms,clingo_id_t value,char const ** ret_op,clingo_id_t * ret_term)513 extern "C" bool clingo_theory_atoms_atom_guard(clingo_theory_atoms_t const *atoms, clingo_id_t value, char const **ret_op, clingo_id_t *ret_term) {
514     GRINGO_CLINGO_TRY {
515         auto guard = atoms->atomGuard(value);
516         *ret_op = guard.first;
517         *ret_term = guard.second;
518     }
519     GRINGO_CLINGO_CATCH;
520 }
521 
clingo_theory_atoms_size(clingo_theory_atoms_t const * atoms,size_t * ret)522 extern "C" bool clingo_theory_atoms_size(clingo_theory_atoms_t const *atoms, size_t *ret) {
523     GRINGO_CLINGO_TRY { *ret = atoms->numAtoms(); }
524     GRINGO_CLINGO_CATCH;
525 }
526 
clingo_theory_atoms_term_to_string_size(clingo_theory_atoms_t const * atoms,clingo_id_t value,size_t * n)527 extern "C" bool clingo_theory_atoms_term_to_string_size(clingo_theory_atoms_t const *atoms, clingo_id_t value, size_t *n) {
528     GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->termStr(value); }); }
529     GRINGO_CLINGO_CATCH;
530 }
531 
clingo_theory_atoms_term_to_string(clingo_theory_atoms_t const * atoms,clingo_id_t value,char * ret,size_t n)532 extern "C" bool clingo_theory_atoms_term_to_string(clingo_theory_atoms_t const *atoms, clingo_id_t value, char *ret, size_t n) {
533     GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->termStr(value); }); }
534     GRINGO_CLINGO_CATCH;
535 }
536 
clingo_theory_atoms_element_to_string_size(clingo_theory_atoms_t const * atoms,clingo_id_t value,size_t * n)537 extern "C" bool clingo_theory_atoms_element_to_string_size(clingo_theory_atoms_t const *atoms, clingo_id_t value, size_t *n) {
538     GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->elemStr(value); }); }
539     GRINGO_CLINGO_CATCH;
540 }
541 
clingo_theory_atoms_element_to_string(clingo_theory_atoms_t const * atoms,clingo_id_t value,char * ret,size_t n)542 extern "C" bool clingo_theory_atoms_element_to_string(clingo_theory_atoms_t const *atoms, clingo_id_t value, char *ret, size_t n) {
543     GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->elemStr(value); }); }
544     GRINGO_CLINGO_CATCH;
545 }
546 
clingo_theory_atoms_atom_to_string_size(clingo_theory_atoms_t const * atoms,clingo_id_t value,size_t * n)547 extern "C" bool clingo_theory_atoms_atom_to_string_size(clingo_theory_atoms_t const *atoms, clingo_id_t value, size_t *n) {
548     GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->atomStr(value); }); }
549     GRINGO_CLINGO_CATCH;
550 }
551 
clingo_theory_atoms_atom_to_string(clingo_theory_atoms_t const * atoms,clingo_id_t value,char * ret,size_t n)552 extern "C" bool clingo_theory_atoms_atom_to_string(clingo_theory_atoms_t const *atoms, clingo_id_t value, char *ret, size_t n) {
553     GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->atomStr(value); }); }
554     GRINGO_CLINGO_CATCH;
555 }
556 
557 // {{{1 assignment
558 
559 struct clingo_assignment : public Potassco::AbstractAssignment { };
560 
clingo_assignment_has_conflict(clingo_assignment_t const * ass)561 extern "C" bool clingo_assignment_has_conflict(clingo_assignment_t const *ass) {
562     return ass->hasConflict();
563 }
564 
clingo_assignment_decision_level(clingo_assignment_t const * ass)565 extern "C" uint32_t clingo_assignment_decision_level(clingo_assignment_t const *ass) {
566     return ass->level();
567 }
568 
clingo_assignment_root_level(clingo_assignment_t const * ass)569 extern "C" uint32_t clingo_assignment_root_level(clingo_assignment_t const *ass) {
570     return ass->rootLevel();
571 }
572 
clingo_assignment_has_literal(clingo_assignment_t const * ass,clingo_literal_t lit)573 extern "C" bool clingo_assignment_has_literal(clingo_assignment_t const *ass, clingo_literal_t lit) {
574     return ass->hasLit(lit);
575 }
576 
clingo_assignment_truth_value(clingo_assignment_t const * ass,clingo_literal_t lit,clingo_truth_value_t * ret)577 extern "C" bool clingo_assignment_truth_value(clingo_assignment_t const *ass, clingo_literal_t lit, clingo_truth_value_t *ret) {
578     GRINGO_CLINGO_TRY { *ret = ass->value(lit); }
579     GRINGO_CLINGO_CATCH;
580 }
581 
clingo_assignment_level(clingo_assignment_t const * ass,clingo_literal_t lit,uint32_t * ret)582 extern "C" bool clingo_assignment_level(clingo_assignment_t const *ass, clingo_literal_t lit, uint32_t *ret) {
583     GRINGO_CLINGO_TRY { *ret = ass->level(lit); }
584     GRINGO_CLINGO_CATCH;
585 }
586 
clingo_assignment_decision(clingo_assignment_t const * ass,uint32_t level,clingo_literal_t * ret)587 extern "C" bool clingo_assignment_decision(clingo_assignment_t const *ass, uint32_t level, clingo_literal_t *ret) {
588     GRINGO_CLINGO_TRY { *ret = ass->decision(level); }
589     GRINGO_CLINGO_CATCH;
590 }
591 
clingo_assignment_is_fixed(clingo_assignment_t const * ass,clingo_literal_t lit,bool * ret)592 extern "C" bool clingo_assignment_is_fixed(clingo_assignment_t const *ass, clingo_literal_t lit, bool *ret) {
593     GRINGO_CLINGO_TRY { *ret = ass->isFixed(lit); }
594     GRINGO_CLINGO_CATCH;
595 }
596 
clingo_assignment_is_true(clingo_assignment_t const * ass,clingo_literal_t lit,bool * ret)597 extern "C" bool clingo_assignment_is_true(clingo_assignment_t const *ass, clingo_literal_t lit, bool *ret) {
598     GRINGO_CLINGO_TRY { *ret = ass->isTrue(lit); }
599     GRINGO_CLINGO_CATCH;
600 }
601 
clingo_assignment_is_false(clingo_assignment_t const * ass,clingo_literal_t lit,bool * ret)602 extern "C" bool clingo_assignment_is_false(clingo_assignment_t const *ass, clingo_literal_t lit, bool *ret) {
603     GRINGO_CLINGO_TRY { *ret = ass->isFalse(lit); }
604     GRINGO_CLINGO_CATCH;
605 }
606 
clingo_assignment_size(clingo_assignment_t const * assignment)607 extern "C" size_t clingo_assignment_size(clingo_assignment_t const *assignment) {
608     return assignment->size();
609 }
610 
clingo_assignment_is_total(clingo_assignment_t const * assignment)611 extern "C" bool clingo_assignment_is_total(clingo_assignment_t const *assignment) {
612     return assignment->isTotal();
613 }
614 
clingo_assignment_at(clingo_assignment_t const * assignment,size_t offset,clingo_literal_t * literal)615 extern "C" bool clingo_assignment_at(clingo_assignment_t const *assignment, size_t offset, clingo_literal_t *literal) {
616     GRINGO_CLINGO_TRY {
617         if (offset >= assignment->size()) {
618             throw std::runtime_error("invalid offset");
619         }
620         *literal = numeric_cast<clingo_literal_t>(offset + 1);
621     }
622     GRINGO_CLINGO_CATCH;
623 }
624 
clingo_assignment_trail_size(clingo_assignment_t const * assignment,uint32_t * ret)625 extern "C" bool clingo_assignment_trail_size(clingo_assignment_t const *assignment, uint32_t *ret) {
626     GRINGO_CLINGO_TRY { *ret = assignment->trailSize(); }
627     GRINGO_CLINGO_CATCH;
628 }
629 
clingo_assignment_trail_begin(clingo_assignment_t const * assignment,uint32_t level,uint32_t * ret)630 extern "C" bool clingo_assignment_trail_begin(clingo_assignment_t const *assignment, uint32_t level, uint32_t *ret) {
631     GRINGO_CLINGO_TRY { *ret = assignment->trailBegin(level); }
632     GRINGO_CLINGO_CATCH;
633 }
634 
clingo_assignment_trail_end(clingo_assignment_t const * assignment,uint32_t level,uint32_t * ret)635 extern "C" bool clingo_assignment_trail_end(clingo_assignment_t const *assignment, uint32_t level, uint32_t *ret) {
636     GRINGO_CLINGO_TRY { *ret = assignment->trailEnd(level); }
637     GRINGO_CLINGO_CATCH;
638 }
639 
clingo_assignment_trail_at(clingo_assignment_t const * assignment,uint32_t offset,clingo_literal_t * ret)640 extern "C" bool clingo_assignment_trail_at(clingo_assignment_t const *assignment, uint32_t offset, clingo_literal_t *ret) {
641     GRINGO_CLINGO_TRY { *ret = assignment->trailAt(offset); }
642     GRINGO_CLINGO_CATCH;
643 }
644 
645 // {{{1 propagate init
646 
clingo_propagate_init_solver_literal(clingo_propagate_init_t const * init,clingo_literal_t lit,clingo_literal_t * ret)647 extern "C" bool clingo_propagate_init_solver_literal(clingo_propagate_init_t const *init, clingo_literal_t lit, clingo_literal_t *ret) {
648     GRINGO_CLINGO_TRY { *ret = init->mapLit(lit); }
649     GRINGO_CLINGO_CATCH;
650 }
651 
clingo_propagate_init_add_watch(clingo_propagate_init_t * init,clingo_literal_t lit)652 extern "C" bool clingo_propagate_init_add_watch(clingo_propagate_init_t *init, clingo_literal_t lit) {
653     GRINGO_CLINGO_TRY { init->addWatch(lit); }
654     GRINGO_CLINGO_CATCH;
655 }
656 
clingo_propagate_init_add_watch_to_thread(clingo_propagate_init_t * init,clingo_literal_t lit,uint32_t thread_id)657 extern "C" bool clingo_propagate_init_add_watch_to_thread(clingo_propagate_init_t *init, clingo_literal_t lit, uint32_t thread_id) {
658     GRINGO_CLINGO_TRY { init->addWatch(thread_id, lit); }
659     GRINGO_CLINGO_CATCH;
660 }
661 
clingo_propagate_init_remove_watch(clingo_propagate_init_t * init,clingo_literal_t lit)662 extern "C" bool clingo_propagate_init_remove_watch(clingo_propagate_init_t *init, clingo_literal_t lit) {
663     GRINGO_CLINGO_TRY { init->removeWatch(lit); }
664     GRINGO_CLINGO_CATCH;
665 }
666 
clingo_propagate_init_remove_watch_from_thread(clingo_propagate_init_t * init,clingo_literal_t lit,uint32_t thread_id)667 extern "C" bool clingo_propagate_init_remove_watch_from_thread(clingo_propagate_init_t *init, clingo_literal_t lit, uint32_t thread_id) {
668     GRINGO_CLINGO_TRY { init->removeWatch(thread_id, lit); }
669     GRINGO_CLINGO_CATCH;
670 }
671 
clingo_propagate_init_freeze_literal(clingo_propagate_init_t * init,clingo_literal_t lit)672 extern "C" bool clingo_propagate_init_freeze_literal(clingo_propagate_init_t *init, clingo_literal_t lit) {
673     GRINGO_CLINGO_TRY { init->freezeLiteral(lit); }
674     GRINGO_CLINGO_CATCH;
675 }
676 
clingo_propagate_init_number_of_threads(clingo_propagate_init_t const * init)677 extern "C" int clingo_propagate_init_number_of_threads(clingo_propagate_init_t const *init) {
678     return init->threads();
679 }
680 
clingo_propagate_init_symbolic_atoms(clingo_propagate_init_t const * init,clingo_symbolic_atoms_t const ** ret)681 extern "C" bool clingo_propagate_init_symbolic_atoms(clingo_propagate_init_t const *init, clingo_symbolic_atoms_t const **ret) {
682     GRINGO_CLINGO_TRY { *ret = &init->getDomain(); }
683     GRINGO_CLINGO_CATCH;
684 }
685 
clingo_propagate_init_theory_atoms(clingo_propagate_init_t const * init,clingo_theory_atoms_t const ** ret)686 extern "C" bool clingo_propagate_init_theory_atoms(clingo_propagate_init_t const *init, clingo_theory_atoms_t const **ret) {
687     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_theory_atoms const*>(&init->theory()); }
688     GRINGO_CLINGO_CATCH;
689 }
690 
clingo_propagate_init_set_check_mode(clingo_propagate_init_t * init,clingo_propagator_check_mode_t mode)691 extern "C" void clingo_propagate_init_set_check_mode(clingo_propagate_init_t *init, clingo_propagator_check_mode_t mode) {
692     init->setCheckMode(mode);
693 }
694 
clingo_propagate_init_get_check_mode(clingo_propagate_init_t const * init)695 extern "C" clingo_propagator_check_mode_t clingo_propagate_init_get_check_mode(clingo_propagate_init_t const *init) {
696     return init->getCheckMode();
697 }
698 
clingo_propagate_init_assignment(clingo_propagate_init_t const * init)699 extern "C" clingo_assignment_t const *clingo_propagate_init_assignment(clingo_propagate_init_t const *init) {
700     return static_cast<clingo_assignment_t const *>(&init->assignment());
701 }
702 
clingo_propagate_init_add_literal(clingo_propagate_init_t * init,bool freeze,clingo_literal_t * ret)703 extern "C" bool clingo_propagate_init_add_literal(clingo_propagate_init_t *init, bool freeze, clingo_literal_t *ret) {
704     GRINGO_CLINGO_TRY { *ret = init->addLiteral(freeze); }
705     GRINGO_CLINGO_CATCH;
706 }
707 
clingo_propagate_init_add_clause(clingo_propagate_init_t * init,clingo_literal_t const * literals,size_t size,bool * ret)708 extern "C" bool clingo_propagate_init_add_clause(clingo_propagate_init_t *init, clingo_literal_t const *literals, size_t size, bool *ret) {
709     GRINGO_CLINGO_TRY { *ret = init->addClause(Potassco::LitSpan{literals, size}); }
710     GRINGO_CLINGO_CATCH;
711 }
712 
clingo_propagate_init_add_weight_constraint(clingo_propagate_init_t * init,clingo_literal_t literal,clingo_weighted_literal_t const * literals,size_t size,clingo_weight_t bound,clingo_weight_constraint_type_t type,bool compare_equal,bool * ret)713 extern "C" bool clingo_propagate_init_add_weight_constraint(clingo_propagate_init_t *init, clingo_literal_t literal, clingo_weighted_literal_t const *literals, size_t size, clingo_weight_t bound, clingo_weight_constraint_type_t type, bool compare_equal, bool *ret) {
714     GRINGO_CLINGO_TRY { *ret = init->addWeightConstraint(literal, Potassco::WeightLitSpan{reinterpret_cast<Potassco::WeightLit_t const *>(literals), size}, bound, type, compare_equal); }
715     GRINGO_CLINGO_CATCH;
716 }
717 
clingo_propagate_init_add_minimize(clingo_propagate_init_t * init,clingo_literal_t literal,clingo_weight_t weight,clingo_weight_t priority)718 extern "C" bool clingo_propagate_init_add_minimize(clingo_propagate_init_t *init, clingo_literal_t literal, clingo_weight_t weight, clingo_weight_t priority) {
719     GRINGO_CLINGO_TRY { init->addMinimize(literal, weight, priority); }
720     GRINGO_CLINGO_CATCH;
721 }
722 
clingo_propagate_init_propagate(clingo_propagate_init_t * init,bool * ret)723 extern "C" bool clingo_propagate_init_propagate(clingo_propagate_init_t *init, bool *ret) {
724     GRINGO_CLINGO_TRY { *ret = init->propagate(); }
725     GRINGO_CLINGO_CATCH;
726 }
727 
728 // {{{1 propagate control
729 
730 struct clingo_propagate_control : Potassco::AbstractSolver { };
731 
clingo_propagate_control_thread_id(clingo_propagate_control_t const * ctl)732 extern "C" clingo_id_t clingo_propagate_control_thread_id(clingo_propagate_control_t const *ctl) {
733     return ctl->id();
734 }
735 
clingo_propagate_control_assignment(clingo_propagate_control_t const * ctl)736 extern "C" clingo_assignment_t const *clingo_propagate_control_assignment(clingo_propagate_control_t const *ctl) {
737     return static_cast<clingo_assignment_t const *>(&ctl->assignment());
738 }
739 
clingo_propagate_control_add_clause(clingo_propagate_control_t * ctl,clingo_literal_t const * clause,size_t n,clingo_clause_type_t prop,bool * ret)740 extern "C" bool clingo_propagate_control_add_clause(clingo_propagate_control_t *ctl, clingo_literal_t const *clause, size_t n, clingo_clause_type_t prop, bool *ret) {
741     GRINGO_CLINGO_TRY { *ret = ctl->addClause({clause, n}, Potassco::Clause_t(prop)); }
742     GRINGO_CLINGO_CATCH;
743 }
744 
clingo_propagate_control_propagate(clingo_propagate_control_t * ctl,bool * ret)745 extern "C" bool clingo_propagate_control_propagate(clingo_propagate_control_t *ctl, bool *ret) {
746     GRINGO_CLINGO_TRY { *ret = ctl->propagate(); }
747     GRINGO_CLINGO_CATCH;
748 }
749 
clingo_propagate_control_add_literal(clingo_propagate_control_t * control,clingo_literal_t * result)750 extern "C" bool clingo_propagate_control_add_literal(clingo_propagate_control_t *control, clingo_literal_t *result) {
751     GRINGO_CLINGO_TRY { *result = control->addVariable(); }
752     GRINGO_CLINGO_CATCH;
753 }
754 
clingo_propagate_control_add_watch(clingo_propagate_control_t * control,clingo_literal_t literal)755 extern "C" bool clingo_propagate_control_add_watch(clingo_propagate_control_t *control, clingo_literal_t literal) {
756     GRINGO_CLINGO_TRY { control->addWatch(literal); }
757     GRINGO_CLINGO_CATCH;
758 }
759 
clingo_propagate_control_has_watch(clingo_propagate_control_t const * control,clingo_literal_t literal)760 extern "C" bool clingo_propagate_control_has_watch(clingo_propagate_control_t const *control, clingo_literal_t literal) {
761     return control->hasWatch(literal);
762 }
763 
clingo_propagate_control_remove_watch(clingo_propagate_control_t * control,clingo_literal_t literal)764 extern "C" void clingo_propagate_control_remove_watch(clingo_propagate_control_t *control, clingo_literal_t literal) {
765     control->removeWatch(literal);
766 }
767 
768 // {{{1 model
769 
770 struct clingo_solve_control : clingo_model { };
771 
clingo_model_thread_id(clingo_model_t const * ctl,clingo_id_t * ret)772 extern "C" bool clingo_model_thread_id(clingo_model_t const *ctl, clingo_id_t *ret) {
773     GRINGO_CLINGO_TRY { *ret = ctl->threadId(); }
774     GRINGO_CLINGO_CATCH;
775 }
776 
clingo_solve_control_add_clause(clingo_solve_control_t * ctl,clingo_literal_t const * clause,size_t n)777 extern "C" bool clingo_solve_control_add_clause(clingo_solve_control_t *ctl, clingo_literal_t const *clause, size_t n) {
778     GRINGO_CLINGO_TRY { ctl->addClause(Potassco::toSpan(clause, n)); }
779     GRINGO_CLINGO_CATCH;
780 }
781 
clingo_solve_control_symbolic_atoms(clingo_solve_control_t const * control,clingo_symbolic_atoms_t const ** atoms)782 extern "C" bool clingo_solve_control_symbolic_atoms(clingo_solve_control_t const *control, clingo_symbolic_atoms_t const **atoms) {
783     GRINGO_CLINGO_TRY { *atoms = &control->getDomain(); }
784     GRINGO_CLINGO_CATCH;
785 }
clingo_model_contains(clingo_model_t const * m,clingo_symbol_t atom,bool * ret)786 extern "C" bool clingo_model_contains(clingo_model_t const *m, clingo_symbol_t atom, bool *ret) {
787     GRINGO_CLINGO_TRY { *ret = m->contains(Symbol(atom)); }
788     GRINGO_CLINGO_CATCH;
789 }
790 
clingo_model_symbols_size(clingo_model_t const * m,clingo_show_type_bitset_t show,size_t * n)791 extern "C" bool clingo_model_symbols_size(clingo_model_t const *m, clingo_show_type_bitset_t show, size_t *n) {
792     GRINGO_CLINGO_TRY {
793         // TODO: implement matching C++ functions ...
794         SymSpan atoms = m->atoms(show);
795         *n = atoms.size;
796     }
797     GRINGO_CLINGO_CATCH;
798 }
799 
clingo_model_symbols(clingo_model_t const * m,clingo_show_type_bitset_t show,clingo_symbol_t * ret,size_t n)800 extern "C" bool clingo_model_symbols(clingo_model_t const *m, clingo_show_type_bitset_t show, clingo_symbol_t *ret, size_t n) {
801     GRINGO_CLINGO_TRY {
802         // TODO: implement matching C++ functions ...
803         SymSpan atoms = m->atoms(show);
804         if (n < atoms.size) { throw std::length_error("not enough space"); }
805         for (auto it = atoms.first, ie = it + atoms.size; it != ie; ++it) { *ret++ = it->rep(); }
806     }
807     GRINGO_CLINGO_CATCH;
808 }
809 
clingo_model_optimality_proven(clingo_model_t const * m,bool * proven)810 extern "C" bool clingo_model_optimality_proven(clingo_model_t const *m, bool *proven) {
811     GRINGO_CLINGO_TRY { *proven = m->optimality_proven(); }
812     GRINGO_CLINGO_CATCH;
813 }
814 
clingo_model_cost_size(clingo_model_t const * m,size_t * n)815 extern "C" bool clingo_model_cost_size(clingo_model_t const *m, size_t *n) {
816     GRINGO_CLINGO_TRY {
817         // TODO: implement matching C++ functions ...
818         auto opt = m->optimization();
819         *n = opt.size();
820     }
821     GRINGO_CLINGO_CATCH;
822 }
823 
clingo_model_cost(clingo_model_t const * m,int64_t * ret,size_t n)824 extern "C" bool clingo_model_cost(clingo_model_t const *m, int64_t *ret, size_t n) {
825     GRINGO_CLINGO_TRY {
826         // TODO: implement matching C++ functions ...
827         auto opt = m->optimization();
828         if (n < opt.size()) { throw std::length_error("not enough space"); }
829         std::copy(opt.begin(), opt.end(), ret);
830     }
831     GRINGO_CLINGO_CATCH;
832 }
833 
clingo_model_extend(clingo_model_t * model,clingo_symbol_t const * symbols,size_t size)834 extern "C" bool clingo_model_extend(clingo_model_t *model, clingo_symbol_t const *symbols, size_t size) {
835     GRINGO_CLINGO_TRY { model->add({reinterpret_cast<Symbol const *>(symbols), size}); }
836     GRINGO_CLINGO_CATCH;
837 }
838 
clingo_model_context(clingo_model_t const * m,clingo_solve_control_t ** ret)839 extern "C" bool clingo_model_context(clingo_model_t const *m, clingo_solve_control_t **ret) {
840     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_solve_control_t*>(const_cast<clingo_model_t *>(m)); }
841     GRINGO_CLINGO_CATCH;
842 }
843 
clingo_model_number(clingo_model_t const * m,uint64_t * n)844 extern "C" bool clingo_model_number(clingo_model_t const *m, uint64_t *n) {
845     GRINGO_CLINGO_TRY { *n = m->number(); }
846     GRINGO_CLINGO_CATCH;
847 }
848 
clingo_model_type(clingo_model_t const * m,clingo_model_type_t * ret)849 extern "C" bool clingo_model_type(clingo_model_t const *m, clingo_model_type_t *ret) {
850     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_model_type_t>(m->type()); }
851     GRINGO_CLINGO_CATCH;
852 }
853 
clingo_model_is_true(clingo_model_t const * m,clingo_literal_t lit,bool * result)854 extern "C" bool clingo_model_is_true(clingo_model_t const *m, clingo_literal_t lit, bool *result) {
855     GRINGO_CLINGO_TRY { *result = static_cast<clingo_model_type_t>(m->isTrue(lit)); }
856     GRINGO_CLINGO_CATCH;
857 }
858 
859 // {{{1 configuration
860 
861 struct clingo_configuration : ConfigProxy { };
862 
clingo_configuration_type(clingo_configuration_t const * conf,clingo_id_t key,clingo_configuration_type_bitset_t * ret)863 extern "C" bool clingo_configuration_type(clingo_configuration_t const *conf, clingo_id_t key, clingo_configuration_type_bitset_t *ret) {
864     GRINGO_CLINGO_TRY {
865         int map_size, array_size, value_size;
866         conf->getKeyInfo(key, &map_size, &array_size, nullptr, &value_size);
867         *ret = 0;
868         if (map_size > 0) { *ret |= clingo_configuration_type_map; }
869         if (array_size >= 0) { *ret |= clingo_configuration_type_array; }
870         if (value_size >= 0) { *ret |= clingo_configuration_type_value; }
871     }
872     GRINGO_CLINGO_CATCH;
873 }
874 
clingo_configuration_map_at(clingo_configuration_t const * conf,clingo_id_t key,char const * name,clingo_id_t * subkey)875 extern "C" bool clingo_configuration_map_at(clingo_configuration_t const *conf, clingo_id_t key, char const *name, clingo_id_t* subkey) {
876     GRINGO_CLINGO_TRY { *subkey = conf->getSubKey(key, name); }
877     GRINGO_CLINGO_CATCH;
878 }
879 
clingo_configuration_map_has_subkey(clingo_configuration_t const * conf,clingo_id_t key,char const * name,bool * result)880 extern "C" bool clingo_configuration_map_has_subkey(clingo_configuration_t const *conf, clingo_id_t key, char const *name, bool *result) {
881     GRINGO_CLINGO_TRY { *result = conf->hasSubKey(key, name); }
882     GRINGO_CLINGO_CATCH;
883 }
884 
clingo_configuration_map_subkey_name(clingo_configuration_t const * conf,clingo_id_t key,size_t index,char const ** name)885 extern "C" bool clingo_configuration_map_subkey_name(clingo_configuration_t const *conf, clingo_id_t key, size_t index, char const **name) {
886     GRINGO_CLINGO_TRY { *name = conf->getSubKeyName(key, numeric_cast<unsigned>(index)); }
887     GRINGO_CLINGO_CATCH;
888 }
889 
clingo_configuration_map_size(clingo_configuration_t const * conf,clingo_id_t key,size_t * ret)890 extern "C" bool clingo_configuration_map_size(clingo_configuration_t const *conf, clingo_id_t key, size_t* ret) {
891     GRINGO_CLINGO_TRY {
892         int n;
893         conf->getKeyInfo(key, &n, nullptr, nullptr, nullptr);
894         if (n < 0) { throw std::runtime_error("not an array"); }
895         *ret = n;
896     }
897     GRINGO_CLINGO_CATCH;
898 }
899 
clingo_configuration_array_at(clingo_configuration_t const * conf,clingo_id_t key,size_t idx,clingo_id_t * ret)900 extern "C" bool clingo_configuration_array_at(clingo_configuration_t const *conf, clingo_id_t key, size_t idx, clingo_id_t *ret) {
901     GRINGO_CLINGO_TRY { *ret = conf->getArrKey(key, numeric_cast<unsigned>(idx)); }
902     GRINGO_CLINGO_CATCH;
903 }
904 
clingo_configuration_array_size(clingo_configuration_t const * conf,clingo_id_t key,size_t * ret)905 extern "C" bool clingo_configuration_array_size(clingo_configuration_t const *conf, clingo_id_t key, size_t *ret) {
906     GRINGO_CLINGO_TRY {
907         int n;
908         conf->getKeyInfo(key, nullptr, &n, nullptr, nullptr);
909         if (n < 0) { throw std::runtime_error("not an array"); }
910         *ret = n;
911     }
912     GRINGO_CLINGO_CATCH;
913 }
914 
clingo_configuration_root(clingo_configuration_t const * conf,clingo_id_t * ret)915 extern "C" bool clingo_configuration_root(clingo_configuration_t const *conf, clingo_id_t *ret) {
916     GRINGO_CLINGO_TRY { *ret = conf->getRootKey(); }
917     GRINGO_CLINGO_CATCH;
918 }
919 
clingo_configuration_description(clingo_configuration_t const * conf,clingo_id_t key,char const ** ret)920 extern "C" bool clingo_configuration_description(clingo_configuration_t const *conf, clingo_id_t key, char const **ret) {
921     GRINGO_CLINGO_TRY {
922         conf->getKeyInfo(key, nullptr, nullptr, ret, nullptr);
923         if (!ret) { throw std::runtime_error("no description"); }
924     }
925     GRINGO_CLINGO_CATCH;
926 }
927 
clingo_configuration_value_get_size(clingo_configuration_t const * conf,clingo_id_t key,size_t * n)928 extern "C" bool clingo_configuration_value_get_size(clingo_configuration_t const *conf, clingo_id_t key, size_t *n) {
929     GRINGO_CLINGO_TRY {
930         std::string value;
931         conf->getKeyValue(key, value);
932         *n = value.size() + 1;
933     }
934     GRINGO_CLINGO_CATCH;
935 }
936 
clingo_configuration_value_get(clingo_configuration_t const * conf,clingo_id_t key,char * ret,size_t n)937 extern "C" bool clingo_configuration_value_get(clingo_configuration_t const *conf, clingo_id_t key, char *ret, size_t n) {
938     GRINGO_CLINGO_TRY {
939         std::string value;
940         conf->getKeyValue(key, value);
941         if (n < value.size() + 1) { throw std::length_error("not enough space"); }
942         std::strcpy(ret, value.c_str());
943     }
944     GRINGO_CLINGO_CATCH;
945 }
946 
clingo_configuration_value_set(clingo_configuration_t * conf,clingo_id_t key,char const * val)947 extern "C" bool clingo_configuration_value_set(clingo_configuration_t *conf, clingo_id_t key, char const *val) {
948     GRINGO_CLINGO_TRY { conf->setKeyValue(key, val); }
949     GRINGO_CLINGO_CATCH;
950 }
951 
clingo_configuration_value_is_assigned(clingo_configuration_t const * conf,clingo_id_t key,bool * ret)952 extern "C" bool clingo_configuration_value_is_assigned(clingo_configuration_t const *conf, clingo_id_t key, bool *ret) {
953     GRINGO_CLINGO_TRY {
954         int n = 0;
955         conf->getKeyInfo(key, nullptr, nullptr, nullptr, &n);
956         if (n < 0) { throw std::runtime_error("not a value"); }
957         *ret = n > 0;
958     }
959     GRINGO_CLINGO_CATCH;
960 }
961 
962 // {{{1 statistics
963 
964 struct clingo_statistic : public Potassco::AbstractStatistics { };
965 
clingo_statistics_root(clingo_statistics_t const * stats,uint64_t * ret)966 extern "C" bool clingo_statistics_root(clingo_statistics_t const *stats, uint64_t *ret) {
967     GRINGO_CLINGO_TRY { *ret = stats->root(); }
968     GRINGO_CLINGO_CATCH;
969 }
970 
clingo_statistics_type(clingo_statistics_t const * stats,uint64_t key,clingo_statistics_type_t * ret)971 extern "C" bool clingo_statistics_type(clingo_statistics_t const *stats, uint64_t key, clingo_statistics_type_t *ret) {
972     GRINGO_CLINGO_TRY { *ret = stats->type(key); }
973     GRINGO_CLINGO_CATCH;
974 }
975 
clingo_statistics_array_size(clingo_statistics_t const * stats,uint64_t key,size_t * ret)976 extern "C" bool clingo_statistics_array_size(clingo_statistics_t const *stats, uint64_t key, size_t *ret) {
977     GRINGO_CLINGO_TRY { *ret = stats->size(key); }
978     GRINGO_CLINGO_CATCH;
979 }
980 
clingo_statistics_array_at(clingo_statistics_t const * stats,uint64_t key,size_t index,uint64_t * ret)981 extern "C" bool clingo_statistics_array_at(clingo_statistics_t const *stats, uint64_t key, size_t index, uint64_t *ret) {
982     GRINGO_CLINGO_TRY { *ret = stats->at(key, index); }
983     GRINGO_CLINGO_CATCH;
984 }
985 
clingo_statistics_array_push(clingo_statistics_t * stats,uint64_t key,clingo_statistics_type_t type,uint64_t * ret)986 extern "C" bool clingo_statistics_array_push(clingo_statistics_t *stats, uint64_t key, clingo_statistics_type_t type, uint64_t *ret) {
987     GRINGO_CLINGO_TRY { *ret = stats->push(key, static_cast<Potassco::Statistics_t>(type)); }
988     GRINGO_CLINGO_CATCH;
989 }
990 
clingo_statistics_map_size(clingo_statistics_t const * stats,uint64_t key,size_t * n)991 extern "C" bool clingo_statistics_map_size(clingo_statistics_t const *stats, uint64_t key, size_t *n) {
992     GRINGO_CLINGO_TRY { *n = stats->size(key); }
993     GRINGO_CLINGO_CATCH;
994 }
995 
clingo_statistics_map_has_subkey(clingo_statistics_t const * stats,uint64_t key,char const * name,bool * result)996 extern "C" bool clingo_statistics_map_has_subkey(clingo_statistics_t const *stats, uint64_t key, char const *name, bool* result) {
997     GRINGO_CLINGO_TRY { uint64_t temp; *result = stats->find(key, name, &temp); }
998     GRINGO_CLINGO_CATCH;
999 }
1000 
clingo_statistics_map_subkey_name(clingo_statistics_t const * stats,uint64_t key,size_t index,char const ** name)1001 extern "C" bool clingo_statistics_map_subkey_name(clingo_statistics_t const *stats, uint64_t key, size_t index, char const **name) {
1002     GRINGO_CLINGO_TRY { *name = stats->key(key, index); }
1003     GRINGO_CLINGO_CATCH;
1004 }
1005 
clingo_statistics_map_at(clingo_statistics_t const * stats,uint64_t key,char const * name,uint64_t * ret)1006 extern "C" bool clingo_statistics_map_at(clingo_statistics_t const *stats, uint64_t key, char const *name, uint64_t *ret) {
1007     GRINGO_CLINGO_TRY { *ret = stats->get(key, name); }
1008     GRINGO_CLINGO_CATCH;
1009 }
1010 
clingo_statistics_map_add_subkey(clingo_statistics_t * stats,uint64_t key,char const * name,clingo_statistics_type_t type,uint64_t * ret)1011 extern "C" bool clingo_statistics_map_add_subkey(clingo_statistics_t *stats, uint64_t key, char const *name, clingo_statistics_type_t type, uint64_t *ret) {
1012     GRINGO_CLINGO_TRY { *ret = stats->add(key, name, static_cast<Potassco::Statistics_t>(type)); }
1013     GRINGO_CLINGO_CATCH;
1014 }
1015 
clingo_statistics_value_get(clingo_statistics_t const * stats,uint64_t key,double * value)1016 extern "C" bool clingo_statistics_value_get(clingo_statistics_t const *stats, uint64_t key, double *value) {
1017     GRINGO_CLINGO_TRY { *value = stats->value(key); }
1018     GRINGO_CLINGO_CATCH;
1019 }
1020 
clingo_statistics_value_set(clingo_statistics_t * stats,uint64_t key,double value)1021 extern "C" bool clingo_statistics_value_set(clingo_statistics_t *stats, uint64_t key, double value) {
1022     GRINGO_CLINGO_TRY { stats->set(key, value); }
1023     GRINGO_CLINGO_CATCH;
1024 }
1025 
1026 
1027 // {{{1 global functions
1028 
clingo_parse_term(char const * str,clingo_logger_t logger,void * data,unsigned message_limit,clingo_symbol_t * ret)1029 extern "C" bool clingo_parse_term(char const *str, clingo_logger_t logger, void *data, unsigned message_limit, clingo_symbol_t *ret) {
1030     GRINGO_CLINGO_TRY {
1031         Input::GroundTermParser parser;
1032         Logger::Printer printer;
1033         if (logger) {
1034             printer = [logger, data](Warnings code, char const *msg) { logger(static_cast<clingo_warning_t>(code), msg, data); };
1035         }
1036         Logger log(printer, message_limit);
1037         Symbol sym = parser.parse(str, log);
1038         if (sym.type() == SymbolType::Special) { throw std::runtime_error("parsing failed"); }
1039         *ret = sym.rep();
1040     }
1041     GRINGO_CLINGO_CATCH;
1042 }
1043 
clingo_add_string(char const * str,char const ** ret)1044 extern "C" bool clingo_add_string(char const *str, char const **ret) {
1045     GRINGO_CLINGO_TRY { *ret = String(str).c_str(); }
1046     GRINGO_CLINGO_CATCH;
1047 }
1048 
clingo_version(int * major,int * minor,int * revision)1049 extern "C" void clingo_version(int *major, int *minor, int *revision) {
1050     *major = CLINGO_VERSION_MAJOR;
1051     *minor = CLINGO_VERSION_MINOR;
1052     *revision = CLINGO_VERSION_REVISION;
1053 }
1054 
1055 // {{{1 backend
1056 
1057 struct clingo_backend : clingo_control_t { };
1058 
clingo_backend_begin(clingo_backend_t * backend)1059 extern "C" bool clingo_backend_begin(clingo_backend_t *backend) {
1060     GRINGO_CLINGO_TRY {
1061         if (!backend->beginAddBackend()) { throw std::runtime_error("backend not available"); }
1062     }
1063     GRINGO_CLINGO_CATCH;
1064 }
1065 
clingo_backend_end(clingo_backend_t * backend)1066 extern "C" bool clingo_backend_end(clingo_backend_t *backend) {
1067     GRINGO_CLINGO_TRY { backend->endAddBackend(); }
1068     GRINGO_CLINGO_CATCH;
1069 }
1070 
clingo_backend_rule(clingo_backend_t * backend,bool choice,clingo_atom_t const * head,size_t head_n,clingo_literal_t const * body,size_t body_n)1071 extern "C" bool clingo_backend_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_n, clingo_literal_t const *body, size_t body_n) {
1072     GRINGO_CLINGO_TRY {
1073         if (body_n == 0 && head_n == 1 && !choice) { backend->addFact(*head); }
1074         outputRule(*backend->getBackend(), choice, {head, head_n}, {body, body_n});
1075     }
1076     GRINGO_CLINGO_CATCH;
1077 }
1078 
clingo_backend_weight_rule(clingo_backend_t * backend,bool choice,clingo_atom_t const * head,size_t head_n,clingo_weight_t lower,clingo_weighted_literal_t const * body,size_t body_n)1079 extern "C" bool clingo_backend_weight_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_n, clingo_weight_t lower, clingo_weighted_literal_t const *body, size_t body_n) {
1080     GRINGO_CLINGO_TRY { outputRule(*backend->getBackend(), choice, {head, head_n}, lower, {reinterpret_cast<Potassco::WeightLit_t const *>(body), body_n}); }
1081     GRINGO_CLINGO_CATCH;
1082 }
1083 
clingo_backend_minimize(clingo_backend_t * backend,clingo_weight_t prio,clingo_weighted_literal_t const * lits,size_t lits_n)1084 extern "C" bool clingo_backend_minimize(clingo_backend_t *backend, clingo_weight_t prio, clingo_weighted_literal_t const* lits, size_t lits_n) {
1085     GRINGO_CLINGO_TRY { backend->getBackend()->minimize(prio, {reinterpret_cast<Potassco::WeightLit_t const *>(lits), lits_n}); }
1086     GRINGO_CLINGO_CATCH;
1087 }
1088 
clingo_backend_project(clingo_backend_t * backend,clingo_atom_t const * atoms,size_t n)1089 extern "C" bool clingo_backend_project(clingo_backend_t *backend, clingo_atom_t const *atoms, size_t n) {
1090     GRINGO_CLINGO_TRY { backend->getBackend()->project({atoms, n}); }
1091     GRINGO_CLINGO_CATCH;
1092 }
1093 
clingo_backend_external(clingo_backend_t * backend,clingo_atom_t atom,clingo_external_type_t v)1094 extern "C" bool clingo_backend_external(clingo_backend_t *backend, clingo_atom_t atom, clingo_external_type_t v) {
1095     GRINGO_CLINGO_TRY { backend->getBackend()->external(atom, Potassco::Value_t(v)); }
1096     GRINGO_CLINGO_CATCH;
1097 }
1098 
clingo_backend_assume(clingo_backend_t * backend,clingo_literal_t const * literals,size_t n)1099 extern "C" bool clingo_backend_assume(clingo_backend_t *backend, clingo_literal_t const *literals, size_t n) {
1100     GRINGO_CLINGO_TRY { backend->getBackend()->assume({literals, n}); }
1101     GRINGO_CLINGO_CATCH;
1102 }
1103 
clingo_backend_heuristic(clingo_backend_t * backend,clingo_atom_t atom,clingo_heuristic_type_t type,int bias,unsigned priority,clingo_literal_t const * condition,size_t condition_n)1104 extern "C" bool clingo_backend_heuristic(clingo_backend_t *backend, clingo_atom_t atom, clingo_heuristic_type_t type, int bias, unsigned priority, clingo_literal_t const *condition, size_t condition_n) {
1105     GRINGO_CLINGO_TRY { backend->getBackend()->heuristic(atom, Potassco::Heuristic_t(type), bias, priority, {condition, condition_n}); }
1106     GRINGO_CLINGO_CATCH;
1107 }
1108 
clingo_backend_acyc_edge(clingo_backend_t * backend,int node_u,int node_v,clingo_literal_t const * condition,size_t condition_n)1109 extern "C" bool clingo_backend_acyc_edge(clingo_backend_t *backend, int node_u, int node_v, clingo_literal_t const *condition, size_t condition_n) {
1110     GRINGO_CLINGO_TRY { backend->getBackend()->acycEdge(node_u, node_v, {condition, condition_n}); }
1111     GRINGO_CLINGO_CATCH;
1112 }
1113 
clingo_backend_add_atom(clingo_backend_t * backend,clingo_symbol_t * symbol,clingo_atom_t * ret)1114 extern "C" bool clingo_backend_add_atom(clingo_backend_t *backend, clingo_symbol_t *symbol, clingo_atom_t *ret) {
1115     GRINGO_CLINGO_TRY {
1116         if (symbol) {
1117             if (Symbol{*symbol}.type() != SymbolType::Fun) {
1118                 throw std::runtime_error("function expected");
1119             }
1120             *ret = backend->addAtom(Symbol{*symbol});
1121         }
1122         else { *ret = backend->addProgramAtom(); }
1123     }
1124     GRINGO_CLINGO_CATCH;
1125 }
1126 
1127 // {{{1 solve handle
1128 
1129 struct clingo_solve_handle : public Gringo::SolveFuture { };
1130 
clingo_solve_handle_get(clingo_solve_handle_t * handle,clingo_solve_result_bitset_t * result)1131 extern "C" bool clingo_solve_handle_get(clingo_solve_handle_t *handle, clingo_solve_result_bitset_t *result) {
1132     GRINGO_CLINGO_TRY { *result = handle->get(); }
1133     GRINGO_CLINGO_CATCH;
1134 }
1135 
clingo_solve_handle_wait(clingo_solve_handle_t * handle,double timeout,bool * result)1136 extern "C" void clingo_solve_handle_wait(clingo_solve_handle_t *handle, double timeout, bool *result) {
1137     try { *result = handle->wait(timeout); }
1138     catch (...) { std::terminate(); }
1139 }
clingo_solve_handle_cancel(clingo_solve_handle_t * handle)1140 extern "C" bool clingo_solve_handle_cancel(clingo_solve_handle_t *handle) {
1141     GRINGO_CLINGO_TRY { handle->cancel(); }
1142     GRINGO_CLINGO_CATCH;
1143 }
clingo_solve_handle_close(clingo_solve_handle_t * handle)1144 extern "C" bool clingo_solve_handle_close(clingo_solve_handle_t *handle) {
1145     GRINGO_CLINGO_TRY { if (handle) { delete handle; } }
1146     GRINGO_CLINGO_CATCH;
1147 }
clingo_solve_handle_model(clingo_solve_handle_t * handle,clingo_model_t const ** model)1148 extern "C" bool clingo_solve_handle_model(clingo_solve_handle_t *handle, clingo_model_t const **model) {
1149     GRINGO_CLINGO_TRY {
1150         *model = handle->model();
1151     }
1152     GRINGO_CLINGO_CATCH;
1153 }
clingo_solve_handle_core(clingo_solve_handle_t * handle,clingo_literal_t const ** core,size_t * size)1154 extern "C" bool clingo_solve_handle_core(clingo_solve_handle_t *handle, clingo_literal_t const **core, size_t *size) {
1155     GRINGO_CLINGO_TRY {
1156         auto core_span = handle->unsatCore();
1157         *core = core_span.first;
1158         *size = core_span.size;
1159     }
1160     GRINGO_CLINGO_CATCH;
1161 }
clingo_solve_handle_resume(clingo_solve_handle_t * handle)1162 extern "C" bool clingo_solve_handle_resume(clingo_solve_handle_t *handle) {
1163     GRINGO_CLINGO_TRY { handle->resume(); }
1164     GRINGO_CLINGO_CATCH;
1165 }
1166 
1167 // {{{1 ast
1168 
1169 #define C(name) \
1170     static_assert(clingo_ast_type_##name >= 0, "no matching type existis"); \
1171     clingo_ast_argument clingo_ast_argument_##name[] =
1172 #define A(name, type) { clingo_ast_attribute_##name, clingo_ast_attribute_type_##type }
1173 #define E(name) { #name, clingo_ast_argument_##name, sizeof(clingo_ast_argument_##name) / sizeof(clingo_ast_argument_t) }
1174 
1175 // terms
C(id)1176 C(id) { A(location, location), A(name, string) };
C(variable)1177 C(variable) { A(location, location), A(name, string) };
C(symbolic_term)1178 C(symbolic_term) { A(location, location), A(symbol, symbol) };
C(unary_operation)1179 C(unary_operation) { A(location, location), A(operator_type, number), A(argument, ast) };
C(binary_operation)1180 C(binary_operation) { A(location, location), A(operator_type, number), A(left, ast), A(right, ast) };
C(interval)1181 C(interval) { A(location, location), A(left, ast), A(right, ast) };
C(function)1182 C(function) { A(location, location), A(name, string), A(arguments, ast_array), A(external, number) };
C(pool)1183 C(pool) { A(location, location), A(arguments, ast_array) };
1184 // csp terms
C(csp_product)1185 C(csp_product) { A(location, location), A(coefficient, ast), A(variable, optional_ast) };
C(csp_sum)1186 C(csp_sum) { A(location, location), A(terms, ast_array) };
C(csp_guard)1187 C(csp_guard) { A(comparison, number), A(term, ast) };
1188 // simple atoms
C(boolean_constant)1189 C(boolean_constant) { A(value, number) };
C(symbolic_atom)1190 C(symbolic_atom) { A(symbol, ast) };
C(comparison)1191 C(comparison) { A(comparison, number), A(left, ast), A(right, ast) };
C(csp_literal)1192 C(csp_literal) { A(location, location), A(term, ast), A(guards, ast_array) };
1193 // aggregates
C(aggregate_guard)1194 C(aggregate_guard) { A(comparison, number), A(term, ast) };
C(conditional_literal)1195 C(conditional_literal) { A(location, location), A(literal, ast), A(condition, ast_array) };
C(aggregate)1196 C(aggregate) { A(location, location), A(left_guard, optional_ast), A(elements, ast_array), A(right_guard, optional_ast) };
C(body_aggregate_element)1197 C(body_aggregate_element) { A(terms, ast_array), A(condition, ast_array) };
C(body_aggregate)1198 C(body_aggregate) { A(location, location), A(left_guard, optional_ast), A(function, number), A(elements, ast_array), A(right_guard, optional_ast) };
C(head_aggregate_element)1199 C(head_aggregate_element) { A(terms, ast_array), A(condition, ast) };
C(head_aggregate)1200 C(head_aggregate) { A(location, location), A(left_guard, optional_ast), A(function, number), A(elements, ast_array), A(right_guard, optional_ast) };
C(disjunction)1201 C(disjunction) { A(location, location), A(elements, ast_array) };
C(disjoint_element)1202 C(disjoint_element) { A(location, location), A(terms, ast_array), A(term, ast), A(condition, ast_array) };
C(disjoint)1203 C(disjoint) { A(location, location), A(elements, ast_array) };
1204 // theory atoms
C(theory_sequence)1205 C(theory_sequence) { A(location, location), A(sequence_type, number), A(terms, ast_array) };
C(theory_function)1206 C(theory_function) { A(location, location), A(name, string), A(arguments, ast_array) };
C(theory_unparsed_term_element)1207 C(theory_unparsed_term_element) { A(operators, string_array), A(term, ast) };
C(theory_unparsed_term)1208 C(theory_unparsed_term) { A(location, location), A(elements, ast_array) };
C(theory_guard)1209 C(theory_guard) { A(operator_name, string), A(term, ast) };
C(theory_atom_element)1210 C(theory_atom_element) { A(terms, ast_array), A(condition, ast_array) };
C(theory_atom)1211 C(theory_atom) { A(location, location), A(term, ast), A(elements, ast_array), A(guard, optional_ast) };
1212 // literals
C(literal)1213 C(literal) { A(location, location), A(sign, number), A(atom, ast) };
1214 // theory definition
C(theory_operator_definition)1215 C(theory_operator_definition) { A(location, location), A(name, string), A(priority, number), A(operator_type, number) };
C(theory_term_definition)1216 C(theory_term_definition) { A(location, location), A(name, string), A(operators, ast_array) };
C(theory_guard_definition)1217 C(theory_guard_definition) { A(operators, string_array), A(term, string) };
C(theory_atom_definition)1218 C(theory_atom_definition) { A(location, location), A(atom_type, number), A(name, string), A(arity, number), A(term, string), A(guard, optional_ast) };
1219 // statemets
C(rule)1220 C(rule) { A(location, location), A(head, ast), A(body, ast_array) };
C(definition)1221 C(definition) { A(location, location), A(name, string), A(value, ast), A(is_default, number) };
C(show_signature)1222 C(show_signature) { A(location, location), A(name, string), A(arity, number), A(positive, number), A(csp, number) };
C(show_term)1223 C(show_term) { A(location, location), A(term, ast), A(body, ast_array), A(csp, number) };
C(minimize)1224 C(minimize) { A(location, location), A(weight, ast), A(priority, ast), A(terms, ast_array), A(body, ast_array) };
C(script)1225 C(script) { A(location, location), A(name, string), A(code, string) };
C(program)1226 C(program) { A(location, location), A(name, string), A(parameters, ast_array) };
C(external)1227 C(external) { A(location, location), A(atom, ast), A(body, ast_array), A(external_type, ast) };
C(edge)1228 C(edge) { A(location, location), A(node_u, ast), A(node_v, ast), A(body, ast_array) };
C(heuristic)1229 C(heuristic) { A(location, location), A(atom, ast), A(body, ast_array), A(bias, ast), A(priority, ast), A(modifier, ast) };
C(project_atom)1230 C(project_atom) { A(location, location), A(atom, ast), A(body, ast_array) };
C(project_signature)1231 C(project_signature) { A(location, location), A(name, string), A(arity, number), A(positive, number) };
C(defined)1232 C(defined) { A(location, location), A(name, string), A(arity, number), A(positive, number) };
C(theory_definition)1233 C(theory_definition) { A(location, location), A(name, string), A(terms, ast_array), A(atoms, ast_array) };
1234 
1235 clingo_ast_constructor_t const clingo_ast_constructor_list[] = {
1236     // terms
1237     E(id),
1238     E(variable),
1239     E(symbolic_term),
1240     E(unary_operation),
1241     E(binary_operation),
1242     E(interval),
1243     E(function),
1244     E(pool),
1245     // csp terms
1246     E(csp_product),
1247     E(csp_sum),
1248     E(csp_guard),
1249     // simple atoms
1250     E(boolean_constant),
1251     E(symbolic_atom),
1252     E(comparison),
1253     E(csp_literal),
1254     // aggregates
1255     E(aggregate_guard),
1256     E(conditional_literal),
1257     E(aggregate),
1258     E(body_aggregate_element),
1259     E(body_aggregate),
1260     E(head_aggregate_element),
1261     E(head_aggregate),
1262     E(disjunction),
1263     E(disjoint_element),
1264     E(disjoint),
1265     // theory atoms
1266     E(theory_sequence),
1267     E(theory_function),
1268     E(theory_unparsed_term_element),
1269     E(theory_unparsed_term),
1270     E(theory_guard),
1271     E(theory_atom_element),
1272     E(theory_atom),
1273     // literals
1274     E(literal),
1275     // theory definition
1276     E(theory_operator_definition),
1277     E(theory_term_definition),
1278     E(theory_guard_definition),
1279     E(theory_atom_definition),
1280     // statemets
1281     E(rule),
1282     E(definition),
1283     E(show_signature),
1284     E(show_term),
1285     E(minimize),
1286     E(script),
1287     E(program),
1288     E(external),
1289     E(edge),
1290     E(heuristic),
1291     E(project_atom),
1292     E(project_signature),
1293     E(defined),
1294     E(theory_definition)
1295 };
1296 
1297 clingo_ast_constructors_t g_clingo_ast_constructors = {
1298     clingo_ast_constructor_list, sizeof(clingo_ast_constructor_list) / sizeof(clingo_ast_constructor_t)
1299 };
1300 
1301 char const * attribute_list[] = {
1302     "argument",
1303     "arguments",
1304     "arity",
1305     "atom",
1306     "atoms",
1307     "atom_type",
1308     "bias",
1309     "body",
1310     "code",
1311     "coefficient",
1312     "comparison",
1313     "condition",
1314     "csp",
1315     "elements",
1316     "external",
1317     "external_type",
1318     "function",
1319     "guard",
1320     "guards",
1321     "head",
1322     "is_default",
1323     "left",
1324     "left_guard",
1325     "literal",
1326     "location",
1327     "modifier",
1328     "name",
1329     "node_u",
1330     "node_v",
1331     "operator_name",
1332     "operator_type",
1333     "operators",
1334     "parameters",
1335     "positive",
1336     "priority",
1337     "right",
1338     "right_guard",
1339     "sequence_type",
1340     "sign",
1341     "symbol",
1342     "term",
1343     "terms",
1344     "value",
1345     "variable",
1346     "weight",
1347 };
1348 
1349 clingo_ast_attribute_names_t g_clingo_ast_attribute_names = {
1350     attribute_list,
1351     sizeof(attribute_list) / sizeof(char const *)
1352 };
1353 
1354 #undef E
1355 #undef A
1356 #undef C
1357 
clingo_ast_build(clingo_ast_type_t type,clingo_ast_t ** ast,...)1358 extern "C" bool clingo_ast_build(clingo_ast_type_t type, clingo_ast_t **ast, ...) {
1359     GRINGO_CLINGO_TRY {
1360         va_list args;
1361         va_start(args, ast);
1362 
1363         Input::SAST sast{static_cast<clingo_ast_type_e>(type)};
1364 
1365         auto const &cons = g_clingo_ast_constructors.constructors[type];
1366         for (auto it = cons.arguments, ie = it + cons.size; it != ie; ++it) {
1367             auto attribute = static_cast<clingo_ast_attribute_e>(it->attribute);
1368             switch (static_cast<clingo_ast_attribute_type_e>(it->type)) {
1369                 case clingo_ast_attribute_type_number: {
1370                     sast->value(attribute, va_arg(args, int));
1371                     break;
1372                 }
1373                 case clingo_ast_attribute_type_symbol: {
1374                     sast->value(attribute, Symbol{va_arg(args, clingo_symbol_t)});
1375                     break;
1376                 }
1377                 case clingo_ast_attribute_type_location: {
1378                     sast->value(attribute, conv(*va_arg(args, clingo_location_t*)));
1379                     break;
1380                 }
1381                 case clingo_ast_attribute_type_string: {
1382                     sast->value(attribute, String{va_arg(args, char const*)});
1383                     break;
1384                 }
1385                 case clingo_ast_attribute_type_ast: {
1386                     sast->value(attribute, Input::SAST{va_arg(args, Input::AST*)});
1387                     break;
1388                 }
1389                 case clingo_ast_attribute_type_optional_ast: {
1390                     sast->value(attribute, Input::OAST{Input::SAST{va_arg(args, Input::AST*)}});
1391                     break;
1392                 }
1393                 case clingo_ast_attribute_type_string_array: {
1394                     auto *data = va_arg(args, char const**);
1395                     sast->value(attribute, Input::AST::StrVec{data, data + va_arg(args, size_t)});
1396                     break;
1397                 }
1398                 case clingo_ast_attribute_type_ast_array: {
1399                     auto *data = va_arg(args, Input::AST**);
1400                     sast->value(attribute, Input::AST::ASTVec{data, data + va_arg(args, size_t)});
1401                     break;
1402                 }
1403             }
1404         }
1405 
1406         *ast = reinterpret_cast<clingo_ast_t*>(sast.release());
1407     }
1408     GRINGO_CLINGO_CATCH;
1409 }
1410 
clingo_ast_get_type(clingo_ast_t * ast,clingo_ast_type_t * type)1411 extern "C" bool clingo_ast_get_type(clingo_ast_t *ast, clingo_ast_type_t *type) {
1412     GRINGO_CLINGO_TRY {
1413         *type = ast->ast.type();
1414     }
1415     GRINGO_CLINGO_CATCH;
1416 }
1417 
clingo_ast_copy(clingo_ast_t * ast,clingo_ast_t ** copy)1418 extern "C" bool clingo_ast_copy(clingo_ast_t *ast, clingo_ast_t **copy) {
1419     GRINGO_CLINGO_TRY {
1420         *copy = reinterpret_cast<clingo_ast_t*>(ast->ast.copy().release());
1421     }
1422     GRINGO_CLINGO_CATCH;
1423 }
1424 
clingo_ast_deep_copy(clingo_ast_t * ast,clingo_ast_t ** copy)1425 extern "C" bool clingo_ast_deep_copy(clingo_ast_t *ast, clingo_ast_t **copy) {
1426     GRINGO_CLINGO_TRY {
1427         *copy = reinterpret_cast<clingo_ast_t*>(ast->ast.deepcopy().release());
1428     }
1429     GRINGO_CLINGO_CATCH;
1430 }
1431 
clingo_ast_less_than(clingo_ast_t * a,clingo_ast_t * b)1432 extern "C" bool clingo_ast_less_than(clingo_ast_t *a, clingo_ast_t *b) {
1433     return a->ast < b->ast;
1434 }
1435 
clingo_ast_equal(clingo_ast_t * a,clingo_ast_t * b)1436 extern "C" bool clingo_ast_equal(clingo_ast_t *a, clingo_ast_t *b) {
1437     return a->ast == b->ast;
1438 }
1439 
clingo_ast_hash(clingo_ast_t * a)1440 extern "C" size_t clingo_ast_hash(clingo_ast_t *a) {
1441     return a->ast.hash();
1442 }
1443 
clingo_ast_to_string_size(clingo_ast_t * ast,size_t * size)1444 extern "C" bool clingo_ast_to_string_size(clingo_ast_t *ast, size_t *size) {
1445     GRINGO_CLINGO_TRY { *size = print_size([&ast](std::ostream &out) { out << ast->ast; }); }
1446     GRINGO_CLINGO_CATCH;
1447 }
1448 
clingo_ast_to_string(clingo_ast_t * ast,char * string,size_t size)1449 extern "C" bool clingo_ast_to_string(clingo_ast_t *ast, char *string, size_t size) {
1450     GRINGO_CLINGO_TRY { print(string, size, [&ast](std::ostream &out) { out << ast->ast; }); }
1451     GRINGO_CLINGO_CATCH;
1452 }
1453 
clingo_ast_acquire(clingo_ast_t * ast)1454 extern "C" void clingo_ast_acquire(clingo_ast_t *ast) {
1455     ast->ast.incRef();
1456 }
1457 
clingo_ast_release(clingo_ast_t * ast)1458 extern "C" void clingo_ast_release(clingo_ast_t *ast) {
1459     ast->ast.decRef();
1460     if (ast->ast.refCount() == 0) {
1461         delete ast;
1462     }
1463 }
1464 
1465 template <class T>
get_attr(clingo_ast_t * ast,clingo_ast_attribute_t attribute)1466 T &get_attr(clingo_ast_t *ast, clingo_ast_attribute_t attribute) {
1467     return mpark::get<T>(ast->ast.value(static_cast<clingo_ast_attribute_e>(attribute)));
1468 }
1469 
clingo_ast_has_attribute(clingo_ast_t * ast,clingo_ast_attribute_t attribute,bool * has_attribute)1470 extern "C" bool clingo_ast_has_attribute(clingo_ast_t *ast, clingo_ast_attribute_t attribute, bool *has_attribute) {
1471     GRINGO_CLINGO_TRY {
1472         *has_attribute = ast->ast.hasValue(static_cast<clingo_ast_attribute_e>(attribute));
1473     }
1474     GRINGO_CLINGO_CATCH;
1475 }
1476 
clingo_ast_attribute_type(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_ast_attribute_type_t * type)1477 extern "C" bool clingo_ast_attribute_type(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_ast_attribute_type_t *type) {
1478     GRINGO_CLINGO_TRY {
1479         *type = static_cast<clingo_ast_attribute_type_t>(ast->ast.value(static_cast<clingo_ast_attribute_e>(attribute)).index());
1480     }
1481     GRINGO_CLINGO_CATCH;
1482 }
1483 
clingo_ast_attribute_get_number(clingo_ast_t * ast,clingo_ast_attribute_t attribute,int * value)1484 extern "C" bool clingo_ast_attribute_get_number(clingo_ast_t *ast, clingo_ast_attribute_t attribute, int *value) {
1485     GRINGO_CLINGO_TRY {
1486         *value = get_attr<int>(ast, attribute);
1487     }
1488     GRINGO_CLINGO_CATCH;
1489 }
1490 
clingo_ast_attribute_set_number(clingo_ast_t * ast,clingo_ast_attribute_t attribute,int value)1491 extern "C" bool clingo_ast_attribute_set_number(clingo_ast_t *ast, clingo_ast_attribute_t attribute, int value) {
1492     GRINGO_CLINGO_TRY {
1493         get_attr<int>(ast, attribute) = value;
1494     }
1495     GRINGO_CLINGO_CATCH;
1496 }
1497 
clingo_ast_attribute_get_symbol(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_symbol_t * value)1498 extern "C" bool clingo_ast_attribute_get_symbol(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_symbol_t *value) {
1499     GRINGO_CLINGO_TRY {
1500         *value = get_attr<Symbol>(ast, attribute).rep();
1501     }
1502     GRINGO_CLINGO_CATCH;
1503 }
1504 
clingo_ast_attribute_set_symbol(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_symbol_t value)1505 extern "C" bool clingo_ast_attribute_set_symbol(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_symbol_t value) {
1506     GRINGO_CLINGO_TRY {
1507         get_attr<Symbol>(ast, attribute) = Symbol{value};
1508     }
1509     GRINGO_CLINGO_CATCH;
1510 }
1511 
clingo_ast_attribute_get_location(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_location_t * value)1512 extern "C" bool clingo_ast_attribute_get_location(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_location_t *value) {
1513     GRINGO_CLINGO_TRY {
1514         *value = conv(get_attr<Location>(ast, attribute));
1515     }
1516     GRINGO_CLINGO_CATCH;
1517 }
1518 
clingo_ast_attribute_set_location(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_location_t const * value)1519 extern "C" bool clingo_ast_attribute_set_location(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_location_t const *value) {
1520     GRINGO_CLINGO_TRY {
1521         get_attr<Location>(ast, attribute) = conv(*value);
1522     }
1523     GRINGO_CLINGO_CATCH;
1524 }
1525 
clingo_ast_attribute_get_string(clingo_ast_t * ast,clingo_ast_attribute_t attribute,char const ** value)1526 extern "C" bool clingo_ast_attribute_get_string(clingo_ast_t *ast, clingo_ast_attribute_t attribute, char const **value) {
1527     GRINGO_CLINGO_TRY {
1528         *value = get_attr<String>(ast, attribute).c_str();
1529     }
1530     GRINGO_CLINGO_CATCH;
1531 }
1532 
clingo_ast_attribute_set_string(clingo_ast_t * ast,clingo_ast_attribute_t attribute,char const * value)1533 extern "C" bool clingo_ast_attribute_set_string(clingo_ast_t *ast, clingo_ast_attribute_t attribute, char const *value) {
1534     GRINGO_CLINGO_TRY {
1535         get_attr<String>(ast, attribute) = value;
1536     }
1537     GRINGO_CLINGO_CATCH;
1538 }
1539 
clingo_ast_attribute_get_optional_ast(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_ast_t ** value)1540 extern "C" bool clingo_ast_attribute_get_optional_ast(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_ast_t **value) {
1541     GRINGO_CLINGO_TRY {
1542         *value = reinterpret_cast<clingo_ast_t*>(get_attr<Input::OAST>(ast, attribute).ast.get());
1543         if (*value != nullptr) {
1544             (*value)->ast.incRef();
1545         }
1546     }
1547     GRINGO_CLINGO_CATCH;
1548 }
1549 
clingo_ast_attribute_set_optional_ast(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_ast_t * value)1550 extern "C" bool clingo_ast_attribute_set_optional_ast(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_ast_t *value) {
1551     GRINGO_CLINGO_TRY {
1552         get_attr<Input::OAST>(ast, attribute).ast = Input::SAST{reinterpret_cast<Input::AST*>(value)};
1553     }
1554     GRINGO_CLINGO_CATCH;
1555 }
1556 
clingo_ast_attribute_get_ast(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_ast_t ** value)1557 extern "C" bool clingo_ast_attribute_get_ast(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_ast_t **value) {
1558     GRINGO_CLINGO_TRY {
1559         *value = reinterpret_cast<clingo_ast_t*>(get_attr<Input::SAST>(ast, attribute).get());
1560         (*value)->ast.incRef();
1561     }
1562     GRINGO_CLINGO_CATCH;
1563 }
1564 
clingo_ast_attribute_set_ast(clingo_ast_t * ast,clingo_ast_attribute_t attribute,clingo_ast_t * value)1565 extern "C" bool clingo_ast_attribute_set_ast(clingo_ast_t *ast, clingo_ast_attribute_t attribute, clingo_ast_t *value) {
1566     GRINGO_CLINGO_TRY {
1567         if (value == nullptr) {
1568             throw std::runtime_error("ast must not be null");
1569         }
1570         get_attr<Input::SAST>(ast, attribute) = Input::SAST{reinterpret_cast<Input::AST*>(value)};
1571     }
1572     GRINGO_CLINGO_CATCH;
1573 }
1574 
clingo_ast_attribute_get_string_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,char const ** value)1575 extern "C" bool clingo_ast_attribute_get_string_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, char const **value) {
1576     GRINGO_CLINGO_TRY {
1577         *value = get_attr<Input::AST::StrVec>(ast, attribute).at(index).c_str();
1578     }
1579     GRINGO_CLINGO_CATCH;
1580 }
1581 
clingo_ast_attribute_set_string_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,char const * value)1582 extern "C" bool clingo_ast_attribute_set_string_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, char const *value) {
1583     GRINGO_CLINGO_TRY {
1584         get_attr<Input::AST::StrVec>(ast, attribute)[index] = value;
1585     }
1586     GRINGO_CLINGO_CATCH;
1587 }
1588 
clingo_ast_attribute_delete_string_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index)1589 extern "C" bool clingo_ast_attribute_delete_string_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index) {
1590     GRINGO_CLINGO_TRY {
1591         auto &arr = get_attr<Input::AST::StrVec>(ast, attribute);
1592         arr.erase(arr.begin() + index);
1593     }
1594     GRINGO_CLINGO_CATCH;
1595 }
1596 
clingo_ast_attribute_size_string_array(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t * size)1597 extern "C" bool clingo_ast_attribute_size_string_array(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t *size) {
1598     GRINGO_CLINGO_TRY {
1599         *size = get_attr<Input::AST::StrVec>(ast, attribute).size();
1600     }
1601     GRINGO_CLINGO_CATCH;
1602 }
1603 
clingo_ast_attribute_insert_string_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,char const * value)1604 extern "C" bool clingo_ast_attribute_insert_string_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, char const *value) {
1605     GRINGO_CLINGO_TRY {
1606         auto &arr = get_attr<Input::AST::StrVec>(ast, attribute);
1607         arr.insert(arr.begin() + index, value);
1608     }
1609     GRINGO_CLINGO_CATCH;
1610 }
1611 
clingo_ast_attribute_get_ast_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,clingo_ast_t ** value)1612 extern "C" bool clingo_ast_attribute_get_ast_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, clingo_ast_t **value) {
1613     GRINGO_CLINGO_TRY {
1614         *value = reinterpret_cast<clingo_ast_t*>(get_attr<Input::AST::ASTVec>(ast, attribute).at(index).get());
1615         (*value)->ast.incRef();
1616     }
1617     GRINGO_CLINGO_CATCH;
1618 }
1619 
clingo_ast_attribute_set_ast_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,clingo_ast_t * value)1620 extern "C" bool clingo_ast_attribute_set_ast_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, clingo_ast_t *value) {
1621     GRINGO_CLINGO_TRY {
1622         if (value == nullptr) {
1623             throw std::runtime_error("ast must not be null");
1624         }
1625         get_attr<Input::AST::ASTVec>(ast, attribute)[index] = Input::SAST{reinterpret_cast<Input::AST*>(value)};
1626     }
1627     GRINGO_CLINGO_CATCH;
1628 }
1629 
clingo_ast_attribute_delete_ast_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index)1630 extern "C" bool clingo_ast_attribute_delete_ast_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index) {
1631     GRINGO_CLINGO_TRY {
1632         auto &arr = get_attr<Input::AST::ASTVec>(ast, attribute);
1633         arr.erase(arr.begin() + index);
1634     }
1635     GRINGO_CLINGO_CATCH;
1636 }
1637 
clingo_ast_attribute_size_ast_array(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t * size)1638 extern "C" bool clingo_ast_attribute_size_ast_array(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t *size) {
1639     GRINGO_CLINGO_TRY {
1640         *size = get_attr<Input::AST::ASTVec>(ast, attribute).size();
1641     }
1642     GRINGO_CLINGO_CATCH;
1643 }
1644 
clingo_ast_attribute_insert_ast_at(clingo_ast_t * ast,clingo_ast_attribute_t attribute,size_t index,clingo_ast_t * value)1645 extern "C" bool clingo_ast_attribute_insert_ast_at(clingo_ast_t *ast, clingo_ast_attribute_t attribute, size_t index, clingo_ast_t *value) {
1646     GRINGO_CLINGO_TRY {
1647         if (value == nullptr) {
1648             throw std::runtime_error("ast must not be null");
1649         }
1650         auto &arr = get_attr<Input::AST::ASTVec>(ast, attribute);
1651         arr.insert(arr.begin() + index, Input::SAST{reinterpret_cast<Input::AST*>(value)});
1652     }
1653     GRINGO_CLINGO_CATCH;
1654 }
1655 
clingo_ast_parse_string(char const * program,clingo_ast_callback_t cb,void * cb_data,clingo_logger_t logger,void * logger_data,unsigned message_limit)1656 extern "C" bool clingo_ast_parse_string(char const *program, clingo_ast_callback_t cb, void *cb_data, clingo_logger_t logger, void *logger_data, unsigned message_limit) {
1657     GRINGO_CLINGO_TRY {
1658         auto builder = Input::build([cb, cb_data](Input::SAST ast) {
1659             forwardError(cb(reinterpret_cast<clingo_ast_t*>(ast.get()), cb_data));
1660         });
1661         bool incmode = false;
1662         Input::NonGroundParser parser{*builder, incmode};
1663         Logger::Printer printer;
1664         if (logger != nullptr) { printer = [logger, logger_data](Warnings code, char const *msg) { logger(static_cast<clingo_warning_t>(code), msg, logger_data); }; }
1665         Logger log(printer, message_limit);
1666         parser.pushStream("<string>", gringo_make_unique<std::istringstream>(program), log);
1667         parser.parse(log);
1668         if (log.hasError()) { throw std::runtime_error("syntax error"); }
1669     }
1670     GRINGO_CLINGO_CATCH;
1671 }
1672 
clingo_ast_parse_files(char const * const * file,size_t n,clingo_ast_callback_t cb,void * cb_data,clingo_logger_t logger,void * logger_data,unsigned message_limit)1673 extern "C" bool clingo_ast_parse_files(char const * const *file, size_t n, clingo_ast_callback_t cb, void *cb_data, clingo_logger_t logger, void *logger_data, unsigned message_limit) {
1674     GRINGO_CLINGO_TRY {
1675         auto builder = Input::build([cb, cb_data](Input::SAST ast) {
1676             forwardError(cb(reinterpret_cast<clingo_ast_t*>(ast.get()), cb_data));
1677         });
1678         bool incmode = false;
1679         Input::NonGroundParser parser(*builder, incmode);
1680         Logger::Printer printer;
1681         if (logger != nullptr) { printer = [logger, logger_data](Warnings code, char const *msg) { logger(static_cast<clingo_warning_t>(code), msg, logger_data); }; }
1682         Logger log(printer, message_limit);
1683         for (auto it = file, ie = file + n; it != ie; ++it) {
1684             parser.pushFile(std::string{*it}, log);
1685         }
1686         if (n == 0) {
1687             parser.pushFile("-", log);
1688         }
1689         parser.parse(log);
1690         if (log.hasError()) { throw std::runtime_error("syntax error"); }
1691     }
1692     GRINGO_CLINGO_CATCH;
1693 }
1694 
clingo_ast_unpool(clingo_ast_t * ast,clingo_ast_unpool_type_bitset_t unpool_type,clingo_ast_callback_t callback,void * callback_data)1695 extern "C" bool clingo_ast_unpool(clingo_ast_t *ast, clingo_ast_unpool_type_bitset_t unpool_type, clingo_ast_callback_t callback, void *callback_data) {
1696     GRINGO_CLINGO_TRY {
1697         Input::SAST sast{&ast->ast};
1698         auto pool = Input::unpool(sast, unpool_type);
1699         if (pool.has_value()) {
1700             for (auto &unpooled : *pool) {
1701                 forwardError(callback(reinterpret_cast<clingo_ast_t*>(unpooled.get()), callback_data));
1702             }
1703         }
1704         else {
1705             forwardError(callback(ast, callback_data));
1706         }
1707     }
1708     GRINGO_CLINGO_CATCH;
1709 }
1710 
1711 // {{{1 control
1712 
1713 struct clingo_program_builder : clingo_control_t { };
clingo_program_builder_begin(clingo_program_builder_t * bld)1714 extern "C" bool clingo_program_builder_begin(clingo_program_builder_t *bld) {
1715     GRINGO_CLINGO_TRY { bld->beginAdd(); }
1716     GRINGO_CLINGO_CATCH;
1717 }
1718 
clingo_program_builder_add(clingo_program_builder_t * bld,clingo_ast_t * ast)1719 extern "C" bool clingo_program_builder_add(clingo_program_builder_t *bld, clingo_ast_t *ast) {
1720     GRINGO_CLINGO_TRY { bld->add(*ast); }
1721     GRINGO_CLINGO_CATCH;
1722 }
1723 
clingo_program_builder_end(clingo_program_builder_t * bld)1724 extern "C" bool clingo_program_builder_end(clingo_program_builder_t *bld) {
1725     GRINGO_CLINGO_TRY { bld->endAdd(); }
1726     GRINGO_CLINGO_CATCH;
1727 }
1728 
clingo_control_free(clingo_control_t * ctl)1729 extern "C" void clingo_control_free(clingo_control_t *ctl) {
1730     delete ctl;
1731 }
1732 
clingo_control_add(clingo_control_t * ctl,char const * name,char const * const * params,size_t n,char const * part)1733 extern "C" bool clingo_control_add(clingo_control_t *ctl, char const *name, char const * const *params, size_t n, char const *part) {
1734     GRINGO_CLINGO_TRY {
1735         StringVec p;
1736         for (char const * const *it = params, * const *ie = it + n; it != ie; ++it) {
1737             p.emplace_back(*it);
1738         }
1739         ctl->add(name, p, part);
1740     }
1741     GRINGO_CLINGO_CATCH;
1742 }
1743 
1744 namespace {
1745 
1746 struct ClingoContext : Context {
ClingoContext__anonb1f002eb1111::ClingoContext1747     ClingoContext(clingo_control_t *ctl, clingo_ground_callback_t cb, void *data)
1748     : ctl(ctl)
1749     , cb(cb)
1750     , data(data) {}
1751 
callable__anonb1f002eb1111::ClingoContext1752     bool callable(String) override {
1753         return cb != nullptr;
1754     }
1755 
call__anonb1f002eb1111::ClingoContext1756     SymVec call(Location const &loc, String name, SymSpan args, Logger &) override {
1757         assert(cb);
1758         clingo_location_t loc_c{loc.beginFilename.c_str(), loc.endFilename.c_str(), loc.beginLine, loc.endLine, loc.beginColumn, loc.endColumn};
1759         auto ret = cb(&loc_c, name.c_str(), reinterpret_cast<clingo_symbol_t const *>(args.first), args.size, data, [](clingo_symbol_t const * ret_c, size_t n, void *data) -> bool {
1760             auto t = static_cast<ClingoContext*>(data);
1761             GRINGO_CLINGO_TRY {
1762                 for (auto it = ret_c, ie = it + n; it != ie; ++it) {
1763                     t->ret.emplace_back(Symbol(*it));
1764                 }
1765             } GRINGO_CLINGO_CATCH;
1766         }, this);
1767         if (!ret) { throw ClingoError(); }
1768         return std::move(this->ret);
1769     }
exec__anonb1f002eb1111::ClingoContext1770     void exec(String, Location, String) override {
1771         throw std::logic_error("Context::exec: not supported");
1772     }
1773     ~ClingoContext() noexcept = default;
1774 
1775     clingo_control_t *ctl;
1776     clingo_ground_callback_t cb;
1777     void *data;
1778     SymVec ret;
1779 };
1780 
1781 }
1782 
clingo_control_ground(clingo_control_t * ctl,clingo_part_t const * vec,size_t n,clingo_ground_callback_t cb,void * data)1783 extern "C" bool clingo_control_ground(clingo_control_t *ctl, clingo_part_t const * vec, size_t n, clingo_ground_callback_t cb, void *data) {
1784     GRINGO_CLINGO_TRY {
1785         Control::GroundVec gv;
1786         gv.reserve(n);
1787         for (auto it = vec, ie = it + n; it != ie; ++it) {
1788             SymVec params;
1789             params.reserve(it->size);
1790             for (auto jt = it->params, je = jt + it->size; jt != je; ++jt) {
1791                 params.emplace_back(Symbol(*jt));
1792             }
1793             gv.emplace_back(it->name, params);
1794         }
1795         ClingoContext cctx(ctl, cb, data);
1796         ctl->ground(gv, cb ? &cctx : nullptr);
1797     } GRINGO_CLINGO_CATCH;
1798 }
1799 
1800 namespace {
1801 
1802 class ClingoSolveEventHandler : public SolveEventHandler {
1803 public:
ClingoSolveEventHandler(clingo_solve_event_callback_t cb,void * data)1804     ClingoSolveEventHandler(clingo_solve_event_callback_t cb, void *data)
1805     : cb_(cb)
1806     , data_(data) { }
1807 private:
on_model(Model & model)1808     bool on_model(Model &model) override {
1809         bool goon = true;
1810         if (!cb_(clingo_solve_event_type_model, &model, data_, &goon)) { throw ClingoError(); }
1811         return goon;
1812     }
on_unsat(Potassco::Span<int64_t> optimization)1813     bool on_unsat(Potassco::Span<int64_t> optimization) override {
1814         bool goon = true;
1815         if (!cb_(clingo_solve_event_type_unsat, &optimization, data_, &goon)) {
1816             clingo_terminate("error in SolveEventHandler::on_unsat going to terminate");
1817         }
1818         return goon;
1819     }
on_finish(SolveResult ret,Potassco::AbstractStatistics * step,Potassco::AbstractStatistics * accu)1820     void on_finish(SolveResult ret, Potassco::AbstractStatistics *step, Potassco::AbstractStatistics *accu) override {
1821         bool goon = true;
1822         clingo_statistics_t *stats[] = {static_cast<clingo_statistics_t*>(step), static_cast<clingo_statistics_t*>(accu)};
1823         if (step && accu && !cb_(clingo_solve_event_type_statistics, &stats, data_, &goon)) {
1824             clingo_terminate("error in SolveEventHandler::on_statistics going to terminate");
1825         }
1826         if (!cb_(clingo_solve_event_type_finish, &ret, data_, &goon)) {
1827             clingo_terminate("error in SolveEventHandler::on_finish going to terminate");
1828         }
1829     }
1830 private:
1831     clingo_solve_event_callback_t cb_;
1832     void *data_;
1833 };
1834 
1835 } // namespace
1836 
clingo_control_solve(clingo_control_t * control,clingo_solve_mode_bitset_t mode,clingo_literal_t const * assumptions,size_t assumptions_size,clingo_solve_event_callback_t notify,void * data,clingo_solve_handle_t ** handle)1837 extern "C" bool clingo_control_solve(clingo_control_t *control, clingo_solve_mode_bitset_t mode, clingo_literal_t const *assumptions, size_t assumptions_size, clingo_solve_event_callback_t notify, void *data, clingo_solve_handle_t **handle) {
1838     GRINGO_CLINGO_TRY { *handle = static_cast<clingo_solve_handle_t*>(control->solve(
1839         Potassco::toSpan(assumptions, assumptions_size),
1840         mode,
1841         notify ? gringo_make_unique<ClingoSolveEventHandler>(notify, data) : nullptr
1842     ).release()); }
1843     GRINGO_CLINGO_CATCH;
1844 }
1845 
clingo_control_assign_external(clingo_control_t * ctl,clingo_literal_t literal,clingo_truth_value_t value)1846 extern "C" bool clingo_control_assign_external(clingo_control_t *ctl, clingo_literal_t literal, clingo_truth_value_t value) {
1847     GRINGO_CLINGO_TRY {
1848         if (literal < 0) {
1849             literal = -literal;
1850             if      (value == Potassco::Value_t::True)  { value = Potassco::Value_t::False; }
1851             else if (value == Potassco::Value_t::False) { value = Potassco::Value_t::True; }
1852         }
1853         ctl->assignExternal(literal, static_cast<Potassco::Value_t>(value));
1854     }
1855     GRINGO_CLINGO_CATCH;
1856 }
1857 
clingo_control_release_external(clingo_control_t * ctl,clingo_literal_t literal)1858 extern "C" bool clingo_control_release_external(clingo_control_t *ctl, clingo_literal_t literal) {
1859     GRINGO_CLINGO_TRY { ctl->assignExternal(std::abs(literal), Potassco::Value_t::Release); }
1860     GRINGO_CLINGO_CATCH;
1861 }
1862 
clingo_control_program_builder(clingo_control_t * ctl,clingo_program_builder_t ** ret)1863 extern "C" bool clingo_control_program_builder(clingo_control_t *ctl, clingo_program_builder_t **ret) {
1864     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_program_builder_t*>(ctl); }
1865     GRINGO_CLINGO_CATCH;
1866 }
1867 
clingo_control_symbolic_atoms(clingo_control_t const * ctl,clingo_symbolic_atoms_t const ** ret)1868 extern "C" bool clingo_control_symbolic_atoms(clingo_control_t const *ctl, clingo_symbolic_atoms_t const **ret) {
1869     GRINGO_CLINGO_TRY { *ret = &ctl->getDomain(); }
1870     GRINGO_CLINGO_CATCH;
1871 }
1872 
clingo_control_theory_atoms(clingo_control_t const * ctl,clingo_theory_atoms_t const ** ret)1873 extern "C" bool clingo_control_theory_atoms(clingo_control_t const *ctl, clingo_theory_atoms_t const **ret) {
1874     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_theory_atoms const *>(&ctl->theory()); }
1875     GRINGO_CLINGO_CATCH;
1876 }
1877 
1878 namespace {
1879 
1880 class ClingoPropagator : public Propagator {
1881 public:
ClingoPropagator(clingo_propagator_t prop,void * data)1882     ClingoPropagator(clingo_propagator_t prop, void *data)
1883     : prop_(prop)
1884     , data_(data) { }
init(PropagateInit & init)1885     void init(PropagateInit &init) override {
1886         if (prop_.init && !prop_.init(&init, data_)) { throw ClingoError(); }
1887     }
1888 
propagate(Potassco::AbstractSolver & solver,ChangeList const & changes)1889     void propagate(Potassco::AbstractSolver& solver, ChangeList const &changes) override {
1890         if (prop_.propagate && !prop_.propagate(static_cast<clingo_propagate_control_t*>(&solver), changes.first, changes.size, data_)) { throw ClingoError(); }
1891     }
1892 
undo(Potassco::AbstractSolver const & solver,ChangeList const & undo)1893     void undo(Potassco::AbstractSolver const &solver, ChangeList const &undo) override {
1894         if (prop_.undo) { prop_.undo(static_cast<clingo_propagate_control_t const *>(&solver), undo.first, undo.size, data_); }
1895     }
1896 
check(Potassco::AbstractSolver & solver)1897     void check(Potassco::AbstractSolver& solver) override {
1898         if (prop_.check && !prop_.check(static_cast<clingo_propagate_control_t*>(&solver), data_)) { throw ClingoError(); }
1899     }
1900 
hasHeuristic() const1901     bool hasHeuristic() const override {
1902         return prop_.decide;
1903     }
1904 
decide(Id_t solverId,Potassco::AbstractAssignment const & assignment,Lit fallback)1905     Lit decide(Id_t solverId, Potassco::AbstractAssignment const &assignment, Lit fallback) override {
1906         clingo_literal_t decision = 0;
1907         if (prop_.decide && !prop_.decide(solverId, const_cast<clingo_assignment_t*>(static_cast<clingo_assignment_t const*>(&assignment)), fallback, data_, &decision)) { throw ClingoError(); }
1908         return decision;
1909     }
1910 private:
1911     clingo_propagator_t prop_;
1912     void *data_;
1913 };
1914 
1915 } // namespace
1916 
clingo_control_register_propagator(clingo_control_t * ctl,clingo_propagator_t const * propagator,void * data,bool sequential)1917 extern "C" bool clingo_control_register_propagator(clingo_control_t *ctl, clingo_propagator_t const *propagator, void *data, bool sequential) {
1918     GRINGO_CLINGO_TRY { ctl->registerPropagator(gringo_make_unique<ClingoPropagator>(*propagator, data), sequential); }
1919     GRINGO_CLINGO_CATCH;
1920 }
1921 
clingo_control_has_const(clingo_control_t const * ctl,char const * name,bool * ret)1922 extern "C" bool clingo_control_has_const(clingo_control_t const *ctl, char const *name, bool *ret) {
1923     GRINGO_CLINGO_TRY {
1924         auto sym = ctl->getConst(name);
1925         *ret = sym.type() != SymbolType::Special;
1926     }
1927     GRINGO_CLINGO_CATCH;
1928 }
1929 
clingo_control_get_const(clingo_control_t const * ctl,char const * name,clingo_symbol_t * ret)1930 extern "C" bool clingo_control_get_const(clingo_control_t const *ctl, char const *name, clingo_symbol_t *ret) {
1931     GRINGO_CLINGO_TRY {
1932         auto sym = ctl->getConst(name);
1933         *ret = sym.type() != SymbolType::Special ? sym.rep() : Symbol::createId(name).rep();
1934     }
1935     GRINGO_CLINGO_CATCH;
1936 }
1937 
clingo_control_interrupt(clingo_control_t * ctl)1938 extern "C" void clingo_control_interrupt(clingo_control_t *ctl) {
1939     ctl->interrupt();
1940 }
1941 
clingo_control_load(clingo_control_t * ctl,char const * file)1942 extern "C" bool clingo_control_load(clingo_control_t *ctl, char const *file) {
1943     GRINGO_CLINGO_TRY { ctl->load(file); }
1944     GRINGO_CLINGO_CATCH;
1945 }
1946 
clingo_control_set_enable_enumeration_assumption(clingo_control_t * ctl,bool value)1947 extern "C" bool clingo_control_set_enable_enumeration_assumption(clingo_control_t *ctl, bool value) {
1948     GRINGO_CLINGO_TRY { ctl->useEnumAssumption(value); }
1949     GRINGO_CLINGO_CATCH;
1950 }
1951 
clingo_control_get_enable_enumeration_assumption(clingo_control_t * ctl)1952 extern "C" bool clingo_control_get_enable_enumeration_assumption(clingo_control_t *ctl) {
1953     return ctl->useEnumAssumption();
1954 }
1955 
clingo_control_cleanup(clingo_control_t * ctl)1956 extern "C" bool clingo_control_cleanup(clingo_control_t *ctl) {
1957     GRINGO_CLINGO_TRY { ctl->cleanup(); }
1958     GRINGO_CLINGO_CATCH;
1959 }
1960 
clingo_control_set_enable_cleanup(clingo_control_t * ctl,bool value)1961 extern "C" bool clingo_control_set_enable_cleanup(clingo_control_t *ctl, bool value) {
1962     GRINGO_CLINGO_TRY { ctl->enableCleanup(value); }
1963     GRINGO_CLINGO_CATCH;
1964 }
1965 
clingo_control_get_enable_cleanup(clingo_control_t * ctl)1966 extern "C" bool clingo_control_get_enable_cleanup(clingo_control_t *ctl) {
1967     return ctl->enableCleanup();
1968 }
1969 
clingo_control_backend(clingo_control_t * ctl,clingo_backend_t ** ret)1970 extern "C" bool clingo_control_backend(clingo_control_t *ctl, clingo_backend_t **ret) {
1971     GRINGO_CLINGO_TRY { *ret = static_cast<clingo_backend_t*>(ctl); }
1972     GRINGO_CLINGO_CATCH;
1973 }
1974 
clingo_control_configuration(clingo_control_t * ctl,clingo_configuration_t ** conf)1975 extern "C" bool clingo_control_configuration(clingo_control_t *ctl, clingo_configuration_t **conf) {
1976     GRINGO_CLINGO_TRY { *conf = static_cast<clingo_configuration_t*>(&ctl->getConf()); }
1977     GRINGO_CLINGO_CATCH;
1978 }
1979 
clingo_control_is_conflicting(clingo_control_t const * control)1980 extern "C" bool clingo_control_is_conflicting(clingo_control_t const *control) {
1981     return control->isConflicting();
1982 }
1983 
clingo_control_statistics(clingo_control_t const * ctl,clingo_statistics_t const ** stats)1984 extern "C" bool clingo_control_statistics(clingo_control_t const *ctl, clingo_statistics_t const **stats) {
1985     GRINGO_CLINGO_TRY { *stats = static_cast<clingo_statistics_t const *>(ctl->statistics()); }
1986     GRINGO_CLINGO_CATCH;
1987 }
1988 
clingo_control_clasp_facade(clingo_control_t * ctl,void ** clasp)1989 extern "C" bool clingo_control_clasp_facade(clingo_control_t *ctl, void **clasp) {
1990     GRINGO_CLINGO_TRY { *clasp = ctl->claspFacade(); }
1991     GRINGO_CLINGO_CATCH;
1992 }
1993 
1994 namespace {
1995 
1996 class Observer : public Backend {
1997 public:
Observer(clingo_ground_program_observer_t obs,void * data)1998     Observer(clingo_ground_program_observer_t obs, void *data) : obs_(obs), data_(data) { }
1999     ~Observer() override = default;
2000 
initProgram(bool incremental)2001     void initProgram(bool incremental) override {
2002         call(obs_.init_program, incremental);
2003     }
beginStep()2004     void beginStep() override {
2005         call(obs_.begin_step);
2006     }
endStep()2007     void endStep() override {
2008         call(obs_.end_step);
2009     }
2010 
rule(Potassco::Head_t ht,Potassco::AtomSpan const & head,Potassco::LitSpan const & body)2011     void rule(Potassco::Head_t ht, Potassco::AtomSpan const& head,Potassco::LitSpan const &body) override {
2012         call(obs_.rule, ht == Potassco::Head_t::Choice, head.first, head.size, body.first, body.size);
2013     }
rule(Potassco::Head_t ht,Potassco::AtomSpan const & head,Weight_t bound,Potassco::WeightLitSpan const & body)2014     void rule(Potassco::Head_t ht, Potassco::AtomSpan const &head, Weight_t bound,Potassco::WeightLitSpan const &body) override {
2015         call(obs_.weight_rule, ht == Potassco::Head_t::Choice, head.first, head.size, bound, reinterpret_cast<clingo_weighted_literal_t const *>(body.first), body.size);
2016     }
minimize(Weight_t prio,Potassco::WeightLitSpan const & lits)2017     void minimize(Weight_t prio, Potassco::WeightLitSpan const &lits) override {
2018         call(obs_.minimize, prio, reinterpret_cast<clingo_weighted_literal_t const *>(lits.first), lits.size);
2019     }
project(Potassco::AtomSpan const & atoms)2020     void project(Potassco::AtomSpan const &atoms) override {
2021         call(obs_.project, atoms.first, atoms.size);
2022     }
output(Symbol sym,Potassco::Atom_t atom)2023     void output(Symbol sym, Potassco::Atom_t atom) override {
2024         call(obs_.output_atom, sym.rep(), atom);
2025     }
output(Symbol sym,Potassco::LitSpan const & condition)2026     void output(Symbol sym, Potassco::LitSpan const& condition) override {
2027         call(obs_.output_term, sym.rep(), condition.first, condition.size);
2028     }
output(Symbol sym,int value,Potassco::LitSpan const & condition)2029     void output(Symbol sym, int value, Potassco::LitSpan const& condition) override {
2030         call(obs_.output_csp, sym.rep(), value, condition.first, condition.size);
2031     }
external(Atom_t a,Potassco::Value_t v)2032     void external(Atom_t a, Potassco::Value_t v) override {
2033         call(obs_.external, a, v);
2034     }
assume(Potassco::LitSpan const & lits)2035     void assume(Potassco::LitSpan const &lits) override {
2036         call(obs_.assume, lits.first, lits.size);
2037     }
heuristic(Atom_t a,Potassco::Heuristic_t t,int bias,unsigned prio,Potassco::LitSpan const & condition)2038     void heuristic(Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, Potassco::LitSpan const &condition) override {
2039         call(obs_.heuristic, a, t, bias, prio, condition.first, condition.size);
2040     }
acycEdge(int s,int t,Potassco::LitSpan const & condition)2041     void acycEdge(int s, int t, Potassco::LitSpan const &condition) override {
2042         call(obs_.acyc_edge, s, t, condition.first, condition.size);
2043     }
2044 
theoryTerm(Id_t termId,int number)2045     void theoryTerm(Id_t termId, int number) override {
2046         call(obs_.theory_term_number, termId, number);
2047     }
theoryTerm(Id_t termId,StringSpan const & name)2048     void theoryTerm(Id_t termId, StringSpan const &name) override {
2049         std::string s{name.first, name.size};
2050         call(obs_.theory_term_string, termId, s.c_str());
2051     }
theoryTerm(Id_t termId,int cId,Potassco::IdSpan const & args)2052     void theoryTerm(Id_t termId, int cId, Potassco::IdSpan const &args) override {
2053         call(obs_.theory_term_compound, termId, cId, args.first, args.size);
2054     }
theoryElement(Id_t elementId,Potassco::IdSpan const & terms,Potassco::LitSpan const & cond)2055     void theoryElement(Id_t elementId, Potassco::IdSpan const &terms, Potassco::LitSpan const &cond) override {
2056         call(obs_.theory_element, elementId, terms.first, terms.size, cond.first, cond.size);
2057     }
theoryAtom(Id_t atomOrZero,Id_t termId,Potassco::IdSpan const & elements)2058     void theoryAtom(Id_t atomOrZero, Id_t termId, Potassco::IdSpan const &elements) override {
2059         call(obs_.theory_atom, atomOrZero, termId, elements.first, elements.size);
2060     }
theoryAtom(Id_t atomOrZero,Id_t termId,Potassco::IdSpan const & elements,Id_t op,Id_t rhs)2061     void theoryAtom(Id_t atomOrZero, Id_t termId, Potassco::IdSpan const &elements, Id_t op, Id_t rhs) override {
2062         call(obs_.theory_atom_with_guard, atomOrZero, termId, elements.first, elements.size, op, rhs);
2063     }
2064 private:
2065     template <class CB, class... Args>
call(CB * cb,Args &&...args)2066     void call(CB *cb, Args&&... args) {
2067         if (cb && !(*cb)(std::forward<Args>(args)..., data_)) { throw ClingoError(); }
2068     }
2069 private:
2070     clingo_ground_program_observer_t obs_;
2071     void *data_;
2072 };
2073 
2074 } // namespace
2075 
clingo_control_register_observer(clingo_control_t * control,clingo_ground_program_observer_t const * observer,bool replace,void * data)2076 extern "C" bool clingo_control_register_observer(clingo_control_t *control, clingo_ground_program_observer_t const *observer, bool replace, void *data) {
2077     GRINGO_CLINGO_TRY { control->registerObserver(gringo_make_unique<Observer>(*observer, data), replace); }
2078     GRINGO_CLINGO_CATCH;
2079 }
2080 
clingo_control_new(char const * const * args,size_t n,clingo_logger_t logger,void * data,unsigned message_limit,clingo_control_t ** ctl)2081 extern "C" bool clingo_control_new(char const *const * args, size_t n, clingo_logger_t logger, void *data, unsigned message_limit, clingo_control_t **ctl) {
2082     GRINGO_CLINGO_TRY {
2083         static std::mutex mut;
2084         std::lock_guard<std::mutex> grd(mut);
2085         *ctl = new ClingoLib(g_scripts(), numeric_cast<int>(n), args, logger ? [logger, data](Warnings code, char const *msg) { logger(static_cast<clingo_warning_t>(code), msg, data); } : Logger::Printer(nullptr), message_limit);
2086     }
2087     GRINGO_CLINGO_CATCH;
2088 }
2089 
2090 namespace {
2091 
2092 class CScript : public Script {
2093 public:
CScript(clingo_script_t script,void * data)2094     CScript(clingo_script_t script, void *data) : script_(script), data_(data) { }
~CScript()2095     ~CScript() noexcept override {
2096         if (script_.free) { script_.free(data_); }
2097     }
2098 private:
exec(String,Location loc,String code)2099     void exec(String, Location loc, String code) override {
2100         if (script_.execute) {
2101             auto l = conv(loc);
2102             forwardError(script_.execute(&l, code.c_str(), data_));
2103         }
2104     }
call(Location const & loc,String name,SymSpan args,Logger &)2105     SymVec call(Location const &loc, String name, SymSpan args, Logger &) override {
2106         using Data = std::pair<SymVec, std::exception_ptr>;
2107         Data data;
2108         auto l = conv(loc);
2109         forwardError(script_.call(
2110             &l, name.c_str(), reinterpret_cast<clingo_symbol_t const *>(args.first), args.size,
2111             [](clingo_symbol_t const *symbols, size_t symbols_size, void *pdata) {
2112                 auto &data = *static_cast<Data*>(pdata);
2113                 GRINGO_CALLBACK_TRY {
2114                     for (auto it = symbols, ie = it + symbols_size; it != ie; ++it) {
2115                         data.first.emplace_back(Symbol{*it});
2116                     }
2117                 }
2118                 GRINGO_CALLBACK_CATCH(data.second);
2119             },
2120             &data, data_), &data.second);
2121         return data.first;
2122     }
callable(String name)2123     bool callable(String name) override {
2124         bool ret;
2125         forwardError(script_.callable(name.c_str(), &ret, data_));
2126         return ret;
2127     }
main(Control & ctl)2128     void main(Control &ctl) override {
2129         forwardError(script_.main(&ctl, data_));
2130     }
version()2131     char const *version() override {
2132         return script_.version;
2133     }
2134 private:
2135     clingo_script_t script_;
2136     void *data_;
2137 };
2138 
2139 } // namespace
2140 
clingo_register_script(char const * type,clingo_script_t const * script,void * data)2141 extern "C" CLINGO_VISIBILITY_DEFAULT bool clingo_register_script(char const *type, clingo_script_t const *script, void *data) {
2142     GRINGO_CLINGO_TRY { g_scripts().registerScript(type, gringo_make_unique<CScript>(*script, data)); }
2143     GRINGO_CLINGO_CATCH;
2144 }
2145 
clingo_script_version(char const * type)2146 extern "C" CLINGO_VISIBILITY_DEFAULT char const *clingo_script_version(char const *type) {
2147     return g_scripts().version(type);
2148 }
2149 
clingo_main_(int argc,char * argv[])2150 extern "C" CLINGO_VISIBILITY_DEFAULT int clingo_main_(int argc, char *argv[]) {
2151     Gringo::ClingoApp app;
2152     return app.main(argc, argv);
2153 }
2154 
str_duplicate(char const * str)2155 char *str_duplicate(char const *str) {
2156     char *ret = new char[strlen(str) + 1];
2157     std::strcpy(ret, str);
2158     return ret;
2159 }
2160 
2161 struct clingo_options : ClingoApp {};
2162 
2163 namespace {
2164 
2165 class CClingoApp : public IClingoApp {
2166 public:
CClingoApp(clingo_application_t app,void * data)2167     CClingoApp(clingo_application_t app, void *data)
2168     : app_(app)
2169     , data_{data} {
2170         name_ = app_.program_name ? app_.program_name(data_) : IClingoApp::program_name();
2171         version_ = app_.version ? app_.version(data_) : IClingoApp::version();
2172     }
message_limit() const2173     unsigned message_limit() const override {
2174         if (app_.message_limit) {
2175             return app_.message_limit(data_);
2176         }
2177         else {
2178             return IClingoApp::message_limit();
2179         }
2180     }
program_name() const2181     char const *program_name() const override {
2182         return name_;
2183     }
version() const2184     char const *version() const override {
2185         return version_;
2186     }
has_main() const2187     bool has_main() const override {
2188         return app_.main;
2189     }
main(ClingoControl & ctl,std::vector<std::string> const & files)2190     void main(ClingoControl &ctl, std::vector<std::string> const &files) override {
2191         assert(has_main());
2192         std::vector<char const *> c_files;
2193         for (auto &x : files) {
2194             c_files.emplace_back(x.c_str());
2195         }
2196         forwardError(app_.main(&ctl, c_files.data(), c_files.size(), data_));
2197     }
has_log() const2198     bool has_log() const override { return app_.logger; }
log(Gringo::Warnings code,char const * message)2199     void log(Gringo::Warnings code, char const *message) noexcept override {
2200         assert(has_log());
2201         app_.logger(static_cast<clingo_warning_t>(code), message, data_);
2202     }
has_printer() const2203     bool has_printer() const override { return app_.printer; }
print_model(Model * model,std::function<void ()> printer)2204     void print_model(Model *model, std::function<void()> printer) override {
2205         forwardError(app_.printer(model, [](void *data) {
2206             GRINGO_CLINGO_TRY {
2207                 (*static_cast<std::function<void()>*>(data))();
2208             }
2209             GRINGO_CLINGO_CATCH;
2210         }, &printer, data_));
2211     }
2212 
register_options(ClingoApp & app)2213     void register_options(ClingoApp &app) override {
2214         if (app_.register_options) {
2215             forwardError(app_.register_options(static_cast<clingo_options_t*>(&app), data_));
2216         }
2217     }
validate_options()2218     void validate_options() override {
2219         if (app_.validate_options) {
2220             forwardError(app_.validate_options(data_));
2221         }
2222     }
2223 private:
2224     clingo_application_t app_;
2225     void *data_;
2226     char const *name_;
2227     char const *version_;
2228 };
2229 
2230 } // namespace
2231 
clingo_options_add(clingo_options_t * options,char const * group,char const * option,char const * description,bool (* parse)(char const * value,void * data),void * data,bool multi,char const * argument)2232 extern "C" CLINGO_VISIBILITY_DEFAULT bool clingo_options_add(clingo_options_t *options, char const *group, char const *option, char const *description, bool (*parse) (char const *value, void *data), void *data, bool multi, char const *argument) {
2233     GRINGO_CLINGO_TRY {
2234         options->addOption(group, option, description, [parse, data](char const *value) { return parse(value, data); }, argument, multi);
2235     }
2236     GRINGO_CLINGO_CATCH;
2237 }
2238 
clingo_options_add_flag(clingo_options_t * options,char const * group,char const * option,char const * description,bool * target)2239 extern "C" CLINGO_VISIBILITY_DEFAULT bool clingo_options_add_flag(clingo_options_t *options, char const *group, char const *option, char const *description, bool *target) {
2240     GRINGO_CLINGO_TRY { options->addFlag(group, option, description, *target); }
2241     GRINGO_CLINGO_CATCH;
2242 }
2243 
clingo_main(clingo_application * application,char const * const * arguments,size_t size,void * data)2244 extern "C" CLINGO_VISIBILITY_DEFAULT int clingo_main(clingo_application *application, char const *const * arguments, size_t size, void *data) {
2245     try {
2246         UIClingoApp app = gringo_make_unique<CClingoApp>(*application, data);
2247         std::vector<std::unique_ptr<char[]>> args_buf;
2248         std::vector<char *> args;
2249         args_buf.emplace_back(str_duplicate(app->program_name()));
2250         for (auto arg = arguments, end = arguments + size; arg != end; ++arg) {
2251             args_buf.emplace_back(str_duplicate(*arg));
2252         }
2253         args_buf.emplace_back(nullptr);
2254         for (auto &x : args_buf) { args.emplace_back(x.get()); }
2255         return Gringo::ClingoApp{std::move(app)}.main(args.size() - 1, args.data());
2256     }
2257     catch (...) {
2258         handleError();
2259         std::cerr << "error during initialization: going to terminate:\n" << clingo_error_message() << std::endl;
2260         std::terminate();
2261     }
2262 }
2263 
2264 // }}}1
2265 
2266 #if defined(__GNUC__) && !defined(__clang__)
2267 #pragma GCC diagnostic pop
2268 #endif
2269 
2270