diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index 5eaa3f785656e2c21061e546cf3ac2fa4a823b0b..221ef79b738512674908acd4fbd1ca1bc3f6c604 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -1,163 +1,8 @@ #include <ASTNodeAffectationExpressionBuilder.hpp> #include <PEGGrammar.hpp> -#include <SymbolTable.hpp> -#include <Demangle.hpp> - -template <typename Op> -struct AffOp; - -template <> -struct AffOp<language::eq_op> -{ - template <typename A, typename B> - PUGS_INLINE void - eval(A& a, const B& b) - { - a = b; - } -}; - -template <> -struct AffOp<language::multiplyeq_op> -{ - template <typename A, typename B> - PUGS_INLINE void - eval(A& a, const B& b) - { - a *= b; - } -}; - -template <> -struct AffOp<language::divideeq_op> -{ - template <typename A, typename B> - PUGS_INLINE void - eval(A& a, const B& b) - { - a /= b; - } -}; - -template <> -struct AffOp<language::pluseq_op> -{ - template <typename A, typename B> - PUGS_INLINE void - eval(A& a, const B& b) - { - a += b; - } -}; - -template <> -struct AffOp<language::minuseq_op> -{ - template <typename A, typename B> - PUGS_INLINE void - eval(A& a, const B& b) - { - a -= b; - } -}; - -template <typename OperatorT, typename ValueT, typename DataT> -class AffectationProcessor final : public INodeProcessor -{ - private: - ASTNode& m_node; - ASTNodeDataVariant* p_value{nullptr}; - - static inline const bool _is_defined{[] { - if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { - if constexpr (not std::is_same_v<OperatorT, language::eq_op>) { - return false; - } - } - return true; - }()}; - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - if constexpr (_is_defined) { - m_node.children[1]->execute(exec_policy); - - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - if constexpr (std::is_same_v<ValueT, DataT>) { - *p_value = m_node.children[1]->m_value; - } else { - *p_value = static_cast<ValueT>(std::get<DataT>(m_node.children[1]->m_value)); - } - } else { - AffOp<OperatorT>().eval(std::get<ValueT>(*p_value), std::get<DataT>(m_node.children[1]->m_value)); - } - } - } - - AffectationProcessor(ASTNode& node) : m_node{node} - { - if constexpr (_is_defined) { - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); - p_value = &i_symbol->second.value(); - } else { - throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); - } - } -}; - -template <typename OperatorT, typename DataT> -class AffectationToStringProcessor final : public INodeProcessor -{ - private: - ASTNode& m_node; - ASTNodeDataVariant* p_value{nullptr}; - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - m_node.children[1]->execute(exec_policy); - - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - if constexpr (std::is_same_v<std::string, DataT>) { - *p_value = m_node.children[1]->m_value; - } else { - *p_value = std::to_string(std::get<DataT>(m_node.children[1]->m_value)); - } - } else if constexpr (std::is_same_v<OperatorT, language::pluseq_op>) { - if constexpr (std::is_same_v<std::string, DataT>) { - std::get<std::string>(*p_value) += std::get<std::string>(m_node.children[1]->m_value); - } else { - std::get<std::string>(*p_value) += std::to_string(std::get<DataT>(m_node.children[1]->m_value)); - } - } - } - - AffectationToStringProcessor(ASTNode& node) : m_node{node} - { - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); - p_value = &i_symbol->second.value(); - } -}; +#include <node_processor/AffectationProcessor.hpp> +#include <node_processor/AffectationToStringProcessor.hpp> ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n) { diff --git a/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp index 496668c57a7738cbcd351d3834ba0c7800c51d3c..3d16d8fa4a4fab1673da8aa346d9027c95ca65d8 100644 --- a/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp +++ b/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp @@ -1,259 +1,8 @@ #include <ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <PEGGrammar.hpp> -#include <SymbolTable.hpp> -#include <Demangle.hpp> - -#include <type_traits> - -template <typename Op> -struct BinOp; - -template <> -struct BinOp<language::and_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a and b) - { - return a and b; - } -}; - -template <> -struct BinOp<language::or_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a or b) - { - return a or b; - } -}; - -template <> -struct BinOp<language::xor_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a xor b) - { - return a xor b; - } -}; - -template <> -struct BinOp<language::eqeq_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a == b) - { - return a == b; - } -}; - -template <> -struct BinOp<language::not_eq_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a != b) - { - return a != b; - } -}; - -template <> -struct BinOp<language::lesser_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a < b) - { - return a < b; - } -}; - -template <> -struct BinOp<language::lesser_or_eq_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a <= b) - { - return a <= b; - } -}; - -template <> -struct BinOp<language::greater_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a > b) - { - return a > b; - } -}; - -template <> -struct BinOp<language::greater_or_eq_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a >= b) - { - return a >= b; - } -}; - -template <> -struct BinOp<language::plus_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a + b) - { - return a + b; - } -}; - -template <> -struct BinOp<language::minus_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a - b) - { - return a - b; - } -}; - -template <> -struct BinOp<language::multiply_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a * b) - { - return a * b; - } -}; - -template <> -struct BinOp<language::divide_op> -{ - template <typename A, typename B> - PUGS_INLINE auto - eval(const A& a, const B& b) -> decltype(a / b) - { - return a / b; - } -}; - -template <typename BinaryOpT, typename A_DataT, typename B_DataT> -class BinaryExpressionProcessor final : public INodeProcessor -{ - ASTNode& m_node; - - PUGS_INLINE auto - _eval(const ASTNodeDataVariant& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) - { - // Add 'signed' when necessary to avoid signed/unsigned comparison warnings - if constexpr ((not(std::is_same_v<A_DataT, bool> or std::is_same_v<B_DataT, bool>)) and - (std::is_same_v<BinaryOpT, language::and_op> or std::is_same_v<BinaryOpT, language::or_op> or - std::is_same_v<BinaryOpT, language::xor_op> or std::is_same_v<BinaryOpT, language::eqeq_op> or - std::is_same_v<BinaryOpT, language::not_eq_op> or std::is_same_v<BinaryOpT, language::lesser_op> or - std::is_same_v<BinaryOpT, language::lesser_or_eq_op> or - std::is_same_v<BinaryOpT, language::greater_op> or - std::is_same_v<BinaryOpT, language::greater_or_eq_op>) and - (std::is_signed_v<A_DataT> xor std::is_signed_v<B_DataT>)) { - if constexpr (std::is_unsigned_v<A_DataT>) { - using signed_A_DataT = std::make_signed_t<A_DataT>; - const signed_A_DataT signed_a = static_cast<signed_A_DataT>(std::get<A_DataT>(a)); - value = BinOp<BinaryOpT>().eval(signed_a, std::get<B_DataT>(b)); - } else { - using signed_B_DataT = std::make_signed_t<B_DataT>; - const signed_B_DataT signed_b = static_cast<signed_B_DataT>(std::get<B_DataT>(b)); - value = BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), signed_b); - } - } else { - auto result = BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)); - if constexpr (std::is_same_v<decltype(result), int>) { - value = static_cast<int64_t>(result); - } else { - value = result; - } - } - } - - static inline const bool _is_defined{[] { - if constexpr (std::is_same_v<BinaryOpT, language::xor_op>) { - return std::is_same_v<std::decay_t<A_DataT>, std::decay_t<B_DataT>> and std::is_integral_v<std::decay_t<A_DataT>>; - } - return true; - }()}; - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - if constexpr (_is_defined) { - m_node.children[0]->execute(exec_policy); - m_node.children[1]->execute(exec_policy); - - this->_eval(m_node.children[0]->m_value, m_node.children[1]->m_value, m_node.m_value); - } - } - - BinaryExpressionProcessor(ASTNode& node) : m_node{node} - { - if constexpr (not _is_defined) { - throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); - } - } -}; - -template <typename B_DataT> -class ConcatExpressionProcessor final : public INodeProcessor -{ - ASTNode& m_node; - - PUGS_INLINE auto - _eval(const std::string& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) - { - if constexpr (std::is_same_v<B_DataT, std::string>) { - value = a + std::get<B_DataT>(b); - } else { - value = a + std::to_string(std::get<B_DataT>(b)); - } - } - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - m_node.children[0]->execute(exec_policy); - m_node.children[1]->execute(exec_policy); - - this->_eval(std::get<std::string>(m_node.children[0]->m_value), m_node.children[1]->m_value, m_node.m_value); - } - - ConcatExpressionProcessor(ASTNode& node) : m_node{node} {} -}; +#include <node_processor/BinaryExpressionProcessor.hpp> +#include <node_processor/ConcatExpressionProcessor.hpp> ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(ASTNode& n) { diff --git a/src/language/ASTNodeIncDecExpressionBuilder.cpp b/src/language/ASTNodeIncDecExpressionBuilder.cpp index 485c5d6532f08b624f60563ffae966860836d129..12e4f0fd6ad9cb61458a16b2aa2ed8bbf55e453b 100644 --- a/src/language/ASTNodeIncDecExpressionBuilder.cpp +++ b/src/language/ASTNodeIncDecExpressionBuilder.cpp @@ -1,101 +1,7 @@ #include <ASTNodeIncDecExpressionBuilder.hpp> #include <PEGGrammar.hpp> -#include <SymbolTable.hpp> -#include <Demangle.hpp> - -template <typename Op> -struct IncDecOp; - -template <> -struct IncDecOp<language::unary_minusminus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return --a; - } -}; - -template <> -struct IncDecOp<language::unary_plusplus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return ++a; - } -}; - -template <> -struct IncDecOp<language::post_minusminus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return a--; - } -}; - -template <> -struct IncDecOp<language::post_plusplus> -{ - template <typename A> - PUGS_INLINE A - eval(A& a) - { - return a++; - } -}; - -template <typename IncDecOpT, typename ValueT, typename DataT> -class IncDecExpressionProcessor final : public INodeProcessor -{ - ASTNode& m_node; - ASTNodeDataVariant* p_value{nullptr}; - - static inline const bool _is_defined{[] { - if constexpr (std::is_same_v<IncDecOpT, language::unary_minusminus> or - std::is_same_v<IncDecOpT, language::unary_plusplus> or - std::is_same_v<IncDecOpT, language::post_minusminus> or - std::is_same_v<IncDecOpT, language::post_plusplus>) { - return not std::is_same_v<std::decay_t<DataT>, bool>; - } - return true; - }()}; - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue&) - { - if constexpr (_is_defined) { - m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); - } - } - - IncDecExpressionProcessor(ASTNode& node) : m_node{node} - { - if constexpr (_is_defined) { - Assert(m_node.children[0]->is<language::name>()); - // It is sure at this point that children 0 is a variable name - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); - p_value = &i_symbol->second.value(); - } else { - throw parse_error("invalid operand to unary operator", std::vector{m_node.begin()}); - } - } -}; +#include <node_processor/IncDecExpressionProcessor.hpp> ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) { diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp index 8d70f9f65173548335dd944deeebe837eb379a77..4e59b0dace058546ba18bef7b45ac799050d8f5d 100644 --- a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -1,61 +1,7 @@ #include <ASTNodeUnaryOperatorExpressionBuilder.hpp> #include <PEGGrammar.hpp> -#include <SymbolTable.hpp> -#include <Demangle.hpp> - -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 -{ - ASTNode& m_node; - - PUGS_INLINE ValueT - _eval(const ASTNodeDataVariant& a) - { - return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); - } - - public: - std::string - describe() const - { - return demangle<decltype(*this)>(); - } - - void - execute(ExecUntilBreakOrContinue& exec_policy) - { - m_node.children[0]->execute(exec_policy); - m_node.m_value = this->_eval(m_node.children[0]->m_value); - } - - UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} -}; +#include <node_processor/UnaryExpressionProcessor.hpp> ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n) { diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6ed12a1d33aaea2d71a8dace679ab8fc5a9cb54e --- /dev/null +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -0,0 +1,122 @@ +#ifndef AFFECTATION_PROCESSOR_HPP +#define AFFECTATION_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <SymbolTable.hpp> + +#include <Demangle.hpp> + +template <typename Op> +struct AffOp; + +template <> +struct AffOp<language::eq_op> +{ + template <typename A, typename B> + PUGS_INLINE void + eval(A& a, const B& b) + { + a = b; + } +}; + +template <> +struct AffOp<language::multiplyeq_op> +{ + template <typename A, typename B> + PUGS_INLINE void + eval(A& a, const B& b) + { + a *= b; + } +}; + +template <> +struct AffOp<language::divideeq_op> +{ + template <typename A, typename B> + PUGS_INLINE void + eval(A& a, const B& b) + { + a /= b; + } +}; + +template <> +struct AffOp<language::pluseq_op> +{ + template <typename A, typename B> + PUGS_INLINE void + eval(A& a, const B& b) + { + a += b; + } +}; + +template <> +struct AffOp<language::minuseq_op> +{ + template <typename A, typename B> + PUGS_INLINE void + eval(A& a, const B& b) + { + a -= b; + } +}; + +template <typename OperatorT, typename ValueT, typename DataT> +class AffectationProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + ASTNodeDataVariant* p_value{nullptr}; + + static inline const bool _is_defined{[] { + if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { + if constexpr (not std::is_same_v<OperatorT, language::eq_op>) { + return false; + } + } + return true; + }()}; + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + if constexpr (_is_defined) { + m_node.children[1]->execute(exec_policy); + + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { + if constexpr (std::is_same_v<ValueT, DataT>) { + *p_value = m_node.children[1]->m_value; + } else { + *p_value = static_cast<ValueT>(std::get<DataT>(m_node.children[1]->m_value)); + } + } else { + AffOp<OperatorT>().eval(std::get<ValueT>(*p_value), std::get<DataT>(m_node.children[1]->m_value)); + } + } + } + + AffectationProcessor(ASTNode& node) : m_node{node} + { + if constexpr (_is_defined) { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + p_value = &i_symbol->second.value(); + } else { + throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); + } + } +}; + +#endif // AFFECTATION_PROCESSOR_HPP diff --git a/src/language/node_processor/AffectationToStringProcessor.hpp b/src/language/node_processor/AffectationToStringProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..456a65deb46455c62e1343b5bf95d82bb63df5c5 --- /dev/null +++ b/src/language/node_processor/AffectationToStringProcessor.hpp @@ -0,0 +1,53 @@ +#ifndef AFFECTATION_TO_STRING_PROCESSOR_HPP +#define AFFECTATION_TO_STRING_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <SymbolTable.hpp> + +#include <Demangle.hpp> + +template <typename OperatorT, typename DataT> +class AffectationToStringProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + ASTNodeDataVariant* p_value{nullptr}; + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[1]->execute(exec_policy); + + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { + if constexpr (std::is_same_v<std::string, DataT>) { + *p_value = m_node.children[1]->m_value; + } else { + *p_value = std::to_string(std::get<DataT>(m_node.children[1]->m_value)); + } + } else if constexpr (std::is_same_v<OperatorT, language::pluseq_op>) { + if constexpr (std::is_same_v<std::string, DataT>) { + std::get<std::string>(*p_value) += std::get<std::string>(m_node.children[1]->m_value); + } else { + std::get<std::string>(*p_value) += std::to_string(std::get<DataT>(m_node.children[1]->m_value)); + } + } + } + + AffectationToStringProcessor(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + p_value = &i_symbol->second.value(); + } +}; + +#endif // AFFECTATION_TO_STRING_PROCESSOR_HPP diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6fa8d683b78072194c15984aa8a480f0775c3376 --- /dev/null +++ b/src/language/node_processor/BinaryExpressionProcessor.hpp @@ -0,0 +1,225 @@ +#ifndef BINARY_EXPRESSION_PROCESSOR_HPP +#define BINARY_EXPRESSION_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <Demangle.hpp> + +#include <type_traits> + +template <typename Op> +struct BinOp; + +template <> +struct BinOp<language::and_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a and b) + { + return a and b; + } +}; + +template <> +struct BinOp<language::or_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a or b) + { + return a or b; + } +}; + +template <> +struct BinOp<language::xor_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a xor b) + { + return a xor b; + } +}; + +template <> +struct BinOp<language::eqeq_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a == b) + { + return a == b; + } +}; + +template <> +struct BinOp<language::not_eq_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a != b) + { + return a != b; + } +}; + +template <> +struct BinOp<language::lesser_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a < b) + { + return a < b; + } +}; + +template <> +struct BinOp<language::lesser_or_eq_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a <= b) + { + return a <= b; + } +}; + +template <> +struct BinOp<language::greater_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a > b) + { + return a > b; + } +}; + +template <> +struct BinOp<language::greater_or_eq_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a >= b) + { + return a >= b; + } +}; + +template <> +struct BinOp<language::plus_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a + b) + { + return a + b; + } +}; + +template <> +struct BinOp<language::minus_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a - b) + { + return a - b; + } +}; + +template <> +struct BinOp<language::multiply_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a * b) + { + return a * b; + } +}; + +template <> +struct BinOp<language::divide_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a / b) + { + return a / b; + } +}; + +template <typename BinaryOpT, typename A_DataT, typename B_DataT> +class BinaryExpressionProcessor final : public INodeProcessor +{ + ASTNode& m_node; + + PUGS_INLINE auto + _eval(const ASTNodeDataVariant& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) + { + // Add 'signed' when necessary to avoid signed/unsigned comparison warnings + if constexpr ((not(std::is_same_v<A_DataT, bool> or std::is_same_v<B_DataT, bool>)) and + (std::is_same_v<BinaryOpT, language::and_op> or std::is_same_v<BinaryOpT, language::or_op> or + std::is_same_v<BinaryOpT, language::xor_op> or std::is_same_v<BinaryOpT, language::eqeq_op> or + std::is_same_v<BinaryOpT, language::not_eq_op> or std::is_same_v<BinaryOpT, language::lesser_op> or + std::is_same_v<BinaryOpT, language::lesser_or_eq_op> or + std::is_same_v<BinaryOpT, language::greater_op> or + std::is_same_v<BinaryOpT, language::greater_or_eq_op>) and + (std::is_signed_v<A_DataT> xor std::is_signed_v<B_DataT>)) { + if constexpr (std::is_unsigned_v<A_DataT>) { + using signed_A_DataT = std::make_signed_t<A_DataT>; + const signed_A_DataT signed_a = static_cast<signed_A_DataT>(std::get<A_DataT>(a)); + value = BinOp<BinaryOpT>().eval(signed_a, std::get<B_DataT>(b)); + } else { + using signed_B_DataT = std::make_signed_t<B_DataT>; + const signed_B_DataT signed_b = static_cast<signed_B_DataT>(std::get<B_DataT>(b)); + value = BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), signed_b); + } + } else { + auto result = BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)); + if constexpr (std::is_same_v<decltype(result), int>) { + value = static_cast<int64_t>(result); + } else { + value = result; + } + } + } + + static inline const bool _is_defined{[] { + if constexpr (std::is_same_v<BinaryOpT, language::xor_op>) { + return std::is_same_v<std::decay_t<A_DataT>, std::decay_t<B_DataT>> and std::is_integral_v<std::decay_t<A_DataT>>; + } + return true; + }()}; + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + if constexpr (_is_defined) { + m_node.children[0]->execute(exec_policy); + m_node.children[1]->execute(exec_policy); + + this->_eval(m_node.children[0]->m_value, m_node.children[1]->m_value, m_node.m_value); + } + } + + BinaryExpressionProcessor(ASTNode& node) : m_node{node} + { + if constexpr (not _is_defined) { + throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); + } + } +}; + +#endif // BINARY_EXPRESSION_PROCESSOR_HPP diff --git a/src/language/node_processor/ConcatExpressionProcessor.hpp b/src/language/node_processor/ConcatExpressionProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1f0c80bed669c5efd6b72db0d042e4902f663c30 --- /dev/null +++ b/src/language/node_processor/ConcatExpressionProcessor.hpp @@ -0,0 +1,44 @@ +#ifndef CONCAT_EXPRESSION_PROCESSOR_HPP +#define CONCAT_EXPRESSION_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <Demangle.hpp> + +#include <type_traits> + +template <typename B_DataT> +class ConcatExpressionProcessor final : public INodeProcessor +{ + ASTNode& m_node; + + PUGS_INLINE auto + _eval(const std::string& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) + { + if constexpr (std::is_same_v<B_DataT, std::string>) { + value = a + std::get<B_DataT>(b); + } else { + value = a + std::to_string(std::get<B_DataT>(b)); + } + } + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[0]->execute(exec_policy); + m_node.children[1]->execute(exec_policy); + + this->_eval(std::get<std::string>(m_node.children[0]->m_value), m_node.children[1]->m_value, m_node.m_value); + } + + ConcatExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + +#endif // CONCAT_EXPRESSION_PROCESSOR_HPP diff --git a/src/language/node_processor/IncDecExpressionProcessor.hpp b/src/language/node_processor/IncDecExpressionProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..df85452a26cb74b79ca0929a9b806b63bdd24102 --- /dev/null +++ b/src/language/node_processor/IncDecExpressionProcessor.hpp @@ -0,0 +1,103 @@ +#ifndef INC_DEC_EXPRESSION_PROCESSOR_HPP +#define INC_DEC_EXPRESSION_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <SymbolTable.hpp> + +#include <Demangle.hpp> + +template <typename Op> +struct IncDecOp; + +template <> +struct IncDecOp<language::unary_minusminus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return --a; + } +}; + +template <> +struct IncDecOp<language::unary_plusplus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return ++a; + } +}; + +template <> +struct IncDecOp<language::post_minusminus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return a--; + } +}; + +template <> +struct IncDecOp<language::post_plusplus> +{ + template <typename A> + PUGS_INLINE A + eval(A& a) + { + return a++; + } +}; + +template <typename IncDecOpT, typename ValueT, typename DataT> +class IncDecExpressionProcessor final : public INodeProcessor +{ + ASTNode& m_node; + ASTNodeDataVariant* p_value{nullptr}; + + static inline const bool _is_defined{[] { + if constexpr (std::is_same_v<IncDecOpT, language::unary_minusminus> or + std::is_same_v<IncDecOpT, language::unary_plusplus> or + std::is_same_v<IncDecOpT, language::post_minusminus> or + std::is_same_v<IncDecOpT, language::post_plusplus>) { + return not std::is_same_v<std::decay_t<DataT>, bool>; + } + return true; + }()}; + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue&) + { + if constexpr (_is_defined) { + m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); + } + } + + IncDecExpressionProcessor(ASTNode& node) : m_node{node} + { + if constexpr (_is_defined) { + Assert(m_node.children[0]->is<language::name>()); + // It is sure at this point that children 0 is a variable name + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + p_value = &i_symbol->second.value(); + } else { + throw parse_error("invalid operand to unary operator", std::vector{m_node.begin()}); + } + } +}; + +#endif // INC_DEC_EXPRESSION_PROCESSOR_HPP diff --git a/src/language/node_processor/UnaryExpressionProcessor.hpp b/src/language/node_processor/UnaryExpressionProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61f294e111c01805b95ecb64adeb08e175ea4aa1 --- /dev/null +++ b/src/language/node_processor/UnaryExpressionProcessor.hpp @@ -0,0 +1,63 @@ +#ifndef UNARY_EXPRESSION_PROCESSOR_HPP +#define UNARY_EXPRESSION_PROCESSOR_HPP + +#include <node_processor/INodeProcessor.hpp> + +#include <SymbolTable.hpp> + +#include <Demangle.hpp> + +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 +{ + ASTNode& m_node; + + PUGS_INLINE ValueT + _eval(const ASTNodeDataVariant& a) + { + return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); + } + + public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[0]->execute(exec_policy); + m_node.m_value = this->_eval(m_node.children[0]->m_value); + } + + UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + +#endif // UNARY_EXPRESSION_PROCESSOR_HPP