From 34d37b4999c881f1d8352dca0d6ac0b29a9bb7bf Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Wed, 13 May 2020 19:48:40 +0200 Subject: [PATCH] Improve numerical function evaluation in C++ - code is now generic (even if more testing remains). - data types are now check accordingly to catch error in a clean way In some cases (generally?) data types can only be checked at runtime. This is the case for instance if function definition depends on the dimension (which is likely to happen in many cases). Thus a special procedure has been developed to indicate where the semantic error occurs at runtime. (this is in some way related to issue #19) --- src/language/ASTNodeDataType.cpp | 10 +- src/language/ASTNodeDataTypeBuilder.cpp | 6 +- .../ASTNodeNaturalConversionChecker.cpp | 8 +- src/language/ASTSymbolTableBuilder.cpp | 2 +- src/language/BuiltinFunctionEmbedder.hpp | 17 +- src/language/FunctionTable.hpp | 14 +- src/language/MeshModule.cpp | 25 +-- src/language/PugsFunctionAdapter.hpp | 161 ++++++++++++++++-- .../BuiltinFunctionProcessor.hpp | 9 +- src/language/utils/ASTNodeDataTypeTraits.hpp | 28 +++ src/language/utils/RuntimeError.hpp | 27 +++ src/utils/Exceptions.cpp | 6 +- ...st_ASTNodeAffectationExpressionBuilder.cpp | 5 +- tests/test_ASTNodeDataTypeBuilder.cpp | 10 +- tests/test_FunctionTable.cpp | 7 +- 15 files changed, 273 insertions(+), 62 deletions(-) create mode 100644 src/language/utils/ASTNodeDataTypeTraits.hpp create mode 100644 src/language/utils/RuntimeError.hpp diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp index 942336835..0c5bdb27a 100644 --- a/src/language/ASTNodeDataType.cpp +++ b/src/language/ASTNodeDataType.cpp @@ -2,6 +2,7 @@ #include <language/ASTNode.hpp> #include <language/PEGGrammar.hpp> +#include <utils/PugsAssert.hpp> ASTNodeDataType getVectorDataType(const ASTNode& type_node) @@ -90,11 +91,14 @@ dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& dat bool isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& target_data_type) { + Assert((data_type != ASTNodeDataType::undefined_t) and (target_data_type != ASTNodeDataType::undefined_t)); if (target_data_type == data_type) { - if (data_type != ASTNodeDataType::type_id_t) { - return true; - } else { + if (data_type == ASTNodeDataType::type_id_t) { return (data_type.typeName() == target_data_type.typeName()); + } else if (data_type == ASTNodeDataType::vector_t) { + return (data_type.dimension() == target_data_type.dimension()); + } else { + return true; } } else if (target_data_type == ASTNodeDataType::bool_t) { return false; diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index a03abf3a9..7ae2758fd 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -207,6 +207,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const for (size_t i = 0; i < nb_parameter_domains; ++i) { simple_type_allocator(*parameters_domain_node.children[i], *parameters_name_node.children[i]); } + parameters_name_node.m_data_type = ASTNodeDataType::list_t; } // build types for compound types @@ -283,6 +284,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } n.m_data_type = ASTNodeDataType::void_t; + return; } else if (n.is_type<language::name>()) { std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table; @@ -442,9 +444,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const n.is_type<language::vector_type>() or n.is_type<language::type_name_id>()) { n.m_data_type = ASTNodeDataType::typename_t; } else if (n.is_type<language::name_list>() or n.is_type<language::lvalue_list>() or - n.is_type<language::function_argument_list>()) { - n.m_data_type = ASTNodeDataType::void_t; - } else if (n.is_type<language::expression_list>()) { + n.is_type<language::function_argument_list>() or n.is_type<language::expression_list>()) { n.m_data_type = ASTNodeDataType::list_t; } } diff --git a/src/language/ASTNodeNaturalConversionChecker.cpp b/src/language/ASTNodeNaturalConversionChecker.cpp index d7027ce1a..e80cd2623 100644 --- a/src/language/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ASTNodeNaturalConversionChecker.cpp @@ -1,6 +1,7 @@ #include <language/ASTNodeNaturalConversionChecker.hpp> #include <language/PEGGrammar.hpp> +#include <utils/Exceptions.hpp> void ASTNodeNaturalConversionChecker::_checkIsNaturalTypeConversion(const ASTNode& node, @@ -12,7 +13,12 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalTypeConversion(const ASTNode& no error_message << "invalid implicit conversion: "; error_message << rang::fgB::red << dataTypeName(data_type) << " -> " << dataTypeName(target_data_type) << rang::fg::reset; - throw parse_error(error_message.str(), node.begin()); + + if ((data_type == ASTNodeDataType::undefined_t) or (target_data_type == ASTNodeDataType::undefined_t)) { + throw UnexpectedError(error_message.str()); + } else { + throw parse_error(error_message.str(), node.begin()); + } } } diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp index f0ed7ece3..07dc16e33 100644 --- a/src/language/ASTSymbolTableBuilder.cpp +++ b/src/language/ASTSymbolTableBuilder.cpp @@ -33,7 +33,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> } size_t function_id = - symbol_table->functionTable().add(FunctionDescriptor{std::move(n.children[1]), std::move(n.children[2])}); + symbol_table->functionTable().add(FunctionDescriptor{symbol, std::move(n.children[1]), std::move(n.children[2])}); i_symbol->attributes().value() = function_id; n.children.resize(1); } else { diff --git a/src/language/BuiltinFunctionEmbedder.hpp b/src/language/BuiltinFunctionEmbedder.hpp index 79eb78e4c..169a1f196 100644 --- a/src/language/BuiltinFunctionEmbedder.hpp +++ b/src/language/BuiltinFunctionEmbedder.hpp @@ -5,6 +5,7 @@ #include <language/DataHandler.hpp> #include <language/DataVariant.hpp> #include <language/FunctionTable.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <utils/Demangle.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsTraits.hpp> @@ -13,22 +14,6 @@ #include <memory> #include <vector> -template <typename T> -inline ASTNodeDataType ast_node_data_type_from = ASTNodeDataType::undefined_t; - -template <> -inline ASTNodeDataType ast_node_data_type_from<void> = ASTNodeDataType::void_t; -template <> -inline ASTNodeDataType ast_node_data_type_from<bool> = ASTNodeDataType::bool_t; -template <> -inline ASTNodeDataType ast_node_data_type_from<int64_t> = ASTNodeDataType::int_t; -template <> -inline ASTNodeDataType ast_node_data_type_from<uint64_t> = ASTNodeDataType::unsigned_int_t; -template <> -inline ASTNodeDataType ast_node_data_type_from<double> = ASTNodeDataType::double_t; -template <> -inline ASTNodeDataType ast_node_data_type_from<std::string> = ASTNodeDataType::string_t; - class IBuiltinFunctionEmbedder { public: diff --git a/src/language/FunctionTable.hpp b/src/language/FunctionTable.hpp index a2b7b95af..af262d196 100644 --- a/src/language/FunctionTable.hpp +++ b/src/language/FunctionTable.hpp @@ -10,10 +10,18 @@ class FunctionDescriptor { + std::string m_name; + std::unique_ptr<ASTNode> m_domain_mapping_node; std::unique_ptr<ASTNode> m_definition_node; public: + const std::string& + name() const + { + return m_name; + } + auto& domainMappingNode() const { @@ -30,8 +38,10 @@ class FunctionDescriptor FunctionDescriptor& operator=(FunctionDescriptor&&) = default; - FunctionDescriptor(std::unique_ptr<ASTNode>&& domain_mapping_node, std::unique_ptr<ASTNode>&& definition_node) - : m_domain_mapping_node(std::move(domain_mapping_node)), m_definition_node(std::move(definition_node)) + FunctionDescriptor(const std::string& name, + std::unique_ptr<ASTNode>&& domain_mapping_node, + std::unique_ptr<ASTNode>&& definition_node) + : m_name{name}, m_domain_mapping_node(std::move(domain_mapping_node)), m_definition_node(std::move(definition_node)) {} FunctionDescriptor(FunctionDescriptor&&) = default; diff --git a/src/language/MeshModule.cpp b/src/language/MeshModule.cpp index cd987e244..b8e64da51 100644 --- a/src/language/MeshModule.cpp +++ b/src/language/MeshModule.cpp @@ -12,14 +12,13 @@ #include <utils/Exceptions.hpp> #include <Kokkos_Core.hpp> + +#include <array> #include <cstdio> template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<IMesh>> = {ASTNodeDataType::type_id_t, "mesh"}; -template <> -inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> = {ASTNodeDataType::function_t}; - template <typename T> class MeshTransformation; template <typename OutputType, typename... InputType> @@ -30,13 +29,16 @@ class MeshTransformation<OutputType(InputType...)> : public PugsFunctionAdapter< public: static inline std::shared_ptr<Mesh<Connectivity<Dimension>>> - transform(FunctionSymbolId function_symbol_id, std::shared_ptr<const IMesh> p_mesh) + transform(const FunctionSymbolId& function_symbol_id, std::shared_ptr<const IMesh> p_mesh) { using MeshType = Mesh<Connectivity<Dimension>>; const MeshType& given_mesh = dynamic_cast<const MeshType&>(*p_mesh); - auto& expression = Adapter::getFunctionExpression(function_symbol_id); - auto convert_result = Adapter::getResultConverter(expression.m_data_type); + const auto flatten_args = Adapter::getFlattenArgs(function_symbol_id); + + auto& expression = Adapter::getFunctionExpression(function_symbol_id); + auto convert_result = Adapter::getResultConverter(expression.m_data_type); + Array<ExecutionPolicy> context_list = Adapter::getContextList(expression); NodeValue<const OutputType> given_xr = given_mesh.xr(); @@ -45,13 +47,14 @@ class MeshTransformation<OutputType(InputType...)> : public PugsFunctionAdapter< using execution_space = typename Kokkos::DefaultExecutionSpace::execution_space; Kokkos::Experimental::UniqueToken<execution_space, Kokkos::Experimental::UniqueTokenScope::Global> tokens; - parallel_for(given_mesh.numberOfNodes(), [=, &expression, &tokens](NodeId r) { + parallel_for(given_mesh.numberOfNodes(), [=, &expression, &flatten_args, &tokens](NodeId r) { const int32_t t = tokens.acquire(); auto& execution_policy = context_list[t]; - Adapter::convertArgs(execution_policy.currentContext(), given_xr[r]); - xr[r] = convert_result(expression.execute(execution_policy)); + Adapter::convertArgs(execution_policy.currentContext(), flatten_args, given_xr[r]); + auto result = expression.execute(execution_policy); + xr[r] = convert_result(std::move(result)); tokens.release(t); }); @@ -80,7 +83,7 @@ MeshModule::MeshModule() FunctionSymbolId>>( std::function<std::shared_ptr<IMesh>(std::shared_ptr<IMesh>, FunctionSymbolId)>{ [](std::shared_ptr<IMesh> p_mesh, - FunctionSymbolId function_id) -> std::shared_ptr<IMesh> { + const FunctionSymbolId& function_id) -> std::shared_ptr<IMesh> { switch (p_mesh->dimension()) { case 1: { using TransformT = TinyVector<1>(TinyVector<1>); @@ -95,7 +98,7 @@ MeshModule::MeshModule() return MeshTransformation<TransformT>::transform(function_id, p_mesh); } default: { - throw NormalError("invalid mesh dimension"); + throw UnexpectedError("invalid mesh dimension"); } } }} diff --git a/src/language/PugsFunctionAdapter.hpp b/src/language/PugsFunctionAdapter.hpp index 262299728..fc2b752cb 100644 --- a/src/language/PugsFunctionAdapter.hpp +++ b/src/language/PugsFunctionAdapter.hpp @@ -2,38 +2,177 @@ #define PUGS_FUNCTION_ADAPTER_HPP #include <language/ASTNode.hpp> +#include <language/ASTNodeDataType.hpp> #include <language/SymbolTable.hpp> #include <language/node_processor/ExecutionPolicy.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> +#include <language/utils/RuntimeError.hpp> #include <utils/Array.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsMacros.hpp> #include <Kokkos_Core.hpp> +#include <array> + template <typename T> class PugsFunctionAdapter; template <typename OutputType, typename... InputType> class PugsFunctionAdapter<OutputType(InputType...)> { + protected: + using FlattenList = std::array<int32_t, sizeof...(InputType)>; + private: + template <typename T> + PUGS_INLINE static void + _flattenArgT(const T&, ExecutionPolicy::Context&, size_t&) + { + throw UnexpectedError("cannot flatten type " + demangle<T>()); + } + + template <size_t N> + PUGS_INLINE static void + _flattenArgT(const TinyVector<N>& t, ExecutionPolicy::Context& context, size_t& i_context) + { + for (size_t i = 0; i < N; ++i) { + context[i_context + i] = t[i]; + } + } + template <typename T, typename... Args> PUGS_INLINE static void - _convertArgs(const Args&&... args, const T& t, ExecutionPolicy::Context& context) + _convertArgs(const T& t, + const Args&&... args, + ExecutionPolicy::Context& context, + const FlattenList& flatten, + size_t i_context) { - context[sizeof...(args)] = t; + if (flatten[sizeof...(args)]) { + _flattenArgT(t, context, i_context); + } else { + context[i_context++] = t; + } if constexpr (sizeof...(args) > 0) { - _convertArgs(std::forward<Args>(args)..., context); + _convertArgs(std::forward<Args>(args)..., context, flatten, i_context); } } + template <typename Arg, typename... RemainingArgs> + [[nodiscard]] PUGS_INLINE static bool + _checkValidArgumentDataType(const ASTNode& input_expression, FlattenList& flatten_list) noexcept + { + constexpr const ASTNodeDataType& expected_input_data_type = ast_node_data_type_from<Arg>; + const ASTNodeDataType& input_data_type = input_expression.m_data_type; + + constexpr size_t i_argument = sizeof...(InputType) - 1 - sizeof...(RemainingArgs); + flatten_list[i_argument] = false; + + if (not isNaturalConversion(expected_input_data_type, input_data_type)) { + if ((expected_input_data_type == ASTNodeDataType::vector_t) and (input_data_type == ASTNodeDataType::list_t)) { + flatten_list[i_argument] = true; + if (expected_input_data_type.dimension() != input_expression.children.size()) { + return false; + } else { + for (const auto& child : input_expression.children) { + const ASTNodeDataType& data_type = child->m_data_type; + if (not isNaturalConversion(ast_node_data_type_from<double>, data_type)) { + return false; + } + } + } + } else { + return false; + } + } + if constexpr (sizeof...(RemainingArgs) == 0) { + return true; + } else { + return false; + } + } + + [[nodiscard]] PUGS_INLINE static bool + _checkValidInputDataType(const ASTNode& input_expression, FlattenList& flatten_list) noexcept + { + return _checkValidArgumentDataType<InputType...>(input_expression, flatten_list); + } + + [[nodiscard]] PUGS_INLINE static bool + _checkValidOutputDataType(const ASTNode& return_expression) noexcept + { + constexpr const ASTNodeDataType& expected_return_data_type = ast_node_data_type_from<OutputType>; + const ASTNodeDataType& return_data_type = return_expression.m_data_type; + + if (not isNaturalConversion(return_data_type, expected_return_data_type)) { + if (expected_return_data_type == ASTNodeDataType::vector_t) { + if (return_data_type == ASTNodeDataType::list_t) { + if (expected_return_data_type.dimension() != return_expression.children.size()) { + return false; + } else { + for (const auto& child : return_expression.children) { + const ASTNodeDataType& data_type = child->m_data_type; + if (not isNaturalConversion(data_type, ast_node_data_type_from<double>)) { + return false; + } + } + } + } + } + } + return true; + } + + template <typename Arg, typename... RemainingArgs> + [[nodiscard]] PUGS_INLINE static std::string + _getCompoundTypeName() + { + if constexpr (sizeof...(RemainingArgs) > 0) { + return dataTypeName(ast_node_data_type_from<Arg>) + _getCompoundTypeName<RemainingArgs...>(); + } else { + return dataTypeName(ast_node_data_type_from<Arg>); + } + } + + [[nodiscard]] static std::string + _getInputDataTypeName() + { + return _getCompoundTypeName<InputType...>(); + } + protected: - PUGS_INLINE static auto& - getFunctionExpression(FunctionSymbolId function_symbol_id) + [[nodiscard]] PUGS_INLINE static FlattenList + getFlattenArgs(const FunctionSymbolId& function_symbol_id) + { + auto& function = function_symbol_id.symbolTable().functionTable()[function_symbol_id.id()]; + + FlattenList flatten_list; + + bool has_valid_input = _checkValidInputDataType(*function.definitionNode().children[0], flatten_list); + bool has_valid_output = _checkValidOutputDataType(*function.definitionNode().children[1]); + + if (not(has_valid_input and has_valid_output)) { + std::ostringstream error_message; + error_message << "invalid function type" << rang::style::reset << "\nnote: expecting " << rang::fgB::yellow + << _getInputDataTypeName() << " -> " << dataTypeName(ast_node_data_type_from<OutputType>) + << rang::style::reset << '\n' + << "note: provided function " << rang::fgB::magenta << function.name() << ": " + << function.domainMappingNode().string() << rang::style::reset << std::ends; + throw RuntimeError(error_message.str()); + } + + return flatten_list; + } + + [[nodiscard]] PUGS_INLINE static auto& + getFunctionExpression(const FunctionSymbolId& function_symbol_id) { - return *function_symbol_id.symbolTable().functionTable()[function_symbol_id.id()].definitionNode().children[1]; + auto& function = function_symbol_id.symbolTable().functionTable()[function_symbol_id.id()]; + + return *function.definitionNode().children[1]; } - PUGS_INLINE static auto + [[nodiscard]] PUGS_INLINE static auto getContextList(const ASTNode& expression) { Array<ExecutionPolicy> context_list(Kokkos::DefaultExecutionSpace::impl_thread_pool_size()); @@ -50,14 +189,14 @@ class PugsFunctionAdapter<OutputType(InputType...)> template <typename... Args> PUGS_INLINE static void - convertArgs(ExecutionPolicy::Context& context, const Args&... args) + convertArgs(ExecutionPolicy::Context& context, const FlattenList& flatten, const Args&... args) { static_assert(std::is_same_v<std::tuple<InputType...>, std::tuple<Args...>>, "unexpected input type"); - _convertArgs(args..., context); + _convertArgs(args..., context, flatten, 0); } - PUGS_INLINE static std::function<OutputType(DataVariant&& result)> - getResultConverter(ASTNodeDataType data_type) + [[nodiscard]] PUGS_INLINE static std::function<OutputType(DataVariant&& result)> + getResultConverter(const ASTNodeDataType& data_type) { switch (data_type) { case ASTNodeDataType::list_t: { diff --git a/src/language/node_processor/BuiltinFunctionProcessor.hpp b/src/language/node_processor/BuiltinFunctionProcessor.hpp index 3a4b48503..a2c32d598 100644 --- a/src/language/node_processor/BuiltinFunctionProcessor.hpp +++ b/src/language/node_processor/BuiltinFunctionProcessor.hpp @@ -5,6 +5,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/FunctionArgumentConverter.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/RuntimeError.hpp> class BuiltinFunctionExpressionProcessor final : public INodeProcessor { @@ -59,8 +60,12 @@ class BuiltinFunctionProcessor : public INodeProcessor m_argument_converters[i]->convert(context_exec_policy, std::move(argument_values[i])); } } - - return m_function_expression_processor->execute(context_exec_policy); + try { + return m_function_expression_processor->execute(context_exec_policy); + } + catch (RuntimeError& e) { + throw parse_error(e.message(), {m_argument_node.begin()}); + } } BuiltinFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {} diff --git a/src/language/utils/ASTNodeDataTypeTraits.hpp b/src/language/utils/ASTNodeDataTypeTraits.hpp new file mode 100644 index 000000000..14435925d --- /dev/null +++ b/src/language/utils/ASTNodeDataTypeTraits.hpp @@ -0,0 +1,28 @@ +#ifndef AST_NODE_DATA_TYPE_TRAITS_H +#define AST_NODE_DATA_TYPE_TRAITS_H + +#include <algebra/TinyVector.hpp> +#include <language/ASTNodeDataType.hpp> +#include <language/FunctionSymbolId.hpp> + +template <typename T> +inline ASTNodeDataType ast_node_data_type_from = ASTNodeDataType::undefined_t; + +template <> +inline ASTNodeDataType ast_node_data_type_from<void> = ASTNodeDataType::void_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<bool> = ASTNodeDataType::bool_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<int64_t> = ASTNodeDataType::int_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<uint64_t> = ASTNodeDataType::unsigned_int_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<double> = ASTNodeDataType::double_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<std::string> = ASTNodeDataType::string_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> = ASTNodeDataType::function_t; +template <size_t N> +inline ASTNodeDataType ast_node_data_type_from<TinyVector<N>> = {ASTNodeDataType::vector_t, N}; + +#endif // AST_NODE_DATA_TYPE_TRAITS_H diff --git a/src/language/utils/RuntimeError.hpp b/src/language/utils/RuntimeError.hpp new file mode 100644 index 000000000..b5e2c11a5 --- /dev/null +++ b/src/language/utils/RuntimeError.hpp @@ -0,0 +1,27 @@ +#ifndef RUNTIME_ERROR_HPP +#define RUNTIME_ERROR_HPP + +#include <string> + +class RuntimeError +{ + private: + std::string m_message; + + public: + const std::string& + message() const + { + return m_message; + } + + RuntimeError(const std::string& message) : m_message{message} {} + + RuntimeError() = delete; + RuntimeError(const RuntimeError&) = delete; + RuntimeError(RuntimeError&&) = delete; + + ~RuntimeError() = default; +}; + +#endif // RUNTIME_ERROR_HPP diff --git a/src/utils/Exceptions.cpp b/src/utils/Exceptions.cpp index 85534848f..1bf598b7c 100644 --- a/src/utils/Exceptions.cpp +++ b/src/utils/Exceptions.cpp @@ -10,7 +10,7 @@ RawError::RawError(std::string_view error_msg) : IExitError(std::string{error_ms NormalError::NormalError(std::string_view error_msg) : IExitError([&] { std::ostringstream os; - os << rang::style::bold << "Error:" << rang::style::reset << ' ' << error_msg; + os << rang::style::bold << "error:" << rang::style::reset << ' ' << error_msg; return os.str(); }()) {} @@ -18,7 +18,7 @@ NormalError::NormalError(std::string_view error_msg) UnexpectedError::UnexpectedError(std::string_view error_msg) : IBacktraceError([&] { std::ostringstream os; - os << rang::fgB::red << "Unexpected error:" << rang::style::reset << ' ' << error_msg; + os << rang::fgB::red << "unexpected error:" << rang::style::reset << ' ' << error_msg; return os.str(); }()) {} @@ -26,7 +26,7 @@ UnexpectedError::UnexpectedError(std::string_view error_msg) NotImplementedError::NotImplementedError(std::string_view error_msg) : IBacktraceError([&] { std::ostringstream os; - os << rang::fgB::yellow << "Not implemented yet:" << rang::style::reset << ' ' << error_msg; + os << rang::fgB::yellow << "not implemented yet:" << rang::style::reset << ' ' << error_msg; return os.str(); }()) {} diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp index dce1fac55..9f4c26d7f 100644 --- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp @@ -1123,7 +1123,8 @@ let x : R, x=1; x/=2.3; ast->children.emplace_back(std::make_unique<ASTNode>()); ast->children.emplace_back(std::make_unique<ASTNode>()); - REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, "invalid implicit conversion: undefined -> Z"); + REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, + "unexpected error: invalid implicit conversion: undefined -> Z"); } SECTION("Invalid string rhs") @@ -1135,7 +1136,7 @@ let x : R, x=1; x/=2.3; ast->children.emplace_back(std::make_unique<ASTNode>()); ast->children.emplace_back(std::make_unique<ASTNode>()); REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, - "invalid implicit conversion: undefined -> string"); + "unexpected error: invalid implicit conversion: undefined -> string"); } SECTION("Invalid string affectation operator") diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 0d5a33060..3f5f361f5 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -241,7 +241,7 @@ let (x,b,n,s) : R*B*N*string; std::string_view result = R"( (root:void) `-(language::var_declaration:typename) - +-(language::name_list:void) + +-(language::name_list:list) | +-(language::name:x:R) | +-(language::name:b:B) | +-(language::name:n:N) @@ -663,7 +663,7 @@ let diff : R, diff = substract(3,2); +-(language::name:diff:R) `-(language::function_evaluation:R) +-(language::name:substract:function) - `-(language::function_argument_list:void) + `-(language::function_argument_list:list) +-(language::integer:3:Z) `-(language::integer:2:Z) )"; @@ -758,7 +758,7 @@ let s : string, s = cat("foo", "bar"); +-(language::name:s:string) `-(language::function_evaluation:string) +-(language::name:cat:function) - `-(language::function_argument_list:void) + `-(language::function_argument_list:list) +-(language::literal:"foo":string) `-(language::literal:"bar":string) )"; @@ -778,13 +778,13 @@ let (x,x2) : R*R, (x,x2) = x_x2(3); +-(language::fct_declaration:void) | `-(language::name:x_x2:function) `-(language::var_declaration:typename) - +-(language::name_list:void) + +-(language::name_list:list) | +-(language::name:x:R) | `-(language::name:x2:R) +-(language::type_expression:typename) | +-(language::R_set:typename) | `-(language::R_set:typename) - +-(language::name_list:void) + +-(language::name_list:list) | +-(language::name:x:R) | `-(language::name:x2:R) `-(language::function_evaluation:typename) diff --git a/tests/test_FunctionTable.cpp b/tests/test_FunctionTable.cpp index d056f0727..5c9d26f39 100644 --- a/tests/test_FunctionTable.cpp +++ b/tests/test_FunctionTable.cpp @@ -15,7 +15,7 @@ TEST_CASE("FunctionTable", "[language]") std::unique_ptr definition_node = std::make_unique<ASTNode>(); definition_node->m_data_type = ASTNodeDataType::double_t; - FunctionDescriptor f{std::move(domain_mapping_node), std::move(definition_node)}; + FunctionDescriptor f{"f", std::move(domain_mapping_node), std::move(definition_node)}; REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t); REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t); @@ -68,7 +68,8 @@ TEST_CASE("FunctionTable", "[language]") std::unique_ptr definition_node = std::make_unique<ASTNode>(); definition_node->m_data_type = ASTNodeDataType::double_t; - size_t function_id = table.add(FunctionDescriptor{std::move(domain_mapping_node), std::move(definition_node)}); + size_t function_id = + table.add(FunctionDescriptor{"function", std::move(domain_mapping_node), std::move(definition_node)}); REQUIRE(domain_mapping_node == nullptr); REQUIRE(definition_node == nullptr); @@ -80,10 +81,12 @@ TEST_CASE("FunctionTable", "[language]") REQUIRE(const_table.size() == 1); auto& f = table[function_id]; + REQUIRE(f.name() == "function"); REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t); REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t); const auto& const_f = const_table[function_id]; + REQUIRE(const_f.name() == "function"); REQUIRE(const_f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t); REQUIRE(const_f.definitionNode().m_data_type == ASTNodeDataType::double_t); -- GitLab