From 87aecbd6219958f5ff7b3ec410a2aeeab8e02d98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Wardy=C5=84ski?= <no@email>
Date: Thu, 4 Nov 2010 22:44:31 +0100
Subject: [PATCH] Adding "Or" logical predicate

---
 libwccl/CMakeLists.txt      |  1 +
 libwccl/ops/or.cpp          | 19 +++++++++
 libwccl/ops/or.h            | 36 ++++++++++++++++
 tests/logicalpredicates.cpp | 84 +++++++++++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+)
 create mode 100644 libwccl/ops/or.cpp
 create mode 100644 libwccl/ops/or.h

diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index ccf8411..b271d96 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -17,6 +17,7 @@ SET(libwccl_STAT_SRC
 	exception.cpp
 	main.cpp
 	ops/and.cpp
+	ops/or.cpp
 	ops/logicalpredicate.cpp
 	ops/predicate.cpp
 	sentencecontext.cpp
diff --git a/libwccl/ops/or.cpp b/libwccl/ops/or.cpp
new file mode 100644
index 0000000..7d9cf16
--- /dev/null
+++ b/libwccl/ops/or.cpp
@@ -0,0 +1,19 @@
+#include <libwccl/ops/or.h>
+
+namespace Wccl {
+
+Or::BaseRetValPtr Or::apply_internal(const SentenceContext &context) const
+{
+	foreach(BoolFunctionPtr expression, *expressions_) {
+		if(expression->apply(context)->get_value()) {
+			return Predicate::True->apply(context);
+		}
+	}
+	return Predicate::False->apply(context);
+}
+
+const std::string Or::raw_operator_name() const {
+	return "or";
+}
+
+} /* end ns Wccl */
diff --git a/libwccl/ops/or.h b/libwccl/ops/or.h
new file mode 100644
index 0000000..f337166
--- /dev/null
+++ b/libwccl/ops/or.h
@@ -0,0 +1,36 @@
+#ifndef OR_H
+#define OR_H
+
+#include <boost/foreach.hpp>
+#define foreach         BOOST_FOREACH
+
+#include <libwccl/ops/logicalpredicate.h>
+
+namespace Wccl {
+
+/**
+ * Operator that realises logical predicate "or"
+ */
+class Or : public LogicalPredicate
+{
+public:
+	Or(const boost::shared_ptr<BoolFunctionPtrVector>& expressions)
+		: LogicalPredicate(expressions)
+	{
+	}
+
+protected :
+	typedef FunctionBase::BaseRetValPtr BaseRetValPtr ;
+
+	/**
+	 * "Or" predicate evaluates expressions one by one in order from left to right,
+	 * and True is returned once an expression evaluating to True is found.
+	 * If all of the expressions were False, False is returned.
+	 */
+	virtual BaseRetValPtr apply_internal(const SentenceContext&) const;
+
+	virtual const std::string raw_operator_name() const;
+};
+
+} /* end ns Wccl */
+#endif // OR_H
diff --git a/tests/logicalpredicates.cpp b/tests/logicalpredicates.cpp
index 31ef9fb..ae27e1b 100644
--- a/tests/logicalpredicates.cpp
+++ b/tests/logicalpredicates.cpp
@@ -6,6 +6,7 @@
 #include <libwccl/ops/constant.h>
 #include <libwccl/ops/logicalpredicate.h>
 #include <libwccl/ops/and.h>
+#include <libwccl/ops/or.h>
 #include <libwccl/values/bool.h>
 #include <libwccl/sentencecontext.h>
 
@@ -50,6 +51,7 @@ BOOST_FIXTURE_TEST_CASE(and_1arg, PredFix)
 	BOOST_CHECK_EQUAL(false, pred_and.apply(sc)->get_value());
 }
 
+
 BOOST_FIXTURE_TEST_CASE(and_2arg, PredFix)
 {
 	for(int arg1 = 0; arg1 < 2; ++arg1) {
@@ -79,6 +81,49 @@ BOOST_FIXTURE_TEST_CASE(and_3arg, PredFix)
 	}
 }
 
+BOOST_FIXTURE_TEST_CASE(or_1arg, PredFix)
+{
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Or::BoolFunctionPtrVector());
+    v->push_back(true_constant);
+    Or pred_or(v);
+    BOOST_CHECK_EQUAL(true, pred_or.apply(sc)->get_value());
+    v->clear();
+    v->push_back(false_constant);
+    BOOST_CHECK_EQUAL(false, pred_or.apply(sc)->get_value());
+}
+
+
+BOOST_FIXTURE_TEST_CASE(or_2arg, PredFix)
+{
+    for(int arg1 = 0; arg1 < 2; ++arg1) {
+        for(int arg2 = 0; arg2 < 2; ++arg2) {
+            boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Or::BoolFunctionPtrVector());
+            v->push_back(arg1 != 0 ? true_constant : false_constant);
+            v->push_back(arg2 != 0 ? true_constant : false_constant);
+            Or pred_or(v);
+            BOOST_CHECK_EQUAL((arg1 != 0) || (arg2 != 0), pred_or.apply(sc)->get_value());
+        }
+    }
+}
+
+BOOST_FIXTURE_TEST_CASE(or_3arg, PredFix)
+{
+    for(int arg1 = 0; arg1 < 2; ++arg1) {
+        for(int arg2 = 0; arg2 < 2; ++arg2) {
+            for(int arg3 = 0; arg3 < 2; ++arg3) {
+                boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Or::BoolFunctionPtrVector());
+                v->push_back(arg1 != 0 ? true_constant : false_constant);
+                v->push_back(arg2 != 0 ? true_constant : false_constant);
+                v->push_back(arg3 != 0 ? true_constant : false_constant);
+                Or pred_or(v);
+                BOOST_CHECK_EQUAL((arg1 != 0) || (arg2 != 0) || (arg3 != 0), pred_or.apply(sc)->get_value());
+            }
+        }
+    }
+}
+
+//------ to_string test cases -------
+
 BOOST_FIXTURE_TEST_CASE(and_to_string, PredFix)
 {
 	boost::shared_ptr<And::BoolFunctionPtrVector> v(new And::BoolFunctionPtrVector());
@@ -117,4 +162,43 @@ BOOST_FIXTURE_TEST_CASE(and_to_raw_string, PredFix)
 	BOOST_CHECK_EQUAL("and(true, and(false, true, true))", another_and.to_raw_string());
 }
 
+BOOST_FIXTURE_TEST_CASE(or_to_string, PredFix)
+{
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Or::BoolFunctionPtrVector());
+    v->push_back(true_constant);
+    boost::shared_ptr<Function<Bool> > pred_or(new Or(v));
+    BOOST_CHECK_EQUAL("or(true)", pred_or->to_string(tagset));
+    v->push_back(false_constant);
+    BOOST_CHECK_EQUAL("or(true, false)", pred_or->to_string(tagset));
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("or(true, false, true)", pred_or->to_string(tagset));
+
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v2(new Or::BoolFunctionPtrVector());
+    v2->push_back(pred_or);
+	v2->push_back(false_constant);
+    Or another_or(v2);
+    BOOST_CHECK_EQUAL("or(or(true, false, true), false)", another_or.to_raw_string());
+    v2->push_back(true_constant);
+    BOOST_CHECK_EQUAL("or(or(true, false, true), false, true)", another_or.to_raw_string());
+}
+
+BOOST_FIXTURE_TEST_CASE(or_to_raw_string, PredFix)
+{
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Or::BoolFunctionPtrVector());
+    v->push_back(false_constant);
+    boost::shared_ptr<Function<Bool> > pred_or(new Or(v));
+    BOOST_CHECK_EQUAL("or(false)", pred_or->to_raw_string());
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("or(false, true)", pred_or->to_raw_string());
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("or(false, true, true)", pred_or->to_raw_string());
+
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v2(new Or::BoolFunctionPtrVector());
+    v2->push_back(true_constant);
+    v2->push_back(pred_or);
+    Or another_or(v2);
+    BOOST_CHECK_EQUAL("or(true, or(false, true, true))", another_or.to_raw_string());
+
+}
+
 BOOST_AUTO_TEST_SUITE_END()
-- 
GitLab