From f5206c93393de181556806cc5e26d27ab4b0a707 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 16 Aug 2017 09:09:03 +0200
Subject: [PATCH] detect noop casts

---
 alib2cli/src/ast/params/CastParam.h          |  8 +++++++-
 alib2cli/src/ast/statements/CastStatement.h  |  8 +++++++-
 alib2common/src/abstraction/CastRegistry.hpp | 14 ++++++++++++++
 alib2common/src/abstraction/Registry.cpp     |  4 ++++
 alib2common/src/abstraction/Registry.h       |  1 +
 5 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/alib2cli/src/ast/params/CastParam.h b/alib2cli/src/ast/params/CastParam.h
index fc4bba8bc9..66bb2aade9 100644
--- a/alib2cli/src/ast/params/CastParam.h
+++ b/alib2cli/src/ast/params/CastParam.h
@@ -14,11 +14,17 @@ public:
 	}
 
 	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override {
+		std::string type = m_type->eval ( environment );
+
 		std::shared_ptr < abstraction::OperationAbstraction > translatedParam = m_param->translateAndEval ( prev, environment  );
 
+		if ( abstraction::Registry::isCastNoOp ( type, translatedParam->getReturnType ( ) ) ) {
+			return translatedParam;
+		}
+
 		bool normalize;
 
-		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( m_type->eval ( environment ), translatedParam->getReturnType ( ), normalize );
+		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( type, translatedParam->getReturnType ( ), normalize );
 		res->attachInput ( translatedParam, 0 );
 		res->eval ( );
 
diff --git a/alib2cli/src/ast/statements/CastStatement.h b/alib2cli/src/ast/statements/CastStatement.h
index 73ff0d7dc0..ff6325f114 100644
--- a/alib2cli/src/ast/statements/CastStatement.h
+++ b/alib2cli/src/ast/statements/CastStatement.h
@@ -14,11 +14,17 @@ public:
 	}
 
 	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override {
+		std::string type = m_type->eval ( environment );
+
 		std::shared_ptr < abstraction::OperationAbstraction > translatedStatement = m_statement->translateAndEval ( prev, environment );
 
+		if ( abstraction::Registry::isCastNoOp ( type, translatedStatement->getReturnType ( ) ) ) {
+			return translatedStatement;
+		}
+
 		bool normalize;
 
-		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( m_type->eval ( environment ), translatedStatement->getReturnType ( ), normalize );
+		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( type, translatedStatement->getReturnType ( ), normalize );
 		res->attachInput ( translatedStatement, 0 );
 		res->eval ( );
 
diff --git a/alib2common/src/abstraction/CastRegistry.hpp b/alib2common/src/abstraction/CastRegistry.hpp
index 3f9ccec3ee..2c5f58b371 100644
--- a/alib2common/src/abstraction/CastRegistry.hpp
+++ b/alib2common/src/abstraction/CastRegistry.hpp
@@ -105,6 +105,20 @@ public:
 		throw exception::CommonException ( "Entry from " + param + " to " + target + " not available." );
 	}
 
+	static bool isNoOp ( const std::string & target, const std::string & param ) {
+		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 ); } );
+		else
+			targetTypes.insert ( target );
+
+		for ( const std::string & toType : targetTypes )
+			if ( param == toType )
+				return true;
+
+		return false;
+	}
+
 	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & target, const std::string & param ) {
 		bool normalize;
 		return getAbstraction ( target, param, normalize );
diff --git a/alib2common/src/abstraction/Registry.cpp b/alib2common/src/abstraction/Registry.cpp
index bcd193558d..a997f9a36b 100644
--- a/alib2common/src/abstraction/Registry.cpp
+++ b/alib2common/src/abstraction/Registry.cpp
@@ -42,6 +42,10 @@ std::shared_ptr < abstraction::OperationAbstraction > Registry::getCastAbstracti
 	return CastRegistry::getAbstraction ( target, param, normalize );
 }
 
+bool Registry::isCastNoOp ( const std::string & target, const std::string & param ) {
+	return CastRegistry::isNoOp ( target, param );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getImmediateAbstraction ( const std::string & result, std::string value ) {
 	return ImmediateRegistry::getAbstraction ( result, std::move ( value ) );
 }
diff --git a/alib2common/src/abstraction/Registry.h b/alib2common/src/abstraction/Registry.h
index 6e32c1cece..4b096583fb 100644
--- a/alib2common/src/abstraction/Registry.h
+++ b/alib2common/src/abstraction/Registry.h
@@ -21,6 +21,7 @@ public:
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes );
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, bool & unwrap, bool & normalize );
 	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( const std::string & target, const std::string & param, bool & normalize );
+	static bool isCastNoOp ( const std::string & target, const std::string & param );
 	static std::shared_ptr < abstraction::OperationAbstraction > getImmediateAbstraction ( const std::string & result, std::string value );
 	static std::shared_ptr < abstraction::OperationAbstraction > getNormalizeAbstraction ( const std::string & param );
 	static std::shared_ptr < abstraction::OperationAbstraction > getDowncastAbstraction ( const std::string & concrete, const std::string & base );
-- 
GitLab