diff --git a/src/language/ast/ASTNode.hpp b/src/language/ast/ASTNode.hpp index 19e410b72f9f68f12b9ae357fbf88c3a06d53309..5bdf311458db4f2a7d64a55399ce5c699ad428ba 100644 --- a/src/language/ast/ASTNode.hpp +++ b/src/language/ast/ASTNode.hpp @@ -5,6 +5,7 @@ #include <language/node_processor/INodeProcessor.hpp> #include <language/utils/ASTNodeDataType.hpp> #include <language/utils/DataVariant.hpp> +#include <language/utils/ParseError.hpp> #include <utils/PugsAssert.hpp> #include <utils/PugsMacros.hpp> @@ -88,7 +89,12 @@ class ASTNode : public TAO_PEGTL_NAMESPACE::parse_tree::basic_node<ASTNode> { Assert(m_node_processor, "undefined node processor"); if (exec_policy.exec()) { - return m_node_processor->execute(exec_policy); + try { + return m_node_processor->execute(exec_policy); + } + catch (std::bad_variant_access& e) { + throw ParseError("trying to use an uninitialized value while executing expression", std::vector{this->begin()}); + } } else { return {}; } diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 002c0e4ed7aa427a20734689089de590cfd96bc0..99474495200376537c45794024bc4a18b78e7259 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -71,7 +71,7 @@ template <typename OperatorT, typename ValueT, typename DataT> class AffectationExecutor final : public IAffectationExecutor { private: - ValueT& m_lhs; + DataVariant& m_lhs; static inline const bool m_is_defined{[] { if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { @@ -83,7 +83,7 @@ class AffectationExecutor final : public IAffectationExecutor }()}; public: - AffectationExecutor(ASTNode& node, ValueT& lhs) : m_lhs(lhs) + AffectationExecutor(ASTNode& node, DataVariant& lhs) : m_lhs(lhs) { // LCOV_EXCL_START if constexpr (not m_is_defined) { @@ -110,28 +110,29 @@ class AffectationExecutor final : public IAffectationExecutor } } else { if constexpr (std::is_same_v<std::string, DataT>) { - m_lhs += std::get<std::string>(rhs); + std::get<std::string>(m_lhs) += std::get<std::string>(rhs); } else if constexpr (std::is_arithmetic_v<DataT>) { - m_lhs += std::to_string(std::get<DataT>(rhs)); + std::get<std::string>(m_lhs) += std::to_string(std::get<DataT>(rhs)); } else { std::ostringstream os; os << std::get<DataT>(rhs); - m_lhs += os.str(); + std::get<std::string>(m_lhs) += os.str(); } } } else { if constexpr (std::is_same_v<OperatorT, language::eq_op>) { if constexpr (std::is_convertible_v<DataT, ValueT>) { - m_lhs = std::get<DataT>(rhs); + m_lhs = static_cast<ValueT>(std::get<DataT>(rhs)); } else if constexpr (std::is_same_v<DataT, AggregateDataVariant>) { const AggregateDataVariant& v = std::get<AggregateDataVariant>(rhs); if constexpr (is_tiny_vector_v<ValueT>) { - for (size_t i = 0; i < m_lhs.dimension(); ++i) { + ValueT value; + for (size_t i = 0; i < ValueT::Dimension; ++i) { std::visit( [&](auto&& vi) { using Vi_T = std::decay_t<decltype(vi)>; if constexpr (std::is_convertible_v<Vi_T, double>) { - m_lhs[i] = vi; + value[i] = vi; } else { // LCOV_EXCL_START throw UnexpectedError("unexpected rhs type in affectation"); @@ -140,14 +141,16 @@ class AffectationExecutor final : public IAffectationExecutor }, v[i]); } + m_lhs = value; } else if constexpr (is_tiny_matrix_v<ValueT>) { - for (size_t i = 0, l = 0; i < m_lhs.numberOfRows(); ++i) { - for (size_t j = 0; j < m_lhs.numberOfColumns(); ++j, ++l) { + ValueT value; + for (size_t i = 0, l = 0; i < ValueT::NumberOfRows; ++i) { + for (size_t j = 0; j < ValueT::NumberOfColumns; ++j, ++l) { std::visit( [&](auto&& Aij) { using Aij_T = std::decay_t<decltype(Aij)>; if constexpr (std::is_convertible_v<Aij_T, double>) { - m_lhs(i, j) = Aij; + value(i, j) = Aij; } else { // LCOV_EXCL_START throw UnexpectedError("unexpected rhs type in affectation"); @@ -157,6 +160,7 @@ class AffectationExecutor final : public IAffectationExecutor v[l]); } } + m_lhs = value; } else { static_assert(is_tiny_matrix_v<ValueT> or is_tiny_vector_v<ValueT>, "invalid rhs type"); } @@ -190,7 +194,7 @@ class AffectationExecutor final : public IAffectationExecutor throw UnexpectedError("invalid value type"); } } else { - AffOp<OperatorT>().eval(m_lhs, std::get<DataT>(rhs)); + AffOp<OperatorT>().eval(std::get<ValueT>(m_lhs), std::get<DataT>(rhs)); } } } else if (std::is_same_v<OperatorT, language::eq_op>) { @@ -378,12 +382,8 @@ class AffectationProcessor final : public INodeProcessor Assert(found); DataVariant& value = i_symbol->attributes().value(); - if (not std::holds_alternative<ValueT>(value)) { - value = ValueT{}; - } - using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ValueT>(value)); + return std::make_unique<AffectationExecutorT>(lhs_node, value); } else if (lhs_node.is_type<language::subscript_expression>()) { auto& array_expression = *lhs_node.children[0]; Assert(array_expression.is_type<language::name>()); @@ -493,8 +493,12 @@ class AffectationProcessor final : public INodeProcessor DataVariant execute(ExecutionPolicy& exec_policy) { + // try { m_affectation_executor->affect(exec_policy, m_rhs_node.execute(exec_policy)); - + // } + // catch (std::bad_variant_access& e) { + // throw ParseError("trying to uninitialized value", std::vector{m_rhs_node.begin()}); + // } return {}; } @@ -865,7 +869,7 @@ class ListAffectationProcessor final : public INodeProcessor value = ValueT{}; } - m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value))); + m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, value)); } else if (lhs_node.is_type<language::subscript_expression>()) { auto& array_subscript_expression = lhs_node; diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index ac3ba21fe241f8ea9416192fc0ce97f865bb0883..6a8117d570ae7933efd66f5e4d6d8cda906d28e4 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -60,43 +60,51 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder using Ti_Type = std::decay_t<decltype(std::get<I>(t))>; using Vi_Type = std::decay_t<decltype(v_i)>; - if constexpr ((std::is_same_v<Vi_Type, Ti_Type>)) { - std::get<I>(t) = v_i; - } else if constexpr ((std::is_arithmetic_v<Vi_Type>)and(std::is_arithmetic_v<Ti_Type> or - std::is_same_v<Ti_Type, std::string>)) { - std::get<I>(t) = v_i; - } else if constexpr (is_shared_ptr_v<Ti_Type>) { - if constexpr (std::is_same_v<Vi_Type, EmbeddedData>) { - using Ti_handeled_type = typename Ti_Type::element_type; - try { - auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i.get()); - std::get<I>(t) = data_handler.data_ptr(); - } - catch (std::bad_cast&) { - throw UnexpectedError("unexpected argument types while casting: invalid EmbeddedData type, expecting " + - demangle<DataHandler<Ti_handeled_type>>()); + if constexpr (std::is_same_v<Vi_Type, std::monostate>) { + // The argument is used undefined + throw std::bad_variant_access{}; + } else { + if constexpr ((std::is_same_v<Vi_Type, Ti_Type>)) { + std::get<I>(t) = v_i; + } else if constexpr ((std::is_arithmetic_v<Vi_Type>)and(std::is_arithmetic_v<Ti_Type> or + std::is_same_v<Ti_Type, std::string>)) { + std::get<I>(t) = v_i; + } else if constexpr (is_shared_ptr_v<Ti_Type>) { + if constexpr (std::is_same_v<Vi_Type, EmbeddedData>) { + using Ti_handeled_type = typename Ti_Type::element_type; + try { + auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i.get()); + std::get<I>(t) = data_handler.data_ptr(); + } + catch (std::bad_cast&) { + throw UnexpectedError("unexpected argument types while casting: invalid EmbeddedData type, expecting " + + demangle<DataHandler<Ti_handeled_type>>()); + } + } else { + throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData"); } - } else { - throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData"); - } - } else if constexpr (std::is_same_v<Vi_Type, std::vector<EmbeddedData>>) { - if constexpr (is_std_vector_v<Ti_Type>) { - using Ti_value_type = typename Ti_Type::value_type; - if constexpr (is_shared_ptr_v<Ti_value_type>) { - static_assert(is_shared_ptr_v<Ti_value_type>, "expecting shared_ptr"); - - using Ti_handeled_type = typename Ti_value_type::element_type; - std::get<I>(t).resize(v_i.size()); - for (size_t j = 0; j < v_i.size(); ++j) { - try { - auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get()); - std::get<I>(t)[j] = data_handler.data_ptr(); - } - catch (std::bad_cast&) { - throw UnexpectedError( - "unexpected argument types while casting: invalid EmbeddedData type, expecting " + - demangle<DataHandler<Ti_handeled_type>>()); + } else if constexpr (std::is_same_v<Vi_Type, std::vector<EmbeddedData>>) { + if constexpr (is_std_vector_v<Ti_Type>) { + using Ti_value_type = typename Ti_Type::value_type; + if constexpr (is_shared_ptr_v<Ti_value_type>) { + static_assert(is_shared_ptr_v<Ti_value_type>, "expecting shared_ptr"); + + using Ti_handeled_type = typename Ti_value_type::element_type; + std::get<I>(t).resize(v_i.size()); + for (size_t j = 0; j < v_i.size(); ++j) { + try { + auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get()); + std::get<I>(t)[j] = data_handler.data_ptr(); + } + catch (std::bad_cast&) { + throw UnexpectedError( + "unexpected argument types while casting: invalid EmbeddedData type, expecting " + + demangle<DataHandler<Ti_handeled_type>>()); + } } + } else { + throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + + demangle<Ti_Type>() + '"'); } } else { throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + @@ -106,9 +114,6 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + demangle<Ti_Type>() + '"'); } - } else { - throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + - demangle<Ti_Type>() + '"'); } }, v[I]);