From 4cec627816dbc10e4adbac80b4926618866eb5c7 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 14 Aug 2017 21:21:34 +0200
Subject: [PATCH] normalize after cast if needed

---
 alib2cli/src/ast/params/CastParam.h           | 12 +++++-
 alib2cli/src/ast/statements/CastStatement.h   | 13 ++++++-
 alib2common/src/abstraction/CastRegistry.hpp  | 39 +++++++++++++------
 .../src/abstraction/OperationAbstraction.hpp  |  2 +-
 .../src/abstraction/PrimitiveRegistrator.cpp  | 18 ++++-----
 alib2common/src/abstraction/Registry.cpp      |  4 +-
 alib2common/src/abstraction/Registry.h        |  2 +-
 .../abstraction/ValueOperationAbstraction.hpp |  6 +--
 .../abstraction/VoidOperationAbstraction.hpp  |  2 +-
 .../src/registration/CastRegistration.hpp     |  5 ++-
 10 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/alib2cli/src/ast/params/CastParam.h b/alib2cli/src/ast/params/CastParam.h
index 6f1b9e6b21..0f7c0876dd 100644
--- a/alib2cli/src/ast/params/CastParam.h
+++ b/alib2cli/src/ast/params/CastParam.h
@@ -16,10 +16,20 @@ public:
 	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override {
 		std::shared_ptr < abstraction::OperationAbstraction > translatedParam = m_param->translateAndEval ( prev, environment  );
 
-		std::shared_ptr < abstraction::OperationAbstraction > res = translatedParam->getCastFromResult ( m_type );
+		bool normalize;
+
+		std::shared_ptr < abstraction::OperationAbstraction > res = translatedParam->getCastFromResult ( m_type, normalize );
 		res->attachInput ( translatedParam, 0 );
 		res->eval ( );
 
+		if ( normalize ) {
+			std::shared_ptr < abstraction::OperationAbstraction > normalized = res->getNormalizeResult ( );
+			normalized->attachInput ( res, 0 );
+			normalized->eval ( );
+
+			res = normalized;
+		}
+
 		return res;
 	}
 
diff --git a/alib2cli/src/ast/statements/CastStatement.h b/alib2cli/src/ast/statements/CastStatement.h
index 3829b6cc4e..864a901c1d 100644
--- a/alib2cli/src/ast/statements/CastStatement.h
+++ b/alib2cli/src/ast/statements/CastStatement.h
@@ -16,9 +16,20 @@ public:
 	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override {
 		std::shared_ptr < abstraction::OperationAbstraction > translatedStatement = m_statement->translateAndEval ( prev, environment );
 
-		std::shared_ptr < abstraction::OperationAbstraction > res = translatedStatement->getCastFromResult ( m_type );
+		bool normalize = false;
+
+		std::shared_ptr < abstraction::OperationAbstraction > res = translatedStatement->getCastFromResult ( m_type, normalize );
 		res->attachInput ( translatedStatement, 0 );
 		res->eval ( );
+
+		if ( normalize ) {
+			std::shared_ptr < abstraction::OperationAbstraction > normalized = res->getNormalizeResult ( );
+			normalized->attachInput ( res, 0 );
+			normalized->eval ( );
+
+			res = normalized;
+		}
+
 		return res;
 	}
 
diff --git a/alib2common/src/abstraction/CastRegistry.hpp b/alib2common/src/abstraction/CastRegistry.hpp
index 0d55ef8ab8..2f62000d96 100644
--- a/alib2common/src/abstraction/CastRegistry.hpp
+++ b/alib2common/src/abstraction/CastRegistry.hpp
@@ -21,15 +21,23 @@ namespace abstraction {
 
 class CastRegistry {
 	class Entry {
+		bool m_normalize;
 	public:
+		Entry ( bool normalize ) : m_normalize ( normalize ) {
+		}
+
 		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const = 0;
 
+		bool getNormalize ( ) const {
+			return m_normalize;
+		}
+
 	};
 
 	template < class Return, class Param >
 	class DefaultEntryImpl : public Entry {
 	public:
-		DefaultEntryImpl ( ) {
+		DefaultEntryImpl ( bool normalize ) : Entry ( normalize ) {
 		}
 
 		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
@@ -39,7 +47,7 @@ class CastRegistry {
 	class AlgorithmEntryImpl : public Entry {
 		std::function < Return ( Param ) > m_callback;
 	public:
-		AlgorithmEntryImpl ( std::function < Return ( Param ) > callback ) : m_callback ( callback ) {
+		AlgorithmEntryImpl ( std::function < Return ( Param ) > callback, bool normalize ) : Entry ( normalize ), m_callback ( callback ) {
 		}
 
 		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
@@ -52,34 +60,34 @@ class CastRegistry {
 
 public:
 	template < class TargetType, class ParamType >
-	static void registerCast ( std::string target, std::string param ) {
-		if ( ! getEntries ( ).insert ( std::make_pair ( std::make_pair ( target, param ), std::unique_ptr < Entry > ( new DefaultEntryImpl < TargetType, ParamType > ( ) ) ) ).second )
+	static void registerCast ( std::string target, std::string param, bool normalize ) {
+		if ( ! getEntries ( ).insert ( std::make_pair ( std::make_pair ( target, param ), std::unique_ptr < Entry > ( new DefaultEntryImpl < TargetType, ParamType > ( normalize ) ) ) ).second )
 			throw ::exception::CommonException ( "Entry from " + param + " to " + target + " already registered." );
 	}
 
 	template < class TargetType, class ParamType >
-	static void registerCast ( ) {
+	static void registerCast ( bool normalize ) {
 		std::string target = ext::to_string < TargetType > ( );
 		std::string param = ext::to_string < ParamType > ( );
 
-		registerCast < TargetType, ParamType > ( target, param );
+		registerCast < TargetType, ParamType > ( target, param, normalize );
 	}
 
 	template < class TargetType, class ParamType >
-	static void registerCastAlgorithm ( std::string target, std::string param, TargetType ( * callback ) ( ParamType ) ) {
-		if ( ! getEntries ( ).insert ( std::make_pair ( std::make_pair ( target, param ), std::unique_ptr < Entry > ( new AlgorithmEntryImpl < TargetType, ParamType > ( callback ) ) ) ).second )
+	static void registerCastAlgorithm ( std::string target, std::string param, TargetType ( * callback ) ( ParamType ), bool normalize ) {
+		if ( ! getEntries ( ).insert ( std::make_pair ( std::make_pair ( target, param ), std::unique_ptr < Entry > ( new AlgorithmEntryImpl < TargetType, ParamType > ( callback, normalize ) ) ) ).second )
 			throw ::exception::CommonException ( "Entry from " + param + " to " + target + " already registered." );
 	}
 
 	template < class TargetType, class ParamType >
-	static void registerCastAlgorithm ( TargetType ( * callback ) ( ParamType ) ) {
+	static void registerCastAlgorithm ( TargetType ( * callback ) ( ParamType ), bool normalize ) {
 		std::string target = ext::to_string < TargetType > ( );
 		std::string param = ext::to_string < ParamType > ( );
 
-		registerCastAlgorithm < TargetType, ParamType > ( target, param, callback );
+		registerCastAlgorithm < TargetType, ParamType > ( target, param, callback, normalize );
 	}
 
-	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( std::string target, std::string param ) {
+	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( std::string target, std::string param, bool & normalize ) {
 		std::set < std::string > targetTypes;
 		if ( alib::namingApi::hasTypes ( target ) )
 			targetTypes = ext::transform < std::string > ( alib::namingApi::getTypes ( target ), [ ] ( const ext::type_index & type ) { return ext::to_string ( type ); } );
@@ -88,13 +96,20 @@ public:
 
 		for ( const std::string & toType : targetTypes ) {
 			auto cast = getEntries ( ).find ( std::make_pair ( toType, param ) );
-			if ( cast != getEntries ( ).end ( ) )
+			if ( cast != getEntries ( ).end ( ) ) {
+				normalize = cast->second->getNormalize ( );
 				return cast->second->getAbstraction ( );
+			}
 		}
 
 		throw exception::CommonException ( "Entry from " + param + " to " + target + " not available." );
 	}
 
+	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( std::string target, std::string param ) {
+		bool normalize;
+		return getAbstraction ( std::move ( target ), std::move ( param ), normalize );
+	}
+
 };
 
 } /* namespace abstraction */
diff --git a/alib2common/src/abstraction/OperationAbstraction.hpp b/alib2common/src/abstraction/OperationAbstraction.hpp
index 81f702f64d..3f9ad2e667 100644
--- a/alib2common/src/abstraction/OperationAbstraction.hpp
+++ b/alib2common/src/abstraction/OperationAbstraction.hpp
@@ -40,7 +40,7 @@ public:
 
 	virtual std::shared_ptr < OperationAbstraction > getXmlFileWriterFromResult ( const std::string & filename ) const = 0;
 	virtual std::shared_ptr < OperationAbstraction > getValuePrinterFromResult ( ) const = 0;
-	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string & type ) const = 0;
+	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string & type, bool & normalize ) const = 0;
 	virtual std::shared_ptr < OperationAbstraction > getNormalizeResult ( ) const = 0;
 	virtual std::shared_ptr < OperationAbstraction > getDowncastResult ( ) const = 0;
 
diff --git a/alib2common/src/abstraction/PrimitiveRegistrator.cpp b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
index 370bb4b32d..97974e243b 100644
--- a/alib2common/src/abstraction/PrimitiveRegistrator.cpp
+++ b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
@@ -22,19 +22,19 @@ namespace abstraction {
 class PrimitiveCasts {
 public:
 	PrimitiveCasts ( ) {
-		abstraction::CastRegistry::registerCast < double, int > ( );
-		abstraction::CastRegistry::registerCast < int, double > ( );
+		abstraction::CastRegistry::registerCast < double, int > ( false );
+		abstraction::CastRegistry::registerCast < int, double > ( false );
 
-		abstraction::CastRegistry::registerCastAlgorithm < std::string, int > ( ext::to_string );
-		abstraction::CastRegistry::registerCastAlgorithm < int, std::string > ( (int(*)(std::string)) ext::from_string < int > );
+		abstraction::CastRegistry::registerCastAlgorithm < std::string, int > ( ext::to_string, false );
+		abstraction::CastRegistry::registerCastAlgorithm < int, std::string > ( (int(*)(std::string)) ext::from_string < int >, false );
 
-		abstraction::CastRegistry::registerCast < bool, int > ( );
+		abstraction::CastRegistry::registerCast < bool, int > ( false );
 
-		abstraction::CastRegistry::registerCast < size_t, int > ( "size_t", ext::to_string < int > ( ) );
-		abstraction::CastRegistry::registerCast < size_t, int > ( );
-		abstraction::CastRegistry::registerCast < int, size_t > ( );
+		abstraction::CastRegistry::registerCast < size_t, int > ( "size_t", ext::to_string < int > ( ), false );
+		abstraction::CastRegistry::registerCast < size_t, int > ( false );
+		abstraction::CastRegistry::registerCast < int, size_t > ( false );
 
-		abstraction::CastRegistry::registerCast < int, primitive::Integer > ( );
+		abstraction::CastRegistry::registerCast < int, primitive::Integer > ( false );
 	
 		abstraction::XmlFileWriterRegistry::registerXmlFileWriter < int > ( );
 		abstraction::XmlFileWriterRegistry::registerXmlFileWriter < double > ( );
diff --git a/alib2common/src/abstraction/Registry.cpp b/alib2common/src/abstraction/Registry.cpp
index 6ae0f879db..86410f8b09 100644
--- a/alib2common/src/abstraction/Registry.cpp
+++ b/alib2common/src/abstraction/Registry.cpp
@@ -38,8 +38,8 @@ std::shared_ptr < abstraction::OperationAbstraction > Registry::getAlgorithmAbst
 	return AlgorithmRegistry::getAbstraction ( std::move ( name ), paramTypes, unwrap, normalize );
 }
 
-std::shared_ptr < abstraction::OperationAbstraction > Registry::getCastAbstraction ( std::string target, std::string param ) {
-	return CastRegistry::getAbstraction ( std::move ( target ), std::move ( param ) );
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getCastAbstraction ( std::string target, std::string param, bool & normalize ) {
+	return CastRegistry::getAbstraction ( std::move ( target ), std::move ( param ), normalize );
 }
 
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getImmediateAbstraction ( std::string result, std::string value ) {
diff --git a/alib2common/src/abstraction/Registry.h b/alib2common/src/abstraction/Registry.h
index 5daefbb8cf..8a7d67cd61 100644
--- a/alib2common/src/abstraction/Registry.h
+++ b/alib2common/src/abstraction/Registry.h
@@ -20,7 +20,7 @@ public:
 
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( std::string name, const ext::vector < ext::type_index > & paramTypes );
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( std::string name, const ext::vector < ext::type_index > & paramTypes, bool & unwrap, bool & normalize );
-	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( std::string target, std::string param );
+	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( std::string target, std::string param, bool & normalize );
 	static std::shared_ptr < abstraction::OperationAbstraction > getImmediateAbstraction ( std::string result, std::string value );
 	static std::shared_ptr < abstraction::OperationAbstraction > getNormalizeAbstraction ( std::string param );
 	static std::shared_ptr < abstraction::OperationAbstraction > getDowncastAbstraction ( std::string concrete, std::string base );
diff --git a/alib2common/src/abstraction/ValueOperationAbstraction.hpp b/alib2common/src/abstraction/ValueOperationAbstraction.hpp
index ec43b9ad3f..5f6c50bf5f 100644
--- a/alib2common/src/abstraction/ValueOperationAbstraction.hpp
+++ b/alib2common/src/abstraction/ValueOperationAbstraction.hpp
@@ -52,11 +52,11 @@ public:
 	virtual std::shared_ptr < OperationAbstraction > getValuePrinterFromResult ( ) const override {
 		std::string param = ext::to_string < ReturnType > ( );
 		return Registry::getValuePrinterAbstraction ( param );
-}
+	}
 
-	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string & target ) const override {
+	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string & target, bool & normalize ) const override {
 		std::string param = ext::to_string < ReturnType > ( );
-		return Registry::getCastAbstraction ( target, param );
+		return Registry::getCastAbstraction ( target, param, normalize );
 	}
 
 	virtual std::shared_ptr < OperationAbstraction > getNormalizeResult ( ) const override {
diff --git a/alib2common/src/abstraction/VoidOperationAbstraction.hpp b/alib2common/src/abstraction/VoidOperationAbstraction.hpp
index b686c7ee47..2df106a3a7 100644
--- a/alib2common/src/abstraction/VoidOperationAbstraction.hpp
+++ b/alib2common/src/abstraction/VoidOperationAbstraction.hpp
@@ -33,7 +33,7 @@ public:
 		throw exception::CommonException ( "Void algorithm does not have a result." );
 	}
 
-	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string & ) const override {
+	virtual std::shared_ptr < OperationAbstraction > getCastFromResult ( const std::string &, bool & ) const override {
 		throw exception::CommonException ( "Void algorithm does not have a result." );
 	}
 
diff --git a/alib2common/src/registration/CastRegistration.hpp b/alib2common/src/registration/CastRegistration.hpp
index 2dc1e7fa66..9d9ff52e82 100644
--- a/alib2common/src/registration/CastRegistration.hpp
+++ b/alib2common/src/registration/CastRegistration.hpp
@@ -5,6 +5,8 @@
 #include <introspection/Casts.hpp>
 #include <abstraction/CastRegistry.hpp>
 
+#include <registration/NormalizationRegistration.hpp>
+
 namespace registration {
 
 template < class To, class From >
@@ -15,7 +17,8 @@ public:
 
 		introspection::Casts::registerCast < From, To > ( );
 
-		abstraction::CastRegistry::registerCast < To, From > ( );
+		bool normalize = registration::NormalizationRegister < To > ( ).requireNormalization ( );
+		abstraction::CastRegistry::registerCast < To, From > ( normalize );
 	}
 
 	CastRegister ( To ( * castFunction ) ( const From & ) ) {
-- 
GitLab