From 469cb3581f057e85ab454876ad852bc3ac7b7cde Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Tue, 25 Jul 2023 21:33:57 +0300 Subject: [PATCH] printing fixes --- CMakeLists.txt | 9 +++ deps/tree-sitter-lang | 2 +- etc/kate_highlighting_lang.xml | 2 + include/basic_builders.hpp | 4 ++ include/basic_nodes.hpp | 22 ++++--- include/basic_printers.hpp | 20 +++--- include/doc_nodes.hpp | 52 +++++++++++---- include/expression_nodes.hpp | 25 +++----- include/statement_nodes.hpp | 14 ++++- include/statement_printers.hpp | 4 +- include/tokens.hpp | 6 ++ include/tree_sitter_wrapper.hpp | 10 +++ src/basic_builders.cpp | 21 +++++-- src/basic_printers.cpp | 6 ++ src/doc_builders.cpp | 4 +- src/doc_printers.cpp | 22 ++++++- src/expression_builders.cpp | 12 ++-- src/expression_printers.cpp | 62 +++++++++++++----- src/statement_builders.cpp | 38 +++++++++-- src/statement_printers.cpp | 108 +++++++++++++++----------------- src/type_printers.cpp | 17 +++-- tests/formatting.langexp | 7 ++- tests/test.langexp | 2 +- 23 files changed, 318 insertions(+), 151 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97bce64..c3f4f84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,13 +12,22 @@ include_directories(include add_executable(lang src/main.cpp + src/type_nodes.cpp src/expression_nodes.cpp + src/basic_builders.cpp src/type_builders.cpp src/doc_builders.cpp src/expression_builders.cpp src/statement_builders.cpp + + src/basic_printers.cpp + src/type_printers.cpp + src/doc_printers.cpp + src/expression_printers.cpp + src/statement_printers.cpp + include/tree_sitter_wrapper.hpp deps/tree-sitter-lang/src/tree_sitter/parser.h deps/tree-sitter-lang/src/parser.c diff --git a/deps/tree-sitter-lang b/deps/tree-sitter-lang index 18d84f5..1c19b47 160000 --- a/deps/tree-sitter-lang +++ b/deps/tree-sitter-lang @@ -1 +1 @@ -Subproject commit 18d84f5f28da3722749477b3bfa58e1dba397bf5 +Subproject commit 1c19b471990acb91cc0ccc9426d988debab8cb27 diff --git a/etc/kate_highlighting_lang.xml b/etc/kate_highlighting_lang.xml index e6eb2c5..d58a95a 100644 --- a/etc/kate_highlighting_lang.xml +++ b/etc/kate_highlighting_lang.xml @@ -44,6 +44,8 @@ + + diff --git a/include/basic_builders.hpp b/include/basic_builders.hpp index 86d2d8b..733cd73 100644 --- a/include/basic_builders.hpp +++ b/include/basic_builders.hpp @@ -47,4 +47,8 @@ nodes::Identifier build_operator(parser::ParseTree::Node parser_node); nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node); +// --- empty lines + +nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node); + } // namespace builders diff --git a/include/basic_nodes.hpp b/include/basic_nodes.hpp index 1cf34a1..150157a 100644 --- a/include/basic_nodes.hpp +++ b/include/basic_nodes.hpp @@ -53,15 +53,9 @@ public: return std::nullopt; } - std::variant * - get_any() { - return &value_; - } + auto get_any() { return &value_; } - const std::variant * - get_any() const { - return &value_; - } + auto get_any() const { return &value_; } private: std::variant value_; @@ -86,7 +80,7 @@ public: Identifier(Node node, IdentifierType type, const std::string &value) : Node(node), type_(type), value_(value) {} - IdentifierType get_type() { return type_; } + IdentifierType get_type() const { return type_; } std::string *get() { return &value_; } @@ -97,4 +91,14 @@ private: std::string value_; }; +class EmptyLines : public Node { +public: + EmptyLines(Node node, size_t size) : Node(node), size_(size) {} + + size_t size() const { return size_; } + +private: + size_t size_; +}; + } // namespace nodes diff --git a/include/basic_printers.hpp b/include/basic_printers.hpp index e584761..6059c7d 100644 --- a/include/basic_printers.hpp +++ b/include/basic_printers.hpp @@ -11,7 +11,7 @@ public: bool print_words_instead_of_symbols) : output_(output), tab_width_(tab_width), width_limit_(width_limit), print_words_instead_of_symbols_(print_words_instead_of_symbols), - current_position_(0), current_indentation_level_(0) {} + current_position_(0), indentation_level_(0) {} void print_converted(const std::string &value) { for (auto &ch : value) { @@ -34,7 +34,7 @@ public: void new_indent_line() { end_line(); - print_spaces(current_indentation_level_ * tab_width_); + print_spaces(indentation_level_); } void new_line(size_t indentation) { @@ -42,9 +42,9 @@ public: print_spaces(indentation); } - void indent() { current_indentation_level_ += tab_width_; } + void indent() { indentation_level_ += tab_width_; } - void deindent() { current_indentation_level_ -= tab_width_; } + void deindent() { indentation_level_ -= tab_width_; } void tab() { print_spaces(tab_width_); } @@ -66,12 +66,10 @@ public: size_t get_current_position() const { return current_position_; } - size_t get_current_indentation_level() const { - return current_indentation_level_; - } + size_t get_indentation_level() const { return indentation_level_; } - size_t set_current_indentation_level(size_t indentation_level) { - current_indentation_level_ = indentation_level; + void set_indentation_level(size_t indentation_level) { + indentation_level_ = indentation_level; } private: @@ -117,7 +115,7 @@ private: bool print_words_instead_of_symbols_ = false; size_t current_position_ = 0; - size_t current_indentation_level_ = 0; + size_t indentation_level_ = 0; }; void print_literal(const nodes::Literal &literal, Printer &printer); @@ -126,4 +124,6 @@ void print_identifier(const nodes::Identifier &identifier, Printer &printer); void print_annotation(const std::string &annotation, Printer &printer); +void print_empty_lines(const nodes::EmptyLines &empty_lines, Printer &printer); + } // namespace printers diff --git a/include/doc_nodes.hpp b/include/doc_nodes.hpp index 52bde93..ef6a128 100644 --- a/include/doc_nodes.hpp +++ b/include/doc_nodes.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace nodes { @@ -16,8 +17,9 @@ public: SymbolDocs(const std::string &description) : description_(description) {} bool add_annotation_info(const std::string &annotation, std::string &&info) { - if (annotations_info_.count(annotation) == 0) { - annotations_info_[annotation] = std::move(info); + if (annotations_info_ids_.count(annotation) == 0) { + annotations_info_ids_[annotation] = annotations_info_.size(); + annotations_info_.emplace_back(annotation, std::move(info)); return true; } return false; @@ -25,13 +27,16 @@ public: bool add_annotation_info(const std::string &annotation, const std::string &info) { - if (annotations_info_.count(annotation) == 0) { - annotations_info_[annotation] = info; + if (annotations_info_ids_.count(annotation) == 0) { + annotations_info_ids_[annotation] = annotations_info_.size(); + annotations_info_.emplace_back(annotation, std::move(info)); return true; } return false; } + // + std::optional get_description() { if (description_.has_value()) { return &description_.value(); @@ -46,27 +51,52 @@ public: return std::nullopt; } + // + std::optional get_annotation_info(const std::string &annotation) { - auto info_iterator = annotations_info_.find(annotation); - if (info_iterator != annotations_info_.end()) { - return &info_iterator->second; + auto info_iterator = annotations_info_ids_.find(annotation); + if (info_iterator != annotations_info_ids_.end()) { + return &annotations_info_[info_iterator->second].second; } return std::nullopt; } std::optional get_annotation_info(const std::string &annotation) const { - auto info_iterator = annotations_info_.find(annotation); - if (info_iterator != annotations_info_.end()) { - return &info_iterator->second; + auto info_iterator = annotations_info_ids_.find(annotation); + if (info_iterator != annotations_info_ids_.end()) { + return &annotations_info_[info_iterator->second].second; } return std::nullopt; } + // + + size_t get_annotations_info_size() const { return annotations_info_.size(); } + + std::string *get_annotation(size_t id) { + return &annotations_info_[id].first; + } + + const std::string *get_annotation(size_t id) const { + return &annotations_info_[id].first; + } + + std::string *get_annotation_info(size_t id) { + return &annotations_info_[id].second; + } + + const std::string *get_annotation_info(size_t id) const { + return &annotations_info_[id].second; + } + + // + private: std::optional description_; - std::unordered_map annotations_info_; + std::vector> annotations_info_; + std::unordered_map annotations_info_ids_; }; } // namespace nodes diff --git a/include/expression_nodes.hpp b/include/expression_nodes.hpp index bb49b6f..28098e5 100644 --- a/include/expression_nodes.hpp +++ b/include/expression_nodes.hpp @@ -167,13 +167,13 @@ public: : Node(node), type_(LOOP), expression_(expression) {} // WHILE - Loop(Node node, ExpressionProxy expression, ExpressionProxy condition) + Loop(Node node, ExpressionProxy condition, ExpressionProxy expression) : Node(node), type_(WHILE), expression_(expression), condition_(condition) {} // FOR - Loop(Node node, ExpressionProxy expression, ExpressionProxy variable, - ExpressionProxy interval) + Loop(Node node, ExpressionProxy variable, ExpressionProxy interval, + ExpressionProxy expression) : Node(node), type_(FOR), expression_(expression), variable_(variable), interval_(interval) {} @@ -528,19 +528,9 @@ public: return std::nullopt; } - std::variant * - get_any() { - return &expression_; - } + auto get_any() { return &expression_; } - const std::variant * - get_any() const { - return &expression_; - } + auto get_any() const { return &expression_; } bool is_scoped() const { return is_scoped_; } @@ -570,7 +560,10 @@ private: NameExpression, Constructor, Lambda, // --- literal - Literal + Literal, + + // --- empty lines + EmptyLines > expression_; diff --git a/include/statement_nodes.hpp b/include/statement_nodes.hpp index 8078f93..82006cb 100644 --- a/include/statement_nodes.hpp +++ b/include/statement_nodes.hpp @@ -75,13 +75,16 @@ public: std::vector &&types, std::vector &&optional_arguments, std::vector &&result_arguments, + bool is_annotations_same_to_names, std::optional expression) : Node(node), docs_(std::move(docs)), constraints_(std::move(constraints)), modifier_(modifier), name_(name), annotations_(std::move(annotations)), arguments_(std::move(arguments)), reference_types_(std::move(reference_types)), types_(std::move(types)), optional_arguments_(optional_arguments), - result_arguments_(result_arguments), expression_(expression) {} + result_arguments_(result_arguments), + is_annotations_same_to_names_(is_annotations_same_to_names), + expression_(expression) {} // @@ -91,7 +94,7 @@ public: // - size_t get_constraints_size() const { return arguments_.size(); } + size_t get_constraints_size() const { return constraints_.size(); } Constraint *get_constraint(size_t id) { return &constraints_.at(id); } @@ -159,6 +162,12 @@ public: // + bool is_annotations_same_to_names() const { + return is_annotations_same_to_names_; + } + + // + std::optional get_expression() { if (expression_.has_value()) { return expression_.value().get(); @@ -184,6 +193,7 @@ private: std::vector types_; std::vector optional_arguments_; std::vector result_arguments_; + bool is_annotations_same_to_names_; std::optional expression_; }; // refactor ?? diff --git a/include/statement_printers.hpp b/include/statement_printers.hpp index 29c3013..40bc228 100644 --- a/include/statement_printers.hpp +++ b/include/statement_printers.hpp @@ -5,9 +5,9 @@ namespace printers { -void print_source_file(Printer &printer); // TODO +// void print_source_file(Printer &printer); // TODO -void print_statement(Printer &printer); // TODO +// void print_statement(Printer &printer); // TODO void print_import(const nodes::Import &statement, Printer &printer); diff --git a/include/tokens.hpp b/include/tokens.hpp index 51ef609..051ccbf 100644 --- a/include/tokens.hpp +++ b/include/tokens.hpp @@ -62,6 +62,8 @@ enum class Type { DEFINITION_INFO, ANNOTATION_INFO, + EMPTY_LINES, + // --- tokens PLACEHOLDER, @@ -146,6 +148,8 @@ const static std::string TYPE = "type"; const static std::string DEFINITION_INFO = "definition_info"; const static std::string ANNOTATION_INFO = "annotation_info"; +const static std::string EMPTY_LINES = "empty_lines"; + // --- tokens const static std::string PLACEHOLDER = "placeholder"; @@ -228,6 +232,8 @@ inline Type string_to_type(const std::string &str) { return Type::DEFINITION_INFO; } else if (str == ANNOTATION_INFO) { return Type::ANNOTATION_INFO; + } else if (str == EMPTY_LINES) { + return Type::EMPTY_LINES; } else if (str == PLACEHOLDER) { return Type::PLACEHOLDER; } else if (str == SIMPLE_NAME_IDENTIFIER) { diff --git a/include/tree_sitter_wrapper.hpp b/include/tree_sitter_wrapper.hpp index 87e35f4..717495a 100644 --- a/include/tree_sitter_wrapper.hpp +++ b/include/tree_sitter_wrapper.hpp @@ -63,6 +63,16 @@ public: return source_->substr(start, end - start); } + size_t get_value_length() const { // from source + if (is_null()) { + error_handling::handle_general_error( + "Null parsing node method called (get_value_length)"); + } + size_t start = ts_node_start_byte(node_); + size_t end = ts_node_end_byte(node_); + return end - start; + } + bool is_null() const { return ts_node_is_null(node_); } bool is_named() const { diff --git a/src/basic_builders.cpp b/src/basic_builders.cpp index f354525..387e223 100644 --- a/src/basic_builders.cpp +++ b/src/basic_builders.cpp @@ -224,12 +224,14 @@ std::string build_annotation(parser::ParseTree::Node parser_node) { nodes::Identifier build_operator(parser::ParseTree::Node parser_node) { std::string identifier = parser_node.get_value(); - if (identifier.size() > 0 && identifier.front() != '.') { - // for not point only identifiers - while (identifier.size() > 0 && identifier.back() == '.') { - identifier.pop_back(); - } - } + // --- points needed for proper printing + // if (identifier.size() > 0 && identifier.front() != '.') { + // // for not point only identifiers + // while (identifier.size() > 0 && identifier.back() == '.') { + // identifier.pop_back(); + // } + // } + // --- return nodes::Identifier(build_node(parser_node), nodes::Identifier::OPERATOR, identifier); @@ -240,4 +242,11 @@ nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node) { nodes::Identifier::PLACEHOLDER, "_"); } +// --- empty lines + +nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node) { + return nodes::EmptyLines(build_node(parser_node), + parser_node.get_value_length() - 1); +} + } // namespace builders diff --git a/src/basic_printers.cpp b/src/basic_printers.cpp index dfca297..eedde37 100644 --- a/src/basic_printers.cpp +++ b/src/basic_printers.cpp @@ -53,4 +53,10 @@ void print_annotation(const std::string &annotation, Printer &printer) { printer.print(annotation); } +void print_empty_lines(const nodes::EmptyLines &empty_lines, Printer &printer) { + for (size_t i = 0; i < empty_lines.size(); ++i) { + printer.new_indent_line(); + } +} + } // namespace printers diff --git a/src/doc_builders.cpp b/src/doc_builders.cpp index d2604d7..9d5f6db 100644 --- a/src/doc_builders.cpp +++ b/src/doc_builders.cpp @@ -18,8 +18,8 @@ nodes::SymbolDocs build_symbol_docs( // remove newline delimeters (": " at each new line size_t j = 0; - for (size_t i = 0; i < description.value().size(); ++i, ++j) { - if (j != i) { + for (size_t i = 2; i < description.value().size(); ++i, ++j) { + if (j != i) { // always true description.value()[j] = description.value()[i]; } diff --git a/src/doc_printers.cpp b/src/doc_printers.cpp index 3c0bada..e2e0906 100644 --- a/src/doc_printers.cpp +++ b/src/doc_printers.cpp @@ -1,4 +1,5 @@ #include "doc_printers.hpp" +#include "basic_printers.hpp" #include "utils.hpp" namespace printers { @@ -6,8 +7,27 @@ namespace printers { // TODO void print_docs(const nodes::SymbolDocs &docs, Printer &printer) { + auto description = docs.get_description(); - error_handling::handle_general_error("Docs printing unimplemented yet"); + if (description.has_value()) { + printer.print(": "); + for (auto &ch : *description.value()) { + if (ch == '\n') { + printer.new_indent_line(); + printer.print(": "); + } else { + printer.print(std::string(1, ch)); + } + } + printer.new_indent_line(); + } + + for (size_t i = 0; i < docs.get_annotations_info_size(); ++i) { + print_annotation(*docs.get_annotation(i), printer); + printer.space(); + printer.print(*docs.get_annotation_info(i)); + printer.new_indent_line(); + } } // IN PROGRESS diff --git a/src/expression_builders.cpp b/src/expression_builders.cpp index 883b826..754149a 100644 --- a/src/expression_builders.cpp +++ b/src/expression_builders.cpp @@ -16,9 +16,10 @@ build_expression(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { tokens::Type type = tokens::string_to_type(parser_node.get_type()); - auto maybe_parenthesis = parser_node.next_sibling(); + auto maybe_parenthesis = parser_node.previous_sibling(); bool is_scoped = - (!maybe_parenthesis.is_null() && maybe_parenthesis.get_value() == "("); + (!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() && + maybe_parenthesis.get_value() == "("); switch (type) { // --- flow control @@ -119,6 +120,9 @@ build_expression(parser::ParseTree::Node parser_node, case tokens::Type::NULL_LITERAL: return expression_storage.add_expression( nodes::Expression(build_null_literal(parser_node), is_scoped)); + case tokens::Type::EMPTY_LINES: + return expression_storage.add_expression( + nodes::Expression(build_empty_lines(parser_node), is_scoped)); default: error_handling::handle_parsing_error("Unexprected expression node type", parser_node); @@ -271,7 +275,7 @@ build_comma_expression(parser::ParseTree::Node parser_node, return nodes::NameExpression( build_node(parser_node), nodes::Identifier( - build_node(parser_node), // can't find more precise location' + build_node(parser_node), // can't find more precise location nodes::Identifier::SIMPLE_NAME, ","), std::move(arguments), std::nullopt, false, true); } @@ -308,7 +312,7 @@ build_container(parser::ParseTree::Node parser_node, nodes::Container::ContainerType container_type) { std::vector expressions; - auto current_node = parser_node.nth_named_child(0).next_named_sibling(); + auto current_node = parser_node.nth_named_child(0); while (!current_node.is_null()) { expressions.push_back( diff --git a/src/expression_printers.cpp b/src/expression_printers.cpp index 84b40e2..d354e25 100644 --- a/src/expression_printers.cpp +++ b/src/expression_printers.cpp @@ -2,6 +2,7 @@ #include "basic_nodes.hpp" #include "basic_printers.hpp" #include "expression_nodes.hpp" +#include "tokens.hpp" #include "type_printers.hpp" namespace printers { @@ -60,6 +61,10 @@ void print_expression(const nodes::Expression &expression, case 12: // Literal print_literal(*expression.get().value(), printer); break; + // --- empty lines + case 13: // EmptyLines + print_empty_lines(*expression.get().value(), printer); + break; } if (expression.is_scoped()) { @@ -100,9 +105,9 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) { printer.space(); - size_t previous_indentation_level = printer.get_current_indentation_level(); + size_t previous_indentation_level = printer.get_indentation_level(); - printer.set_current_indentation_level(printer.current_position()); + printer.set_indentation_level(printer.current_position()); for (size_t i = 0; i < expression.cases_size(); ++i) { print_case(*expression.get_case(i), printer); @@ -112,7 +117,7 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) { } } - printer.set_current_indentation_level(previous_indentation_level); + printer.set_indentation_level(previous_indentation_level); } // IN PROGRESS @@ -123,17 +128,19 @@ void print_condition(const nodes::Condition &expression, if (i == 0) { printer.print(printer.print_words_instead_of_symbols() ? "if " : "?? "); } else { + printer.new_indent_line(); printer.print(printer.print_words_instead_of_symbols() ? "elif " : "!! "); } print_expression(*expression.get_case(i).first, printer); - printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> "); + printer.print(printer.print_words_instead_of_symbols() ? " do " : " => "); print_expression(*expression.get_case(i).second, printer); } if (expression.get_else_case().has_value()) { + printer.new_indent_line(); printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> "); print_expression(*expression.get_else_case().value(), printer); } @@ -163,7 +170,6 @@ void print_loop(const nodes::Loop &expression, printers::Printer &printer) { printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> "); print_expression(*expression.get_expression(), printer); - printer.print(";"); } // IN PROGRESS // --- containers @@ -177,16 +183,23 @@ void print_container(const nodes::Container &expression, } else { printer.print("{"); printer.indent(); - printer.new_indent_line(); } for (size_t i = 0; i < expression.expressions_size(); ++i) { + bool is_empty_lines_expression = expression.get_expression(i)->get().has_value(); + + if (!is_array && !is_empty_lines_expression) { + printer.new_indent_line(); + } print_expression(*expression.get_expression(i), printer); if (is_array) { - printer.space(); + if (i + 1 < expression.expressions_size()) { + printer.space(); + } } else { - printer.print(";"); - printer.new_indent_line(); + if (!is_empty_lines_expression) { + printer.print(";"); + } } } @@ -194,8 +207,8 @@ void print_container(const nodes::Container &expression, printer.print("]]"); } else { printer.deindent(); - printer.print("}"); printer.new_indent_line(); + printer.print("}"); } } // IN PROGRESS @@ -234,10 +247,10 @@ void print_name_definition(const nodes::NameDefinition &expression, } else { switch (expression.get_modifier()) { case nodes::NameDefinition::LET: - printer.print("% "); + printer.print("%"); break; case nodes::NameDefinition::VAR: - printer.print("$ "); + printer.print("$"); break; default: break; @@ -343,7 +356,7 @@ void print_name_expression(const nodes::NameExpression &expression, print_expression(*expression.get_argument_value(0), printer); if (expression.is_point_call()) { printer.print("."); - } else { + } else if (*expression.get_name()->get() != ",") { printer.space(); } } else if (expression.get_prefix().has_value()) { @@ -351,10 +364,27 @@ void print_name_expression(const nodes::NameExpression &expression, printer.print("."); } - // TODO: properly print operator name + // + + bool operator_called_as_function = + (!expression.is_operator_call() && + expression.get_name()->get_type() == nodes::Identifier::OPERATOR); + + if (operator_called_as_function) { + printer.print("( "); + } + print_identifier(*expression.get_name(), printer); - for (size_t i = 0; i < expression.arguments_size(); ++i) { + if (operator_called_as_function) { + printer.print(" )"); + } + + // + + for (size_t i = + expression.is_operator_call() || expression.is_point_call() ? 1 : 0; + i < expression.arguments_size(); ++i) { printer.space(); if (expression.get_argument_annotation(i).has_value()) { @@ -384,7 +414,7 @@ void print_constructor(const nodes::Constructor &expression, } // IN PROGRESS void print_lambda(const nodes::Lambda &expression, printers::Printer &printer) { - printer.print(printer.print_words_instead_of_symbols() ? "lambda " : "\\ "); + printer.print(printer.print_words_instead_of_symbols() ? "lambda " : "\\"); for (size_t i = 0; i < expression.arguments_size(); ++i) { print_identifier(*expression.get_argument(i), printer); diff --git a/src/statement_builders.cpp b/src/statement_builders.cpp index d650d2f..1a843a9 100644 --- a/src/statement_builders.cpp +++ b/src/statement_builders.cpp @@ -2,11 +2,13 @@ #include "basic_builders.hpp" #include "basic_nodes.hpp" +#include "basic_printers.hpp" #include "doc_builders.hpp" #include "doc_nodes.hpp" #include "error_handling.hpp" #include "expression_builders.hpp" #include "statement_nodes.hpp" +#include "statement_printers.hpp" #include "tokens.hpp" #include "tree_sitter_wrapper.hpp" #include "type_builders.hpp" @@ -37,18 +39,42 @@ void build_statement(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { tokens::Type type = tokens::string_to_type(parser_node.get_type()); + printers::Printer printer(std::cout, 2, 80, false); + switch (type) { case tokens::Type::IMPORT: build_import(parser_node); + printers::print_import(build_import(parser_node), + printer); // TODO TEMPORARY + printer.new_indent_line(); return; case tokens::Type::TYPE_DEFINITION: build_type_definition(parser_node, expression_storage, type_storage); + printers::print_type_definition( + build_type_definition(parser_node, expression_storage, type_storage), + printer); // TODO TEMPORARY + printer.new_indent_line(); return; case tokens::Type::FUNCTION_DEFINITION: build_function_definition(parser_node, expression_storage, type_storage); + printers::print_function_definition( + build_function_definition(parser_node, expression_storage, + type_storage), + printer); // TODO TEMPORARY + printer.new_indent_line(); return; case tokens::Type::TYPECLASS_DEFINITION: build_typeclass_definition(parser_node, expression_storage, type_storage); + printers::print_typeclass_definition( + build_typeclass_definition(parser_node, expression_storage, + type_storage), + printer); // TODO TEMPORARY + printer.new_indent_line(); + return; + case tokens::Type::EMPTY_LINES: + build_empty_lines(parser_node); + printers::print_empty_lines(build_empty_lines(parser_node), + printer); // TODO TEMPORARY return; default: error_handling::handle_parsing_error("Unexprected statement node type", @@ -219,7 +245,7 @@ build_function_definition(parser::ParseTree::Node parser_node, nodes::FunctionDefinition::STATIC; current_node = name_node.previous_sibling(); - if (!current_node.is_null() && current_node.is_named()) { + if (!current_node.is_null() && !current_node.is_named()) { std::string modifier_str = current_node.get_value(); if (modifier_str == "%" || modifier_str == "let") { modifier = nodes::FunctionDefinition::LET; @@ -270,11 +296,11 @@ build_function_definition(parser::ParseTree::Node parser_node, argument_reference_types.push_back(last_reference_type); arguments.push_back(build_identifier(current_node)); optional_arguments.push_back(!current_node.next_sibling().is_null() && - current_node.next_sibling().is_named() && + !current_node.next_sibling().is_named() && current_node.next_sibling().get_value() == "?"); result_arguments.push_back(!current_node.next_sibling().is_null() && - current_node.next_sibling().is_named() && + !current_node.next_sibling().is_named() && current_node.next_sibling().get_value() == "!"); if (optional_arguments.back() || result_arguments.back()) { @@ -306,7 +332,10 @@ build_function_definition(parser::ParseTree::Node parser_node, std::vector> *annotations = nullptr; std::vector *reference_types = nullptr; - if (!at_least_one_argument_annotation_found) { + bool is_annotations_same_to_names = + (!at_least_one_argument_annotation_found && types.empty()); + + if (is_annotations_same_to_names) { for (size_t i = 0; i < argument_annotations.size(); ++i) { std::string argument_annotation = *arguments[i].get(); argument_annotations[i] = @@ -346,6 +375,7 @@ build_function_definition(parser::ParseTree::Node parser_node, std::move(*annotations), std::move(arguments), std::move(*reference_types), std::move(types), std::move(optional_arguments), std::move(result_arguments), + is_annotations_same_to_names, expression_node.has_value() ? build_expression(expression_node.value(), expression_storage, type_storage) diff --git a/src/statement_printers.cpp b/src/statement_printers.cpp index a51e2a1..ce5c368 100644 --- a/src/statement_printers.cpp +++ b/src/statement_printers.cpp @@ -28,9 +28,6 @@ void print_import(const nodes::Import &statement, Printer &printer) { } } printer.print(";"); - - printer.new_indent_line(); - printer.new_indent_line(); } // IN PROGRESS void print_constraint(const nodes::Constraint &statement, Printer &printer) { @@ -39,6 +36,28 @@ void print_constraint(const nodes::Constraint &statement, Printer &printer) { printer.print(";"); } +template +void print_statement_methods(const T &statement, Printer &printer) { + if (statement.get_methods_size() > 0) { + printer.print(" {"); + printer.indent(); + + for (size_t i = 0; i < statement.get_methods_size(); ++i) { + printer.new_indent_line(); + print_function_definition(*statement.get_method(i), printer); + if (i + 1 < statement.get_methods_size()) { + printer.new_indent_line(); + } + } + + printer.deindent(); + printer.new_indent_line(); + printer.print("}"); + } else { + printer.print(";"); + } +} + void print_type_definition(const nodes::TypeDefinition &statement, Printer &printer) { print_docs(*statement.get_docs(), printer); // TODO @@ -57,33 +76,16 @@ void print_type_definition(const nodes::TypeDefinition &statement, if (statement.get_type().has_value()) { printer.print(" = "); - size_t previous_indentation_level = printer.get_current_indentation_level(); + size_t previous_indentation_level = printer.get_indentation_level(); - printer.set_current_indentation_level(printer.get_current_position()); + printer.set_indentation_level(printer.get_current_position() - 2); print_variant_type(*statement.get_type().value(), printer); - printer.set_current_indentation_level(previous_indentation_level); - } - - // TODO: same to typeclass, make separated function - if (statement.get_methods_size() > 0) { - printer.print(" {"); - printer.indent(); - - for (size_t i = 0; i < statement.get_methods_size(); ++i) { - printer.new_indent_line(); - print_function_definition(*statement.get_method(i), printer); - printer.new_indent_line(); - } - - printer.deindent(); - printer.new_indent_line(); - printer.print("} "); - } else { - printer.print(";"); + printer.set_indentation_level(previous_indentation_level); } + print_statement_methods(statement, printer); } // IN PROGRESS void print_function_definition(const nodes::FunctionDefinition &statement, @@ -99,22 +101,36 @@ void print_function_definition(const nodes::FunctionDefinition &statement, case nodes::FunctionDefinition::STATIC: break; case nodes::FunctionDefinition::LET: - printer.print(printer.print_words_instead_of_symbols() ? "let " : "% "); + printer.print(printer.print_words_instead_of_symbols() ? "let " : "%"); break; case nodes::FunctionDefinition::VAR: - printer.print(printer.print_words_instead_of_symbols() ? "var " : "$ "); + printer.print(printer.print_words_instead_of_symbols() ? "var " : "$"); break; default: // remove ?? break; } + bool operator_called_as_function = + (statement.get_name()->get_type() == nodes::Identifier::OPERATOR); + + if (operator_called_as_function) { + printer.print("( "); + } + print_identifier(*statement.get_name(), printer); + if (operator_called_as_function) { + printer.print(" )"); + } + // TODO: same fragments with function type, maybe better make separated // function for (size_t i = 0; i < statement.get_arguments_size(); ++i) { + printer.space(); + if (statement.get_argument_types_size() == 0) { - if (statement.get_argument_annotation(i).has_value()) { + if (!statement.is_annotations_same_to_names() && + statement.get_argument_annotation(i).has_value()) { print_annotation(*statement.get_argument_annotation(i).value(), printer); printer.space(); @@ -154,7 +170,7 @@ void print_function_definition(const nodes::FunctionDefinition &statement, } } - if (statement.get_argument_types_size() > 0) { // TODO + if (statement.get_argument_types_size() > 0) { printer.print(" :"); for (size_t i = 0; i < statement.get_argument_types_size(); ++i) { printer.space(); @@ -183,22 +199,18 @@ void print_function_definition(const nodes::FunctionDefinition &statement, } print_type(*statement.get_argument_type(i), printer); - - // TODO: can't be optional and result in same time - - if (statement.is_argument_optional(i)) { - printer.print("?"); - } - - if (statement.is_argument_result(i)) { - printer.print("!"); - } } } if (statement.get_expression().has_value()) { printer.print(" = "); print_expression(*statement.get_expression().value(), printer); + if (!statement.get_expression() + .value() + ->get() + .has_value()) { + printer.print(";"); + } } else { printer.print(";"); } @@ -218,25 +230,7 @@ void print_typeclass_definition(const nodes::TypeclassDefinition &statement, } } - if (statement.get_methods_size() > 0) { - printer.print(" {"); - printer.indent(); - - for (size_t i = 0; i < statement.get_methods_size(); ++i) { - printer.new_indent_line(); - print_function_definition(*statement.get_method(i), printer); - printer.new_indent_line(); - } - - printer.deindent(); - printer.new_indent_line(); - printer.print("} "); - } else { - printer.print(";"); - } - - printer.new_indent_line(); - printer.new_indent_line(); + print_statement_methods(statement, printer); } // IN PROGRESS } // namespace printers diff --git a/src/type_printers.cpp b/src/type_printers.cpp index 75c3034..82e99be 100644 --- a/src/type_printers.cpp +++ b/src/type_printers.cpp @@ -19,12 +19,16 @@ void print_type(const nodes::Type &type, printers::Printer &printer) { printer.print("!"); } - printer.print("["); - for (size_t i = 0; i < type.get_parametrs_size(); ++i) { - print_type(*type.get_parameter(i), printer); - printer.space(); + if (type.get_parametrs_size() > 0) { + printer.print("["); + for (size_t i = 0; i < type.get_parametrs_size(); ++i) { + print_type(*type.get_parameter(i), printer); + if (i + 1 < type.get_parametrs_size()) { + printer.space(); + } + } + printer.print("]"); } - printer.print("]"); } void print_tuple_type(const nodes::TupleType &type, @@ -37,6 +41,7 @@ void print_tuple_type(const nodes::TupleType &type, if (annotation.has_value()) { print_annotation(*annotation.value(), printer); + printer.space(); } print_type(*type.get(i), printer); @@ -46,7 +51,7 @@ void print_tuple_type(const nodes::TupleType &type, void print_variant_type(const nodes::VariantType &type, printers::Printer &printer) { for (size_t i = 0; i < type.size(); ++i) { - if (type.size() > 1 || i > 0) { + if (i > 0) { printer.print("| "); } diff --git a/tests/formatting.langexp b/tests/formatting.langexp index b2f698c..7f54128 100644 --- a/tests/formatting.langexp +++ b/tests/formatting.langexp @@ -85,7 +85,7 @@ func 'a 'b 'c - : A B C -> D + : A B C -> D; func 'a 'b 'c : @@ -127,7 +127,7 @@ func = { // operators, containers, modifiers -func { +func = { x + y; @@ -167,10 +167,11 @@ func { <> x; x?; +} // other -func { +func = { x .func a b c; diff --git a/tests/test.langexp b/tests/test.langexp index f76a9f1..da5b29a 100644 --- a/tests/test.langexp +++ b/tests/test.langexp @@ -90,7 +90,7 @@ func_2 = { maybe_something!; // open optional: if null then return default value (operator) - %x := maybe_something ?| value + %x := maybe_something ?| value; %y := Fruit @apple ();