From 50f93170fc32dda97f567faa110565243bd5d617 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 24 Jun 2019 16:38:53 +0200 Subject: [PATCH] Apply same strategy to unary operators --- src/language/ASTNodeExpressionBuilder.cpp | 110 +--------------- .../ASTNodeUnaryOperatorExpressionBuilder.cpp | 120 ++++++++++++++++++ .../ASTNodeUnaryOperatorExpressionBuilder.hpp | 14 ++ src/language/CMakeLists.txt | 1 + 4 files changed, 138 insertions(+), 107 deletions(-) create mode 100644 src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp create mode 100644 src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index 6dc2db33c..b89fd96c3 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -3,6 +3,7 @@ #include <ASTNodeAffectationExpressionBuilder.hpp> #include <ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <ASTNodeIncDecExpressionBuilder.hpp> +#include <ASTNodeUnaryOperatorExpressionBuilder.hpp> #include <PEGGrammar.hpp> #include <SymbolTable.hpp> @@ -38,54 +39,6 @@ class NoProcess final : public INodeProcessor } }; -template <typename Op> -struct UnaryOp; - -template <> -struct UnaryOp<language::unary_minus> -{ - template <typename A> - PUGS_INLINE A - eval(const A& a) - { - return -a; - } -}; - -template <> -struct UnaryOp<language::unary_not> -{ - template <typename A> - PUGS_INLINE bool - eval(const A& a) - { - return not a; - } -}; - -template <typename UnaryOpT, typename ValueT, typename DataT> -class UnaryExpressionProcessor final : public INodeProcessor -{ - Node& m_node; - - public: - PUGS_INLINE ValueT - eval(const DataVariant& a) - { - return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); - } - - public: - UnaryExpressionProcessor(Node& node) : m_node{node} {} - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - m_node.children[0]->execute(exec_policy); - m_node.m_value = eval(m_node.children[0]->m_value); - } -}; - class IfStatement final : public INodeProcessor { Node& m_node; @@ -313,61 +266,6 @@ namespace internal void build_node_type(Node& n) { - auto set_unary_operator_processor = [](Node& n, const auto& operator_v) { - auto set_unary_operator_processor_for_data = [&](const auto& value, const DataType& data_type) { - using OperatorT = std::decay_t<decltype(operator_v)>; - using ValueT = std::decay_t<decltype(value)>; - switch (data_type) { - case DataType::bool_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n); - break; - } - case DataType::unsigned_int_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); - break; - } - case DataType::int_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n); - break; - } - case DataType::double_t: { - n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n); - break; - } - default: { - throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); - } - } - }; - - auto set_unary_operator_processor_for_value = [&](const DataType& value_type) { - const DataType data_type = n.children[0]->m_data_type; - switch (value_type) { - case DataType::bool_t: { - set_unary_operator_processor_for_data(bool{}, data_type); - break; - } - case DataType::unsigned_int_t: { - set_unary_operator_processor_for_data(uint64_t{}, data_type); - break; - } - case DataType::int_t: { - set_unary_operator_processor_for_data(int64_t{}, data_type); - break; - } - case DataType::double_t: { - set_unary_operator_processor_for_data(double{}, data_type); - break; - } - default: { - throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); - } - } - }; - - set_unary_operator_processor_for_value(n.m_data_type); - }; - if (n.is_root() or n.is<language::bloc>()) { n.m_node_processor = std::make_unique<NodeList>(n); } else if (n.is<language::declaration>()) { @@ -386,10 +284,8 @@ build_node_type(Node& n) } else if (n.is<language::name>()) { n.m_node_processor = std::make_unique<NameExpression>(n); - } else if (n.is<language::unary_minus>()) { - set_unary_operator_processor(n, language::unary_minus{}); - } else if (n.is<language::unary_not>()) { - set_unary_operator_processor(n, language::unary_not{}); + } else if (n.is<language::unary_minus>() or n.is<language::unary_not>()) { + ASTNodeUnaryOperatorExpressionBuilder{n}; } else if (n.is<language::unary_minusminus>() or n.is<language::unary_plusplus>() or n.is<language::post_minusminus>() or n.is<language::post_plusplus>()) { diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp new file mode 100644 index 000000000..c4bdb6f0a --- /dev/null +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -0,0 +1,120 @@ +#include <ASTNodeUnaryOperatorExpressionBuilder.hpp> +#include <PEGGrammar.hpp> +#include <SymbolTable.hpp> + +namespace language +{ +template <typename Op> +struct UnaryOp; + +template <> +struct UnaryOp<language::unary_minus> +{ + template <typename A> + PUGS_INLINE A + eval(const A& a) + { + return -a; + } +}; + +template <> +struct UnaryOp<language::unary_not> +{ + template <typename A> + PUGS_INLINE bool + eval(const A& a) + { + return not a; + } +}; + +template <typename UnaryOpT, typename ValueT, typename DataT> +class UnaryExpressionProcessor final : public INodeProcessor +{ + Node& m_node; + + public: + PUGS_INLINE ValueT + eval(const DataVariant& a) + { + return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); + } + + public: + UnaryExpressionProcessor(Node& node) : m_node{node} {} + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[0]->execute(exec_policy); + m_node.m_value = eval(m_node.children[0]->m_value); + } +}; + +ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(Node& n) +{ + auto set_unary_operator_processor = [](Node& n, const auto& operator_v) { + auto set_unary_operator_processor_for_data = [&](const auto& value, const DataType& data_type) { + using OperatorT = std::decay_t<decltype(operator_v)>; + using ValueT = std::decay_t<decltype(value)>; + switch (data_type) { + case DataType::bool_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n); + break; + } + case DataType::unsigned_int_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n); + break; + } + case DataType::int_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n); + break; + } + case DataType::double_t: { + n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n); + break; + } + default: { + throw parse_error("undefined operand type for unary operator", std::vector{n.children[0]->begin()}); + } + } + }; + + auto set_unary_operator_processor_for_value = [&](const DataType& value_type) { + const DataType data_type = n.children[0]->m_data_type; + switch (value_type) { + case DataType::bool_t: { + set_unary_operator_processor_for_data(bool{}, data_type); + break; + } + case DataType::unsigned_int_t: { + set_unary_operator_processor_for_data(uint64_t{}, data_type); + break; + } + case DataType::int_t: { + set_unary_operator_processor_for_data(int64_t{}, data_type); + break; + } + case DataType::double_t: { + set_unary_operator_processor_for_data(double{}, data_type); + break; + } + default: { + throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); + } + } + }; + + set_unary_operator_processor_for_value(n.m_data_type); + }; + + if (n.is<language::unary_minus>()) { + set_unary_operator_processor(n, language::unary_minus{}); + } else if (n.is<language::unary_not>()) { + set_unary_operator_processor(n, language::unary_not{}); + } else { + throw parse_error("unexpected error: undefined unary operator", std::vector{n.begin()}); + } +} +} // namespace language diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp new file mode 100644 index 000000000..ea58aa7d8 --- /dev/null +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.hpp @@ -0,0 +1,14 @@ +#ifndef AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP +#define AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP + +#include <ASTNode.hpp> + +namespace language +{ +struct ASTNodeUnaryOperatorExpressionBuilder +{ + ASTNodeUnaryOperatorExpressionBuilder(Node& node); +}; +} // namespace language + +#endif // AST_NODE_UNARY_OPERATOR_EXPRESSION_BUILDER_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index c9699c103..c84943ca4 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -11,6 +11,7 @@ add_library( ASTNodeBinaryOperatorExpressionBuilder.cpp ASTNodeExpressionBuilder.cpp ASTNodeIncDecExpressionBuilder.cpp + ASTNodeUnaryOperatorExpressionBuilder.cpp PugsParser.cpp) #include_directories(${PUGS_SOURCE_DIR}/utils) -- GitLab