From 501b847551a259484ef0c9d9f6237aa4819c3772 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Tr=C3=A1vn=C3=AD=C4=8Dek?= <jan.travnicek@fit.cvut.cz>
Date: Wed, 5 Jan 2022 12:34:58 +0100
Subject: [PATCH] cli: delegate value interpretation in if and while to the
 result interpreter

---
 alib2cli/src/ast/command/IfCommand.h    |  3 +-
 alib2cli/src/ast/command/WhileCommand.h |  3 +-
 alib2cli/src/common/ResultInterpret.h   | 45 ++++++++++++++++++-------
 3 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/alib2cli/src/ast/command/IfCommand.h b/alib2cli/src/ast/command/IfCommand.h
index 144c5294e7..7fc5cc197e 100644
--- a/alib2cli/src/ast/command/IfCommand.h
+++ b/alib2cli/src/ast/command/IfCommand.h
@@ -4,6 +4,7 @@
 #include <environment/Environment.h>
 #include <ast/Statement.h>
 #include <common/CastHelper.h>
+#include <common/ResultInterpret.h>
 
 namespace cli {
 
@@ -21,7 +22,7 @@ public:
 
 		std::shared_ptr < abstraction::Value > castedResult = abstraction::CastHelper::eval ( environment, conditionResult, "bool" );
 
-		if ( std::static_pointer_cast < abstraction::ValueHolderInterface < bool > > ( castedResult )->getValue ( ) )
+		if ( cli::ResultInterpret::value < bool > ( castedResult ) )
 			return m_thenBranch->run ( environment );
 		else if ( m_elseBranch != nullptr )
 			return m_elseBranch->run ( environment );
diff --git a/alib2cli/src/ast/command/WhileCommand.h b/alib2cli/src/ast/command/WhileCommand.h
index 359844f9aa..adf9a7005f 100644
--- a/alib2cli/src/ast/command/WhileCommand.h
+++ b/alib2cli/src/ast/command/WhileCommand.h
@@ -4,6 +4,7 @@
 #include <environment/Environment.h>
 #include <ast/Statement.h>
 #include <common/CastHelper.h>
+#include <common/ResultInterpret.h>
 
 namespace cli {
 
@@ -22,7 +23,7 @@ public:
 
 			std::shared_ptr < abstraction::Value > castedResult = abstraction::CastHelper::eval ( environment, conditionResult, "bool" );
 
-			if ( ! std::static_pointer_cast < abstraction::ValueHolderInterface < bool > > ( castedResult )->getValue ( ) )
+			if ( ! cli::ResultInterpret::value < bool > ( castedResult ) )
 				break;
 
 			res = m_body->run ( environment );
diff --git a/alib2cli/src/common/ResultInterpret.h b/alib2cli/src/common/ResultInterpret.h
index fea7f077ff..a2ffea34cd 100644
--- a/alib2cli/src/common/ResultInterpret.h
+++ b/alib2cli/src/common/ResultInterpret.h
@@ -7,25 +7,46 @@
 namespace cli {
 
 class ResultInterpret {
+	template < class T >
+	static std::optional < T > tryInterpretation ( std::shared_ptr < abstraction::Value > result ) {
+		std::shared_ptr < abstraction::ValueHolderInterface < T > > ptr = std::dynamic_pointer_cast < abstraction::ValueHolderInterface < T > > ( result );
+		if ( ptr )
+			return ptr->getValue ( );
+		else
+			return std::nullopt;
+	}
+
 public:
 	static int cli ( const std::shared_ptr < abstraction::Value > & result ) {
 		if ( result ) {
-			std::shared_ptr < abstraction::ValueHolderInterface < int > > ptr1 = std::dynamic_pointer_cast < abstraction::ValueHolderInterface < int > > ( result );
-			if ( ptr1 )
-				return ptr1->getValue ( );
-			std::shared_ptr < abstraction::ValueHolderInterface < unsigned > > ptr2 = std::dynamic_pointer_cast < abstraction::ValueHolderInterface < unsigned > > ( result );
-			if ( ptr2 )
-				return static_cast < int > ( ptr2->getValue ( ) );
-			std::shared_ptr < abstraction::ValueHolderInterface < bool > > ptr3 = std::dynamic_pointer_cast < abstraction::ValueHolderInterface < bool > > ( result );
-			if ( ptr3 )
-				return static_cast < int > ( ! ptr3->getValue ( ) );
-
-			throw exception::CommonException ( "Invalid result type. Provided: " + result->getType ( ) );
+			std::optional < int > res1 = tryInterpretation < int > ( result );
+			if ( res1 )
+				return res1.value ( );
+
+			std::optional < bool > res2 = tryInterpretation < bool > ( result );
+			if ( res2 )
+				return static_cast < int > ( ! res2.value ( ) );
+
+			std::optional < unsigned > res3 = tryInterpretation < unsigned > ( result );
+			if ( res3 )
+				return static_cast < int > ( res3.value ( ) );
+
+			throw exception::CommonException ( "Invalid result type. Provided: " + ext::to_string ( result->getType ( ) ) );
 		} else {
 			return 0;
 		}
 	}
+
+	template < class T >
+	static T value ( std::shared_ptr < abstraction::Value > result ) {
+		if ( result ) {
+			std::optional < T > res = tryInterpretation < T > ( result );
+			if ( res )
+				return res.value ( );
+		}
+
+		throw exception::CommonException ( "Type " + ext::to_string < T > ( ) + " not provided, instead " + ext::to_string ( result->getType ( ) ) + " provided." );
+	}
 };
 
 } /* namespace cli */
-
-- 
GitLab