diff --git a/alib2abstraction/src/abstraction/Value.cpp b/alib2abstraction/src/abstraction/Value.cpp index fa3887fc38f371a45caa470b9f9098d2052e760c..607f7a6fa9c52b53a5a97728ec770b1d6dce3c00 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 ( bool, bool, bool, bool, bool ) { +std::shared_ptr < abstraction::Value > Void::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, bool, bool, bool, bool, bool ) { throw std::domain_error ( "Void variables are not allowed" ); } @@ -42,7 +42,7 @@ ext::set < abstraction::ParamQualifiers::ParamQualifier > Void::getTypeQualifier LazyValue::LazyValue ( const std::shared_ptr < abstraction::OperationAbstraction > & ref ) : Value ( std::move ( ref ) ) { } -std::shared_ptr < abstraction::Value > LazyValue::clone ( bool, bool, bool, bool, bool ) { +std::shared_ptr < abstraction::Value > LazyValue::clone ( const std::shared_ptr < abstraction::OperationAbstraction > &, bool, bool, bool, bool, bool ) { throw std::domain_error ( "Feature not available on lazy value" ); } @@ -57,7 +57,7 @@ ext::set < abstraction::ParamQualifiers::ParamQualifier > LazyValue::getTypeQual std::shared_ptr < abstraction::Value > LazyValue::getProxyAbstraction ( ) { if ( cache == nullptr ) cache = this->getLifeReference ( )->eval ( ); - return cache; + return cache->getProxyAbstraction ( ); } } /* namespace abstraction */ diff --git a/alib2abstraction/src/abstraction/Value.hpp b/alib2abstraction/src/abstraction/Value.hpp index a63ba825f454d122947a517a11edd628804d175e..8036038ead7a9a008af1058f5103d126775d03a1 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 ( 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, bool isConst, bool isRvalueRef, bool isLvalueRef, 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 ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override; + std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, 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 ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override; + std::shared_ptr < abstraction::Value > clone ( const std::shared_ptr < abstraction::OperationAbstraction > & lifeReference, bool isConst, bool isRvalueRef, bool isLvalueRef, 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 db1f4f44868174f45c47b6baaf92e8be605f2e7b..178d5cda2ff39e44366545a8969d25fa3203a396 100644 --- a/alib2abstraction/src/abstraction/ValueHolder.hpp +++ b/alib2abstraction/src/abstraction/ValueHolder.hpp @@ -120,26 +120,26 @@ public: this->setData ( std::forward < Type > ( value ) ); } - std::shared_ptr < abstraction::Value > clone ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool isTemporary, bool move ) override { + 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 ) + throw std::domain_error ( "Taking reference to a temporary" ); + if ( isConst && isLvalueRef ) - return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > & > > ( nullptr, retrieveValue < const std::decay_t < Type > & > ( this->getProxyAbstraction ( ), move ), isTemporary ); + 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 ) - return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > && > > ( nullptr, retrieveValue < const std::decay_t < Type > && > ( this->getProxyAbstraction ( ), move ), isTemporary ); + 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 ) - return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > & > > ( nullptr, retrieveValue < std::decay_t < Type > & > ( this->getProxyAbstraction ( ), move ), isTemporary ); + return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > & > > ( lifeReference, retrieveValue < std::decay_t < Type > & > ( this->getProxyAbstraction ( ), move ), isTemporary ); else if ( isRvalueRef ) - return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > && > > ( nullptr, 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 ) - return std::make_shared < abstraction::ValueHolder < const std::decay_t < Type > > > ( nullptr, retrieveValue < const std::decay_t < Type > > ( this->getProxyAbstraction ( ), move ), isTemporary ); - else - return std::make_shared < abstraction::ValueHolder < std::decay_t < Type > > > ( nullptr, retrieveValue < std::decay_t < Type > > ( this->getProxyAbstraction ( ), move ), isTemporary ); - } - + 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 ) + 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 ); } ext::set < abstraction::ParamQualifiers::ParamQualifier > getTypeQualifiers ( ) const override { diff --git a/alib2cli/src/ast/statements/ResultVariableStatement.h b/alib2cli/src/ast/statements/ResultVariableStatement.h index c5f563e69d3e54d987d789f24a7937e59f09727a..cae27b44cf3e3b8fa55e5b2760ca708a229ef119 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 ( false, false, false, false, true ); + std::shared_ptr < abstraction::Value > res = prev->clone ( nullptr, false, false, false, false, true ); environment.setVariable ( m_name->eval ( environment ), res ); return res; }