2023-07-23 19:40:27 +03:00
|
|
|
#include "statement_builders.hpp"
|
2023-07-22 19:49:52 +03:00
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
#include "basic_builders.hpp"
|
|
|
|
|
#include "basic_nodes.hpp"
|
|
|
|
|
#include "doc_builders.hpp"
|
|
|
|
|
#include "doc_nodes.hpp"
|
|
|
|
|
#include "error_handling.hpp"
|
|
|
|
|
#include "expression_builders.hpp"
|
2023-07-22 19:49:52 +03:00
|
|
|
#include "statement_nodes.hpp"
|
2023-07-23 19:40:27 +03:00
|
|
|
#include "tokens.hpp"
|
2023-07-22 19:49:52 +03:00
|
|
|
#include "tree_sitter_wrapper.hpp"
|
2023-07-23 19:40:27 +03:00
|
|
|
#include "type_builders.hpp"
|
|
|
|
|
#include "type_nodes.hpp"
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
#include <vector>
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
namespace builders {
|
|
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
// TODO: return some info ??
|
|
|
|
|
// statement+
|
|
|
|
|
void build_source_file(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::TypeStorage &type_storage) {
|
|
|
|
|
auto current_node = parser_node.nth_named_child(0);
|
|
|
|
|
while (!current_node.is_null()) {
|
|
|
|
|
build_statement(current_node, expression_storage, type_storage);
|
|
|
|
|
// TODO: do something with statement
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-22 19:49:52 +03:00
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
// TODO: return some info ??
|
|
|
|
|
// import | type_definition | function_definition | typeclass_definition
|
|
|
|
|
void build_statement(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::TypeStorage &type_storage) {
|
|
|
|
|
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case tokens::Type::IMPORT:
|
|
|
|
|
build_import(parser_node);
|
|
|
|
|
return;
|
|
|
|
|
case tokens::Type::TYPE_DEFINITION:
|
|
|
|
|
build_type_definition(parser_node, expression_storage, type_storage);
|
|
|
|
|
return;
|
|
|
|
|
case tokens::Type::FUNCTION_DEFINITION:
|
|
|
|
|
build_function_definition(parser_node, expression_storage, type_storage);
|
|
|
|
|
return;
|
|
|
|
|
case tokens::Type::TYPECLASS_DEFINITION:
|
|
|
|
|
build_typeclass_definition(parser_node, expression_storage, type_storage);
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
error_handling::handle_parsing_error("Unexprected statement node type",
|
|
|
|
|
parser_node);
|
|
|
|
|
}
|
|
|
|
|
error_handling::handle_general_error("Unreachable");
|
|
|
|
|
exit(1); // unreachable} // IN PROCESS
|
|
|
|
|
}
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
// ('::' | 'import') simple_name ('=' simple_name)? (':' identifier*)?
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::Import build_import(parser::ParseTree::Node parser_node) {
|
|
|
|
|
|
|
|
|
|
auto name_node = parser_node.child_by_field_name("name");
|
|
|
|
|
auto module_node = parser_node.child_by_field_name("module");
|
|
|
|
|
if (module_node.is_null()) {
|
|
|
|
|
module_node = name_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<nodes::Identifier> symbols;
|
|
|
|
|
|
|
|
|
|
auto current_node = module_node.next_named_sibling();
|
|
|
|
|
while (!current_node.is_null()) {
|
|
|
|
|
symbols.push_back(build_identifier(current_node));
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes::Import(build_node(parser_node), build_identifier(name_node),
|
|
|
|
|
build_identifier(module_node), std::move(symbols));
|
|
|
|
|
}
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
// '?' expression
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::Constraint build_constraint(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
|
|
|
|
nodes::TypeStorage &type_storage) {
|
2023-07-23 19:40:27 +03:00
|
|
|
return nodes::Constraint(build_node(parser_node),
|
|
|
|
|
build_expression(parser_node.nth_named_child(0),
|
|
|
|
|
expression_storage, type_storage));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser::ParseTree::Node collect_symbol_doc_nodes(
|
|
|
|
|
parser::ParseTree::Node start_parser_node,
|
|
|
|
|
std::optional<parser::ParseTree::Node> &description_node,
|
|
|
|
|
std::vector<parser::ParseTree::Node> &annotation_nodes) {
|
|
|
|
|
auto current_node = start_parser_node;
|
|
|
|
|
|
|
|
|
|
description_node = std::nullopt;
|
|
|
|
|
annotation_nodes.clear();
|
|
|
|
|
|
|
|
|
|
if (current_node.is_null()) {
|
|
|
|
|
return current_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tokens::string_to_type(current_node.get_type()) ==
|
|
|
|
|
tokens::Type::DEFINITION_INFO) {
|
|
|
|
|
description_node = current_node;
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!current_node.is_null() &&
|
|
|
|
|
tokens::string_to_type(current_node.get_type()) ==
|
|
|
|
|
tokens::Type::ANNOTATION_INFO) {
|
|
|
|
|
annotation_nodes.push_back(current_node);
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return current_node;
|
|
|
|
|
}
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
// definition_info? annotation_info* '^'? simple_type (argument_type* '='
|
2023-07-23 19:40:27 +03:00
|
|
|
// variant_type)? ('{' function_definition* '}' | ';')
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::TypeDefinition
|
2023-07-23 19:40:27 +03:00
|
|
|
build_type_definition(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::TypeStorage &type_storage) {
|
|
|
|
|
bool is_on_heap = parser_node.nth_child(0).get_value() == "^";
|
2023-07-22 19:49:52 +03:00
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
std::optional<parser::ParseTree::Node> description_node;
|
|
|
|
|
std::vector<parser::ParseTree::Node> annotation_nodes;
|
2023-07-22 19:49:52 +03:00
|
|
|
|
2023-07-23 19:40:27 +03:00
|
|
|
auto name_node = collect_symbol_doc_nodes(parser_node.nth_named_child(0),
|
|
|
|
|
description_node, annotation_nodes);
|
|
|
|
|
|
|
|
|
|
std::vector<nodes::Identifier> arguments;
|
|
|
|
|
std::vector<nodes::FunctionDefinition> methods;
|
|
|
|
|
|
|
|
|
|
std::optional<parser::ParseTree::Node> type_node;
|
|
|
|
|
|
|
|
|
|
auto current_node = name_node.next_named_sibling();
|
|
|
|
|
while (!current_node.is_null()) {
|
|
|
|
|
switch (tokens::string_to_type(current_node.get_type())) {
|
|
|
|
|
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
|
|
|
|
|
arguments.push_back(build_identifier(current_node));
|
|
|
|
|
break;
|
|
|
|
|
case tokens::Type::VARIANT_TYPE:
|
|
|
|
|
if (type_node.has_value()) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"More then one type node in type definition", parser_node);
|
|
|
|
|
}
|
|
|
|
|
type_node = current_node;
|
|
|
|
|
break;
|
|
|
|
|
case tokens::Type::FUNCTION_DEFINITION:
|
|
|
|
|
methods.push_back(build_function_definition(
|
|
|
|
|
current_node, expression_storage, type_storage));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"Unexprected node type in type definition", parser_node);
|
|
|
|
|
}
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!type_node.has_value() && !annotation_nodes.empty()) {
|
|
|
|
|
error_handling::handle_parsing_error("", parser_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<nodes::VariantType> type =
|
|
|
|
|
type_node.has_value()
|
|
|
|
|
? build_variant_type(type_node.value(), type_storage)
|
|
|
|
|
: std::optional<nodes::VariantType>();
|
|
|
|
|
|
|
|
|
|
std::unordered_set<std::string> annotations;
|
|
|
|
|
|
|
|
|
|
// collect annotations from type
|
|
|
|
|
if (type.has_value()) {
|
|
|
|
|
for (size_t i = 0; i < type.value().size(); ++i) {
|
|
|
|
|
auto constructor_annotations = type.value().get(i)->get_all_annotations();
|
|
|
|
|
for (auto &annotation : constructor_annotations) {
|
|
|
|
|
annotations.insert(annotation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes::TypeDefinition(
|
|
|
|
|
build_node(parser_node),
|
|
|
|
|
build_symbol_docs(description_node, annotation_nodes, annotations),
|
|
|
|
|
is_on_heap, build_identifier(name_node), std::move(arguments),
|
|
|
|
|
std::move(type), std::move(methods));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// definition_info? annotation_info* (constraint ';')* _var_let_? (simple_name
|
|
|
|
|
// | '(' operator ')') (annotation? _reference_? argument_name '?'?)* (:
|
|
|
|
|
// (annotation? _reference_ type)+)?
|
2023-07-22 19:49:52 +03:00
|
|
|
// ('=' (block | expression ';') | ';')
|
|
|
|
|
nodes::FunctionDefinition
|
2023-07-23 19:40:27 +03:00
|
|
|
build_function_definition(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::TypeStorage &type_storage) {
|
|
|
|
|
|
|
|
|
|
std::optional<parser::ParseTree::Node> description_node;
|
|
|
|
|
std::vector<parser::ParseTree::Node> annotation_nodes;
|
|
|
|
|
|
|
|
|
|
std::vector<nodes::Constraint> constraints;
|
|
|
|
|
|
|
|
|
|
auto current_node = collect_symbol_doc_nodes(
|
|
|
|
|
parser_node.nth_named_child(0), description_node, annotation_nodes);
|
|
|
|
|
|
|
|
|
|
while (!current_node.is_null() &&
|
|
|
|
|
tokens::string_to_type(current_node.get_type()) ==
|
|
|
|
|
tokens::Type::CONSTRAINT) {
|
|
|
|
|
constraints.push_back(
|
|
|
|
|
build_constraint(current_node, expression_storage, type_storage));
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto name_node = current_node;
|
|
|
|
|
|
|
|
|
|
nodes::FunctionDefinition::ModifierType modifier =
|
|
|
|
|
nodes::FunctionDefinition::STATIC;
|
|
|
|
|
|
|
|
|
|
current_node = name_node.previous_sibling();
|
|
|
|
|
if (current_node.is_named()) {
|
|
|
|
|
std::string modifier_str = current_node.get_value();
|
|
|
|
|
if (modifier_str == "%" || modifier_str == "let") {
|
|
|
|
|
modifier = nodes::FunctionDefinition::LET;
|
|
|
|
|
} else if (modifier_str == "$" || modifier_str == "var") {
|
|
|
|
|
modifier = nodes::FunctionDefinition::VAR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::optional<std::string>> argument_annotations;
|
|
|
|
|
std::vector<nodes::Modifier> argument_reference_types;
|
|
|
|
|
std::vector<nodes::Identifier> arguments;
|
|
|
|
|
|
|
|
|
|
std::vector<std::optional<std::string>> type_annotations;
|
|
|
|
|
std::vector<nodes::Modifier> type_reference_types;
|
|
|
|
|
std::vector<std::optional<nodes::TypeProxy>> types;
|
|
|
|
|
|
|
|
|
|
std::optional<parser::ParseTree::Node> expression_node;
|
|
|
|
|
|
|
|
|
|
current_node = name_node.next_named_sibling();
|
|
|
|
|
|
|
|
|
|
bool at_least_one_argument_annotation_found = false;
|
|
|
|
|
bool at_least_one_argument_reference_type_found = false;
|
|
|
|
|
|
|
|
|
|
std::optional<std::string> last_annotation;
|
|
|
|
|
nodes::Modifier last_reference_type = nodes::Modifier::NONE;
|
|
|
|
|
while (!current_node.is_null()) {
|
|
|
|
|
auto maybe_reference_node = current_node.previous_sibling();
|
|
|
|
|
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
|
|
|
|
last_reference_type = build_modifier(maybe_reference_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (tokens::string_to_type(current_node.get_type())) {
|
|
|
|
|
case tokens::Type::ANNOTATION_IDENTIFIER:
|
|
|
|
|
last_annotation = build_annotation(current_node);
|
|
|
|
|
break;
|
|
|
|
|
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
|
|
|
|
if (last_annotation.has_value()) {
|
|
|
|
|
at_least_one_argument_annotation_found = true;
|
|
|
|
|
}
|
|
|
|
|
if (last_reference_type != nodes::Modifier::NONE) {
|
|
|
|
|
at_least_one_argument_reference_type_found = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
argument_annotations.push_back(last_annotation);
|
|
|
|
|
argument_reference_types.push_back(last_reference_type);
|
|
|
|
|
arguments.push_back(build_identifier(current_node));
|
|
|
|
|
last_reference_type = nodes::Modifier::NONE;
|
|
|
|
|
last_annotation = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
case tokens::Type::TYPE:
|
|
|
|
|
type_annotations.push_back(last_annotation);
|
|
|
|
|
type_reference_types.push_back(last_reference_type);
|
|
|
|
|
types.push_back(build_type(current_node, type_storage));
|
|
|
|
|
last_reference_type = nodes::Modifier::NONE;
|
|
|
|
|
last_annotation = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (expression_node.has_value()) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"More then one expression found in function definition",
|
|
|
|
|
parser_node);
|
|
|
|
|
}
|
|
|
|
|
expression_node = current_node;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::optional<std::string>> *annotations = nullptr;
|
|
|
|
|
std::vector<nodes::Modifier> *reference_types = nullptr;
|
|
|
|
|
|
|
|
|
|
if (!at_least_one_argument_annotation_found) {
|
|
|
|
|
for (size_t i = 0; i < argument_annotations.size(); ++i) {
|
|
|
|
|
argument_annotations[i] = *arguments[i].get();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (types.empty()) {
|
|
|
|
|
annotations = &argument_annotations;
|
|
|
|
|
reference_types = &argument_reference_types;
|
|
|
|
|
} else if (at_least_one_argument_annotation_found) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"It is impossible to use argument annotations when types explicitely "
|
|
|
|
|
"defined. Use type annotations instead.",
|
|
|
|
|
parser_node);
|
|
|
|
|
} else if (at_least_one_argument_reference_type_found) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"It is impossible to use argument reference types when types "
|
|
|
|
|
"explicitely defined. Use type reference types instead.",
|
|
|
|
|
parser_node);
|
|
|
|
|
} else {
|
|
|
|
|
annotations = &type_annotations;
|
|
|
|
|
reference_types = &type_reference_types;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<std::string> annotations_set;
|
|
|
|
|
for (auto &annotation : *annotations) {
|
|
|
|
|
if (annotation.has_value()) {
|
|
|
|
|
if (!annotations_set.insert(annotation.value()).second) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"Two or more same annotations found in function definition",
|
|
|
|
|
parser_node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes::FunctionDefinition(
|
|
|
|
|
build_node(parser_node),
|
|
|
|
|
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
|
|
|
|
std::move(constraints), modifier, build_identifier(name_node),
|
|
|
|
|
std::move(*annotations), std::move(arguments),
|
|
|
|
|
std::move(*reference_types), std::move(types),
|
|
|
|
|
expression_node.has_value()
|
|
|
|
|
? build_expression(expression_node.value(), expression_storage,
|
|
|
|
|
type_storage)
|
|
|
|
|
: std::optional<nodes::ExpressionProxy>());
|
|
|
|
|
} // TODO: refactor ??
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
// definition_info? annotation_info* typeclass_identifier (':'
|
|
|
|
|
// typeclass_identifier+)? ('{' function_definition* '}' | ';')
|
|
|
|
|
nodes::TypeclassDefinition
|
2023-07-23 19:40:27 +03:00
|
|
|
build_typeclass_definition(parser::ParseTree::Node parser_node,
|
2023-07-22 19:49:52 +03:00
|
|
|
nodes::ExpressionStorage &expression_storage,
|
2023-07-23 19:40:27 +03:00
|
|
|
nodes::TypeStorage &type_storage) {
|
|
|
|
|
|
|
|
|
|
std::optional<parser::ParseTree::Node> description_node;
|
|
|
|
|
std::vector<parser::ParseTree::Node> annotation_nodes;
|
|
|
|
|
|
|
|
|
|
auto name_node = collect_symbol_doc_nodes(parser_node.nth_named_child(0),
|
|
|
|
|
description_node, annotation_nodes);
|
|
|
|
|
|
|
|
|
|
if (!annotation_nodes.empty()) {
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"Typeclass can't have annotation info nodes", parser_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<nodes::Identifier> base_typeclasses;
|
|
|
|
|
std::vector<nodes::FunctionDefinition> methods;
|
|
|
|
|
|
|
|
|
|
auto current_node = name_node.next_named_sibling();
|
|
|
|
|
while (!current_node.is_null()) {
|
|
|
|
|
switch (tokens::string_to_type(current_node.get_type())) {
|
|
|
|
|
case tokens::Type::TYPECLASS_IDENTIFIER:
|
|
|
|
|
base_typeclasses.push_back(build_identifier(current_node));
|
|
|
|
|
break;
|
|
|
|
|
case tokens::Type::FUNCTION_DEFINITION:
|
|
|
|
|
methods.push_back(build_function_definition(
|
|
|
|
|
current_node, expression_storage, type_storage));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
error_handling::handle_parsing_error(
|
|
|
|
|
"Unexprected node type in type definition", parser_node);
|
|
|
|
|
}
|
|
|
|
|
current_node = current_node.next_named_sibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes::TypeclassDefinition(
|
|
|
|
|
build_node(parser_node), build_symbol_docs(description_node),
|
|
|
|
|
build_identifier(name_node), std::move(base_typeclasses),
|
|
|
|
|
std::move(methods));
|
|
|
|
|
}
|
2023-07-22 19:49:52 +03:00
|
|
|
|
|
|
|
|
} // namespace builders
|