diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index 7f328daf18a7b3f72de0e4b8036cf94bcc675954..22d748344494dc992c01cc6857f0eeb9faa00d75 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -231,5 +231,14 @@ ASTNodeDataTypeBuilder::ASTNodeDataTypeBuilder(ASTNode& node) node.m_data_type = ASTNodeDataType::void_t; this->_buildNodeDataTypes(node); + + FunctionTable& function_table = node.m_symbol_table->functionTable(); + for (size_t function_id = 0; function_id < function_table.size(); ++function_id) { + FunctionDescriptor& function_descriptor = function_table[function_id]; + ASTNode& function_expression = function_descriptor.definitionNode(); + + this->_buildNodeDataTypes(function_expression); + } + std::cout << " - build node data types\n"; } diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index 9f0a6f7eb8ef2d5fcdee10da3d122b381fb5598a..839404a00966c0e61c4d892d303c432f5713f996 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -11,6 +11,7 @@ #include <node_processor/DoWhileProcessor.hpp> #include <node_processor/FakeProcessor.hpp> #include <node_processor/ForProcessor.hpp> +#include <node_processor/FunctionProcessor.hpp> #include <node_processor/IfProcessor.hpp> #include <node_processor/NameProcessor.hpp> #include <node_processor/OStreamProcessor.hpp> @@ -27,16 +28,11 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) n.is<language::pluseq_op>() or n.is<language::minuseq_op>())) { ASTNodeAffectationExpressionBuilder{n}; - } else if (n.is<language::let_declaration>()) { - std::cerr << rang::fgB::red << "\"let expression\" is not defined correctly (declaration should be removed)" - << rang::style::reset << '\n'; + } else if (n.is<language::function_definition>()) { n.m_node_processor = std::make_unique<FakeProcessor>(); - return; } else if (n.is<language::function_evaluation>()) { - std::cerr << rang::fgB::red << "\"function evaluation\" is not defined yet" << rang::style::reset << '\n'; - n.m_node_processor = std::make_unique<FakeProcessor>(); - return; + n.m_node_processor = std::make_unique<FunctionProcessor>(n); } else if (n.is<language::real>()) { n.m_node_processor = std::make_unique<FakeProcessor>(); @@ -105,12 +101,19 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) } } -ASTNodeExpressionBuilder::ASTNodeExpressionBuilder(ASTNode& n) +ASTNodeExpressionBuilder::ASTNodeExpressionBuilder(ASTNode& node) { - Assert(n.is_root()); - n.m_node_processor = std::make_unique<ASTNodeListProcessor>(n); - for (auto& child : n.children) { + Assert(node.is_root()); + node.m_node_processor = std::make_unique<ASTNodeListProcessor>(node); + for (auto& child : node.children) { this->_buildExpression(*child); } - std::cout << " - build node types\n"; + + // Build expressions of functions + FunctionTable& function_table = node.m_symbol_table->functionTable(); + for (size_t function_id = 0; function_id < function_table.size(); ++function_id) { + FunctionDescriptor& function_descriptor = function_table[function_id]; + ASTNode& function_expression = function_descriptor.definitionNode(); + this->_buildExpression(function_expression); + } } diff --git a/src/language/FunctionTable.hpp b/src/language/FunctionTable.hpp index 700439fff4d6d64f38af0c7d95e9f169d6a89507..682a87c4c9e5d4c9b097e88db2cb6ce37876ae00 100644 --- a/src/language/FunctionTable.hpp +++ b/src/language/FunctionTable.hpp @@ -49,6 +49,13 @@ class FunctionTable std::vector<FunctionDescriptor> m_function_descriptor_list; public: + PUGS_INLINE + size_t + size() const + { + return m_function_descriptor_list.size(); + } + PUGS_INLINE FunctionDescriptor& operator[](size_t function_id) { diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4527b0b6ebe3dd337b43f71ce7b88a1025d94038 --- /dev/null +++ b/src/language/node_processor/FunctionProcessor.hpp @@ -0,0 +1,58 @@ +#ifndef FUNCTION_PROCESSOR_HPP +#define FUNCTION_PROCESSOR_HPP + +#include <FunctionTable.hpp> +#include <SymbolTable.hpp> + +#include <PEGGrammar.hpp> + +#include <node_processor/INodeProcessor.hpp> + +class FunctionProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + FunctionDescriptor& m_function_descriptor; + + public: + void + execute(ExecUntilBreakOrContinue& exec_policy) + { + // Compute arguments values + ASTNode& arguments_values = *m_node.children[1]; + arguments_values.execute(exec_policy); + + // Copy arguments to function arguments + ASTNode& definition_node = m_function_descriptor.definitionNode(); + ASTNode& arguments = *definition_node.children[0]; + + if (arguments.is<language::name>()) { + Assert(arguments_values.children.size() == 0); + + auto [i_symbol, found] = arguments.m_symbol_table->find(arguments.string(), arguments.begin()); + Assert(found); + + i_symbol->attributes().value() = arguments_values.m_value; + } else { + throw parse_error("argument list not implemented yet!", definition_node.children[0]->begin()); + } + + ASTNode& function_expression = *definition_node.children[1]; + function_expression.execute(exec_policy); + + m_node.m_value = function_expression.m_value; + } + + FunctionProcessor(ASTNode& node) + : m_node{node}, m_function_descriptor{[&]() -> FunctionDescriptor& { + auto [i_symbol, found] = m_node.m_symbol_table->find(m_node.children[0]->string(), m_node.begin()); + Assert(found); + uint64_t function_id = std::get<uint64_t>(i_symbol->attributes().value()); + + return m_node.m_symbol_table->functionTable()[function_id]; + }()} + {} +}; + +#endif // FUNCTION_PROCESSOR_HPP diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index 394ed133a8ac2d79127d39845696a614befdb5de..d27c0927211731d479d2f9da30790454608c07d0 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -854,6 +854,7 @@ continue; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; // One is sure that language::ignored is not treated so its a good candidate diff --git a/tests/test_ASTNodeJumpPlacementChecker.cpp b/tests/test_ASTNodeJumpPlacementChecker.cpp index 7a7679199089225fc33175f2fda16759b0bf0346..b80a8887dd1792216ddc73b5b2f99c02ae957655 100644 --- a/tests/test_ASTNodeJumpPlacementChecker.cpp +++ b/tests/test_ASTNodeJumpPlacementChecker.cpp @@ -1,6 +1,7 @@ #include <catch2/catch.hpp> #include <ASTBuilder.hpp> +#include <ASTSymbolTableBuilder.hpp> #include <ASTNodeDataTypeBuilder.hpp> #include <ASTNodeJumpPlacementChecker.hpp> @@ -19,7 +20,7 @@ for(;;) { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -35,7 +36,7 @@ while(true) { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -51,7 +52,7 @@ do { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -67,7 +68,7 @@ do { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; ast->children[0]->m_data_type = ASTNodeDataType::undefined_t; @@ -88,7 +89,7 @@ for(;;) { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -104,7 +105,7 @@ while(true) { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -120,7 +121,7 @@ do { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; REQUIRE_NOTHROW(ASTNodeJumpPlacementChecker{*ast}); @@ -136,7 +137,7 @@ do { string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; ast->children[0]->m_data_type = ASTNodeDataType::undefined_t;