From 8e7ce9d430b439995ceddca2c4fb9e24ed323d3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= <john@ankarstrom.se>
Date: Sat, 30 Jul 2022 00:23:51 +0200
Subject: Add non-throwing variants of Query methods.

Pl has also been refactored, so that the unnecessary throw and
catch have been removed.
---
 c/datalistview.cpp |  2 +-
 c/pl.cpp           | 12 ++++++++++++
 c/pl.h             | 28 +++++++++++++++++-----------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/c/datalistview.cpp b/c/datalistview.cpp
index fd37791..ea68f2d 100644
--- a/c/datalistview.cpp
+++ b/c/datalistview.cpp
@@ -53,7 +53,7 @@ void DataListView::ShowEpisode(const int iEpisode)
 	LVITEM lviKey = {LVIF_TEXT};
 	LVITEM lviValue = {LVIF_TEXT};
 
-	for (int i = 0; q.NextSolution(); i++) {
+	for (int i = 0; q.NextSolution(std::nothrow); i++) {
 		std::wstring wsKey;
 		std::wstring wsValue;
 
diff --git a/c/pl.cpp b/c/pl.cpp
index 6e71383..665fe3a 100644
--- a/c/pl.cpp
+++ b/c/pl.cpp
@@ -55,6 +55,10 @@ Query::~Query()
 	PL_cut_query(m_q);
 }
 
+int Query::Cut(std::nothrow_t)
+{
+	return PL_cut_query(m_q);
+}
 int Query::Cut()
 {
 	if (PL_cut_query(m_q)) return 1;
@@ -63,6 +67,10 @@ int Query::Cut()
 }
 
 /* Cut query and invalidate associated data. */
+int Query::Close(std::nothrow_t)
+{
+	return PL_close_query(m_q);
+}
 int Query::Close()
 {
 	if (PL_close_query(m_q)) return 1;
@@ -70,6 +78,10 @@ int Query::Close()
 	return 0;
 }
 
+int Query::NextSolution(std::nothrow_t)
+{
+	return PL_next_solution(m_q);
+}
 int Query::NextSolution()
 {
 	if (PL_next_solution(m_q)) return 1;
diff --git a/c/pl.h b/c/pl.h
index 4a5ea41..c0af4bc 100644
--- a/c/pl.h
+++ b/c/pl.h
@@ -33,8 +33,11 @@ struct Query
 	Query(module_t ctx, predicate_t p, term_t t0);
 	~Query();
 	int Cut();
+	int Cut(std::nothrow_t);
 	int Close();
+	int Close(std::nothrow_t);
 	int NextSolution();
+	int NextSolution(std::nothrow_t);
 private:
 	qid_t m_q;
 };
@@ -92,28 +95,31 @@ inline bool PlGetN(term_t) { return true; }
 template <typename T, typename... U>
 inline bool PlGetN(term_t t, T x, U... xs) { return PlGet(t, x) && PlGetN(t+1, xs...); }
 
-/* Call Prolog predicate, propagating Prolog exceptions. */
-template <typename... T>
-int Plx(const char* const szMod, const char* const szPred, T... xs)
+/* Call Prolog predicate. */
+template <bool Except = false, typename... T>
+int Pl(const char* const szMod, const char* const szPred, T... xs)
 {
 	Frame f;
 	const term_t t = PL_new_term_refs(sizeof...(T));
+
 	if (!PlPutN(t, xs...)) return 0;
 	Query q(NULL, PL_predicate(szPred, sizeof...(T), szMod), t);
-	if (!q.NextSolution()) return 0;
+
+	if constexpr (Except) {
+		if (!q.NextSolution()) return 0;
+	} else {
+		if (!q.NextSolution(std::nothrow)) return 0;
+	}
+
 	if (!PlGetN(t, xs...)) return 0;
 	return 1;
 }
 
-/* Call Prolog predicate, ignoring Prolog exceptions. */
+/* Call Prolog predicate, propagating Prolog exceptions. */
 template <typename... T>
-int Pl(const char* const szMod, const char* const szPred, T... xs)
+int Plx(const char* const szMod, const char* const szPred, T... xs)
 {
-	try {
-		return Plx(szMod, szPred, xs...);
-	} catch (const term_t& t) {
-		return 0;
-	}
+	return Pl<true>(szMod, szPred, xs...);
 }
 
 #endif
-- 
cgit v1.2.3