From e9e282980380786fbd44f33fa48cb4b1bc041389 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Thu, 19 Aug 2021 11:59:01 +0200 Subject: [PATCH] Add ofstream support within the language On the way rewrite OStream handling: `<<` and `>>` are now treated as standard binary operators. This change required the introduction of "global" variable created by module loading since now: cout, cerr and clog are no more keywords but variables of type `ostream`. --- src/language/PEGGrammar.hpp | 14 +-- src/language/ast/ASTBuilder.cpp | 23 +--- ...ASTNodeBinaryOperatorExpressionBuilder.cpp | 5 + src/language/ast/ASTNodeDataTypeBuilder.cpp | 9 +- src/language/ast/ASTNodeExpressionBuilder.cpp | 8 +- src/language/modules/BuiltinModule.cpp | 12 +++ src/language/modules/BuiltinModule.hpp | 10 ++ src/language/modules/CoreModule.cpp | 21 ++++ src/language/modules/IModule.hpp | 6 ++ src/language/modules/ModuleRepository.cpp | 32 ++++++ src/language/modules/ModuleRepository.hpp | 5 + .../BinaryExpressionProcessor.hpp | 31 +++++- .../node_processor/OStreamProcessor.hpp | 38 ------- src/language/utils/BinaryOperatorMangler.hpp | 7 ++ .../utils/BinaryOperatorRegisterForB.cpp | 13 +++ .../utils/BinaryOperatorRegisterForB.hpp | 1 + .../utils/BinaryOperatorRegisterForN.cpp | 13 +++ .../utils/BinaryOperatorRegisterForN.hpp | 1 + .../utils/BinaryOperatorRegisterForR.cpp | 13 +++ .../utils/BinaryOperatorRegisterForR.hpp | 1 + .../utils/BinaryOperatorRegisterForRn.cpp | 17 +++ .../utils/BinaryOperatorRegisterForRn.hpp | 3 +- .../utils/BinaryOperatorRegisterForRnxn.cpp | 17 +++ .../utils/BinaryOperatorRegisterForRnxn.hpp | 3 +- .../utils/BinaryOperatorRegisterForString.cpp | 14 +++ .../utils/BinaryOperatorRegisterForString.hpp | 2 + .../utils/BinaryOperatorRegisterForZ.cpp | 13 +++ .../utils/BinaryOperatorRegisterForZ.hpp | 1 + src/language/utils/CMakeLists.txt | 1 + src/language/utils/OFStream.cpp | 12 +++ src/language/utils/OFStream.hpp | 20 ++++ src/language/utils/OStream.hpp | 36 +++++++ src/language/utils/ValueDescriptor.hpp | 36 +++++++ tests/CMakeLists.txt | 1 - tests/test_ASTBuilder.cpp | 24 +++-- tests/test_ASTNodeDataTypeBuilder.cpp | 15 ++- tests/test_ASTNodeExpressionBuilder.cpp | 6 +- tests/test_ASTNodeTypeCleaner.cpp | 9 +- tests/test_OStreamProcessor.cpp | 100 ------------------ 39 files changed, 391 insertions(+), 202 deletions(-) delete mode 100644 src/language/node_processor/OStreamProcessor.hpp create mode 100644 src/language/utils/OFStream.cpp create mode 100644 src/language/utils/OFStream.hpp create mode 100644 src/language/utils/OStream.hpp create mode 100644 src/language/utils/ValueDescriptor.hpp delete mode 100644 tests/test_OStreamProcessor.cpp diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index a3ad03428..723d9a710 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -126,11 +126,7 @@ struct BREAK : seq < break_kw, ignored > {}; struct continue_kw : TAO_PEGTL_KEYWORD("continue") {}; struct CONTINUE : seq < continue_kw, ignored > {}; -struct cout_kw : TAO_PEGTL_KEYWORD("cout") {}; -struct cerr_kw : TAO_PEGTL_KEYWORD("cerr") {}; -struct clog_kw : TAO_PEGTL_KEYWORD("clog") {}; - -struct keyword : sor < basic_type, import_kw, true_kw, false_kw, let_kw, do_kw, while_kw, for_kw, if_kw, else_kw, and_kw, or_kw, xor_kw, not_kw, break_kw, continue_kw, cout_kw, cerr_kw, clog_kw > {}; +struct keyword : sor < basic_type, import_kw, true_kw, false_kw, let_kw, do_kw, while_kw, for_kw, if_kw, else_kw, and_kw, or_kw, xor_kw, not_kw, break_kw, continue_kw> {}; struct identifier_minus_keyword : minus< identifier, keyword > {}; @@ -218,7 +214,9 @@ struct product : list_must< unary_expression, sor< multiply_op, divide_op > > {} struct sum : list_must< product, sor< plus_op, minus_op > > {}; -struct compare : list_must<sum, sor< lesser_or_eq_op, greater_or_eq_op, lesser_op, greater_op > >{}; +struct shift : list_must<sum, sor< shift_left_op, shift_right_op > >{}; + +struct compare : list_must<shift, sor< lesser_or_eq_op, greater_or_eq_op, lesser_op, greater_op > >{}; struct equality : list_must< compare, sor< eqeq_op, not_eq_op > >{}; @@ -289,15 +287,11 @@ struct for_statement_block; struct for_statement : if_must< FOR, open_parent, for_init, SEMICOL, for_test, SEMICOL, for_post, close_parent, for_statement_block >{}; -struct ostream_object : seq< sor< cout_kw, cerr_kw, clog_kw >, ignored >{}; -struct ostream_statement : seq< ostream_object, star< if_must< shift_left_op, expression, ignored > > >{}; - struct instruction : sor<if_statement, if_must<do_while_statement, semicol>, while_statement, for_statement, - if_must< ostream_statement, semicol >, if_must< BREAK, semicol >, if_must< CONTINUE, semicol >, block, diff --git a/src/language/ast/ASTBuilder.cpp b/src/language/ast/ASTBuilder.cpp index 0c433bbfd..a4dc8c822 100644 --- a/src/language/ast/ASTBuilder.cpp +++ b/src/language/ast/ASTBuilder.cpp @@ -214,20 +214,6 @@ struct ASTBuilder::simplify_for_post : TAO_PEGTL_NAMESPACE::parse_tree::apply<AS } }; -struct ASTBuilder::simplify_stream_statement - : TAO_PEGTL_NAMESPACE::parse_tree::apply<ASTBuilder::simplify_stream_statement> -{ - template <typename... States> - static void - transform(std::unique_ptr<ASTNode>& n, States&&...) - { - for (size_t i = 1; i < n->children.size(); ++i) { - n->children[0]->children.emplace_back(std::move(n->children[i])); - } - n = std::move(n->children[0]); - } -}; - template <typename Rule> using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< Rule, @@ -248,9 +234,6 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< language::vector_type, language::matrix_type, language::string_type, - language::cout_kw, - language::cerr_kw, - language::clog_kw, language::var_declaration, language::fct_declaration, language::type_mapping, @@ -269,6 +252,7 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< language::equality, language::compare, language::sum, + language::shift, language::product, language::affectation, language::expression>, @@ -282,6 +266,8 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< language::name_subscript_expression>, TAO_PEGTL_NAMESPACE::parse_tree::remove_content::on<language::plus_op, language::minus_op, + language::shift_left_op, + language::shift_right_op, language::multiply_op, language::divide_op, language::lesser_op, @@ -308,8 +294,7 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< ASTBuilder::simplify_statement_block::on<language::statement_block>, ASTBuilder::simplify_for_init::on<language::for_init>, ASTBuilder::simplify_for_test::on<language::for_test>, - ASTBuilder::simplify_for_post::on<language::for_post>, - ASTBuilder::simplify_stream_statement::on<language::ostream_statement>>; + ASTBuilder::simplify_for_post::on<language::for_post>>; template <typename InputT> std::unique_ptr<ASTNode> diff --git a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp index b6904220a..c96b8799e 100644 --- a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp @@ -22,6 +22,11 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A } else if (n.is_type<language::minus_op>()) { return binaryOperatorMangler<language::minus_op>(lhs_data_type, rhs_data_type); + } else if (n.is_type<language::shift_left_op>()) { + return binaryOperatorMangler<language::shift_left_op>(lhs_data_type, rhs_data_type); + } else if (n.is_type<language::shift_right_op>()) { + return binaryOperatorMangler<language::shift_right_op>(lhs_data_type, rhs_data_type); + } else if (n.is_type<language::or_op>()) { return binaryOperatorMangler<language::or_op>(lhs_data_type, rhs_data_type); } else if (n.is_type<language::and_op>()) { diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index eb307e2c1..cb9e479df 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -161,8 +161,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } else if (n.is_type<language::literal>()) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>(); - } else if (n.is_type<language::cout_kw>() or n.is_type<language::cerr_kw>() or n.is_type<language::clog_kw>()) { - n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>(); } else if (n.is_type<language::var_declaration>()) { auto& name_node = *(n.children[0]); auto& type_node = *(n.children[1]); @@ -460,6 +458,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } } else if (n.is_type<language::plus_op>() or n.is_type<language::minus_op>() or n.is_type<language::multiply_op>() or n.is_type<language::divide_op>() or + n.is_type<language::shift_left_op>() or n.is_type<language::shift_right_op>() or n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or n.is_type<language::greater_op>() or n.is_type<language::greater_or_eq_op>() or n.is_type<language::eqeq_op>() or n.is_type<language::not_eq_op>() or n.is_type<language::and_op>() or @@ -482,6 +481,12 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const return operator_repository.getBinaryOperatorValueType( binaryOperatorMangler<language::divide_op>(type_0, type_1)); + } else if (n.is_type<language::shift_left_op>()) { + return operator_repository.getBinaryOperatorValueType( + binaryOperatorMangler<language::shift_left_op>(type_0, type_1)); + } else if (n.is_type<language::shift_right_op>()) { + return operator_repository.getBinaryOperatorValueType( + binaryOperatorMangler<language::shift_right_op>(type_0, type_1)); } else if (n.is_type<language::lesser_op>()) { return operator_repository.getBinaryOperatorValueType( binaryOperatorMangler<language::lesser_op>(type_0, type_1)); diff --git a/src/language/ast/ASTNodeExpressionBuilder.cpp b/src/language/ast/ASTNodeExpressionBuilder.cpp index d9b3b4e43..bbbcda43e 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeExpressionBuilder.cpp @@ -18,7 +18,6 @@ #include <language/node_processor/IfProcessor.hpp> #include <language/node_processor/LocalNameProcessor.hpp> #include <language/node_processor/NameProcessor.hpp> -#include <language/node_processor/OStreamProcessor.hpp> #include <language/node_processor/TupleToTinyVectorProcessor.hpp> #include <language/node_processor/TupleToVectorProcessor.hpp> #include <language/node_processor/ValueProcessor.hpp> @@ -105,17 +104,12 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) } else if (n.is_type<language::multiply_op>() or n.is_type<language::divide_op>() or n.is_type<language::plus_op>() or n.is_type<language::minus_op>() or n.is_type<language::or_op>() or n.is_type<language::and_op>() or n.is_type<language::xor_op>() or n.is_type<language::greater_op>() or + n.is_type<language::shift_left_op>() or n.is_type<language::shift_right_op>() or n.is_type<language::greater_or_eq_op>() or n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or n.is_type<language::eqeq_op>() or n.is_type<language::not_eq_op>()) { ASTNodeBinaryOperatorExpressionBuilder{n}; - } else if (n.is_type<language::cout_kw>()) { - n.m_node_processor = std::make_unique<OStreamProcessor>(n, std::cout); - } else if (n.is_type<language::cerr_kw>()) { - n.m_node_processor = std::make_unique<OStreamProcessor>(n, std::cerr); - } else if (n.is_type<language::clog_kw>()) { - n.m_node_processor = std::make_unique<OStreamProcessor>(n, std::clog); } else if (n.is_type<language::if_statement>()) { n.m_node_processor = std::make_unique<IfProcessor>(n); } else if (n.is_type<language::statement_block>()) { diff --git a/src/language/modules/BuiltinModule.cpp b/src/language/modules/BuiltinModule.cpp index 98d8f71c6..cc76f78f7 100644 --- a/src/language/modules/BuiltinModule.cpp +++ b/src/language/modules/BuiltinModule.cpp @@ -2,6 +2,7 @@ #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/TypeDescriptor.hpp> +#include <language/utils/ValueDescriptor.hpp> #include <utils/Exceptions.hpp> #include <memory> @@ -44,6 +45,17 @@ BuiltinModule::_addBuiltinFunction(const std::string& name, } } +void +BuiltinModule::_addNameValue(const std::string& name, const ASTNodeDataType& type, const DataVariant& data) +{ + std::shared_ptr value_descriptor = std::make_shared<ValueDescriptor>(type, data); + + auto [i_type, success] = m_name_value_map.insert(std::make_pair(name, value_descriptor)); + if (not success) { + throw NormalError("variable '" + name + "' cannot be added!\n"); + } +} + void BuiltinModule::_addTypeDescriptor(const ASTNodeDataType& ast_node_data_type) { diff --git a/src/language/modules/BuiltinModule.hpp b/src/language/modules/BuiltinModule.hpp index 2be1d1625..3dd9ad1db 100644 --- a/src/language/modules/BuiltinModule.hpp +++ b/src/language/modules/BuiltinModule.hpp @@ -6,18 +6,22 @@ class IBuiltinFunctionEmbedder; class TypeDescriptor; +class ValueDescriptor; class BuiltinModule : public IModule { protected: NameBuiltinFunctionMap m_name_builtin_function_map; NameTypeMap m_name_type_map; + NameValueMap m_name_value_map; void _addBuiltinFunction(const std::string& name, std::shared_ptr<IBuiltinFunctionEmbedder> builtin_function_embedder); void _addTypeDescriptor(const ASTNodeDataType& type); + void _addNameValue(const std::string& name, const ASTNodeDataType& type, const DataVariant& data); + const bool m_is_mandatory; public: @@ -39,6 +43,12 @@ class BuiltinModule : public IModule return m_name_type_map; } + const NameValueMap& + getNameValueMap() const final + { + return m_name_value_map; + } + BuiltinModule(bool is_mandatory = false); ~BuiltinModule() = default; diff --git a/src/language/modules/CoreModule.cpp b/src/language/modules/CoreModule.cpp index 1cc699455..9b70144e8 100644 --- a/src/language/modules/CoreModule.cpp +++ b/src/language/modules/CoreModule.cpp @@ -22,6 +22,8 @@ #include <language/utils/IncDecOperatorRegisterForN.hpp> #include <language/utils/IncDecOperatorRegisterForR.hpp> #include <language/utils/IncDecOperatorRegisterForZ.hpp> +#include <language/utils/OFStream.hpp> +#include <language/utils/OStream.hpp> #include <language/utils/UnaryOperatorRegisterForB.hpp> #include <language/utils/UnaryOperatorRegisterForN.hpp> #include <language/utils/UnaryOperatorRegisterForR.hpp> @@ -83,6 +85,25 @@ CoreModule::CoreModule() : BuiltinModule(true) []() { RandomEngine::instance().resetRandomSeed(); } )); + + this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const OStream>>); + + this + ->_addBuiltinFunction("ofstream", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const OStream>(const std::string&)>>( + + [](const std::string& filename) { return std::make_shared<const OFStream>(filename); } + + )); + + this->_addNameValue("cout", ast_node_data_type_from<std::shared_ptr<const OStream>>, + EmbeddedData{std::make_shared<DataHandler<const OStream>>(std::make_shared<OStream>(std::cout))}); + + this->_addNameValue("cerr", ast_node_data_type_from<std::shared_ptr<const OStream>>, + EmbeddedData{std::make_shared<DataHandler<const OStream>>(std::make_shared<OStream>(std::cerr))}); + + this->_addNameValue("clog", ast_node_data_type_from<std::shared_ptr<const OStream>>, + EmbeddedData{std::make_shared<DataHandler<const OStream>>(std::make_shared<OStream>(std::clog))}); } void diff --git a/src/language/modules/IModule.hpp b/src/language/modules/IModule.hpp index ceb3fd3df..04aefbe91 100644 --- a/src/language/modules/IModule.hpp +++ b/src/language/modules/IModule.hpp @@ -1,6 +1,8 @@ #ifndef IMODULE_HPP #define IMODULE_HPP +#include <language/utils/DataVariant.hpp> + #include <memory> #include <string> #include <string_view> @@ -8,12 +10,14 @@ class IBuiltinFunctionEmbedder; class TypeDescriptor; +class ValueDescriptor; class IModule { public: using NameBuiltinFunctionMap = std::unordered_map<std::string, std::shared_ptr<IBuiltinFunctionEmbedder>>; using NameTypeMap = std::unordered_map<std::string, std::shared_ptr<TypeDescriptor>>; + using NameValueMap = std::unordered_map<std::string, std::shared_ptr<ValueDescriptor>>; IModule() = default; IModule(IModule&&) = default; @@ -25,6 +29,8 @@ class IModule virtual const NameTypeMap& getNameTypeMap() const = 0; + virtual const NameValueMap& getNameValueMap() const = 0; + virtual void registerOperators() const = 0; virtual std::string_view name() const = 0; diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp index e516ab800..71a1368b9 100644 --- a/src/language/modules/ModuleRepository.cpp +++ b/src/language/modules/ModuleRepository.cpp @@ -13,6 +13,8 @@ #include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> #include <language/utils/TypeDescriptor.hpp> +#include <language/utils/ValueDescriptor.hpp> + #include <utils/PugsAssert.hpp> #include <algorithm> @@ -85,6 +87,28 @@ ModuleRepository::_populateEmbedderTableT(const ASTNode& module_node, } } +void +ModuleRepository::_populateSymbolTable(const ASTNode& module_node, + const std::string& module_name, + const IModule::NameValueMap& name_value_descriptor_map, + SymbolTable& symbol_table) +{ + for (auto [symbol_name, value_descriptor] : name_value_descriptor_map) { + auto [i_symbol, success] = symbol_table.add(symbol_name, module_node.begin()); + + if (not success) { + std::ostringstream error_message; + error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name + << "', it is already defined!"; + throw ParseError(error_message.str(), module_node.begin()); + } + + i_symbol->attributes().setDataType(value_descriptor->type()); + i_symbol->attributes().setIsInitialized(); + i_symbol->attributes().value() = value_descriptor->value(); + } +} + void ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table) { @@ -110,6 +134,8 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table, symbol_table.typeEmbedderTable()); + this->_populateSymbolTable(module_name_node, module_name, populating_module.getNameValueMap(), symbol_table); + for (auto [symbol_name, embedded] : populating_module.getNameTypeMap()) { BasicAffectationRegisterFor<EmbeddedData>(ASTNodeDataType::build<ASTNodeDataType::type_id_t>(symbol_name)); } @@ -132,6 +158,12 @@ ModuleRepository::populateMandatorySymbolTable(const ASTNode& root_node, SymbolT ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table, symbol_table.typeEmbedderTable()); + this->_populateSymbolTable(root_node, module_name, i_module->getNameValueMap(), symbol_table); + + for (auto [symbol_name, embedded] : i_module->getNameTypeMap()) { + BasicAffectationRegisterFor<EmbeddedData>(ASTNodeDataType::build<ASTNodeDataType::type_id_t>(symbol_name)); + } + i_module->registerOperators(); } } diff --git a/src/language/modules/ModuleRepository.hpp b/src/language/modules/ModuleRepository.hpp index c4c9870fc..c7289c8d1 100644 --- a/src/language/modules/ModuleRepository.hpp +++ b/src/language/modules/ModuleRepository.hpp @@ -26,6 +26,11 @@ class ModuleRepository SymbolTable& symbol_table, EmbedderTableT& embedder_table); + void _populateSymbolTable(const ASTNode& module_node, + const std::string& module_name, + const IModule::NameValueMap& name_value_map, + SymbolTable& symbol_table); + public: void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table); void populateMandatorySymbolTable(const ASTNode& root_node, SymbolTable& symbol_table); diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp index 3af45c387..8cc1a430f 100644 --- a/src/language/node_processor/BinaryExpressionProcessor.hpp +++ b/src/language/node_processor/BinaryExpressionProcessor.hpp @@ -82,6 +82,34 @@ struct BinOp<language::lesser_op> } }; +class OStream; + +template <> +struct BinOp<language::shift_left_op> +{ + template <typename A, typename B> + PUGS_INLINE auto + eval(const A& a, const B& b) -> decltype(a << b) + { + if constexpr (std::is_same_v<A, std::shared_ptr<const OStream>> and std::is_same_v<B, bool>) { + return a << std::boolalpha << b; + } else { + return a << b; + } + } +}; + +template <> +struct BinOp<language::shift_right_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> { @@ -286,7 +314,8 @@ struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared PUGS_INLINE DataVariant _eval(const DataVariant& a, const DataVariant& b) { - if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>)) { + if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>) or + (std::is_same_v<std::string, B_DataT>)) { const auto& embedded_a = std::get<EmbeddedData>(a); const auto& b_value = std::get<B_DataT>(b); diff --git a/src/language/node_processor/OStreamProcessor.hpp b/src/language/node_processor/OStreamProcessor.hpp deleted file mode 100644 index e67dd7b6d..000000000 --- a/src/language/node_processor/OStreamProcessor.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef OSTREAM_PROCESSOR_HPP -#define OSTREAM_PROCESSOR_HPP - -#include <language/ast/ASTNode.hpp> -#include <language/node_processor/INodeProcessor.hpp> -#include <language/utils/ParseError.hpp> - -class OStreamProcessor final : public INodeProcessor -{ - private: - ASTNode& m_node; - std::ostream& m_os; - - public: - DataVariant - execute(ExecutionPolicy& exec_policy) - { - for (size_t i = 0; i < m_node.children.size(); ++i) { - m_os << m_node.children[i]->execute(exec_policy); - } - - return {}; - } - - OStreamProcessor(ASTNode& node, std::ostream& os) : m_node{node}, m_os(os) - { - for (auto& child : m_node.children) { - if ((child->m_data_type == ASTNodeDataType::type_name_id_t) or - (child->m_data_type == ASTNodeDataType::function_t) or - (child->m_data_type == ASTNodeDataType::builtin_function_t)) { - throw ParseError("invalid argument, cannot print a '" + dataTypeName(child->m_data_type) + "'", - std::vector{child->begin()}); - } - } - } -}; - -#endif // OSTREAM_PROCESSOR_HPP diff --git a/src/language/utils/BinaryOperatorMangler.hpp b/src/language/utils/BinaryOperatorMangler.hpp index f3648f3fb..d7f0c6c79 100644 --- a/src/language/utils/BinaryOperatorMangler.hpp +++ b/src/language/utils/BinaryOperatorMangler.hpp @@ -13,6 +13,9 @@ struct divide_op; struct plus_op; struct minus_op; +struct shift_left_op; +struct shift_right_op; + struct or_op; struct and_op; struct xor_op; @@ -56,6 +59,10 @@ binaryOperatorMangler(const ASTNodeDataType& lhs_data_type, const ASTNodeDataTyp return "=="; } else if constexpr (std::is_same_v<BinaryOperatorT, language::not_eq_op>) { return "!="; + } else if constexpr (std::is_same_v<BinaryOperatorT, language::shift_left_op>) { + return "<<"; + } else if constexpr (std::is_same_v<BinaryOperatorT, language::shift_right_op>) { + return ">>"; } else { static_assert(std::is_same_v<language::multiply_op, BinaryOperatorT>, "undefined binary operator"); } diff --git a/src/language/utils/BinaryOperatorRegisterForB.cpp b/src/language/utils/BinaryOperatorRegisterForB.cpp index cba803aaf..dc228471d 100644 --- a/src/language/utils/BinaryOperatorRegisterForB.cpp +++ b/src/language/utils/BinaryOperatorRegisterForB.cpp @@ -1,6 +1,18 @@ #include <language/utils/BinaryOperatorRegisterForB.hpp> #include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> + +void +BinaryOperatorRegisterForB::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, bool>>()); +} void BinaryOperatorRegisterForB::_register_comparisons() @@ -61,6 +73,7 @@ BinaryOperatorRegisterForB::_register_divide() BinaryOperatorRegisterForB::BinaryOperatorRegisterForB() { + this->_register_ostream(); this->_register_comparisons(); this->_register_logical_operators(); this->_register_plus(); diff --git a/src/language/utils/BinaryOperatorRegisterForB.hpp b/src/language/utils/BinaryOperatorRegisterForB.hpp index 651411bf7..545b49c50 100644 --- a/src/language/utils/BinaryOperatorRegisterForB.hpp +++ b/src/language/utils/BinaryOperatorRegisterForB.hpp @@ -4,6 +4,7 @@ class BinaryOperatorRegisterForB { private: + void _register_ostream(); void _register_comparisons(); void _register_logical_operators(); void _register_plus(); diff --git a/src/language/utils/BinaryOperatorRegisterForN.cpp b/src/language/utils/BinaryOperatorRegisterForN.cpp index 66d589405..e32e2b53a 100644 --- a/src/language/utils/BinaryOperatorRegisterForN.cpp +++ b/src/language/utils/BinaryOperatorRegisterForN.cpp @@ -1,6 +1,18 @@ #include <language/utils/BinaryOperatorRegisterForN.hpp> #include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> + +void +BinaryOperatorRegisterForN::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, uint64_t>>()); +} void BinaryOperatorRegisterForN::_register_comparisons() @@ -42,6 +54,7 @@ BinaryOperatorRegisterForN::_register_minus() BinaryOperatorRegisterForN::BinaryOperatorRegisterForN() { + this->_register_ostream(); this->_register_comparisons(); this->_register_arithmetic<language::plus_op>(); this->_register_minus(); diff --git a/src/language/utils/BinaryOperatorRegisterForN.hpp b/src/language/utils/BinaryOperatorRegisterForN.hpp index 80dc52b01..997b6be7a 100644 --- a/src/language/utils/BinaryOperatorRegisterForN.hpp +++ b/src/language/utils/BinaryOperatorRegisterForN.hpp @@ -4,6 +4,7 @@ class BinaryOperatorRegisterForN { private: + void _register_ostream(); template <typename OperatorT> void _register_arithmetic(); void _register_comparisons(); diff --git a/src/language/utils/BinaryOperatorRegisterForR.cpp b/src/language/utils/BinaryOperatorRegisterForR.cpp index 4f6998892..cc8ba8a79 100644 --- a/src/language/utils/BinaryOperatorRegisterForR.cpp +++ b/src/language/utils/BinaryOperatorRegisterForR.cpp @@ -1,6 +1,18 @@ #include <language/utils/BinaryOperatorRegisterForR.hpp> #include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> + +void +BinaryOperatorRegisterForR::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, double>>()); +} void BinaryOperatorRegisterForR::_register_comparisons() @@ -44,6 +56,7 @@ BinaryOperatorRegisterForR::_register_arithmetic() BinaryOperatorRegisterForR::BinaryOperatorRegisterForR() { + this->_register_ostream(); this->_register_comparisons(); this->_register_arithmetic<language::plus_op>(); this->_register_arithmetic<language::minus_op>(); diff --git a/src/language/utils/BinaryOperatorRegisterForR.hpp b/src/language/utils/BinaryOperatorRegisterForR.hpp index cbde82fb3..c14fa410f 100644 --- a/src/language/utils/BinaryOperatorRegisterForR.hpp +++ b/src/language/utils/BinaryOperatorRegisterForR.hpp @@ -4,6 +4,7 @@ class BinaryOperatorRegisterForR { private: + void _register_ostream(); template <typename OperatorT> void _register_arithmetic(); void _register_comparisons(); diff --git a/src/language/utils/BinaryOperatorRegisterForRn.cpp b/src/language/utils/BinaryOperatorRegisterForRn.cpp index 41e5b031f..6e900d036 100644 --- a/src/language/utils/BinaryOperatorRegisterForRn.cpp +++ b/src/language/utils/BinaryOperatorRegisterForRn.cpp @@ -1,8 +1,23 @@ #include <language/utils/BinaryOperatorRegisterForRn.hpp> #include <language/utils/BinaryOperatorProcessorBuilder.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> #include <language/utils/OperatorRepository.hpp> +template <size_t Dimension> +void +BinaryOperatorRegisterForRn<Dimension>::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + using Rn = TinyVector<Dimension>; + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, Rn>>()); +} + template <size_t Dimension> void BinaryOperatorRegisterForRn<Dimension>::_register_comparisons() @@ -54,6 +69,8 @@ BinaryOperatorRegisterForRn<Dimension>::_register_arithmetic() template <size_t Dimension> BinaryOperatorRegisterForRn<Dimension>::BinaryOperatorRegisterForRn() { + this->_register_ostream(); + this->_register_comparisons(); this->_register_product_by_a_scalar(); diff --git a/src/language/utils/BinaryOperatorRegisterForRn.hpp b/src/language/utils/BinaryOperatorRegisterForRn.hpp index b9f27d416..fc83d3a67 100644 --- a/src/language/utils/BinaryOperatorRegisterForRn.hpp +++ b/src/language/utils/BinaryOperatorRegisterForRn.hpp @@ -7,10 +7,9 @@ template <size_t Dimension> class BinaryOperatorRegisterForRn { private: + void _register_ostream(); void _register_comparisons(); - void _register_product_by_a_scalar(); - template <typename OperatorT> void _register_arithmetic(); diff --git a/src/language/utils/BinaryOperatorRegisterForRnxn.cpp b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp index 3d8850e79..f164203dd 100644 --- a/src/language/utils/BinaryOperatorRegisterForRnxn.cpp +++ b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp @@ -1,8 +1,23 @@ #include <language/utils/BinaryOperatorRegisterForRnxn.hpp> #include <language/utils/BinaryOperatorProcessorBuilder.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> #include <language/utils/OperatorRepository.hpp> +template <size_t Dimension> +void +BinaryOperatorRegisterForRnxn<Dimension>::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + using Rnxn = TinyMatrix<Dimension>; + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, Rnxn>>()); +} + template <size_t Dimension> void BinaryOperatorRegisterForRnxn<Dimension>::_register_comparisons() @@ -68,6 +83,8 @@ BinaryOperatorRegisterForRnxn<Dimension>::_register_arithmetic() template <size_t Dimension> BinaryOperatorRegisterForRnxn<Dimension>::BinaryOperatorRegisterForRnxn() { + this->_register_ostream(); + this->_register_comparisons(); this->_register_product_by_a_scalar(); diff --git a/src/language/utils/BinaryOperatorRegisterForRnxn.hpp b/src/language/utils/BinaryOperatorRegisterForRnxn.hpp index 594740b62..9edad436b 100644 --- a/src/language/utils/BinaryOperatorRegisterForRnxn.hpp +++ b/src/language/utils/BinaryOperatorRegisterForRnxn.hpp @@ -7,11 +7,10 @@ template <size_t Dimension> class BinaryOperatorRegisterForRnxn { private: + void _register_ostream(); void _register_comparisons(); - void _register_product_by_a_scalar(); void _register_product_by_a_vector(); - template <typename OperatorT> void _register_arithmetic(); diff --git a/src/language/utils/BinaryOperatorRegisterForString.cpp b/src/language/utils/BinaryOperatorRegisterForString.cpp index 0e89cbe00..999950cf1 100644 --- a/src/language/utils/BinaryOperatorRegisterForString.cpp +++ b/src/language/utils/BinaryOperatorRegisterForString.cpp @@ -2,8 +2,20 @@ #include <language/utils/BinaryOperatorProcessorBuilder.hpp> #include <language/utils/ConcatExpressionProcessorBuilder.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> #include <language/utils/OperatorRepository.hpp> +void +BinaryOperatorRegisterForString::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::string>>()); +} + void BinaryOperatorRegisterForString::_register_comparisons() { @@ -27,6 +39,8 @@ BinaryOperatorRegisterForString::_register_concat() BinaryOperatorRegisterForString::BinaryOperatorRegisterForString() { + this->_register_ostream(); + this->_register_comparisons(); this->_register_concat<bool>(); diff --git a/src/language/utils/BinaryOperatorRegisterForString.hpp b/src/language/utils/BinaryOperatorRegisterForString.hpp index 36af13ee6..b7d4a7440 100644 --- a/src/language/utils/BinaryOperatorRegisterForString.hpp +++ b/src/language/utils/BinaryOperatorRegisterForString.hpp @@ -4,6 +4,8 @@ class BinaryOperatorRegisterForString { private: + void _register_ostream(); + void _register_comparisons(); template <typename RHS_T> diff --git a/src/language/utils/BinaryOperatorRegisterForZ.cpp b/src/language/utils/BinaryOperatorRegisterForZ.cpp index cc8b22d11..1d3188502 100644 --- a/src/language/utils/BinaryOperatorRegisterForZ.cpp +++ b/src/language/utils/BinaryOperatorRegisterForZ.cpp @@ -1,6 +1,18 @@ #include <language/utils/BinaryOperatorRegisterForZ.hpp> #include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OStream.hpp> + +void +BinaryOperatorRegisterForZ::_register_ostream() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, int64_t>>()); +} void BinaryOperatorRegisterForZ::_register_comparisons() @@ -36,6 +48,7 @@ BinaryOperatorRegisterForZ::_register_arithmetic() BinaryOperatorRegisterForZ::BinaryOperatorRegisterForZ() { + this->_register_ostream(); this->_register_comparisons(); this->_register_arithmetic<language::plus_op>(); this->_register_arithmetic<language::minus_op>(); diff --git a/src/language/utils/BinaryOperatorRegisterForZ.hpp b/src/language/utils/BinaryOperatorRegisterForZ.hpp index 3f9a7c30c..cb734843d 100644 --- a/src/language/utils/BinaryOperatorRegisterForZ.hpp +++ b/src/language/utils/BinaryOperatorRegisterForZ.hpp @@ -4,6 +4,7 @@ class BinaryOperatorRegisterForZ { private: + void _register_ostream(); template <typename OperatorT> void _register_arithmetic(); void _register_comparisons(); diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index 216a6be6a..c8928003d 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -29,6 +29,7 @@ add_library(PugsLanguageUtils IncDecOperatorRegisterForN.cpp IncDecOperatorRegisterForR.cpp IncDecOperatorRegisterForZ.cpp + OFStream.cpp OperatorRepository.cpp UnaryOperatorRegisterForB.cpp UnaryOperatorRegisterForN.cpp diff --git a/src/language/utils/OFStream.cpp b/src/language/utils/OFStream.cpp new file mode 100644 index 000000000..3bc5e2991 --- /dev/null +++ b/src/language/utils/OFStream.cpp @@ -0,0 +1,12 @@ +#include <language/utils/OFStream.hpp> + +#include <utils/Messenger.hpp> + +OFStream::OFStream(const std::string& filename) +{ + if (parallel::rank() == 0) { + m_fstream.open(filename); + Assert(m_ostream == nullptr, "ostream was already defined"); + m_ostream = &m_fstream; + } +} diff --git a/src/language/utils/OFStream.hpp b/src/language/utils/OFStream.hpp new file mode 100644 index 000000000..589f0fe27 --- /dev/null +++ b/src/language/utils/OFStream.hpp @@ -0,0 +1,20 @@ +#ifndef OFSTREAM_HPP +#define OFSTREAM_HPP + +#include <language/utils/OStream.hpp> + +#include <fstream> + +class OFStream : public OStream +{ + private: + std::ofstream m_fstream; + + public: + OFStream(const std::string& filename); + + OFStream() = default; + ~OFStream() = default; +}; + +#endif // OFSTREAM_HPP diff --git a/src/language/utils/OStream.hpp b/src/language/utils/OStream.hpp new file mode 100644 index 000000000..6abbcf668 --- /dev/null +++ b/src/language/utils/OStream.hpp @@ -0,0 +1,36 @@ +#ifndef OSTREAM_HPP +#define OSTREAM_HPP + +#include <language/utils/ASTNodeDataTypeTraits.hpp> +#include <utils/PugsAssert.hpp> + +#include <memory> + +class OStream +{ + protected: + mutable std::ostream* m_ostream = nullptr; + + public: + template <typename DataT> + friend std::shared_ptr<const OStream> + operator<<(const std::shared_ptr<const OStream>& os, const DataT& t) + { + Assert(os.use_count() > 0); + if (os->m_ostream != nullptr) { + *os->m_ostream << t; + } + return os; + } + + OStream(std::ostream& os) : m_ostream(&os) {} + OStream() = default; + + virtual ~OStream() = default; +}; + +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const OStream>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("ostream"); + +#endif // OSTREAM_HPP diff --git a/src/language/utils/ValueDescriptor.hpp b/src/language/utils/ValueDescriptor.hpp new file mode 100644 index 000000000..36bca3535 --- /dev/null +++ b/src/language/utils/ValueDescriptor.hpp @@ -0,0 +1,36 @@ +#ifndef VALUE_DESCRIPTOR_HPP +#define VALUE_DESCRIPTOR_HPP + +#include <language/utils/ASTNodeDataType.hpp> +#include <language/utils/DataVariant.hpp> + +#include <string> + +class ValueDescriptor +{ + private: + const ASTNodeDataType m_type; + const DataVariant m_value; + + public: + const ASTNodeDataType + type() const + { + return m_type; + } + + const DataVariant + value() const + { + return m_value; + } + + ValueDescriptor(const ASTNodeDataType& type, const DataVariant& value) : m_type{type}, m_value{value} {} + + ValueDescriptor(const ValueDescriptor&) = delete; + ValueDescriptor(ValueDescriptor&&) = delete; + + ~ValueDescriptor() = default; +}; + +#endif // VALUE_DESCRIPTOR_HPP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 62a70aad3..3c7ab2eb4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -86,7 +86,6 @@ add_executable (unit_tests test_MathModule.cpp test_NameProcessor.cpp test_NaNHelper.cpp - test_OStreamProcessor.cpp test_ParseError.cpp test_PETScUtils.cpp test_PugsAssert.cpp diff --git a/tests/test_ASTBuilder.cpp b/tests/test_ASTBuilder.cpp index 387e84b75..3ce2855ef 100644 --- a/tests/test_ASTBuilder.cpp +++ b/tests/test_ASTBuilder.cpp @@ -600,7 +600,7 @@ for(let i:N, i=0; i<10; ++i) { CHECK_AST(data, result); } - SECTION("ostream simplifications") + SECTION("ostream") { std::string_view data = R"( cout << 1+2 << "\n"; @@ -610,16 +610,22 @@ clog << "log " << l << "\n"; std::string_view result = R"( (root) - +-(language::cout_kw) - | +-(language::plus_op) - | | +-(language::integer:1) - | | `-(language::integer:2) + +-(language::shift_left_op) + | +-(language::shift_left_op) + | | +-(language::name:cout) + | | `-(language::plus_op) + | | +-(language::integer:1) + | | `-(language::integer:2) | `-(language::literal:"\n") - +-(language::cerr_kw) + +-(language::shift_left_op) + | +-(language::name:cerr) | `-(language::literal:"error?\n") - `-(language::clog_kw) - +-(language::literal:"log ") - +-(language::name:l) + `-(language::shift_left_op) + +-(language::shift_left_op) + | +-(language::shift_left_op) + | | +-(language::name:clog) + | | `-(language::literal:"log ") + | `-(language::name:l) `-(language::literal:"\n") )"; CHECK_AST(data, result); diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 96af38a0b..2e3835024 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -1413,11 +1413,14 @@ clog << "clog\n"; std::string_view result = R"( (root:void) - +-(language::cout_kw:void) + +-(language::shift_left_op:ostream) + | +-(language::name:cout:ostream) | `-(language::literal:"cout\n":string) - +-(language::cerr_kw:void) + +-(language::shift_left_op:ostream) + | +-(language::name:cerr:ostream) | `-(language::literal:"cerr\n":string) - `-(language::clog_kw:void) + `-(language::shift_left_op:ostream) + +-(language::name:clog:ostream) `-(language::literal:"clog\n":string) )"; @@ -1445,8 +1448,10 @@ for (let i : N, i=0; i<3; ++i){ | `-(language::integer:3:Z) +-(language::unary_plusplus:N) | `-(language::name:i:N) - `-(language::cout_kw:void) - +-(language::name:i:N) + `-(language::shift_left_op:ostream) + +-(language::shift_left_op:ostream) + | +-(language::name:cout:ostream) + | `-(language::name:i:N) `-(language::literal:"\n":string) )"; diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index cb6fdbfef..25a3d3a93 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -684,7 +684,7 @@ cout; std::string result = R"( (root:ASTNodeListProcessor) - `-(language::cout_kw:OStreamProcessor) + `-(language::name:cout:NameProcessor) )"; CHECK_AST(data, result); @@ -698,7 +698,7 @@ cerr; std::string result = R"( (root:ASTNodeListProcessor) - `-(language::cerr_kw:OStreamProcessor) + `-(language::name:cerr:NameProcessor) )"; CHECK_AST(data, result); @@ -712,7 +712,7 @@ clog; std::string result = R"( (root:ASTNodeListProcessor) - `-(language::clog_kw:OStreamProcessor) + `-(language::name:clog:NameProcessor) )"; CHECK_AST(data, result); diff --git a/tests/test_ASTNodeTypeCleaner.cpp b/tests/test_ASTNodeTypeCleaner.cpp index e1abf88d6..d78d4ce17 100644 --- a/tests/test_ASTNodeTypeCleaner.cpp +++ b/tests/test_ASTNodeTypeCleaner.cpp @@ -42,9 +42,12 @@ cout << "two=" << 2 << "\n"; std::string_view result = R"( (root) - `-(language::cout_kw) - +-(language::literal:"two=") - +-(language::integer:2) + `-(language::shift_left_op) + +-(language::shift_left_op) + | +-(language::shift_left_op) + | | +-(language::name:cout) + | | `-(language::literal:"two=") + | `-(language::integer:2) `-(language::literal:"\n") )"; diff --git a/tests/test_OStreamProcessor.cpp b/tests/test_OStreamProcessor.cpp deleted file mode 100644 index 22213d64b..000000000 --- a/tests/test_OStreamProcessor.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include <catch2/catch_test_macros.hpp> -#include <catch2/matchers/catch_matchers_all.hpp> - -#include <language/ast/ASTBuilder.hpp> -#include <language/ast/ASTNodeDataTypeBuilder.hpp> -#include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> -#include <language/ast/ASTNodeExpressionBuilder.hpp> -#include <language/ast/ASTNodeTypeCleaner.hpp> -#include <language/ast/ASTSymbolTableBuilder.hpp> -#include <language/node_processor/OStreamProcessor.hpp> -#include <utils/Demangle.hpp> - -#include <pegtl/string_input.hpp> - -#include <sstream> - -void -_replaceOStream(ASTNode& node, std::ostringstream& sout) -{ - if (node.is_type<language::cout_kw>() or node.is_type<language::cerr_kw>()) { - node.m_node_processor = std::make_unique<OStreamProcessor>(node, sout); - } else { - for (auto& child_node : node.children) { - _replaceOStream(*child_node, sout); - } - } -} - -#define CHECK_OSTREAM_EXPRESSION_RESULT(data, expected_value) \ - { \ - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ - auto ast = ASTBuilder::build(input); \ - \ - ASTSymbolTableBuilder{*ast}; \ - ASTNodeDataTypeBuilder{*ast}; \ - \ - ASTNodeDeclarationToAffectationConverter{*ast}; \ - ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ - \ - ASTNodeExpressionBuilder{*ast}; \ - ExecutionPolicy exec_policy; \ - \ - std::ostringstream sout; \ - _replaceOStream(*ast, sout); \ - \ - ast->execute(exec_policy); \ - \ - REQUIRE(sout.str() == expected_value); \ - } - -#define CHECK_OSTREAM_EXPRESSION_THROWS(data, expected_error) \ - { \ - static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ - static_assert((std::is_same_v<std::decay_t<decltype(expected_error)>, std::string_view>) or \ - (std::is_same_v<std::decay_t<decltype(expected_error)>, std::string>)); \ - \ - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ - auto ast = ASTBuilder::build(input); \ - \ - ASTSymbolTableBuilder{*ast}; \ - ASTNodeDataTypeBuilder{*ast}; \ - \ - ASTNodeDeclarationToAffectationConverter{*ast}; \ - ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \ - \ - REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error); \ - } - -// clazy:excludeall=non-pod-global-static - -TEST_CASE("OStreamProcessor", "[language]") -{ - SECTION("cout") - { - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cout << 2;)", "2"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cout << true;)", "true"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cout << false;)", "false"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cout << "x=" << 2 << "\n";)", "x=2\n"); - } - - SECTION("cerr") - { - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cerr << 2;)", "2"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cerr << true;)", "true"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cerr << false;)", "false"); - CHECK_OSTREAM_EXPRESSION_RESULT(R"(cerr << "x=" << 2 << "\n";)", "x=2\n"); - } - - SECTION("runtime error") - { - std::string_view data_type = R"( -let f : R -> R, x -> 2; -cerr << "f=" << f << "\n"; -)"; - - std::string error_msg = "invalid argument, cannot print a 'function'"; - CHECK_OSTREAM_EXPRESSION_THROWS(data_type, error_msg); - } -} -- GitLab