From 9582c976fc2fefb4ab4fe3ce8aa4b5e35acfe514 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Wardy=C5=84ski?= <no@email>
Date: Thu, 4 Nov 2010 23:26:09 +0100
Subject: [PATCH] Adding "not"/"nor" predicate operator

---
 libwccl/CMakeLists.txt      |  1 +
 libwccl/ops/nor.cpp         | 19 ++++++++
 libwccl/ops/nor.h           | 38 ++++++++++++++++
 tests/logicalpredicates.cpp | 88 +++++++++++++++++++++++++++++++++++--
 4 files changed, 142 insertions(+), 4 deletions(-)
 create mode 100644 libwccl/ops/nor.cpp
 create mode 100644 libwccl/ops/nor.h

diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index b271d96..00ed846 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(libwccl_STAT_SRC
 	ops/and.cpp
 	ops/or.cpp
 	ops/logicalpredicate.cpp
+    ops/nor.cpp
 	ops/predicate.cpp
 	sentencecontext.cpp
 	values/bool.cpp
diff --git a/libwccl/ops/nor.cpp b/libwccl/ops/nor.cpp
new file mode 100644
index 0000000..d547da3
--- /dev/null
+++ b/libwccl/ops/nor.cpp
@@ -0,0 +1,19 @@
+#include <libwccl/ops/nor.h>
+
+namespace Wccl {
+
+Nor::BaseRetValPtr Nor::apply_internal(const SentenceContext &context) const
+{
+	foreach(BoolFunctionPtr expression, *expressions_) {
+		if(expression->apply(context)->get_value()) {
+			return Predicate::False->apply(context);
+		}
+	}
+	return Predicate::True->apply(context);
+}
+
+const std::string Nor::raw_operator_name() const {
+	return "not";
+}
+
+} /* end ns Wccl */
diff --git a/libwccl/ops/nor.h b/libwccl/ops/nor.h
new file mode 100644
index 0000000..368c3c7
--- /dev/null
+++ b/libwccl/ops/nor.h
@@ -0,0 +1,38 @@
+#ifndef NOR_H
+#define NOR_H
+
+#include <boost/foreach.hpp>
+#define foreach         BOOST_FOREACH
+
+#include <libwccl/ops/logicalpredicate.h>
+
+namespace Wccl {
+
+/**
+ * Operator that realises logical predicate "nor",
+ * (note: the operator is called "not" in CCL)
+ */
+class Nor : public LogicalPredicate
+{
+public:
+	Nor(const boost::shared_ptr<BoolFunctionPtrVector>& expressions)
+		: LogicalPredicate(expressions)
+	{
+	}
+
+protected :
+	typedef FunctionBase::BaseRetValPtr BaseRetValPtr ;
+
+	/**
+	 * "Nor" (aka "not") predicate evaluates expressions one by one in order
+     * from left to right, and False is returned once an expression evaluating
+     * to True is found.
+	 * If all of the expressions were False, True is returned.
+	 */
+	virtual BaseRetValPtr apply_internal(const SentenceContext&) const;
+
+	virtual const std::string raw_operator_name() const;
+};
+
+} /* end ns Wccl */
+#endif // NOR_H
diff --git a/tests/logicalpredicates.cpp b/tests/logicalpredicates.cpp
index ae27e1b..df8c12f 100644
--- a/tests/logicalpredicates.cpp
+++ b/tests/logicalpredicates.cpp
@@ -7,6 +7,7 @@
 #include <libwccl/ops/logicalpredicate.h>
 #include <libwccl/ops/and.h>
 #include <libwccl/ops/or.h>
+#include <libwccl/ops/nor.h>
 #include <libwccl/values/bool.h>
 #include <libwccl/sentencecontext.h>
 
@@ -122,6 +123,48 @@ BOOST_FIXTURE_TEST_CASE(or_3arg, PredFix)
     }
 }
 
+BOOST_FIXTURE_TEST_CASE(nor_1arg, PredFix)
+{
+    boost::shared_ptr<Nor::BoolFunctionPtrVector> v(new Nor::BoolFunctionPtrVector());
+    v->push_back(true_constant);
+    Nor pred_nor(v);
+    BOOST_CHECK_EQUAL(false, pred_nor.apply(sc)->get_value());
+    v->clear();
+    v->push_back(false_constant);
+    BOOST_CHECK_EQUAL(true, pred_nor.apply(sc)->get_value());
+}
+
+
+BOOST_FIXTURE_TEST_CASE(nor_2arg, PredFix)
+{
+    for(int arg1 = 0; arg1 < 2; ++arg1) {
+        for(int arg2 = 0; arg2 < 2; ++arg2) {
+            boost::shared_ptr<Nor::BoolFunctionPtrVector> v(new Nor::BoolFunctionPtrVector());
+            v->push_back(arg1 != 0 ? true_constant : false_constant);
+            v->push_back(arg2 != 0 ? true_constant : false_constant);
+            Nor pred_nor(v);
+            BOOST_CHECK_EQUAL(!((arg1 != 0) || (arg2 != 0)), pred_nor.apply(sc)->get_value());
+        }
+    }
+}
+
+BOOST_FIXTURE_TEST_CASE(nor_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<Nor::BoolFunctionPtrVector> v(new Nor::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);
+                Nor pred_nor(v);
+                BOOST_CHECK_EQUAL(!((arg1 != 0) || (arg2 != 0) || (arg3 != 0)), pred_nor.apply(sc)->get_value());
+            }
+        }
+    }
+}
+
+
 //------ to_string test cases -------
 
 BOOST_FIXTURE_TEST_CASE(and_to_string, PredFix)
@@ -139,9 +182,9 @@ BOOST_FIXTURE_TEST_CASE(and_to_string, PredFix)
 	v2->push_back(false_constant);
 	v2->push_back(pred_and);
 	And another_and(v2);
-	BOOST_CHECK_EQUAL("and(false, and(true, false, true))", another_and.to_raw_string());
+	BOOST_CHECK_EQUAL("and(false, and(true, false, true))", another_and.to_string(tagset));
 	v2->push_back(false_constant);
-	BOOST_CHECK_EQUAL("and(false, and(true, false, true), false)", another_and.to_raw_string());
+	BOOST_CHECK_EQUAL("and(false, and(true, false, true), false)", another_and.to_string(tagset));
 }
 
 BOOST_FIXTURE_TEST_CASE(and_to_raw_string, PredFix)
@@ -177,9 +220,9 @@ BOOST_FIXTURE_TEST_CASE(or_to_string, PredFix)
     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());
+    BOOST_CHECK_EQUAL("or(or(true, false, true), false)", another_or.to_string(tagset));
     v2->push_back(true_constant);
-    BOOST_CHECK_EQUAL("or(or(true, false, true), false, true)", another_or.to_raw_string());
+    BOOST_CHECK_EQUAL("or(or(true, false, true), false, true)", another_or.to_string(tagset));
 }
 
 BOOST_FIXTURE_TEST_CASE(or_to_raw_string, PredFix)
@@ -198,7 +241,44 @@ BOOST_FIXTURE_TEST_CASE(or_to_raw_string, PredFix)
     v2->push_back(pred_or);
     Or another_or(v2);
     BOOST_CHECK_EQUAL("or(true, or(false, true, true))", another_or.to_raw_string());
+}
+
+BOOST_FIXTURE_TEST_CASE(nor_to_string, PredFix)
+{
+    boost::shared_ptr<Nor::BoolFunctionPtrVector> v(new Nor::BoolFunctionPtrVector());
+    v->push_back(true_constant);
+    boost::shared_ptr<Function<Bool> > pred_nor(new Nor(v));
+    BOOST_CHECK_EQUAL("not(true)", pred_nor->to_string(tagset));
+    v->push_back(false_constant);
+    BOOST_CHECK_EQUAL("not(true, false)", pred_nor->to_string(tagset));
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("not(true, false, true)", pred_nor->to_string(tagset));
+
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v2(new Nor::BoolFunctionPtrVector());
+    v2->push_back(pred_nor);
+    v2->push_back(false_constant);
+    Nor another_nor(v2);
+    BOOST_CHECK_EQUAL("not(not(true, false, true), false)", another_nor.to_string(tagset));
+    v2->push_back(true_constant);
+    BOOST_CHECK_EQUAL("not(not(true, false, true), false, true)", another_nor.to_string(tagset));
+}
 
+BOOST_FIXTURE_TEST_CASE(nor_to_raw_string, PredFix)
+{
+    boost::shared_ptr<Or::BoolFunctionPtrVector> v(new Nor::BoolFunctionPtrVector());
+    v->push_back(false_constant);
+    boost::shared_ptr<Function<Bool> > pred_nor(new Nor(v));
+    BOOST_CHECK_EQUAL("not(false)", pred_nor->to_raw_string());
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("not(false, true)", pred_nor->to_raw_string());
+    v->push_back(true_constant);
+    BOOST_CHECK_EQUAL("not(false, true, true)", pred_nor->to_raw_string());
+
+    boost::shared_ptr<Nor::BoolFunctionPtrVector> v2(new Nor::BoolFunctionPtrVector());
+    v2->push_back(true_constant);
+    v2->push_back(pred_nor);
+    Nor another_nor(v2);
+    BOOST_CHECK_EQUAL("not(true, not(false, true, true))", another_nor.to_raw_string());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
-- 
GitLab