From e785c6c384b63bb9e1e55f779527f92fdc76c379 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 9 Dec 2019 20:14:43 +0100
Subject: [PATCH] redesign value holder qualifier representation

---
 alib2abstraction/src/abstraction/Value.cpp    |  4 ++--
 alib2abstraction/src/abstraction/Value.hpp    |  6 +++---
 .../src/abstraction/ValueHolder.hpp           | 18 ++++++++----------
 .../src/abstraction/ValueHolderInterface.hpp  | 19 +++++++++++--------
 .../ast/statements/ResultVariableStatement.h  |  2 +-
 5 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/alib2abstraction/src/abstraction/Value.cpp b/alib2abstraction/src/abstraction/Value.cpp
index 3c4b7eb8d4..80de81380b 100644
--- a/alib2abstraction/src/abstraction/Value.cpp
+++ b/alib2abstraction/src/abstraction/Value.cpp
@@ -26,7 +26,7 @@ const std::shared_ptr < abstraction::OperationAbstraction > & Value::getLifeRefe
 }
 
 
-std::shared_ptr < abstraction::Value > Void::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, bool, bool, bool, bool, bool ) {
+std::shared_ptr < abstraction::Value > Void::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, abstraction::ParamQualifiers::ParamQualifierSet, bool, bool ) {
 	throw std::domain_error ( "Void variables are not allowed" );
 }
 
@@ -42,7 +42,7 @@ abstraction::ParamQualifiers::ParamQualifierSet Void::getTypeQualifiers ( ) cons
 LazyValue::LazyValue ( const std::shared_ptr < abstraction::OperationAbstraction > & ref ) : Value ( std::move ( ref ) ) {
 }
 
-std::shared_ptr < abstraction::Value > LazyValue::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, bool, bool, bool, bool, bool ) {
+std::shared_ptr < abstraction::Value > LazyValue::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, abstraction::ParamQualifiers::ParamQualifierSet, bool, bool ) {
 	throw std::domain_error ( "Feature not available on lazy value" );
 }
 
diff --git a/alib2abstraction/src/abstraction/Value.hpp b/alib2abstraction/src/abstraction/Value.hpp
index bd66b6dc93..3ae3de118d 100644
--- a/alib2abstraction/src/abstraction/Value.hpp
+++ b/alib2abstraction/src/abstraction/Value.hpp
@@ -26,7 +26,7 @@ public:
 
 	virtual ~Value ( ) noexcept = default;
 
-	virtual std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move = false ) = 0;
+	virtual std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, abstraction::ParamQualifiers::ParamQualifierSet paramQualifierSet, bool isTemporary, bool move = false ) = 0;
 
 	virtual std::shared_ptr < abstraction::Value > getProxyAbstraction ( );
 
@@ -43,7 +43,7 @@ class Void : public Value {
 public:
 	using Value::Value;
 
-	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override;
+	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, abstraction::ParamQualifiers::ParamQualifierSet paramQualifierSet, bool isTemporary, bool move ) override;
 
 	ext::type_index getTypeIndex ( ) const override;
 
@@ -57,7 +57,7 @@ class LazyValue : public Value {
 public:
 	LazyValue ( const std::shared_ptr < abstraction::OperationAbstraction > & ref );
 
-	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override;
+	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, abstraction::ParamQualifiers::ParamQualifierSet paramQualifierSet, bool isTemporary, bool move ) override;
 
 	ext::type_index getTypeIndex ( ) const override;
 
diff --git a/alib2abstraction/src/abstraction/ValueHolder.hpp b/alib2abstraction/src/abstraction/ValueHolder.hpp
index 69a76efab8..77cafbd5af 100644
--- a/alib2abstraction/src/abstraction/ValueHolder.hpp
+++ b/alib2abstraction/src/abstraction/ValueHolder.hpp
@@ -113,30 +113,28 @@ public:
 
 template < class Type >
 class ValueHolder : public ValueHolderImpl < Type > {
-	using ValueHolderImpl < Type >::ValueHolderImpl;
-
 public:
-	ValueHolder ( const std::shared_ptr < abstraction::OperationAbstraction > & ref, Type && value, bool temporary ) : ValueHolderImpl < Type > ( ref, std::is_const_v < std::remove_reference_t < Type > >, std::is_rvalue_reference_v < Type >, std::is_lvalue_reference_v < Type >, temporary ) {
+	ValueHolder ( const std::shared_ptr < abstraction::OperationAbstraction > & ref, Type && value, bool temporary ) : ValueHolderImpl < Type > ( ref, ParamQualifiers::paramQualifiers < Type > ( ), temporary ) {
 		this->setData ( std::forward < Type > ( value ) );
 	}
 
-	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override {
-		if ( ( isLvalueRef || isRvalueRef ) && this->isTemporary ( ) && ! this->isRef ( ) && lifeReference == nullptr )
+	std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, ParamQualifiers::ParamQualifierSet paramQualifierSet, bool isTemporary, bool move ) override {
+		if ( ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::LREF || paramQualifierSet && ParamQualifiers::ParamQualifierSet::RREF ) && this->isTemporary ( ) && ! this->isRef ( ) && lifeReference == nullptr )
 			throw std::domain_error ( "Taking reference to a temporary" );
 
-		if ( isConst && isLvalueRef )
+		if ( ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::CONST ) && ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::LREF ) )
 			return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > & > > ( lifeReference, retrieveValue < const std::decay_t < Type > & > ( this->getProxyAbstraction ( ), move ), isTemporary );
-		else if ( isConst && isRvalueRef )
+		else if ( ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::CONST ) && ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::RREF ) )
 			return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > && > > ( lifeReference, retrieveValue < const std::decay_t < Type > && > ( this->getProxyAbstraction ( ), move ), isTemporary );
-		else if ( isLvalueRef )
+		else if ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::LREF )
 			return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > & > > ( lifeReference, retrieveValue < std::decay_t < Type > & > ( this->getProxyAbstraction ( ), move ), isTemporary );
-		else if ( isRvalueRef )
+		else if ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::RREF )
 			return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > && > > ( lifeReference, retrieveValue < std::decay_t < Type > && > ( this->getProxyAbstraction ( ), move ), isTemporary );
 		else if constexpr ( std::is_abstract_v < std::decay_t < Type > > )
 			throw std::domain_error ( "Cannot declare value of abstract class." );
 		else if constexpr ( ! std::is_assignable_v < std::decay_t < Type > &, std::decay_t < Type > > )
 			throw std::domain_error ( "Cannot assign value." );
-		else if ( isConst )
+		else if ( paramQualifierSet && ParamQualifiers::ParamQualifierSet::CONST )
 			return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > > > ( lifeReference, retrieveValue < const std::decay_t < Type > > ( this->getProxyAbstraction ( ), move ), isTemporary );
 		else
 			return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > > > ( lifeReference, retrieveValue < std::decay_t < Type > > ( this->getProxyAbstraction ( ), move ), isTemporary );
diff --git a/alib2abstraction/src/abstraction/ValueHolderInterface.hpp b/alib2abstraction/src/abstraction/ValueHolderInterface.hpp
index 3e6abb3272..9a94ce2eff 100644
--- a/alib2abstraction/src/abstraction/ValueHolderInterface.hpp
+++ b/alib2abstraction/src/abstraction/ValueHolderInterface.hpp
@@ -14,19 +14,22 @@ namespace abstraction {
 
 template < class Type >
 class ValueHolderInterface : public Value {
-	bool m_isConst;
-	bool m_isRvalueRef;
-	bool m_isLvalueRef;
+	ParamQualifiers::ParamQualifierSet m_paramQualifierSet;
 	bool m_isTemporary;
 
-public:
-	ValueHolderInterface ( const std::shared_ptr < abstraction::OperationAbstraction > & ref, bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary ) : Value ( ref ), m_isConst ( isConst ), m_isRvalueRef ( isRvalueRef ), m_isLvalueRef ( isLvalueRef ), m_isTemporary ( isTemporary ) {
+protected:
+	ValueHolderInterface ( const std::shared_ptr < abstraction::OperationAbstraction > & ref, ParamQualifiers::ParamQualifierSet paramQualifierSet, bool isTemporary ) : Value ( ref ), m_paramQualifierSet ( paramQualifierSet ), m_isTemporary ( isTemporary ) {
 	}
 
+public:
 	virtual Type && getValue ( ) const = 0;
 
+	ParamQualifiers::ParamQualifierSet getParamQualifiersSet ( ) const {
+		return m_paramQualifierSet;
+	}
+
 	bool isConst ( ) const {
-		return m_isConst;
+		return m_paramQualifierSet && ParamQualifiers::ParamQualifierSet::CONST;
 	}
 
 	bool isRef ( ) const {
@@ -34,11 +37,11 @@ public:
 	}
 
 	bool isRvalueRef ( ) const {
-		return m_isRvalueRef;
+		return m_paramQualifierSet && ParamQualifiers::ParamQualifierSet::RREF;
 	}
 
 	bool isLvalueRef ( ) const {
-		return m_isLvalueRef;
+		return m_paramQualifierSet && ParamQualifiers::ParamQualifierSet::LREF;
 	}
 
 	bool isTemporary ( ) const {
diff --git a/alib2cli/src/ast/statements/ResultVariableStatement.h b/alib2cli/src/ast/statements/ResultVariableStatement.h
index cae27b44cf..cd623aa24c 100644
--- a/alib2cli/src/ast/statements/ResultVariableStatement.h
+++ b/alib2cli/src/ast/statements/ResultVariableStatement.h
@@ -13,7 +13,7 @@ public:
 	}
 
 	std::shared_ptr < abstraction::Value > translateAndEval ( const std::shared_ptr < abstraction::Value > & prev, Environment & environment ) const override {
-		std::shared_ptr < abstraction::Value > res = prev->clone ( nullptr, false, false, false, false, true );
+		std::shared_ptr < abstraction::Value > res = prev->clone ( nullptr, abstraction::ParamQualifiers::ParamQualifierSet::NONE, false, true );
 		environment.setVariable ( m_name->eval ( environment ), res );
 		return res;
 	}
-- 
GitLab