diff --git a/include/basic_nodes.hpp b/include/basic_nodes.hpp index b96c57c..e952301 100644 --- a/include/basic_nodes.hpp +++ b/include/basic_nodes.hpp @@ -8,11 +8,11 @@ namespace nodes { enum class Modifier { - OUT, // -> x - IN, // <- x - REF, // <> x - OR_FALSE, // x? - OR_RETURN, // x! + OUT, // -> x + IN, // <- x + REF, // <> x + OPTIONAL, // x? + RESULT, // x! NONE, }; diff --git a/include/name_tree.hpp b/include/name_tree.hpp index f7b2ae1..5db7479 100644 --- a/include/name_tree.hpp +++ b/include/name_tree.hpp @@ -19,6 +19,8 @@ public: bool insert(const std::string &path, nodes::Statement &&statement); + bool insert(const std::string &path, const nodes::Statement &statement); + std::optional find(const std::string &path); std::optional find(const std::string &path) const; @@ -48,6 +50,14 @@ private: return true; } + bool set_statement(const nodes::Statement &statement) { + if (statement_.has_value()) { + return false; + } + statement_ = statement; + return true; + } + std::optional find(size_t name_id) const { auto name_iter = children_.find(name_id); diff --git a/include/statement_builders.hpp b/include/statement_builders.hpp index 852ecd0..6cd88a4 100644 --- a/include/statement_builders.hpp +++ b/include/statement_builders.hpp @@ -1,5 +1,6 @@ #pragma once +#include "name_tree.hpp" #include "statement_nodes.hpp" #include "tree_sitter_wrapper.hpp" @@ -7,14 +8,18 @@ namespace builders { +// statements (copies of statements are in name_tree) returned to print / +// translate them in required order std::vector build_source_file(parser::ParseTree::Node parser_node, nodes::ExpressionStorage &expression_storage, - nodes::TypeStorage &type_storage); + nodes::TypeStorage &type_storage, names::NameTree &name_tree); +// copy of statement inserted into name_tree nodes::Statement build_statement(parser::ParseTree::Node parser_node, nodes::ExpressionStorage &expression_storage, - nodes::TypeStorage &type_storage); + nodes::TypeStorage &type_storage, + names::NameTree &name_tree); nodes::Import build_import(parser::ParseTree::Node parser_node); diff --git a/include/statement_nodes.hpp b/include/statement_nodes.hpp index c5b1735..85c0d86 100644 --- a/include/statement_nodes.hpp +++ b/include/statement_nodes.hpp @@ -464,6 +464,10 @@ private: class Statement { public: + Statement(const Statement &) = default; + Statement(Statement &&) = default; + Statement &operator=(const Statement &) = default; + template Statement(T &&statement) : expression_(std::forward(statement)) {} diff --git a/include/statement_printers.hpp b/include/statement_printers.hpp index fe1f488..e8c34cb 100644 --- a/include/statement_printers.hpp +++ b/include/statement_printers.hpp @@ -1,6 +1,7 @@ #pragma once #include "basic_printers.hpp" +#include "name_tree.hpp" #include "statement_nodes.hpp" #include diff --git a/src/basic_builders.cpp b/src/basic_builders.cpp index 8105320..d8d136c 100644 --- a/src/basic_builders.cpp +++ b/src/basic_builders.cpp @@ -43,9 +43,9 @@ nodes::Modifier build_modifier(parser::ParseTree::Node parser_node) { std::string modifier = parser_node.get_value(); if (modifier == "?") { - return nodes::Modifier::OR_FALSE; + return nodes::Modifier::OPTIONAL; } else if (modifier == "!") { - return nodes::Modifier::OR_RETURN; + return nodes::Modifier::RESULT; } else if (modifier == "->" || modifier == "out") { return nodes::Modifier::OUT; } else if (modifier == "<-" || modifier == "in") { diff --git a/src/basic_printers.cpp b/src/basic_printers.cpp index bf2647c..7018b89 100644 --- a/src/basic_printers.cpp +++ b/src/basic_printers.cpp @@ -17,10 +17,10 @@ void print_modifier(const nodes::Modifier &modifier, Printer &printer) { case nodes::Modifier::REF: printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> "); break; - case nodes::Modifier::OR_FALSE: + case nodes::Modifier::OPTIONAL: printer.print("?"); break; - case nodes::Modifier::OR_RETURN: + case nodes::Modifier::RESULT: printer.print("!"); break; case nodes::Modifier::NONE: diff --git a/src/expression_printers.cpp b/src/expression_printers.cpp index 327ad02..05eade8 100644 --- a/src/expression_printers.cpp +++ b/src/expression_printers.cpp @@ -338,8 +338,8 @@ void print_modifier_expression(const nodes::ModifierExpression &expression, print_expression(*expression.get_expression(), printer); - if (expression.get_modifier() == nodes::Modifier::OR_FALSE || - expression.get_modifier() == nodes::Modifier::OR_RETURN) { + if (expression.get_modifier() == nodes::Modifier::OPTIONAL || + expression.get_modifier() == nodes::Modifier::RESULT) { print_modifier(expression.get_modifier(), printer); } } diff --git a/src/main.cpp b/src/main.cpp index 9cfe38c..2b35ad1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "basic_printers.hpp" #include "error_handling.hpp" #include "expression_nodes.hpp" +#include "name_tree.hpp" #include "statement_builders.hpp" #include "statement_printers.hpp" #include "type_nodes.hpp" @@ -38,9 +39,10 @@ int main(int argc, char **argv) { nodes::ExpressionStorage expression_storage; nodes::TypeStorage type_storage; + names::NameTree name_tree; auto statements = builders::build_source_file( - parse_tree.get_root(), expression_storage, type_storage); + parse_tree.get_root(), expression_storage, type_storage, name_tree); printers::Printer printer(std::cout, 2, 80, false); printers::print_source_file(statements, printer); diff --git a/src/name_tree.cpp b/src/name_tree.cpp index 439fc2e..a0a9a3d 100644 --- a/src/name_tree.cpp +++ b/src/name_tree.cpp @@ -17,6 +17,20 @@ bool NameTree::insert(const std::string &path, nodes::Statement &&statement) { return true; } +bool NameTree::insert(const std::string &path, + const nodes::Statement &statement) { + auto name_ids = slice_path_to_name_ids(path); + + size_t node_id = add_node(get_root(), name_ids); + + if (nodes_[node_id].get_statement().has_value()) { + return false; + } + + nodes_[node_id].set_statement(statement); + return true; +} + std::optional NameTree::find(const std::string &path) { auto name_ids = slice_path_to_existing_name_ids(path); diff --git a/src/statement_builders.cpp b/src/statement_builders.cpp index fb1a5b3..0a0b1af 100644 --- a/src/statement_builders.cpp +++ b/src/statement_builders.cpp @@ -11,6 +11,7 @@ #include "tree_sitter_wrapper.hpp" #include "type_builders.hpp" #include "type_nodes.hpp" +#include "utils.hpp" #include #include @@ -22,13 +23,14 @@ namespace builders { std::vector build_source_file(parser::ParseTree::Node parser_node, nodes::ExpressionStorage &expression_storage, - nodes::TypeStorage &type_storage) { + nodes::TypeStorage &type_storage, + names::NameTree &name_tree) { std::vector statements; auto current_node = parser_node.nth_named_child(0); while (!current_node.is_null()) { - statements.push_back( - build_statement(current_node, expression_storage, type_storage)); + statements.push_back(build_statement(current_node, expression_storage, + type_storage, name_tree)); current_node = current_node.next_named_sibling(); } @@ -38,29 +40,70 @@ build_source_file(parser::ParseTree::Node parser_node, // import | type_definition | function_definition | typeclass_definition nodes::Statement build_statement(parser::ParseTree::Node parser_node, nodes::ExpressionStorage &expression_storage, - nodes::TypeStorage &type_storage) { + nodes::TypeStorage &type_storage, + names::NameTree &name_tree) { tokens::Type type = tokens::string_to_type(parser_node.get_type()); + std::optional statement_name; + std::optional statement; + switch (type) { case tokens::Type::IMPORT: - return nodes::Statement(build_import(parser_node)); + statement = nodes::Statement(build_import(parser_node)); + statement_name = *statement.value() + .get() + .value() + ->get_module_name() + ->get(); + break; case tokens::Type::TYPE_DEFINITION: - return nodes::Statement( + statement = nodes::Statement( build_type_definition(parser_node, expression_storage, type_storage)); + statement_name = *statement.value() + .get() + .value() + ->get_name() + ->get(); + break; case tokens::Type::FUNCTION_DEFINITION: - return nodes::Statement(build_function_definition( + statement = nodes::Statement(build_function_definition( parser_node, expression_storage, type_storage)); + statement_name = *statement.value() + .get() + .value() + ->get_name() + ->get(); + break; case tokens::Type::TYPECLASS_DEFINITION: - return nodes::Statement(build_typeclass_definition( + statement = nodes::Statement(build_typeclass_definition( parser_node, expression_storage, type_storage)); + statement_name = *statement.value() + .get() + .value() + ->get_name() + ->get(); + break; case tokens::Type::EMPTY_LINES: - return nodes::Statement(build_empty_lines(parser_node)); + statement = build_empty_lines(parser_node); + break; default: error_handling::handle_parsing_error("Unexprected statement node type", parser_node); } - error_handling::handle_general_error("Unreachable"); - exit(1); // unreachable + + if (!statement.has_value()) { + error_handling::handle_general_error("Unreachable"); + } + + if (statement_name.has_value()) { + // TODO: combine statements with same name + if (!name_tree.insert(statement_name.value(), statement.value())) { + error_handling::handle_parsing_error( + "Two or more statements in file have the same name", parser_node); + } + } + + return std::move(statement.value()); } // ('::' | 'import') simple_name ('=' simple_name)? (':' identifier*)? @@ -272,8 +315,8 @@ build_function_definition(parser::ParseTree::Node parser_node, last_after_modifier = build_modifier(maybe_reference_node); // only optional, result allowed - if (last_after_modifier != nodes::Modifier::OR_FALSE && - last_after_modifier != nodes::Modifier::OR_RETURN) { + if (last_after_modifier != nodes::Modifier::OPTIONAL && + last_after_modifier != nodes::Modifier::RESULT) { last_after_modifier = nodes::Modifier::NONE; } } diff --git a/src/statement_printers.cpp b/src/statement_printers.cpp index 2f83478..922f942 100644 --- a/src/statement_printers.cpp +++ b/src/statement_printers.cpp @@ -4,6 +4,7 @@ #include "doc_printers.hpp" #include "expression_nodes.hpp" #include "expression_printers.hpp" +#include "statement_nodes.hpp" #include "type_printers.hpp" namespace printers { diff --git a/src/type_builders.cpp b/src/type_builders.cpp index 7982ff3..b9ddbe4 100644 --- a/src/type_builders.cpp +++ b/src/type_builders.cpp @@ -24,8 +24,8 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parse_node, modifier = build_modifier(current_node); // only optional, result allowed - if (modifier != nodes::Modifier::OR_FALSE && - modifier != nodes::Modifier::OR_RETURN) { + if (modifier != nodes::Modifier::OPTIONAL && + modifier != nodes::Modifier::RESULT) { modifier = nodes::Modifier::NONE; } } diff --git a/tests/test.langexp b/tests/test.langexp index da5b29a..96c9b14 100644 --- a/tests/test.langexp +++ b/tests/test.langexp @@ -2,10 +2,10 @@ :: module; // import module to current namespace -:: _ = module; // import module to current namespace and use functions inside without namespace +:: _ = module_2; // import module to current namespace and use functions inside without namespace -:: module : func1 func2 func3; -:: module_namespace = module; +:: module_3 : func1 func2 func3; +:: module_namespace = module_4; func = { @@ -40,7 +40,7 @@ sum 'a? 'b? = : example that shows that default annotations are argument names (without ') @a is integer @b also integer -sum 'a 'b = 'a + 'b; +sum_2 'a 'b = 'a + 'b; : this function can be used to calculate Fibonacci sequence elements : it is important is some algorithmic tasks @@ -137,7 +137,7 @@ bubble_sort 'arr : <> Array['A] = { } : bubble_sort with names instead of symbols -bubble_sort 'arr : ref Array['A] = { +bubble_sort_2 'arr : ref Array['A] = { var swap_occured := true; for swap_occured do { swap_occured = false; @@ -151,9 +151,7 @@ bubble_sort 'arr : ref Array['A] = { & @key Key & @value Value & @left ^TreeNode['Key 'Value] - & @right ^TreeNode['Key 'Value]; - -TreeNode { + & @right ^TreeNode['Key 'Value] { new = do_something; // static methods $insert 'key = do_something; // const methods @@ -186,7 +184,7 @@ print_two 'a 'b = print 'a, print 'b; swap 'a 'b : <> 'A <> 'A = %c := <- 'a, 'a := <- 'b, 'b := <- c; : previous example with automatic type deduction -swap <> 'a <> 'b = %c := <- 'a, 'a := <- 'b, 'b := <- c; +swap_2 <> 'a <> 'b = %c := <- 'a, 'a := <- 'b, 'b := <- c; : several outputs example scan_three : -> String -> String -> String = scan & scan & scan;