diff --git a/include/builders/type_builders.hpp b/include/builders/type_builders.hpp index 1269e1a..c39607c 100644 --- a/include/builders/type_builders.hpp +++ b/include/builders/type_builders.hpp @@ -8,12 +8,12 @@ namespace builders { nodes::TypeProxy build_type(parser::ParseTree::Node parse_node, nodes::TypeStorage &type_storage); -nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parse_node, - nodes::TypeStorage &type_storage); - nodes::TypeProxy build_variant_type(parser::ParseTree::Node parse_node, nodes::TypeStorage &type_storage); +nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parse_node, + nodes::TypeStorage &type_storage); + nodes::TypeProxy build_array_type(parser::ParseTree::Node parse_node, nodes::TypeStorage &type_storage); diff --git a/include/builtin_identifiers.hpp b/include/builtin_identifiers.hpp deleted file mode 100644 index 409f46b..0000000 --- a/include/builtin_identifiers.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -namespace builtin { - -const static std::string TUPLE_IDENTIFIER = "Tuple"; - -const static std::string VARIANT_IDENTIFIER = "Variant"; - -const static std::string ARRAY_IDENTIFIER = "Array"; - -const static std::string OPTIONAL_IDENTIFIER = "Optional"; - -const static std::string RESULT_IDENTIFIER = "Result"; - -} // namespace builtin diff --git a/include/builtin_types.hpp b/include/builtin_types.hpp new file mode 100644 index 0000000..741e442 --- /dev/null +++ b/include/builtin_types.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "basic_nodes.hpp" + +namespace builtin { + +const static std::string TUPLE_IDENTIFIER = "Tuple"; + +const static std::string VARIANT_IDENTIFIER = "Variant"; + +const static std::string ARRAY_IDENTIFIER = "Array"; + +const static std::string OPTIONAL_IDENTIFIER = "Optional"; + +const static std::string RESULT_IDENTIFIER = "Result"; + +enum class BuiltinType { + TUPLE, + VARIANT, + ARRAY, + OPTIONAL, + RESULT, + NONE, +}; + +inline nodes::Modifier builtin_to_modifier(BuiltinType type) { + switch (type) { + case BuiltinType::OPTIONAL: + return nodes::Modifier::OPTIONAL; + case BuiltinType::RESULT: + return nodes::Modifier::RESULT; + default: + return nodes::Modifier::NONE; + } +} + +} // namespace builtin diff --git a/include/nodes/statement_nodes.hpp b/include/nodes/statement_nodes.hpp index 64726e9..8970ada 100644 --- a/include/nodes/statement_nodes.hpp +++ b/include/nodes/statement_nodes.hpp @@ -1,6 +1,7 @@ #pragma once #include "basic_nodes.hpp" +#include "builtin_types.hpp" #include "doc_nodes.hpp" #include "expression_nodes.hpp" #include "type_nodes.hpp" @@ -92,7 +93,8 @@ public: Modifier before_modifier = Modifier::NONE) : annotation_(annotation), type_(type), before_modifier_(before_modifier), - after_modifier_(type.get()->get_modifier()) {} + after_modifier_( + builtin::builtin_to_modifier(type.get()->to_builtin())) {} // @@ -143,15 +145,18 @@ public: return false; } + auto type_after_modifier = + builtin::builtin_to_modifier(type.get()->to_builtin()); + if (after_modifier_ != Modifier::NONE && - after_modifier_ != type.get()->get_modifier()) { + after_modifier_ != type_after_modifier) { return false; } annotation_ = annotation; type_ = type; before_modifier_ = before_modifier; - after_modifier_ = type.get()->get_modifier(); + after_modifier_ = type_after_modifier; return true; } @@ -335,7 +340,7 @@ public: TypeDefinition(Node node, SymbolDocs &&docs, bool is_on_heap, const Identifier &name, std::vector &&typeclasses, std::vector &&arguments, - std::optional &type) + std::optional type) : Node(node), docs_(std::move(docs)), is_on_heap_(is_on_heap), name_(name), typeclasses_(typeclasses), arguments_(std::move(arguments)), type_(std::move(type)) {} diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index fe7e163..3fe36ba 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -1,7 +1,9 @@ #pragma once #include "basic_nodes.hpp" +#include "builtin_types.hpp" +#include #include #include #include @@ -34,21 +36,28 @@ private: // can't have both optional and result modifiers ?? class Type : public Node { public: - Type(Node node, Identifier &&identifier, bool is_on_heap = false) - : Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap) {} + Type(Node node, Identifier &&identifier, bool is_on_heap = false, + const std::optional &annotation = std::nullopt) + : Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap), + annotation_(annotation) {} - Type(Node node, const Identifier &identifier, bool is_on_heap = false) - : Node(node), name_(identifier), is_on_heap_(is_on_heap) {} + Type(Node node, const Identifier &identifier, bool is_on_heap = false, + const std::optional &annotation = std::nullopt) + : Node(node), name_(identifier), is_on_heap_(is_on_heap), + annotation_(annotation) {} Type(Node node, Identifier &&identifier, std::vector &¶meters, - bool is_on_heap = false) + bool is_on_heap = false, + const std::optional &annotation = std::nullopt) : Node(node), name_(std::move(identifier)), - parameters_(std::move(parameters)), is_on_heap_(is_on_heap) {} + parameters_(std::move(parameters)), is_on_heap_(is_on_heap), + annotation_(annotation) {} Type(Node node, const Identifier &identifier, - std::vector &¶meters, bool is_on_heap = false) + std::vector &¶meters, bool is_on_heap = false, + const std::optional &annotation = std::nullopt) : Node(node), name_(identifier), parameters_(std::move(parameters)), - is_on_heap_(is_on_heap) {} + is_on_heap_(is_on_heap), annotation_(annotation) {} // @@ -74,6 +83,42 @@ public: // + std::optional get_annotation() { + if (annotation_.has_value()) { + return &annotation_.value(); + } + return std::nullopt; + } + + std::optional get_annotation() const { + if (annotation_.has_value()) { + return &annotation_.value(); + } + return std::nullopt; + } + + void set_annotation(std::string &&annotation) { + annotation_ = std::move(annotation); + } + + void set_annotation(const std::string &annotation) { + annotation_ = annotation; + } + + template + void collect_annotations_recursively( + std::insert_iterator insert_iterator) const { + if (annotation_.has_value()) { + insert_iterator = annotation_.value(); + } + + for (auto ¶meter : parameters_) { + parameter.get()->collect_annotations_recursively(insert_iterator); + } + } + + // + bool operator==(const Type &other_type) const { if (name_ != other_type.name_ || is_on_heap_ != other_type.is_on_heap_ || parameters_.size() != other_type.parameters_.size()) { @@ -93,11 +138,33 @@ public: return !(*this == other_type); } + // is parameters count check necessary ?? + builtin::BuiltinType to_builtin() { + if (*name_.get() == builtin::TUPLE_IDENTIFIER && parameters_.size() > 0) { + return builtin::BuiltinType::TUPLE; + } else if (*name_.get() == builtin::VARIANT_IDENTIFIER && + parameters_.size() > 0) { + return builtin::BuiltinType::VARIANT; + } else if (*name_.get() == builtin::ARRAY_IDENTIFIER && + parameters_.size() == 1) { + return builtin::BuiltinType::ARRAY; + } else if (*name_.get() == builtin::OPTIONAL_IDENTIFIER && + parameters_.size() == 1) { + return builtin::BuiltinType::OPTIONAL; + } else if (*name_.get() == builtin::RESULT_IDENTIFIER && + parameters_.size() == 1) { + return builtin::BuiltinType::RESULT; + } else { + return builtin::BuiltinType::NONE; + } + } + private: Identifier name_; std::vector parameters_; // or use allocator ?? bool is_on_heap_ = false; + std::optional annotation_; }; class TypeStorage { diff --git a/src/builders/expression_builders.cpp b/src/builders/expression_builders.cpp index 439ed10..3de368f 100644 --- a/src/builders/expression_builders.cpp +++ b/src/builders/expression_builders.cpp @@ -479,7 +479,18 @@ build_name_expression(parser::ParseTree::Node parser_node, auto current_node = name_node.previous_named_sibling(); if (!current_node.is_null()) { - if (tokens::string_to_type(current_node.get_type()) == tokens::Type::TYPE) { + if (tokens::string_to_type(current_node.get_type()) == + tokens::Type::VARIANT_TYPE || + tokens::string_to_type(current_node.get_type()) == + tokens::Type::TUPLE_TYPE || + tokens::string_to_type(current_node.get_type()) == + tokens::Type::ARRAY_TYPE || + tokens::string_to_type(current_node.get_type()) == + tokens::Type::REFERENCE_TYPE || + tokens::string_to_type(current_node.get_type()) == + tokens::Type::MODIFIED_TYPE || + tokens::string_to_type(current_node.get_type()) == + tokens::Type::SIMPLE_TYPE) { prefix_node = current_node; } else { is_point_call = true; diff --git a/src/builders/statement_builders.cpp b/src/builders/statement_builders.cpp index 4d49c3e..00a0abd 100644 --- a/src/builders/statement_builders.cpp +++ b/src/builders/statement_builders.cpp @@ -209,6 +209,11 @@ nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node, arguments.push_back(build_identifier(current_node)); break; case tokens::Type::VARIANT_TYPE: + case tokens::Type::TUPLE_TYPE: + case tokens::Type::ARRAY_TYPE: + case tokens::Type::REFERENCE_TYPE: + case tokens::Type::MODIFIED_TYPE: + case tokens::Type::SIMPLE_TYPE: if (type_node.has_value()) { error_handling::handle_parsing_error( "More then one type node in type definition", parser_node); @@ -246,22 +251,17 @@ nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node, std::unordered_set annotations; - // collect annotations from type if (type.has_value()) { - for (size_t i = 0; i < type.value().size(); ++i) { - // TODO: deal with annotations - auto constructor_annotations = type.value().get(i)->get_all_annotations(); - for (auto &annotation : constructor_annotations) { - annotations.insert(annotation); - } - } + type.value().get()->collect_annotations_recursively( + std::insert_iterator>( + annotations, annotations.begin())); } return nodes::TypeDefinition( build_node(parser_node), build_symbol_docs(description_node, annotation_nodes, annotations), is_on_heap, std::move(name), std::move(typeclasses), std::move(arguments), - std::move(type)); + type); } // definition_info? annotation_info* (constraint ';')* '.'? (simple_name diff --git a/src/builders/type_builders.cpp b/src/builders/type_builders.cpp index 15034cb..72ec187 100644 --- a/src/builders/type_builders.cpp +++ b/src/builders/type_builders.cpp @@ -1,10 +1,11 @@ #include "type_builders.hpp" #include "basic_builders.hpp" #include "basic_nodes.hpp" -#include "builtin_identifiers.hpp" +#include "builtin_types.hpp" #include "error_handling.hpp" #include "tokens.hpp" #include "type_nodes.hpp" +#include "types.hpp" namespace builders { @@ -39,41 +40,47 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parser_node, exit(1); // unreachable } -// '|'? annotation? type ('|' annotation? type)+ -nodes::TypeProxy build_variant_type(parser::ParseTree::Node parser_node, - nodes::TypeStorage &type_storage) { +nodes::TypeProxy +build_buildin_container_type(parser::ParseTree::Node parser_node, + nodes::TypeStorage &type_storage, + const std::string &type_name) { std::vector parameters; + std::optional current_annotation; + auto current_node = parser_node.nth_named_child(0); - ; while (!current_node.is_null()) { - parameters.push_back(build_type(current_node, type_storage)); + if (tokens::string_to_type(current_node.get_type()) == + tokens::Type::ANNOTATION_IDENTIFIER) { + current_annotation = build_annotation(current_node); + } else { + parameters.push_back(build_type(current_node, type_storage)); + if (current_annotation.has_value()) { + parameters.back().get()->set_annotation(current_annotation.value()); + } + } current_node = current_node.next_named_sibling(); } - return type_storage.add_type(nodes::Type( - build_node(parser_node), - nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE, - builtin::VARIANT_IDENTIFIER), - std::move(parameters), false)); + return type_storage.add_type( + nodes::Type(build_node(parser_node), + nodes::Identifier(build_node(parser_node), + nodes::Identifier::SIMPLE_TYPE, type_name), + std::move(parameters), false)); +} + +// '|'? annotation? type ('|' annotation? type)+ +nodes::TypeProxy build_variant_type(parser::ParseTree::Node parser_node, + nodes::TypeStorage &type_storage) { + return build_buildin_container_type(parser_node, type_storage, + builtin::VARIANT_IDENTIFIER); } // '&'? annotation? type ('&' annotation? type)+ nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { - std::vector parameters; - - auto current_node = parser_node.nth_named_child(0); - while (!current_node.is_null()) { - parameters.push_back(build_type(current_node, type_storage)); - current_node = current_node.next_named_sibling(); - } - - return type_storage.add_type(nodes::Type( - build_node(parser_node), - nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE, - builtin::TUPLE_IDENTIFIER), - std::move(parameters), false)); + return build_buildin_container_type(parser_node, type_storage, + builtin::TUPLE_IDENTIFIER); } // '[[' type ']]' diff --git a/src/printers/type_printers.cpp b/src/printers/type_printers.cpp index ba98de0..419dd0d 100644 --- a/src/printers/type_printers.cpp +++ b/src/printers/type_printers.cpp @@ -11,6 +11,11 @@ void print_type(const nodes::Type &type, printers::Printer &printer) { printer.print("^"); } + if (type.get_annotation().has_value()) { + print_annotation(*type.get_annotation().value(), printer); + printer.space(); + } + print_identifier(*type.get_name(), printer); if (type.get_parametrs_size() > 0) {