From 72355b2352f19f67398849f3f3bbb27b977ee769 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 14 Nov 2019 08:15:17 +0100
Subject: [PATCH] if command

---
 alib2cli/src/ast/command/IfCommand.h | 36 ++++++++++++++++++++++++++++
 alib2cli/src/parser/Parser.cpp       | 19 +++++++++++++++
 alib2cli/src/parser/Parser.h         |  4 ++++
 3 files changed, 59 insertions(+)
 create mode 100644 alib2cli/src/ast/command/IfCommand.h

diff --git a/alib2cli/src/ast/command/IfCommand.h b/alib2cli/src/ast/command/IfCommand.h
new file mode 100644
index 0000000000..a0375242ea
--- /dev/null
+++ b/alib2cli/src/ast/command/IfCommand.h
@@ -0,0 +1,36 @@
+#ifndef _CLI_IF_COMMAND_H_
+#define _CLI_IF_COMMAND_H_
+
+#include <ast/Command.h>
+#include <environment/Environment.h>
+#include <ast/Statement.h>
+#include <common/CastHelper.h>
+
+namespace cli {
+
+class IfCommand : public Command {
+	std::unique_ptr < Expression > m_condition;
+	std::unique_ptr < Command > m_thenBranch;
+	std::unique_ptr < Command > m_elseBranch;
+
+public:
+	IfCommand ( std::unique_ptr < Expression > condition, std::unique_ptr < Command > thenBranch, std::unique_ptr < Command > elseBranch ) : m_condition ( std::move ( condition ) ), m_thenBranch ( std::move ( thenBranch ) ), m_elseBranch ( std::move ( elseBranch ) ) {
+	}
+
+	CommandResult run ( Environment & environment ) const override {
+		std::shared_ptr < abstraction::Value > conditionResult = m_condition->translateAndEval ( environment );
+
+		std::shared_ptr < abstraction::Value > castedResult = abstraction::CastHelper::eval ( environment, conditionResult, "bool" );
+
+		if ( std::static_pointer_cast < abstraction::ValueHolderInterface < bool > > ( castedResult )->getValue ( ) )
+			return m_thenBranch->run ( environment );
+		else if ( m_elseBranch != nullptr )
+			return m_elseBranch->run ( environment );
+
+		return cli::CommandResult::OK;
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_IF_COMMAND_H_ */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 2d62f5eea7..2839050572 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -33,6 +33,7 @@
 #include <ast/command/BlockCommand.h>
 #include <ast/command/EvalCommand.h>
 #include <ast/command/InterpretCommand.h>
+#include <ast/command/IfCommand.h>
 
 #include <ast/expression/BinaryExpression.h>
 #include <ast/expression/PrefixExpression.h>
@@ -450,6 +451,24 @@ std::unique_ptr < Command > Parser::command ( ) {
 		match ( cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING );
 
 		return std::make_unique < InterpretCommand > ( std::move ( fileName ) );
+	} else if ( check_nonreserved_kw ( "if" ) ) {
+		if ( globalScope ( ) )
+			throw exception::CommonException ( "Statement not available in global scope." );
+		match_nonreserved_kw ( "if" );
+		match ( cli::Lexer::TokenType::LEFT_PAREN );
+		std::unique_ptr < Expression > condition = assign_expression ( );
+		match ( cli::Lexer::TokenType::RIGHT_PAREN );
+
+		match_nonreserved_kw ( "then" );
+		std::unique_ptr < Command > thenBranch = semicolon_command ( );
+
+		std::unique_ptr < Command > elseBranch;
+		if ( check_nonreserved_kw ( "else" ) ) {
+			match_nonreserved_kw ( "else" );
+			elseBranch = semicolon_command ( );
+		}
+
+		return std::make_unique < IfCommand > ( std::move ( condition ), std::move ( thenBranch ), std::move ( elseBranch ) );
 	} else {
 		throw exception::CommonException ( "Mismatched set " + ext::to_string ( getCheckOptions ( ) ) + " while expanding parse rule. Token is " + ( ( std::string ) m_current ) + "." );
 	}
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index c7a97844fe..d5770d3a10 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -149,6 +149,10 @@ public:
 		-- m_forceLexerReadNext;
 	}
 
+	bool globalScope ( ) {
+		return m_forceLexerReadNext == 0;
+	}
+
 	std::unique_ptr < Expression > assign_expression ( );
 
 	std::unique_ptr < Expression > or_expression ( );
-- 
GitLab