diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index 23fe98211fc8e4af195219e6594eecc4687b1f9c..c515da24dbd4ebc8bb47f89d5a4266939ccff70a 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -92,10 +92,6 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode set_affectation_processor_for_string_data(data_type); break; } - case ASTNodeDataType::typename_t: { - throw parse_error("unexpected error: compound type affectation NIY", std::vector{n.begin()}); - break; - } default: { throw parse_error("unexpected error: undefined value type for affectation", std::vector{n.begin()}); } diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index 73a423032357b1fa2e4d6301ddbe927ac899358d..3540b0204cfe67673d07cca4520f377c7b490802 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -39,6 +39,10 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo data_type = ASTNodeDataType::string_t; } + if (name_node.is_type<language::name_list>()) { + throw parse_error("unexpected variable list for scalar space", name_node.begin()); + } + Assert(name_node.is_type<language::name>()); name_node.m_data_type = data_type; const std::string& symbol = name_node.string(); diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index d15e7265b5c8d7d417b09fa94b1d3885821f0774..c9378f165ab24dcb935c4bba661cbd6e2c6e5e57 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -1,6 +1,8 @@ #include <ASTNodeExpressionBuilder.hpp> #include <ASTNodeAffectationExpressionBuilder.hpp> +#include <ASTNodeListAffectationExpressionBuilder.hpp> + #include <ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <ASTNodeFunctionEvaluationExpressionBuilder.hpp> #include <ASTNodeIncDecExpressionBuilder.hpp> @@ -27,7 +29,11 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) } else if ((n.is_type<language::eq_op>() or n.is_type<language::multiplyeq_op>() or n.is_type<language::divideeq_op>() or n.is_type<language::pluseq_op>() or n.is_type<language::minuseq_op>())) { - ASTNodeAffectationExpressionBuilder{n}; + if (n.children[0]->is_type<language::name_list>()) { + ASTNodeListAffectationExpressionBuilder{n}; + } else { + ASTNodeAffectationExpressionBuilder{n}; + } } else if (n.is_type<language::function_definition>()) { n.m_node_processor = std::make_unique<FakeProcessor>(); @@ -50,7 +56,7 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) n.m_node_processor = std::make_unique<FakeProcessor>(); } else if (n.is_type<language::expression_list>()) { - n.m_node_processor = std::make_unique<FakeProcessor>(); + n.m_node_processor = std::make_unique<ASTNodeListProcessor>(n); } else if (n.is_type<language::name_list>()) { n.m_node_processor = std::make_unique<FakeProcessor>(); diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ASTNodeListAffectationExpressionBuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9850ca24a68e22ca04fdd51ffa2e09e61127c46a --- /dev/null +++ b/src/language/ASTNodeListAffectationExpressionBuilder.cpp @@ -0,0 +1,146 @@ +#include <ASTNodeListAffectationExpressionBuilder.hpp> +#include <PEGGrammar.hpp> + +#include <node_processor/AffectationProcessor.hpp> +#include <node_processor/AffectationToStringProcessor.hpp> + +template <typename OperatorT> +void +ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor(ASTNode& node) +{ + using ListAffectationProcessorT = ListAffectationProcessor<OperatorT>; + + auto add_affectation_processor = [](ASTNode& value_node, ASTNode& data_node, + std::unique_ptr<ListAffectationProcessorT>& list_affectation_processor) { + auto add_affectation_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) { + using ValueT = std::decay_t<decltype(value)>; + switch (data_type) { + case ASTNodeDataType::bool_t: { + list_affectation_processor->template add<ValueT, bool>(value_node, data_node); + break; + } + case ASTNodeDataType::unsigned_int_t: { + list_affectation_processor->template add<ValueT, uint64_t>(value_node, data_node); + break; + } + case ASTNodeDataType::int_t: { + list_affectation_processor->template add<ValueT, int64_t>(value_node, data_node); + break; + } + case ASTNodeDataType::double_t: { + list_affectation_processor->template add<ValueT, double>(value_node, data_node); + break; + } + default: { + throw parse_error("unexpected error: undefined operand type for affectation", std::vector{data_node.begin()}); + } + } + }; + + // auto add_affectation_processor_for_string_data = [&](const ASTNodeDataType& data_type) { + // if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) { + // switch (data_type) { + // case ASTNodeDataType::bool_t: { + // node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, bool>>(node); + // break; + // } + // case ASTNodeDataType::unsigned_int_t: { + // node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, uint64_t>>(node); + // break; + // } + // case ASTNodeDataType::int_t: { + // node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, int64_t>>(node); + // break; + // } + // case ASTNodeDataType::double_t: { + // node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, double>>(node); + // break; + // } + // case ASTNodeDataType::string_t: { + // node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, std::string>>(node); + // break; + // } + // default: { + // throw parse_error("unexpected error: undefined operand type for string affectation", + // std::vector{node.children[1]->begin()}); + // } + // } + // } else { + // throw parse_error("unexpected error: undefined operator type", std::vector{node.children[0]->begin()}); + // } + // }; + + auto add_affectation_processor_for_value = [&](const ASTNodeDataType& value_type, + const ASTNodeDataType& data_type) { + switch (value_type) { + case ASTNodeDataType::bool_t: { + add_affectation_processor_for_data(bool{}, data_type); + break; + } + case ASTNodeDataType::unsigned_int_t: { + add_affectation_processor_for_data(uint64_t{}, data_type); + break; + } + case ASTNodeDataType::int_t: { + add_affectation_processor_for_data(int64_t{}, data_type); + break; + } + case ASTNodeDataType::double_t: { + add_affectation_processor_for_data(double{}, data_type); + break; + } + case ASTNodeDataType::string_t: { + // add_affectation_processor_for_string_data(data_type); + throw parse_error("unexpected error: string in list NIY", std::vector{value_node.begin()}); + break; + } + default: { + throw parse_error("unexpected error: undefined value type for affectation", std::vector{value_node.begin()}); + } + } + }; + + add_affectation_processor_for_value(value_node.m_data_type, data_node.m_data_type); + }; + + std::unique_ptr list_affectation_processor = std::make_unique<ListAffectationProcessorT>(node); + + ASTNode& name_list_node = *node.children[0]; + ASTNode& expression_list_node = *node.children[1]; + + if (name_list_node.children.size() != expression_list_node.children.size()) { + throw parse_error("incompatible list sizes in affectation", std::vector{node.begin()}); + } else { + for (size_t i = 0; i < name_list_node.children.size(); ++i) { + ASTNode& name_node = *name_list_node.children[i]; + ASTNode& expression_node = *expression_list_node.children[i]; + + add_affectation_processor(name_node, expression_node, list_affectation_processor); + } + } + + node.m_node_processor = std::move(list_affectation_processor); +} + +ASTNodeListAffectationExpressionBuilder::ASTNodeListAffectationExpressionBuilder(ASTNode& n) +{ + if (n.children[1]->is_type<language::expression_list>()) { + if (n.is_type<language::eq_op>()) { + this->_buildListAffectationProcessor<language::eq_op>(n); + } else if (n.is_type<language::multiplyeq_op>()) { + this->_buildListAffectationProcessor<language::multiplyeq_op>(n); + } else if (n.is_type<language::divideeq_op>()) { + this->_buildListAffectationProcessor<language::divideeq_op>(n); + } else if (n.is_type<language::pluseq_op>()) { + this->_buildListAffectationProcessor<language::pluseq_op>(n); + } else if (n.is_type<language::minuseq_op>()) { + this->_buildListAffectationProcessor<language::minuseq_op>(n); + + } else { + throw parse_error("unexpected error: undefined affectation operator", std::vector{n.begin()}); + } + } else { + throw parse_error("unexpected error: invalid right hand side in list affectation", + std::vector{n.children[1]->begin()}); + } +} diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.hpp b/src/language/ASTNodeListAffectationExpressionBuilder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d195b141c1beab7658e1c2aa2fa699cbf87178cc --- /dev/null +++ b/src/language/ASTNodeListAffectationExpressionBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef AST_NODE_LIST_AFFECTATION_EXPRESSION_BUILDER_HPP +#define AST_NODE_LIST_AFFECTATION_EXPRESSION_BUILDER_HPP + +#include <ASTNode.hpp> + +class ASTNodeListAffectationExpressionBuilder +{ + private: + template <typename OperatorT> + void _buildListAffectationProcessor(ASTNode& node); + + public: + ASTNodeListAffectationExpressionBuilder(ASTNode& node); +}; + +#endif // AST_NODE_LIST_AFFECTATION_EXPRESSION_BUILDER_HPP diff --git a/src/language/ASTSymbolInitializationChecker.cpp b/src/language/ASTSymbolInitializationChecker.cpp index 0698b6fad33485f568a776c8f3a6442ff263197a..f42d5a0a88e8ef1ef938bb8d402db4fdf0e2db62 100644 --- a/src/language/ASTSymbolInitializationChecker.cpp +++ b/src/language/ASTSymbolInitializationChecker.cpp @@ -8,16 +8,23 @@ void ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) { if (node.is_type<language::declaration>()) { - if (node.children[1]->is_type<language::name>()) { - const std::string& symbol = node.children[1]->string(); - auto [i_symbol, found] = node.m_symbol_table->find(symbol, node.children[1]->begin()); + auto set_is_initialized = [&](ASTNode& name_node) { + const std::string& symbol = name_node.string(); + auto [i_symbol, found] = node.m_symbol_table->find(symbol, name_node.begin()); Assert(found, "unexpected error, should have been detected through declaration checking"); if (node.children.size() == 3) { this->_checkSymbolInitialization(*node.children[2]); i_symbol->attributes().setIsInitialized(); } - } else { - std::cerr << __FILE__ << ':' << __LINE__ << ": '" << node.children[1]->name() << "' NIY!\n"; + }; + + if (node.children[1]->is_type<language::name>()) { + set_is_initialized(*node.children[1]); + } else if (node.children[1]->is_type<language::name_list>()) { + ASTNode& name_list_node = *node.children[1]; + for (auto& child_node : name_list_node.children) { + set_is_initialized(*child_node); + } } } else if (node.is_type<language::let_declaration>()) { const std::string& symbol = node.children[0]->string(); diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index e00a6a19dd0c350bd0b1493cd2fa011781ddff36..21a0c78feeb929bba99cd30e349375fd19889560 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -23,6 +23,7 @@ add_library( ASTNodeFunctionEvaluationExpressionBuilder.cpp ASTNodeIncDecExpressionBuilder.cpp ASTNodeJumpPlacementChecker.cpp + ASTNodeListAffectationExpressionBuilder.cpp ASTNodeUnaryOperatorExpressionBuilder.cpp ASTNodeValueBuilder.cpp ASTPrinter.cpp diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 50b1fd69caaf17c1a520f3eb8e653c1c660ac4bc..b22af5df3b65f31458e91b433a540e66c54d56d1 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -52,12 +52,18 @@ struct AffOp<language::minuseq_op> } }; +struct IAffectationExecutor +{ + virtual void execute() = 0; + virtual ~IAffectationExecutor() = default; +}; + template <typename OperatorT, typename ValueT, typename DataT> -class AffectationProcessor final : public INodeProcessor +class AffectationExecutor final : public IAffectationExecutor { private: - ASTNode& m_node; - ASTNodeDataVariant* p_value{nullptr}; + ASTNodeDataVariant* m_lhs{nullptr}; + ASTNodeDataVariant* m_rhs{nullptr}; static inline const bool _is_defined{[] { if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { @@ -69,35 +75,91 @@ class AffectationProcessor final : public INodeProcessor }()}; public: - void - execute(ExecUntilBreakOrContinue& exec_policy) + AffectationExecutor(ASTNode& node, ASTNodeDataVariant* lhs, ASTNodeDataVariant* rhs) : m_lhs(lhs), m_rhs(rhs) { - if constexpr (_is_defined) { - m_node.children[1]->execute(exec_policy); + if constexpr (not _is_defined) { + throw parse_error("invalid operands to affectation expression", std::vector{node.begin()}); + } + } + PUGS_INLINE void + execute() + { + if constexpr (_is_defined) { 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; + *m_lhs = *m_rhs; } else { - *p_value = static_cast<ValueT>(std::get<DataT>(m_node.children[1]->m_value)); + *m_lhs = static_cast<ValueT>(std::get<DataT>(*m_rhs)); } } else { - AffOp<OperatorT>().eval(std::get<ValueT>(*p_value), std::get<DataT>(m_node.children[1]->m_value)); + AffOp<OperatorT>().eval(std::get<ValueT>(*m_lhs), std::get<DataT>(*m_rhs)); } } } +}; + +template <typename OperatorT, typename ValueT, typename DataT> +class AffectationProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; + + std::unique_ptr<AffectationExecutorT> m_affectation_executor; + + public: + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[1]->execute(exec_policy); + m_affectation_executor->execute(); + } 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->attributes().value(); - } else { - throw parse_error("invalid operands to affectation expression", std::vector{m_node.begin()}); + 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); + + m_affectation_executor = + std::make_unique<AffectationExecutorT>(m_node, &i_symbol->attributes().value(), &m_node.children[1]->m_value); + } +}; + +template <typename OperatorT> +class ListAffectationProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + std::vector<std::unique_ptr<IAffectationExecutor>> m_affectation_executor_list; + + public: + template <typename ValueT, typename DataT> + void + add(ASTNode& lhs_node, ASTNode& rhs_node) + { + const std::string& symbol = lhs_node.string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->end()); + Assert(found); + + m_affectation_executor_list.emplace_back( + std::make_unique<AffectationExecutor<OperatorT, ValueT, DataT>>(m_node, &i_symbol->attributes().value(), + &rhs_node.m_value)); + } + + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + m_node.children[1]->execute(exec_policy); + for (auto& affectation_executor : m_affectation_executor_list) { + affectation_executor->execute(); } } + + ListAffectationProcessor(ASTNode& node) : m_node{node} {} }; #endif // AFFECTATION_PROCESSOR_HPP