fixes, refactoring (shorter names, visitor)

This commit is contained in:
ProgramSnail 2024-05-01 14:05:29 +03:00
parent 57b1172a4f
commit f58bfd938c
20 changed files with 564 additions and 764 deletions

View file

@ -7,9 +7,7 @@
namespace type_check { namespace type_check {
// IN PROGRESS: modifiers ?? // IN PROGRESS: modifiers ??
nodes::TypeCheckResult Result check(const nodes::Literal &literal, SourcesManager &sources_manager,
type_check_literal(const nodes::Literal &literal, State &state, const Arguments &arguments);
SourcesManager &sources_manager,
const Arguments& arguments);
} // namespace type_check } // namespace type_check

View file

@ -5,7 +5,33 @@
#include "basic_nodes.hpp" #include "basic_nodes.hpp"
namespace builtin::types { namespace builtin {
enum class Type {
// -- containers
TUPLE,
VARIANT,
FUNCTION,
ARRAY,
OPTIONAL,
RESULT,
ERROR,
// -- basic types
FLOAT,
DOUBLE,
INT,
LONG,
INDEX,
CHAR,
UNICODE,
BOOL,
UNIT,
NULL_OPTION,
// -- none
NONE,
};
namespace types {
// -- containers // -- containers
@ -50,30 +76,6 @@ const static std::string NULL_OPTION_IDENTIFIER = "Null";
// //
enum class Type {
// -- containers
TUPLE,
VARIANT,
FUNCTION,
ARRAY,
OPTIONAL,
RESULT,
ERROR,
// -- basic types
FLOAT,
DOUBLE,
INT,
LONG,
INDEX,
CHAR,
UNICODE,
BOOL,
UNIT,
NULL_OPTION,
// -- none
NONE,
};
inline std::string to_string(Type type) { inline std::string to_string(Type type) {
switch (type) { switch (type) {
// -- containers // -- containers
@ -202,4 +204,6 @@ inline std::optional<size_t> get_parameters_count(Type type) {
exit(1); // unreachable exit(1); // unreachable
} }
} // namespace builtin::types } // namespace types
} // namespace builtin

View file

@ -12,77 +12,66 @@
namespace type_check { namespace type_check {
nodes::TypeCheckResult Result check(const nodes::Expression &expression,
type_check_expression(const nodes::Expression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
// --- flow control // --- flow control
nodes::TypeCheckResult type_check_match(const nodes::Match &expression, Result check(const nodes::Match &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
State &state,
const Arguments &arguments);
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, Result check(const nodes::Condition &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments);
const Arguments &arguments);
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, Result check(const nodes::Loop &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
State &state,
const Arguments &arguments);
// --- containers // --- containers
nodes::TypeCheckResult type_check_container(const nodes::Container &expression, Result check(const nodes::Container &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments);
const Arguments &arguments);
// --- modifiers // --- modifiers
nodes::TypeCheckResult type_check_return(const nodes::Return &expression, Result check(const nodes::Return &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
State &state,
const Arguments &arguments);
nodes::TypeCheckResult Result check(const nodes::NameDefinition &expression,
type_check_name_definition(const nodes::NameDefinition &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
nodes::TypeCheckResult type_check_access(const nodes::Access &expression, Result check(const nodes::Access &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
State &state,
const Arguments &arguments);
nodes::TypeCheckResult Result check(const nodes::LoopControl &expression,
type_check_loop_control(const nodes::LoopControl &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
nodes::TypeCheckResult Result check(const nodes::ModifierExpression &expression,
type_check_modifier_expression(const nodes::ModifierExpression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
// --- other // --- other
nodes::TypeCheckResult Result check(const nodes::NameExpression &expression,
type_check_name_expression(const nodes::NameExpression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
nodes::TypeCheckResult Result check(const nodes::Constructor &expression,
type_check_constructor(const nodes::Constructor &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
const Arguments &arguments);
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, Result check(const nodes::Lambda &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments);
State &state,
const Arguments &arguments); Result check(const nodes::Extra &expression, SourcesManager &sources_manager,
State &state, const Arguments &arguments);
Result check(const nodes::EmptyLines &expression,
SourcesManager &sources_manager, State &state,
const Arguments &arguments);
} // namespace type_check } // namespace type_check

View file

@ -217,7 +217,7 @@ public:
bool operator>=(const Type &other) const { return !operator<(other); } bool operator>=(const Type &other) const { return !operator<(other); }
// is parameters count check necessary ?? // is parameters count check necessary ??
builtin::types::Type to_builtin() const { builtin::Type to_builtin() const {
auto builtin_type = builtin::types::to_type(*name_.get()); auto builtin_type = builtin::types::to_type(*name_.get());
auto builtin_type_parameters_count = auto builtin_type_parameters_count =
@ -226,15 +226,13 @@ public:
// for fixed parameter counts // for fixed parameter counts
if (builtin_type_parameters_count.has_value() && if (builtin_type_parameters_count.has_value() &&
builtin_type_parameters_count.value() != parameters_.size()) { builtin_type_parameters_count.value() != parameters_.size()) {
return builtin::types::Type::NONE; return builtin::Type::NONE;
} }
return builtin_type; return builtin_type;
} }
bool is_builtin(builtin::types::Type type) const { bool is_builtin(builtin::Type type) const { return to_builtin() == type; }
return to_builtin() == type;
}
private: private:
Identifier name_; Identifier name_;
@ -247,7 +245,7 @@ class TypeStorage {
friend TypeProxy; friend TypeProxy;
public: public:
TypeProxy primitive_type(builtin::types::Type type) { TypeProxy primitive(builtin::Type type) {
auto iter = primitive_type_ids_.find(type); auto iter = primitive_type_ids_.find(type);
if (iter != primitive_type_ids_.end()) { if (iter != primitive_type_ids_.end()) {
return TypeProxy(*this, iter->second); return TypeProxy(*this, iter->second);
@ -289,7 +287,7 @@ public:
} }
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &&parameters, nodes::TypeProxy add_container_of(std::vector<TypeProxy> &&parameters,
builtin::types::Type container, builtin::Type container,
Node node = Node()) { Node node = Node()) {
for (auto &parameter : parameters) { for (auto &parameter : parameters) {
if (parameter.type_storage_ != this) { if (parameter.type_storage_ != this) {
@ -343,7 +341,7 @@ public:
if (type.is_generic()) { if (type.is_generic()) {
auto iter = resolved_generic_names_.find(*type.get_name()->get()); auto iter = resolved_generic_names_.find(*type.get_name()->get());
// because of undefined order sone types can became resolved earlir // because of undefined order some types can became resolved earlir
// wirking correctly because each generic type has <= 1 successor, no // wirking correctly because each generic type has <= 1 successor, no
// cyclic deps allowed (do check ??) // cyclic deps allowed (do check ??)
if (iter != resolved_generic_names_.end()) { if (iter != resolved_generic_names_.end()) {
@ -471,7 +469,7 @@ private:
private: private:
// check is builtin type instaniated // check is builtin type instaniated
std::unordered_map<builtin::types::Type, size_t> primitive_type_ids_; std::unordered_map<builtin::Type, size_t> primitive_type_ids_;
// deal with generic types and generic names // deal with generic types and generic names
std::unordered_map<std::string, size_t> resolved_generic_names_; std::unordered_map<std::string, size_t> resolved_generic_names_;
@ -485,46 +483,4 @@ private:
std::vector<Type> storage_; std::vector<Type> storage_;
}; };
class TypeCheckResult {
public:
// for invalid type
static TypeCheckResult construct_invalid_result() {
return TypeCheckResult();
}
explicit TypeCheckResult(nodes::TypeProxy type) : type_(type) {}
//
TypeProxy &get() {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
const TypeProxy &get() const {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
void set(TypeProxy type) { type_ = type; }
//
bool is_invalid() const { return !type_.has_value(); }
private:
TypeCheckResult() = default;
private:
nodes::MaybeTypeProxy type_;
};
} // namespace nodes } // namespace nodes

View file

@ -124,17 +124,24 @@ private:
size_t indentation_level_ = 0; size_t indentation_level_ = 0;
}; };
void print_modifier(const nodes::Modifier &modifier, Printer &printer, void print(const nodes::Modifier &modifier, Printer &printer,
bool const_is_none = false); bool const_is_none = false);
void print_literal(const nodes::Literal &literal, Printer &printer); void print(const nodes::Literal &literal, Printer &printer);
void print_identifier(const nodes::Identifier &identifier, Printer &printer); void print(const nodes::Identifier &identifier, Printer &printer);
void print_annotation(const std::string &annotation, Printer &printer); void print_annotation(const std::string &annotation, Printer &printer);
void print_extra(const nodes::Extra &extra, Printer &printer); void print(const nodes::Extra &extra, Printer &printer);
void print_empty_lines(const nodes::EmptyLines &empty_lines, Printer &printer); void print(const nodes::EmptyLines &empty_lines, Printer &printer);
template <typename T>
inline void print(const std::vector<T> &nodes, Printer &printer) {
for (const auto &node : nodes) {
print(node, printer);
}
}
} // namespace printers } // namespace printers

View file

@ -5,6 +5,6 @@
namespace printers { namespace printers {
void print_docs(const nodes::SymbolDocs &docs, Printer &printer); void print(const nodes::SymbolDocs &docs, Printer &printer);
} // namespace printers } // namespace printers

View file

@ -4,48 +4,41 @@
#include "expression_nodes.hpp" #include "expression_nodes.hpp"
namespace printers { namespace printers {
void print_expression(const nodes::Expression &expression, void print(const nodes::Expression &expression, printers::Printer &printer);
printers::Printer &printer);
// --- flow control // --- flow control
void print_case(const nodes::Match::Case &expression, Printer &printer); void print(const nodes::Match::Case &expression, Printer &printer);
void print_match(const nodes::Match &expression, printers::Printer &printer); void print(const nodes::Match &expression, printers::Printer &printer);
void print_condition(const nodes::Condition &expression, void print(const nodes::Condition &expression, printers::Printer &printer);
printers::Printer &printer);
void print_loop(const nodes::Loop &expression, printers::Printer &printer); void print(const nodes::Loop &expression, printers::Printer &printer);
// --- containers // --- containers
void print_container(const nodes::Container &expression, void print(const nodes::Container &expression, printers::Printer &printer);
printers::Printer &printer);
// --- modifiers // --- modifiers
void print_return(const nodes::Return &expression, printers::Printer &printer); void print(const nodes::Return &expression, printers::Printer &printer);
void print_name_definition(const nodes::NameDefinition &expression, void print(const nodes::NameDefinition &expression, printers::Printer &printer);
printers::Printer &printer);
void print_access(const nodes::Access &expression, printers::Printer &printer); void print(const nodes::Access &expression, printers::Printer &printer);
void print_loop_control(const nodes::LoopControl &expression, void print(const nodes::LoopControl &expression, printers::Printer &printer);
printers::Printer &printer);
void print_modifier_expression(const nodes::ModifierExpression &expression, void print(const nodes::ModifierExpression &expression,
printers::Printer &printer); printers::Printer &printer);
// --- other // --- other
void print_name_expression(const nodes::NameExpression &expression, void print(const nodes::NameExpression &expression, printers::Printer &printer);
printers::Printer &printer);
void print_constructor(const nodes::Constructor &expression, void print(const nodes::Constructor &expression, printers::Printer &printer);
printers::Printer &printer);
void print_lambda(const nodes::Lambda &expression, printers::Printer &printer); void print(const nodes::Lambda &expression, printers::Printer &printer);
} // namespace printers } // namespace printers

View file

@ -7,19 +7,17 @@
namespace printers { namespace printers {
void print_source_file(const std::vector<nodes::Statement> &statements, // void print_source_file(const std::vector<nodes::Statement> &statements,
Printer &printer); // Printer &printer);
void print_statement(const nodes::Statement &statements, Printer &printer); void print(const nodes::Statement &statements, Printer &printer);
void print_import(const nodes::Import &statement, Printer &printer); void print(const nodes::Import &statement, Printer &printer);
void print_constraint(const nodes::Constraint &statement, Printer &printer); void print(const nodes::Constraint &statement, Printer &printer);
void print_type_definition(const nodes::TypeDefinition &statement, void print(const nodes::TypeDefinition &statement, Printer &printer);
Printer &printer);
void print_function_definition(const nodes::FunctionDefinition &statement, void print(const nodes::FunctionDefinition &statement, Printer &printer);
Printer &printer);
} // namespace printers } // namespace printers

View file

@ -5,7 +5,7 @@
namespace printers { namespace printers {
void print_type(const nodes::Type &type, printers::Printer &printer); void print(const nodes::Type &type, printers::Printer &printer);
// void print_tuple_type(const nodes::TupleType &type, printers::Printer // void print_tuple_type(const nodes::TupleType &type, printers::Printer
// &printer); // &printer);

View file

@ -49,44 +49,42 @@ public:
void print(std::ostream &out) { void print(std::ostream &out) {
printers::Printer printer(out, 2, 80, true); printers::Printer printer(out, 2, 80, true);
printers::print_source_file(statements_, printer); printers::print(statements_, printer);
} }
// //
nodes::ExpressionStorage *get_expression_storage() { nodes::ExpressionStorage *expressions() { return &expression_storage_; }
return &expression_storage_;
}
const nodes::ExpressionStorage *get_expression_storage() const { const nodes::ExpressionStorage *expressions() const {
return &expression_storage_; return &expression_storage_;
} }
// //
nodes::TypeStorage *get_type_storage() { return &type_storage_; } nodes::TypeStorage *types() { return &type_storage_; }
const nodes::TypeStorage *get_type_storage() const { return &type_storage_; } const nodes::TypeStorage *types() const { return &type_storage_; }
// //
names::NameTree *get_name_tree() { return &name_tree_; } names::NameTree *names() { return &name_tree_; }
const names::NameTree *get_name_tree() const { return &name_tree_; } const names::NameTree *names() const { return &name_tree_; }
// //
error_handling::ErrorLog *get_error_log() { return &error_log_; } error_handling::ErrorLog *errors() { return &error_log_; }
const error_handling::ErrorLog *get_error_log() const { return &error_log_; } const error_handling::ErrorLog *errors() const { return &error_log_; }
// //
size_t statements_size() const { return statements_.size(); } size_t statements_size() const { return statements_.size(); }
nodes::Statement *get_statement(size_t id) { return &statements_.at(id); } nodes::Statement *statement(size_t id) { return &statements_.at(id); }
const nodes::Statement *get_statement(size_t id) const { const nodes::Statement *statement(size_t id) const {
return &statements_.at(id); return &statements_.at(id);
} }

View file

@ -145,23 +145,23 @@ public:
std::vector<Context> contexts_ = {{}}; std::vector<Context> contexts_ = {{}};
}; };
//
class Arguments { class Arguments {
public: public:
Arguments() = default; Arguments() = default;
Arguments expect_builtin(builtin::types::Type type, Arguments expect_builtin(builtin::Type type,
SourcesManager &sources_manager) const { SourcesManager &sources_manager) const {
Arguments copy(*this); Arguments copy(*this);
copy.expected_types_ = { copy.expected_types_ = {sources_manager.types()->primitive(type)};
sources_manager.get_type_storage()->primitive_type(type)};
return copy; return copy;
} }
Arguments pass_builtin(builtin::types::Type type, Arguments pass_builtin(builtin::Type type,
SourcesManager &sources_manager) const { SourcesManager &sources_manager) const {
Arguments copy(*this); Arguments copy(*this);
copy.passed_type_ = copy.passed_type_ = sources_manager.types()->primitive(type);
sources_manager.get_type_storage()->primitive_type(type);
return copy; return copy;
} }
@ -208,6 +208,8 @@ private:
nodes::MaybeTypeProxy passed_type_; nodes::MaybeTypeProxy passed_type_;
}; };
//
class ContextHolder { class ContextHolder {
public: public:
ContextHolder(State &state, const nodes::Node &node, ContextHolder(State &state, const nodes::Node &node,
@ -236,6 +238,52 @@ private:
nodes::MaybeTypeProxy *context_exit_type_; nodes::MaybeTypeProxy *context_exit_type_;
}; };
//
class Result {
public:
// for invalid type
static Result invalid() { return Result(); }
explicit Result(nodes::TypeProxy type) : type_(type) {}
//
nodes::TypeProxy &get() {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
const nodes::TypeProxy &get() const {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
void set(nodes::TypeProxy type) { type_ = type; }
//
bool is_invalid() const { return !type_.has_value(); }
private:
Result() = default;
private:
nodes::MaybeTypeProxy type_;
};
using MaybeResult = std::optional<Result>;
//
nodes::TypeProxy check_same_to_pass_type_in_arguments( nodes::TypeProxy check_same_to_pass_type_in_arguments(
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node, nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
SourcesManager &sources_manager, SourcesManager &sources_manager,
@ -247,15 +295,17 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
// SourcesManager &sources_manager, // SourcesManager &sources_manager,
// const std::string &message = "Type can't be passed to this node"); // const std::string &message = "Type can't be passed to this node");
nodes::TypeCheckResult type_same_to_expected( Result type_same_to_expected(
nodes::TypeProxy type, const Arguments &argumensr, const nodes::Node &node, nodes::TypeProxy type, const Arguments &argumensr, const nodes::Node &node,
SourcesManager &sources_manager, SourcesManager &sources_manager,
const std::string &message = "Different type with expected one", const std::string &message = "Different type with expected one",
bool handle_errors = true); bool handle_errors = true);
nodes::TypeCheckResult type_check_from_arguments( Result type_check_from_arguments(nodes::TypeProxy type,
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node, const Arguments &arguments,
SourcesManager &sources_manager, bool handle_errors = true); const nodes::Node &node,
SourcesManager &sources_manager,
bool handle_errors = true);
std::optional<const nodes::TypeDefinition *> std::optional<const nodes::TypeDefinition *>
find_type_definition(const std::string &name, const nodes::Node &node, find_type_definition(const std::string &name, const nodes::Node &node,
@ -267,15 +317,16 @@ find_name_definition(const std::string &name, const nodes::Node &node,
SourcesManager &sources_manager, SourcesManager &sources_manager,
bool handle_errors = true); bool handle_errors = true);
std::optional<nodes::TypeProxy> nodes::MaybeTypeProxy unfold_user_defined_type(nodes::TypeProxy type,
unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node, const nodes::Node &node,
SourcesManager &sources_manager, SourcesManager &sources_manager,
bool handle_errors = true); bool handle_errors = true);
std::optional<nodes::TypeProxy> nodes::MaybeTypeProxy get_field_type_by_name(nodes::TypeProxy type,
get_field_type_by_name(nodes::TypeProxy type, const std::string &field, const std::string &field,
const nodes::Node &node, SourcesManager &sources_manager, const nodes::Node &node,
bool handle_errors = true); SourcesManager &sources_manager,
bool handle_errors = true);
void type_check_error(const std::string &message, const nodes::Node &node, void type_check_error(const std::string &message, const nodes::Node &node,
SourcesManager &sources_manager, SourcesManager &sources_manager,

View file

@ -6,52 +6,39 @@ nodes::TypeProxy get_literal_type(const nodes::Literal &literal,
SourcesManager &sources_manager) { SourcesManager &sources_manager) {
switch (literal.get_any()->index()) { switch (literal.get_any()->index()) {
case 0: // float case 0: // float
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::FLOAT);
builtin::types::Type::FLOAT);
case 1: // double case 1: // double
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::DOUBLE);
builtin::types::Type::DOUBLE);
case 2: // int32_t case 2: // int32_t
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::INT);
builtin::types::Type::INT);
case 3: // int64_t case 3: // int64_t
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::LONG);
builtin::types::Type::LONG);
case 4: // size_t case 4: // size_t
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::INDEX);
builtin::types::Type::INDEX);
case 5: // std::string case 5: // std::string
return sources_manager.get_type_storage()->add_array_of( return sources_manager.types()->add_array_of(
sources_manager.get_type_storage()->primitive_type( sources_manager.types()->primitive(builtin::Type::CHAR));
builtin::types::Type::CHAR));
case 6: // unicode_string case 6: // unicode_string
return sources_manager.get_type_storage()->add_array_of( return sources_manager.types()->add_array_of(
sources_manager.get_type_storage()->primitive_type( sources_manager.types()->primitive(builtin::Type::UNICODE));
builtin::types::Type::UNICODE));
case 7: // char case 7: // char
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::CHAR);
builtin::types::Type::CHAR);
case 8: // unicode case 8: // unicode
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::UNICODE);
builtin::types::Type::UNICODE);
case 9: // bool case 9: // bool
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::BOOL);
builtin::types::Type::BOOL);
case 10: // unit case 10: // unit
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::UNIT);
builtin::types::Type::UNIT);
case 11: // null case 11: // null
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::NULL_OPTION);
builtin::types::Type::NULL_OPTION);
} }
error_handling::handle_general_error("Unreachable"); error_handling::handle_general_error("Unreachable");
exit(1); // unreachable exit(1); // unreachable
} }
nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal, Result check(const nodes::Literal &literal, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &, const Arguments &arguments) {
const Arguments &arguments) {
auto const type = get_literal_type(literal, sources_manager); auto const type = get_literal_type(literal, sources_manager);
return type_same_to_expected(type, arguments, literal, sources_manager); return type_same_to_expected(type, arguments, literal, sources_manager);
} }

View file

@ -63,7 +63,7 @@ collect_parameters(parser::ParseTree::Node first_node,
nodes::TypeProxy build_container_type(parser::ParseTree::Node parser_node, nodes::TypeProxy build_container_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage, nodes::TypeStorage &type_storage,
builtin::types::Type container) { builtin::Type container) {
std::vector<nodes::TypeProxy> parameters = std::vector<nodes::TypeProxy> parameters =
collect_parameters(parser_node.nth_named_child(0), type_storage); collect_parameters(parser_node.nth_named_child(0), type_storage);
@ -75,14 +75,13 @@ nodes::TypeProxy build_container_type(parser::ParseTree::Node parser_node,
nodes::TypeProxy build_variant_type(parser::ParseTree::Node parser_node, nodes::TypeProxy build_variant_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) { nodes::TypeStorage &type_storage) {
return build_container_type(parser_node, type_storage, return build_container_type(parser_node, type_storage,
builtin::types::Type::VARIANT); builtin::Type::VARIANT);
} }
// '&'? annotation? type ('&' annotation? type)+ // '&'? annotation? type ('&' annotation? type)+
nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node, nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) { nodes::TypeStorage &type_storage) {
return build_container_type(parser_node, type_storage, return build_container_type(parser_node, type_storage, builtin::Type::TUPLE);
builtin::types::Type::TUPLE);
} }
// _reference_ type // _reference_ type

View file

@ -1,5 +1,4 @@
#include "expression_type_check.hpp" #include "expression_type_check.hpp"
#include "basic_nodes.hpp" #include "basic_nodes.hpp"
#include "basic_type_check.hpp" #include "basic_type_check.hpp"
#include "builtin_types.hpp" #include "builtin_types.hpp"
@ -15,89 +14,29 @@
namespace type_check { namespace type_check {
nodes::TypeCheckResult Result type_check_expression(const nodes::Expression &expression,
type_check_expression(const nodes::Expression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
const Arguments &arguments) { return std::visit(
switch (expression.get_any()->index()) { [&sources_manager, &state, &arguments](const auto &arg) -> Result {
// --- flow control return check(arg, sources_manager, state, arguments);
case 0: // Match },
return type_check_match(*expression.get<nodes::Match>().value(), *expression.get_any());
sources_manager, state, arguments);
case 1: // Condition
return type_check_condition(*expression.get<nodes::Condition>().value(),
sources_manager, state, arguments);
case 2: // Loop
return type_check_loop(*expression.get<nodes::Loop>().value(),
sources_manager, state, arguments);
// --- containers
case 3: // Container
return type_check_container(*expression.get<nodes::Container>().value(),
sources_manager, state, arguments);
// --- modifiers
case 4: // Return
return type_check_return(*expression.get<nodes::Return>().value(),
sources_manager, state, arguments);
case 5: // NameDefinition
return type_check_name_definition(
*expression.get<nodes::NameDefinition>().value(), sources_manager,
state, arguments);
case 6: // Access
return type_check_access(*expression.get<nodes::Access>().value(),
sources_manager, state, arguments);
case 7: // LoopControl
return type_check_loop_control(
*expression.get<nodes::LoopControl>().value(), sources_manager, state,
arguments);
case 8: // ModifierExpression
return type_check_modifier_expression(
*expression.get<nodes::ModifierExpression>().value(), sources_manager,
state, arguments);
// --- other
case 9: // NameExpression
return type_check_name_expression(
*expression.get<nodes::NameExpression>().value(), sources_manager,
state, arguments);
case 10: // Constructor
return type_check_constructor(*expression.get<nodes::Constructor>().value(),
sources_manager, state, arguments);
case 11: // Lambda
return type_check_lambda(*expression.get<nodes::Lambda>().value(),
sources_manager, state, arguments);
// --- literal
case 12: // Literal
// TODO
return type_check_literal(*expression.get<nodes::Literal>().value(),
sources_manager, arguments);
// --- empty lines
case 13: // Extra
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
case 14: // EmptyLines
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
}
utils::unreachable();
} }
// --- flow control // --- flow control
nodes::TypeCheckResult type_check_match(const nodes::Match &expression, Result check(const nodes::Match &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
State &state, Result value_result =
const Arguments &arguments) { check(*expression.get_value(), sources_manager, state, Arguments{});
nodes::TypeCheckResult value_result = type_check_expression(
*expression.get_value(), sources_manager, state, Arguments{});
// x :=/=: ... // x :=/=: ...
if (value_result.is_invalid()) { if (value_result.is_invalid()) {
type_check_error("Match value is invalid", expression, sources_manager); type_check_error("Match value is invalid", expression, sources_manager);
} }
std::optional<nodes::TypeCheckResult> expression_result; MaybeResult expression_result;
bool at_least_one_case_with_expression = false; bool at_least_one_case_with_expression = false;
bool at_least_one_case_without_expression = false; bool at_least_one_case_without_expression = false;
@ -106,30 +45,28 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
const nodes::Match::Case *current_case = expression.get_case(i); const nodes::Match::Case *current_case = expression.get_case(i);
// :=/=: x ... // :=/=: x ...
type_check_expression( check(*current_case->get_value(), sources_manager, state,
*current_case->get_value(), sources_manager, state, Arguments{}
Arguments{} .expect_builtin(builtin::Type::BOOL, sources_manager)
.expect_builtin(builtin::types::Type::BOOL, sources_manager) .pass(value_result.is_invalid()
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{} ? nodes::MaybeTypeProxy{}
: expression_result.value().get())); : expression_result.value().get()));
// TODO: use type modifiers ?? // TODO: use type modifiers ??
// ... ?? x ... // ... ?? x ...
if (current_case->get_condition().has_value()) { if (current_case->get_condition().has_value()) {
type_check_expression(*current_case->get_condition().value(), check(*current_case->get_condition().value(), sources_manager, state,
sources_manager, state, Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
Arguments{}.expect_builtin(
builtin::types::Type::BOOL, sources_manager));
} }
// ... -> x // ... -> x
if (current_case->get_expression().has_value()) { if (current_case->get_expression().has_value()) {
at_least_one_case_with_expression = true; at_least_one_case_with_expression = true;
nodes::TypeCheckResult case_result = type_check_expression( Result case_result =
*current_case->get_condition().value(), sources_manager, state, check(*current_case->get_condition().value(), sources_manager, state,
Arguments{}.expect(expression_result.has_value() Arguments{}.expect(expression_result.has_value()
? expression_result.value().get() ? expression_result.value().get()
: nodes::MaybeTypeProxy{})); : nodes::MaybeTypeProxy{}));
if (!expression_result.has_value() && !case_result.is_invalid()) { if (!expression_result.has_value() && !case_result.is_invalid()) {
expression_result = std::move(case_result); expression_result = std::move(case_result);
@ -144,38 +81,33 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
type_check_error( type_check_error(
"All cases should be with or without expression at the same time", "All cases should be with or without expression at the same time",
expression, sources_manager); expression, sources_manager);
expression_result = nodes::TypeCheckResult::construct_invalid_result(); expression_result = Result::invalid();
} }
if (!expression_result.has_value()) { if (!expression_result.has_value()) {
expression_result = nodes::TypeCheckResult{ expression_result =
sources_manager.get_type_storage()->primitive_type( Result{sources_manager.types()->primitive(builtin::Type::UNIT)};
builtin::types::Type::UNIT)};
} }
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->add_array_of( sources_manager.types()->add_array_of(expression_result.value().get()),
expression_result.value().get()),
arguments, expression, sources_manager); arguments, expression, sources_manager);
} }
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression, Result check(const nodes::Condition &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) { MaybeResult expression_result;
std::optional<nodes::TypeCheckResult> expression_result;
for (size_t i = 0; i < expression.cases_size(); ++i) { for (size_t i = 0; i < expression.cases_size(); ++i) {
type_check_expression(*expression.get_case(i).first, sources_manager, state, check(*expression.get_case(i).first, sources_manager, state,
Arguments{}.expect_builtin(builtin::types::Type::BOOL, Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
sources_manager));
nodes::TypeCheckResult case_result = type_check_expression( Result case_result =
*expression.get_case(i).first, sources_manager, state, check(*expression.get_case(i).first, sources_manager, state,
Arguments{}.expect(expression_result.has_value() Arguments{}.expect(expression_result.has_value()
? expression_result.value().get() ? expression_result.value().get()
: nodes::MaybeTypeProxy{})); : nodes::MaybeTypeProxy{}));
if (!expression_result.has_value() && !case_result.is_invalid()) { if (!expression_result.has_value() && !case_result.is_invalid()) {
expression_result = std::move(case_result); expression_result = std::move(case_result);
@ -183,46 +115,40 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
} }
if (expression.get_else_case().has_value()) { if (expression.get_else_case().has_value()) {
type_check_expression( check(*expression.get_else_case().value(), sources_manager, state,
*expression.get_else_case().value(), sources_manager, state, Arguments{}.expect(expression_result.has_value()
Arguments{}.expect(expression_result.has_value() ? expression_result.value().get()
? expression_result.value().get() : nodes::MaybeTypeProxy{}));
: nodes::MaybeTypeProxy{}));
} }
if (!expression_result.has_value()) { if (!expression_result.has_value()) {
type_check_error("There should be at least one case in if statement", type_check_error("There should be at least one case in if statement",
expression, sources_manager); expression, sources_manager);
expression_result = nodes::TypeCheckResult::construct_invalid_result(); expression_result = Result::invalid();
} }
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->add_array_of( sources_manager.types()->add_array_of(expression_result.value().get()),
expression_result.value().get()),
arguments, expression, sources_manager); arguments, expression, sources_manager);
} }
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression, Result check(const nodes::Loop &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
State &state,
const Arguments &arguments) {
// TODO: ranges ?? // TODO: ranges ??
std::optional<nodes::TypeCheckResult> interval_result; MaybeResult interval_result;
std::optional<nodes::TypeCheckResult> variable_result; MaybeResult variable_result;
nodes::TypeCheckResult expression_result = type_check_expression( Result expression_result =
*expression.get_expression(), sources_manager, state, Arguments{}); check(*expression.get_expression(), sources_manager, state, Arguments{});
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Loop::LOOP: // infinity loop, no params case nodes::Loop::LOOP: // infinity loop, no params
break; break;
case nodes::Loop::WHILE: case nodes::Loop::WHILE:
type_check_expression(*expression.get_condition().value(), sources_manager, check(*expression.get_condition().value(), sources_manager, state,
state, Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
sources_manager));
// --- type check is independent from loop itself --- // --- type check is independent from loop itself ---
// if (condition_result.value().is_invalid()) { // if (condition_result.value().is_invalid()) {
@ -232,10 +158,9 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
break; break;
case nodes::Loop::FOR: case nodes::Loop::FOR:
// TODO: expect range ?? // TODO: expect range ??
interval_result = type_check_expression( interval_result = check(
*expression.get_interval().value(), sources_manager, state, *expression.get_interval().value(), sources_manager, state,
Arguments{}.expect_builtin(builtin::types::Type::ARRAY, Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager));
sources_manager));
if (interval_result.value().is_invalid()) { if (interval_result.value().is_invalid()) {
// --- type check is independent from loop itself --- // --- type check is independent from loop itself ---
@ -243,10 +168,10 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
break; break;
} }
variable_result = type_check_expression( variable_result =
*expression.get_variable().value(), sources_manager, state, check(*expression.get_variable().value(), sources_manager, state,
Arguments{}.expect( Arguments{}.expect(
interval_result.value().get().get()->get_parameter_proxy(0))); interval_result.value().get().get()->get_parameter_proxy(0)));
// --- type check is independent from loop itself --- // --- type check is independent from loop itself ---
// if (variable_result.value().is_invalid()) { // if (variable_result.value().is_invalid()) {
@ -262,22 +187,21 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
// TODO: modifier checks ??, modifiers ?? // TODO: modifier checks ??, modifiers ??
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->add_array_of(expression_result.get()), sources_manager.types()->add_array_of(expression_result.get()), arguments,
arguments, expression, sources_manager); expression, sources_manager);
} // IN PROGRESS } // IN PROGRESS
// --- containers // --- containers
nodes::TypeCheckResult type_check_array(const nodes::Container &expression, Result type_check_array(const nodes::Container &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) { MaybeResult last_expression_result;
std::optional<nodes::TypeCheckResult> last_expression_result;
for (size_t i = 0; i < expression.expressions_size(); ++i) { for (size_t i = 0; i < expression.expressions_size(); ++i) {
// elements should have same type, but type is not expected // elements should have same type, but type is not expected
auto expression_result = type_check_expression( auto expression_result = check(*expression.get_expression(i),
*expression.get_expression(i), sources_manager, state, Arguments{}); sources_manager, state, Arguments{});
if (!last_expression_result.has_value()) { if (!last_expression_result.has_value()) {
last_expression_result = expression_result; last_expression_result = expression_result;
@ -285,7 +209,7 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
if (last_expression_result.value().get() != expression_result.get()) { if (last_expression_result.value().get() != expression_result.get()) {
type_check_error("Elements in array should have same type", type_check_error("Elements in array should have same type",
*expression.get_expression(i), sources_manager); *expression.get_expression(i), sources_manager);
// return nodes::TypeCheckResult::construct_invalid_result(); // max // return TypeCheckResult::construct_invalid_result(); // max
// possible checks, so no return // possible checks, so no return
} }
} }
@ -293,50 +217,43 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
if (!last_expression_result.has_value()) { if (!last_expression_result.has_value()) {
type_check_error("Array with zero elements", expression, sources_manager); type_check_error("Array with zero elements", expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
return type_check_from_arguments( return type_check_from_arguments(sources_manager.types()->add_array_of(
sources_manager.get_type_storage()->add_array_of( last_expression_result.value().get()),
last_expression_result.value().get()), arguments, expression, sources_manager);
arguments, expression, sources_manager);
} }
nodes::TypeCheckResult type_check_block(const nodes::Container &expression, Result type_check_block(const nodes::Container &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) {
nodes::MaybeTypeProxy context_exit_type; nodes::MaybeTypeProxy context_exit_type;
{ {
ContextHolder context_holder( ContextHolder context_holder(
state, expression, *sources_manager.get_error_log(), state, expression, *sources_manager.errors(),
&context_exit_type); // TODO: is brought type returned &context_exit_type); // TODO: is brought type returned
for (size_t i = 0; i < expression.expressions_size(); ++i) { for (size_t i = 0; i < expression.expressions_size(); ++i) {
// result types in block are discarded // result types in block are discarded
type_check_expression(*expression.get_expression(i), sources_manager, check(*expression.get_expression(i), sources_manager, state, Arguments{});
state, Arguments{});
} }
} }
nodes::TypeCheckResult block_brought_type = Result block_brought_type =
context_exit_type.has_value() context_exit_type.has_value()
? nodes::TypeCheckResult(context_exit_type.value()) ? Result(context_exit_type.value())
: nodes::TypeCheckResult( : Result(sources_manager.types()->primitive(builtin::Type::UNIT));
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->add_array_of( sources_manager.types()->add_array_of(block_brought_type.get()),
block_brought_type.get()),
arguments, expression, sources_manager); arguments, expression, sources_manager);
} }
nodes::TypeCheckResult type_check_container(const nodes::Container &expression, Result check(const nodes::Container &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) {
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Container::ARRAY: case nodes::Container::ARRAY:
return type_check_array(expression, sources_manager, state, arguments); return type_check_array(expression, sources_manager, state, arguments);
@ -347,12 +264,10 @@ nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
// --- modifiers // --- modifiers
nodes::TypeCheckResult type_check_return(const nodes::Return &expression, Result check(const nodes::Return &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
State &state, auto returned_result =
const Arguments &arguments) { check(*expression.get_expression(), sources_manager, state, Arguments{});
auto returned_result = type_check_expression(
*expression.get_expression(), sources_manager, state, Arguments{});
if (returned_result.is_invalid()) { if (returned_result.is_invalid()) {
return returned_result; return returned_result;
@ -363,29 +278,27 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
if (state.bring_type(returned_result.get())) { if (state.bring_type(returned_result.get())) {
type_check_error("Different brought type to current one", expression, type_check_error("Different brought type to current one", expression,
sources_manager); sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
break; break;
case nodes::Return::RETURN: case nodes::Return::RETURN:
if (!state.return_type(returned_result.get())) { if (!state.return_type(returned_result.get())) {
type_check_error("Different returned type to current one", expression, type_check_error("Different returned type to current one", expression,
sources_manager); sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
break; break;
} }
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->primitive_type( sources_manager.types()->primitive(builtin::Type::UNIT), arguments,
builtin::types::Type::UNIT), expression, sources_manager);
arguments, expression, sources_manager);
} }
// TODO: warning if name is same to package prefix, function prefix, etc. ?? // TODO: warning if name is same to package prefix, function prefix, etc. ??
nodes::TypeCheckResult Result check(const nodes::NameDefinition &expression,
type_check_name_definition(const nodes::NameDefinition &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
const Arguments &arguments) {
if (!arguments.get_passed().has_value()) { if (!arguments.get_passed().has_value()) {
type_check_error("Can't deduce type of new variable from context", type_check_error("Can't deduce type of new variable from context",
expression, sources_manager); expression, sources_manager);
@ -401,8 +314,8 @@ type_check_name_definition(const nodes::NameDefinition &expression,
} }
// variable accessible by reference by default ?? // variable accessible by reference by default ??
sources_manager.get_type_storage()->add_modification_of(variable_type, sources_manager.types()->add_modification_of(variable_type,
nodes::Modifier::REF); nodes::Modifier::REF);
if (!state.insert_variable(*expression.get_name()->get(), variable_type, if (!state.insert_variable(*expression.get_name()->get(), variable_type,
expression.get_modifier())) { expression.get_modifier())) {
@ -412,23 +325,20 @@ type_check_name_definition(const nodes::NameDefinition &expression,
// Return BOOL as any := / =: expression // Return BOOL as any := / =: expression
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->primitive_type( sources_manager.types()->primitive(builtin::Type::BOOL), arguments,
builtin::types::Type::BOOL), expression, sources_manager);
arguments, expression, sources_manager);
} }
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression, Result type_check_array_access(const nodes::Access &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) { auto index_result =
check(*expression.get_index(), sources_manager, state,
Arguments{}.expect_builtin(builtin::Type::INDEX, sources_manager));
auto index_result = type_check_expression( auto value_result =
*expression.get_index(), sources_manager, state, check(*expression.get_value(), sources_manager, state,
Arguments{}.expect_builtin(builtin::types::Type::INDEX, sources_manager)); Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager));
auto value_result = type_check_expression(
*expression.get_value(), sources_manager, state,
Arguments{}.expect_builtin(builtin::types::Type::ARRAY, sources_manager));
if (index_result.is_invalid()) { if (index_result.is_invalid()) {
return index_result; return index_result;
@ -445,13 +355,12 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
sources_manager); sources_manager);
} }
nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression, Result type_check_tuple_access(const nodes::Access &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager, State &state,
State &state, const Arguments &arguments) {
const Arguments &arguments) { auto value_result =
auto value_result = type_check_expression( check(*expression.get_value(), sources_manager, state,
*expression.get_value(), sources_manager, state, Arguments{}.expect_builtin(builtin::Type::TUPLE, sources_manager));
Arguments{}.expect_builtin(builtin::types::Type::TUPLE, sources_manager));
if (value_result.is_invalid()) { if (value_result.is_invalid()) {
return value_result; return value_result;
@ -470,10 +379,8 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression,
expression, sources_manager); expression, sources_manager);
} }
nodes::TypeCheckResult type_check_access(const nodes::Access &expression, Result check(const nodes::Access &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
State &state,
const Arguments &arguments) {
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Access::ARRAY: case nodes::Access::ARRAY:
return type_check_array_access(expression, sources_manager, state, return type_check_array_access(expression, sources_manager, state,
@ -484,48 +391,47 @@ nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
} }
} }
nodes::TypeCheckResult Result check(const nodes::LoopControl &expression,
type_check_loop_control(const nodes::LoopControl &expression, SourcesManager &sources_manager, State &,
SourcesManager &sources_manager, State &, const Arguments &arguments) {
const Arguments &arguments) {
return type_check_from_arguments( return type_check_from_arguments(
sources_manager.get_type_storage()->primitive_type( sources_manager.types()->primitive(builtin::Type::UNIT), arguments,
builtin::types::Type::UNIT), expression, sources_manager);
arguments, expression, sources_manager);
} }
nodes::TypeCheckResult Result check(const nodes::ModifierExpression &expression,
type_check_modifier_expression(const nodes::ModifierExpression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
const Arguments &arguments) { auto modified_result =
auto modified_result = type_check_expression( check(*expression.get_expression(), sources_manager, state, Arguments{});
*expression.get_expression(), sources_manager, state, Arguments{});
if (modified_result.is_invalid()) { if (modified_result.is_invalid()) {
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
if (nodes::utils::is_suffix_modifier( if (nodes::utils::is_suffix_modifier(
expression.get_modifier())) { // optional, result expression.get_modifier())) { // optional, result
// '?' - open optional / result in -> (execute or not execute pattern // '?' - open optional / result in ->
// matching expression) / (value / return) (TODO: alternative for bring) // (execute or not execute pattern
// matching expression) / (value /
// return) (TODO: alternative for bring)
// '!' - open optional / result -> value / panic // '!' - open optional / result -> value / panic
switch (modified_result.get().get()->to_builtin()) { switch (modified_result.get().get()->to_builtin()) {
case builtin::types::Type::OPTIONAL: case builtin::Type::OPTIONAL:
case builtin::types::Type::RESULT: case builtin::Type::RESULT:
// TODO: how to unwrap external modifier ?? // TODO: how to unwrap external modifier ??
modified_result.set(modified_result.get().get()->get_parameter_proxy(0)); modified_result.set(modified_result.get().get()->get_parameter_proxy(0));
break; break;
default: default:
type_check_error("Can unwrap only Optional or Result", expression, type_check_error("Can unwrap only Optional or Result", expression,
sources_manager); sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
} else { } else {
// TODO: check that modifier can be applied // TODO: check that modifier can be applied
modified_result.set(sources_manager.get_type_storage()->add_modification_of( modified_result.set(sources_manager.types()->add_modification_of(
modified_result.get(), expression.get_modifier())); modified_result.get(), expression.get_modifier()));
} }
@ -536,10 +442,9 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression,
// --- other // --- other
// TODO // TODO
nodes::TypeCheckResult Result check(const nodes::NameExpression &expression,
type_check_name_expression(const nodes::NameExpression &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
const Arguments &arguments) {
// TODO: constraints ?? // TODO: constraints ??
const auto name = expression.get_name(); const auto name = expression.get_name();
@ -565,10 +470,11 @@ type_check_name_expression(const nodes::NameExpression &expression,
if (maybe_variable.has_value()) { if (maybe_variable.has_value()) {
auto &type = maybe_variable.value().type; auto &type = maybe_variable.value().type;
for (size_t j = i + 1; j < fragments.size(); ++i) { for (size_t j = i + 1; j < fragments.size(); ++i) {
if (j + 1 ==
if (j + 1 == fragments.size()) { // then this can be method call fragments
// TODO: try to find method or local function .size()) { // then this can be method call
// if found, search to field (without error handling) // TODO: try to find method or local function
// if found, search to field (without error handling)
} }
// TODO: fields from several fragments ? (not acceptable fors methods / // TODO: fields from several fragments ? (not acceptable fors methods /
@ -600,10 +506,10 @@ type_check_name_expression(const nodes::NameExpression &expression,
// TODO: check, if there is variable with this name // TODO: check, if there is variable with this name
// TODO: check var + fields // TODO: check var + fields
const auto maybe_function_definition = find_name_definition_handle_errors( const auto maybe_function_definition =
*name->get(), expression, sources_manager); find_name_definition(*name->get(), expression, sources_manager);
if (!maybe_function_definition.has_value()) { if (!maybe_function_definition.has_value()) {
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
const nodes::FunctionDefinition *function_definition = const nodes::FunctionDefinition *function_definition =
maybe_function_definition.value(); maybe_function_definition.value();
@ -624,13 +530,13 @@ type_check_name_expression(const nodes::NameExpression &expression,
: ""} + : ""} +
")", ")",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
// TODO: try return correct type (function return type), when possible // TODO: try return correct type (function return type), when possible
} }
// TODO: define types for generic function // TODO: define types for generic function
std::vector<nodes::TypeCheckResult> function_argument_results; std::vector<Result> function_argument_results;
for (size_t i = 0; i < arguments_given; for (size_t i = 0; i < arguments_given;
++i) { // TODO: pass types with oud modifier ++i) { // TODO: pass types with oud modifier
const nodes::FunctionDefinition::Argument *argument = const nodes::FunctionDefinition::Argument *argument =
@ -647,7 +553,6 @@ type_check_name_expression(const nodes::NameExpression &expression,
const auto expected_annotation = argument->get_annotation(); const auto expected_annotation = argument->get_annotation();
if (annotation.has_value() != expected_annotation.has_value()) { if (annotation.has_value() != expected_annotation.has_value()) {
type_check_error("Wrong function argument annotation: should be " + type_check_error("Wrong function argument annotation: should be " +
std::string{expected_annotation.has_value() std::string{expected_annotation.has_value()
? *expected_annotation.value() ? *expected_annotation.value()
@ -663,16 +568,16 @@ type_check_name_expression(const nodes::NameExpression &expression,
*expression.get_argument_value(i), sources_manager); *expression.get_argument_value(i), sources_manager);
} }
function_argument_results.push_back(type_check_expression( function_argument_results.push_back(
*expression.get_argument_value(i), sources_manager, state, check(*expression.get_argument_value(i), sources_manager, state,
Arguments{}.expect(argument->get_type_proxy().value()))); Arguments{}.expect(argument->get_type_proxy().value())));
} }
if (function_definition->arguments_size() == 0) { if (function_definition->arguments_size() == 0) {
type_check_error( type_check_error(
"Function arguments size is zero. Returned type is not defined", "Function arguments size is zero. Returned type is not defined",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
// TODO: check condition // TODO: check condition
@ -687,7 +592,7 @@ type_check_name_expression(const nodes::NameExpression &expression,
type_check_error( type_check_error(
"Function argument type is not defined for returned type", expression, "Function argument type is not defined for returned type", expression,
sources_manager); sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
// TODO: invert modifier ?? // TODO: invert modifier ??
@ -697,20 +602,21 @@ type_check_name_expression(const nodes::NameExpression &expression,
} }
// checks for universal call syntax ?? // checks for universal call syntax ??
// TODO: riturn result
} // IN PROGRESS } // IN PROGRESS
// TODO // TODO
nodes::TypeCheckResult Result check(const nodes::Constructor &expression,
type_check_constructor(const nodes::Constructor &expression, SourcesManager &sources_manager, State &state,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
const Arguments &arguments) {
// TODO: constraints ?? // TODO: constraints ??
// TODO: use pass type // TODO: use pass type
const auto maybe_type_definition = find_type_definition_handle_errors( const auto maybe_type_definition = find_type_definition(
*expression.get_type()->get_name()->get(), expression, sources_manager); *expression.get_type()->get_name()->get(), expression, sources_manager);
if (!maybe_type_definition.has_value()) { if (!maybe_type_definition.has_value()) {
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
const nodes::TypeDefinition *type_definition = maybe_type_definition.value(); const nodes::TypeDefinition *type_definition = maybe_type_definition.value();
@ -718,7 +624,7 @@ type_check_constructor(const nodes::Constructor &expression,
type_check_error( type_check_error(
"Type defenition for constructor type not found (declaration only)", "Type defenition for constructor type not found (declaration only)",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
} }
// TODO: deal with anniotations, recursive annotations // TODO: deal with anniotations, recursive annotations
@ -732,7 +638,7 @@ type_check_constructor(const nodes::Constructor &expression,
if (expression.arguments_size() == 0) { if (expression.arguments_size() == 0) {
type_check_error("Number of type constructor arguments should be > 0", type_check_error("Number of type constructor arguments should be > 0",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
// TODO: try return correct type (constructor's type), when possible (not // TODO: try return correct type (constructor's type), when possible (not
// generic) // generic)
} }
@ -743,7 +649,7 @@ type_check_constructor(const nodes::Constructor &expression,
{ // check arguments size, ets. { // check arguments size, ets.
switch (builtin_type) { switch (builtin_type) {
case builtin::types::Type::TUPLE: case builtin::Type::TUPLE:
if (expression.arguments_size() != type.get()->parameters_size()) { if (expression.arguments_size() != type.get()->parameters_size()) {
type_check_error( type_check_error(
"Number of type constructor arguments is different from expected " "Number of type constructor arguments is different from expected "
@ -751,23 +657,23 @@ type_check_constructor(const nodes::Constructor &expression,
std::to_string(expression.arguments_size()) + " instead of " + std::to_string(expression.arguments_size()) + " instead of " +
std::to_string(type.get()->parameters_size()) + ")", std::to_string(type.get()->parameters_size()) + ")",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
// TODO: try return correct type (constructor's type), when possible // TODO: try return correct type (constructor's type), when possible
// (not generic) // (not generic)
} }
break; break;
case builtin::types::Type::VARIANT: case builtin::Type::VARIANT:
case builtin::types::Type::OPTIONAL: case builtin::Type::OPTIONAL:
case builtin::types::Type::RESULT: case builtin::Type::RESULT:
case builtin::types::Type::ERROR: case builtin::Type::ERROR:
case builtin::types::Type::FUNCTION: case builtin::Type::FUNCTION:
case builtin::types::Type::NONE: case builtin::Type::NONE:
if (expression.arguments_size() != 1) { // TODO: better to_string if (expression.arguments_size() != 1) { // TODO: better to_string
type_check_error("Number of type constructor arguments should be = 1 " type_check_error("Number of type constructor arguments should be = 1 "
"(builtin type " + "(builtin type " +
std::to_string(uint(builtin_type)) + ")", std::to_string(uint(builtin_type)) + ")",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
// TODO: try return correct type (constructor's type), when possible // TODO: try return correct type (constructor's type), when possible
// (not generic) // (not generic)
} }
@ -776,13 +682,13 @@ type_check_constructor(const nodes::Constructor &expression,
break; break;
} }
if (get_parameters_count(builtin_type).has_value() && if (builtin::types::get_parameters_count(builtin_type).has_value() &&
type.get()->parameters_size() != type.get()->parameters_size() !=
get_parameters_count(builtin_type).value()) { builtin::types::get_parameters_count(builtin_type).value()) {
type_check_error("Wrong amount of parametars for builtin type", type_check_error("Wrong amount of parametars for builtin type",
expression, sources_manager); expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result(); return Result::invalid();
// TODO: try return correct type (constructor's type), when possible (not // TODO: try return correct type (constructor's type), when possible (not
// generic) // generic)
} }
@ -841,13 +747,13 @@ type_check_constructor(const nodes::Constructor &expression,
}; };
switch (builtin_type) { switch (builtin_type) {
case builtin::types::Type::TUPLE: case builtin::Type::TUPLE:
for (size_t i = 0; i < expression.arguments_size(); ++i) { for (size_t i = 0; i < expression.arguments_size(); ++i) {
check_same_annotation(i, type.get()->get_parameter(i)->get_annotation(), check_same_annotation(i, type.get()->get_parameter(i)->get_annotation(),
true /*log errors*/); true /*log errors*/);
} }
break; break;
case builtin::types::Type::VARIANT: case builtin::Type::VARIANT:
// more then one same annotation ?? // more then one same annotation ??
for (size_t i = 0; i < type.get()->parameters_size(); ++i) { for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
if (check_same_annotation( if (check_same_annotation(
@ -865,14 +771,14 @@ type_check_constructor(const nodes::Constructor &expression,
*expression.get_argument_value(0), sources_manager); *expression.get_argument_value(0), sources_manager);
} }
break; break;
case builtin::types::Type::ERROR: // no anotations ?? case builtin::Type::ERROR: // no anotations ??
check_same_annotation(0, type.get()->get_parameter(0)->get_annotation(), check_same_annotation(0, type.get()->get_parameter(0)->get_annotation(),
true /*log errors*/); true /*log errors*/);
break; break;
case builtin::types::Type::OPTIONAL: case builtin::Type::OPTIONAL:
case builtin::types::Type::RESULT: case builtin::Type::RESULT:
case builtin::types::Type::FUNCTION: case builtin::Type::FUNCTION:
case builtin::types::Type::NONE: case builtin::Type::NONE:
check_no_annotation(0, true /*log errors*/); check_no_annotation(0, true /*log errors*/);
break; break;
default: // array, basic types default: // array, basic types
@ -882,58 +788,51 @@ type_check_constructor(const nodes::Constructor &expression,
{ // type check arguments { // type check arguments
switch (builtin_type) { switch (builtin_type) {
case builtin::types::Type::TUPLE: case builtin::Type::TUPLE:
for (size_t i = 0; i < expression.arguments_size(); ++i) { for (size_t i = 0; i < expression.arguments_size(); ++i) {
type_check_expression( check(*expression.get_argument_value(i), sources_manager, state,
*expression.get_argument_value(i), sources_manager, state, Arguments{}.expect(type.get()->get_parameter_proxy(i)));
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
} }
break; break;
case builtin::types::Type::VARIANT: case builtin::Type::VARIANT:
if (chosen_variant_option.has_value()) { if (chosen_variant_option.has_value()) {
type_check_expression( check(*expression.get_argument_value(0), sources_manager, state,
*expression.get_argument_value(0), sources_manager, state, Arguments{}.expect(type.get()->get_parameter_proxy(
Arguments{}.expect(type.get()->get_parameter_proxy( chosen_variant_option.value())));
chosen_variant_option.value())));
} else { // TODO: error, if there is more then one possible variant in } else { // TODO: error, if there is more then one possible variant in
// answer // answer
nodes::TypeProxies possible_options; nodes::TypeProxies possible_options;
for (size_t i = 0; i < type.get()->parameters_size(); ++i) { for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
possible_options.push_back(type.get()->get_parameter_proxy(i)); possible_options.push_back(type.get()->get_parameter_proxy(i));
} }
type_check_expression(*expression.get_argument_value(0), check(*expression.get_argument_value(0), sources_manager, state,
sources_manager, state, Arguments{}.expect(possible_options));
Arguments{}.expect(possible_options));
} }
break; break;
case builtin::types::Type::OPTIONAL: case builtin::Type::OPTIONAL:
// first parameter or NULL // first parameter or NULL
type_check_expression( check(*expression.get_argument_value(0), sources_manager, state,
*expression.get_argument_value(0), sources_manager, state, Arguments{}.expect({type.get()->get_parameter_proxy(0),
Arguments{}.expect( sources_manager.types()->primitive(
{type.get()->get_parameter_proxy(0), builtin::Type::NULL_OPTION)}));
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::NULL_OPTION)}));
break; break;
case builtin::types::Type::RESULT: case builtin::Type::RESULT:
// first parameter or ERROR[second parameter] // first parameter or ERROR[second parameter]
type_check_expression( check(*expression.get_argument_value(0), sources_manager, state,
*expression.get_argument_value(0), sources_manager, state, Arguments{}.expect({type.get()->get_parameter_proxy(0),
Arguments{}.expect({type.get()->get_parameter_proxy(0), sources_manager.types()->add_error_of(
sources_manager.get_type_storage()->add_error_of( type.get()->get_parameter_proxy(1))}));
type.get()->get_parameter_proxy(1))}));
break; break;
case builtin::types::Type::ERROR: case builtin::Type::ERROR:
// first parameter // first parameter
type_check_expression( check(*expression.get_argument_value(0), sources_manager, state,
*expression.get_argument_value(0), sources_manager, state, Arguments{}.expect(type.get()->get_parameter_proxy(0)));
Arguments{}.expect(type.get()->get_parameter_proxy(0)));
break; break;
case builtin::types::Type::FUNCTION: case builtin::Type::FUNCTION:
case builtin::types::Type::NONE: case builtin::Type::NONE:
// type itself // type itself
type_check_expression(*expression.get_argument_value(0), sources_manager, check(*expression.get_argument_value(0), sources_manager, state,
state, Arguments{}.expect(type)); Arguments{}.expect(type));
break; break;
default: // array, basic types default: // array, basic types
type_check_error("Type can't be constructed", expression, type_check_error("Type can't be constructed", expression,
@ -950,10 +849,8 @@ type_check_constructor(const nodes::Constructor &expression,
} // IN PROGRESS } // IN PROGRESS
// TODO // TODO
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression, Result check(const nodes::Lambda &expression, SourcesManager &sources_manager,
SourcesManager &sources_manager, State &state, const Arguments &arguments) {
State &state,
const Arguments &arguments) {
if (arguments.get_expected().empty()) { if (arguments.get_expected().empty()) {
type_check_error("Can't deduce type of lambda function from context: no " type_check_error("Can't deduce type of lambda function from context: no "
"one type expected", "one type expected",
@ -968,7 +865,7 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
} }
const auto expected_type = arguments.get_expected().front(); const auto expected_type = arguments.get_expected().front();
if (!expected_type.get()->is_builtin(builtin::types::Type::FUNCTION)) { if (!expected_type.get()->is_builtin(builtin::Type::FUNCTION)) {
type_check_error("Type of lambda function should be function", expression, type_check_error("Type of lambda function should be function", expression,
sources_manager); sources_manager);
} }
@ -1002,10 +899,9 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
// TODO: out type is can be not last // TODO: out type is can be not last
if (arguments_given + 1 == arguments_defined) { if (arguments_given + 1 == arguments_defined) {
type_check_expression( check(*expression.get_expression(), sources_manager, state,
*expression.get_expression(), sources_manager, state, Arguments{}.expect(
Arguments{}.expect( expected_type.get()->get_parameter_proxy(arguments_defined - 1)));
expected_type.get()->get_parameter_proxy(arguments_defined - 1)));
} }
// TODO: needed ?? (only passed type check required ??) // TODO: needed ?? (only passed type check required ??)
@ -1013,4 +909,16 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
sources_manager); sources_manager);
} // IN PROGRESS } // IN PROGRESS
Result check(const nodes::Extra &, SourcesManager &sources_manager, State &,
const Arguments &) {
return Result(sources_manager.types()->primitive(builtin::Type::UNIT));
}
Result check(const nodes::EmptyLines &, SourcesManager &sources_manager,
State &, const Arguments &) {
return Result(sources_manager.types()->primitive(builtin::Type::UNIT));
}
} // namespace type_check } // namespace type_check

View file

@ -7,8 +7,8 @@
namespace printers { namespace printers {
void print_modifier(const nodes::Modifier &modifier, Printer &printer, void print(const nodes::Modifier &modifier, Printer &printer,
bool const_is_none) { bool const_is_none) {
switch (modifier) { switch (modifier) {
case nodes::Modifier::IN: case nodes::Modifier::IN:
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- "); printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- ");
@ -85,7 +85,7 @@ void print_modifier(const nodes::Modifier &modifier, Printer &printer,
} }
} }
void print_literal(const nodes::Literal &literal, Printer &printer) { void print(const nodes::Literal &literal, Printer &printer) {
switch (literal.get_any()->index()) { switch (literal.get_any()->index()) {
case 0: // float case 0: // float
printer.print(std::to_string(*literal.get<float>().value())); printer.print(std::to_string(*literal.get<float>().value()));
@ -141,7 +141,7 @@ void print_literal(const nodes::Literal &literal, Printer &printer) {
exit(1); // unreachable exit(1); // unreachable
} }
void print_identifier(const nodes::Identifier &identifier, Printer &printer) { void print(const nodes::Identifier &identifier, Printer &printer) {
printer.print(*identifier.get()); printer.print(*identifier.get());
} }
@ -150,11 +150,11 @@ void print_annotation(const std::string &annotation, Printer &printer) {
printer.print(annotation); printer.print(annotation);
} }
void print_extra(const nodes::Extra &extra, Printer &printer) { void print(const nodes::Extra &extra, Printer &printer) {
printer.print(*extra.content()); printer.print(*extra.content());
} }
void print_empty_lines(const nodes::EmptyLines &empty_lines, Printer &printer) { void print(const nodes::EmptyLines &empty_lines, Printer &printer) {
for (size_t i = 0; i < empty_lines.line_count(); ++i) { for (size_t i = 0; i < empty_lines.line_count(); ++i) {
printer.new_indent_line(); printer.new_indent_line();
} }

View file

@ -6,7 +6,7 @@ namespace printers {
// TODO // TODO
void print_docs(const nodes::SymbolDocs &docs, Printer &printer) { void print(const nodes::SymbolDocs &docs, Printer &printer) {
auto description = docs.get_description(); auto description = docs.get_description();
if (description.has_value()) { if (description.has_value()) {

View file

@ -16,68 +16,13 @@ bool is_block_expression(const nodes::Expression &expression) {
} // namespace utils } // namespace utils
void print_expression(const nodes::Expression &expression, void print(const nodes::Expression &expression, printers::Printer &printer) {
printers::Printer &printer) {
if (expression.is_scoped()) { if (expression.is_scoped()) {
printer.print("("); printer.print("(");
} }
switch (expression.get_any()->index()) { std::visit([&printer](const auto &arg) -> void { print(arg, printer); },
// --- flow control *expression.get_any());
case 0: // Match
print_match(*expression.get<nodes::Match>().value(), printer);
break;
case 1: // Condition
print_condition(*expression.get<nodes::Condition>().value(), printer);
break;
case 2: // Loop
print_loop(*expression.get<nodes::Loop>().value(), printer);
break;
// --- containers
case 3: // Container
print_container(*expression.get<nodes::Container>().value(), printer);
break;
// --- modifiers
case 4: // Return
print_return(*expression.get<nodes::Return>().value(), printer);
break;
case 5: // NameDefinition
print_name_definition(*expression.get<nodes::NameDefinition>().value(),
printer);
break;
case 6: // Access
print_access(*expression.get<nodes::Access>().value(), printer);
break;
case 7: // LoopControl
print_loop_control(*expression.get<nodes::LoopControl>().value(), printer);
break;
case 8: // ModifierExpression
print_modifier_expression(
*expression.get<nodes::ModifierExpression>().value(), printer);
break;
// --- other
case 9: // NameExpression
print_name_expression(*expression.get<nodes::NameExpression>().value(),
printer);
break;
case 10: // Constructor
print_constructor(*expression.get<nodes::Constructor>().value(), printer);
break;
case 11: // Lambda
print_lambda(*expression.get<nodes::Lambda>().value(), printer);
break;
// --- literal
case 12: // Literal
print_literal(*expression.get<nodes::Literal>().value(), printer);
break;
// --- empty lines
case 13: // Extra
print_extra(*expression.get<nodes::Extra>().value(), printer);
break;
case 14: // EmptyLines
print_empty_lines(*expression.get<nodes::EmptyLines>().value(), printer);
break;
}
if (expression.is_scoped()) { if (expression.is_scoped()) {
printer.print(")"); printer.print(")");
@ -86,7 +31,7 @@ void print_expression(const nodes::Expression &expression,
// --- flow control // --- flow control
void print_case(const nodes::Match::Case &expression, Printer &printer) { void print(const nodes::Match::Case &expression, Printer &printer) {
switch (expression.case_type()) { switch (expression.case_type()) {
case nodes::Match::Case::PATTERN_VALUE: case nodes::Match::Case::PATTERN_VALUE:
@ -99,21 +44,21 @@ void print_case(const nodes::Match::Case &expression, Printer &printer) {
printer.space(); printer.space();
print_expression(*expression.get_value(), printer); print(*expression.get_value(), printer);
if (expression.get_condition().has_value()) { if (expression.get_condition().has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " if " : " ?? "); printer.print(printer.print_words_instead_of_symbols() ? " if " : " ?? ");
print_expression(*expression.get_condition().value(), printer); print(*expression.get_condition().value(), printer);
} }
if (expression.get_expression().has_value()) { if (expression.get_expression().has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => "); printer.print(printer.print_words_instead_of_symbols() ? " do " : " => ");
print_expression(*expression.get_expression().value(), printer); print(*expression.get_expression().value(), printer);
} }
} // IN PROGRESS } // IN PROGRESS
void print_match(const nodes::Match &expression, printers::Printer &printer) { void print(const nodes::Match &expression, printers::Printer &printer) {
print_expression(*expression.get_value(), printer); print(*expression.get_value(), printer);
printer.space(); printer.space();
@ -122,7 +67,7 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) {
printer.set_indentation_level(printer.current_position()); printer.set_indentation_level(printer.current_position());
for (size_t i = 0; i < expression.cases_size(); ++i) { for (size_t i = 0; i < expression.cases_size(); ++i) {
print_case(*expression.get_case(i), printer); print(*expression.get_case(i), printer);
if (i + 1 < expression.cases_size()) { if (i + 1 < expression.cases_size()) {
printer.new_indent_line(); printer.new_indent_line();
@ -133,8 +78,7 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) {
} // IN PROGRESS } // IN PROGRESS
void print_condition(const nodes::Condition &expression, void print(const nodes::Condition &expression, printers::Printer &printer) {
printers::Printer &printer) {
for (size_t i = 0; i < expression.cases_size(); ++i) { for (size_t i = 0; i < expression.cases_size(); ++i) {
if (i > 0) { if (i > 0) {
@ -151,11 +95,11 @@ void print_condition(const nodes::Condition &expression,
printer.print(printer.print_words_instead_of_symbols() ? "elif " : "!! "); printer.print(printer.print_words_instead_of_symbols() ? "elif " : "!! ");
} }
print_expression(*expression.get_case(i).first, printer); print(*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); print(*expression.get_case(i).second, printer);
} }
if (expression.cases_size() == 0) { if (expression.cases_size() == 0) {
@ -171,11 +115,11 @@ void print_condition(const nodes::Condition &expression,
printer.new_indent_line(); printer.new_indent_line();
} }
printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> "); printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> ");
print_expression(*expression.get_else_case().value(), printer); print(*expression.get_else_case().value(), printer);
} }
} }
void print_loop(const nodes::Loop &expression, printers::Printer &printer) { void print(const nodes::Loop &expression, printers::Printer &printer) {
printer.print(printer.print_words_instead_of_symbols() ? "for" : "@"); printer.print(printer.print_words_instead_of_symbols() ? "for" : "@");
switch (expression.get_type()) { switch (expression.get_type()) {
@ -184,27 +128,26 @@ void print_loop(const nodes::Loop &expression, printers::Printer &printer) {
break; break;
case nodes::Loop::WHILE: case nodes::Loop::WHILE:
printer.space(); printer.space();
print_expression(*expression.get_condition().value(), printer); print(*expression.get_condition().value(), printer);
printer.space(); printer.space();
break; break;
case nodes::Loop::FOR: case nodes::Loop::FOR:
printer.space(); printer.space();
print_expression(*expression.get_variable().value(), printer); print(*expression.get_variable().value(), printer);
printer.print(" : "); printer.print(" : ");
print_expression(*expression.get_interval().value(), printer); print(*expression.get_interval().value(), printer);
printer.space(); printer.space();
break; break;
} }
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> "); printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
print_expression(*expression.get_expression(), printer); print(*expression.get_expression(), printer);
} // IN PROGRESS } // IN PROGRESS
// --- containers // --- containers
void print_container(const nodes::Container &expression, void print(const nodes::Container &expression, printers::Printer &printer) {
printers::Printer &printer) {
bool is_array = expression.get_type() == nodes::Container::ARRAY; bool is_array = expression.get_type() == nodes::Container::ARRAY;
if (is_array) { if (is_array) {
@ -224,7 +167,7 @@ void print_container(const nodes::Container &expression,
if (!is_array && !is_empty_lines) { if (!is_array && !is_empty_lines) {
printer.new_indent_line(); printer.new_indent_line();
} }
print_expression(*expression.get_expression(i), printer); print(*expression.get_expression(i), printer);
if (is_array) { if (is_array) {
if (i + 1 < expression.expressions_size()) { if (i + 1 < expression.expressions_size()) {
printer.space(); printer.space();
@ -247,7 +190,7 @@ void print_container(const nodes::Container &expression,
// --- modifiers // --- modifiers
void print_return(const nodes::Return &expression, printers::Printer &printer) { void print(const nodes::Return &expression, printers::Printer &printer) {
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Return::RETURN: case nodes::Return::RETURN:
@ -260,11 +203,11 @@ void print_return(const nodes::Return &expression, printers::Printer &printer) {
break; break;
} }
print_expression(*expression.get_expression(), printer); print(*expression.get_expression(), printer);
} }
void print_name_definition(const nodes::NameDefinition &expression, void print(const nodes::NameDefinition &expression,
printers::Printer &printer) { printers::Printer &printer) {
if (printer.print_words_instead_of_symbols()) { if (printer.print_words_instead_of_symbols()) {
switch (expression.get_modifier()) { switch (expression.get_modifier()) {
@ -290,11 +233,11 @@ void print_name_definition(const nodes::NameDefinition &expression,
} }
} }
print_identifier(*expression.get_name(), printer); print(*expression.get_name(), printer);
} }
void print_access(const nodes::Access &expression, printers::Printer &printer) { void print(const nodes::Access &expression, printers::Printer &printer) {
print_expression(*expression.get_value(), printer); print(*expression.get_value(), printer);
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Access::ARRAY: case nodes::Access::ARRAY:
@ -307,7 +250,7 @@ void print_access(const nodes::Access &expression, printers::Printer &printer) {
break; break;
} }
print_expression(*expression.get_index(), printer); print(*expression.get_index(), printer);
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Access::ARRAY: case nodes::Access::ARRAY:
@ -320,8 +263,7 @@ void print_access(const nodes::Access &expression, printers::Printer &printer) {
} }
} }
void print_loop_control(const nodes::LoopControl &expression, void print(const nodes::LoopControl &expression, printers::Printer &printer) {
printers::Printer &printer) {
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::LoopControl::BREAK: case nodes::LoopControl::BREAK:
printer.print("break"); printer.print("break");
@ -334,30 +276,30 @@ void print_loop_control(const nodes::LoopControl &expression,
} }
} }
void print_modifier_expression(const nodes::ModifierExpression &expression, void print(const nodes::ModifierExpression &expression,
printers::Printer &printer) { printers::Printer &printer) {
if (expression.get_modifier() != nodes::Modifier::OPTIONAL && if (expression.get_modifier() != nodes::Modifier::OPTIONAL &&
expression.get_modifier() != nodes::Modifier::RESULT) { expression.get_modifier() != nodes::Modifier::RESULT) {
print_modifier(expression.get_modifier(), printer); print(expression.get_modifier(), printer);
} }
print_expression(*expression.get_expression(), printer); print(*expression.get_expression(), printer);
if (expression.get_modifier() == nodes::Modifier::OPTIONAL || if (expression.get_modifier() == nodes::Modifier::OPTIONAL ||
expression.get_modifier() == nodes::Modifier::RESULT) { expression.get_modifier() == nodes::Modifier::RESULT) {
print_modifier(expression.get_modifier(), printer); print(expression.get_modifier(), printer);
} }
} }
// --- other // --- other
void print_name_expression(const nodes::NameExpression &expression, void print(const nodes::NameExpression &expression,
printers::Printer &printer) { printers::Printer &printer) {
bool is_comma_operator = (*expression.get_name()->get() == ","); bool is_comma_operator = (*expression.get_name()->get() == ",");
bool is_range_operator = (*expression.get_name()->get() == ".."); bool is_range_operator = (*expression.get_name()->get() == "..");
if (expression.is_operator_call() || expression.is_point_call()) { if (expression.is_operator_call() || expression.is_point_call()) {
print_expression(*expression.get_argument_value(0), printer); print(*expression.get_argument_value(0), printer);
if (expression.is_point_call()) { if (expression.is_point_call()) {
printer.print("."); printer.print(".");
@ -366,7 +308,7 @@ void print_name_expression(const nodes::NameExpression &expression,
printer.space(); printer.space();
} }
} else if (expression.get_prefix().has_value()) { } else if (expression.get_prefix().has_value()) {
print_type(*expression.get_prefix().value(), printer); print(*expression.get_prefix().value(), printer);
printer.print("."); printer.print(".");
} }
@ -380,7 +322,7 @@ void print_name_expression(const nodes::NameExpression &expression,
printer.print("( "); printer.print("( ");
} }
print_identifier(*expression.get_name(), printer); print(*expression.get_name(), printer);
if (operator_called_as_function) { if (operator_called_as_function) {
printer.print(" )"); printer.print(" )");
@ -399,14 +341,13 @@ void print_name_expression(const nodes::NameExpression &expression,
print_annotation(*expression.get_argument_annotation(i).value(), printer); print_annotation(*expression.get_argument_annotation(i).value(), printer);
printer.space(); printer.space();
} }
print_expression(*expression.get_argument_value(i), printer); print(*expression.get_argument_value(i), printer);
} }
} // IN PROGRESS } // IN PROGRESS
void print_constructor(const nodes::Constructor &expression, void print(const nodes::Constructor &expression, printers::Printer &printer) {
printers::Printer &printer) { print(*expression.get_type(), printer);
print_type(*expression.get_type(), printer);
for (size_t i = 0; i < expression.arguments_size(); ++i) { for (size_t i = 0; i < expression.arguments_size(); ++i) {
printer.space(); printer.space();
@ -416,22 +357,22 @@ void print_constructor(const nodes::Constructor &expression,
printer.space(); printer.space();
} }
print_expression(*expression.get_argument_value(i), printer); print(*expression.get_argument_value(i), printer);
} }
} // IN PROGRESS } // IN PROGRESS
void print_lambda(const nodes::Lambda &expression, printers::Printer &printer) { void print(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) { for (size_t i = 0; i < expression.arguments_size(); ++i) {
print_identifier(*expression.get_argument(i), printer); print(*expression.get_argument(i), printer);
printer.space(); printer.space();
} }
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> "); printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
print_expression(*expression.get_expression(), printer); print(*expression.get_expression(), printer);
} // IN PROGRESS } // IN PROGRESS

View file

@ -10,48 +10,27 @@
namespace printers { namespace printers {
void print_source_file(const std::vector<nodes::Statement> &statements, // void print_source_file(const std::vector<nodes::Statement> &statements,
Printer &printer) { // Printer &printer) {
for (auto &statement : statements) { // for (const auto &statement : statements) {
print_statement(statement, printer); // print(statement, printer);
} // }
// }
void print(const nodes::Statement &statement, Printer &printer) {
std::visit([&printer](const auto &arg) -> void { print(arg, printer); },
*statement.get_any());
} }
void print_statement(const nodes::Statement &statement, Printer &printer) { void print(const nodes::Import &statement, Printer &printer) {
switch (statement.get_any()->index()) {
case 0: // Import
print_import(*statement.get<nodes::Import>().value(), printer);
printer.new_indent_line();
break;
case 1: // TypeDefinition
print_type_definition(*statement.get<nodes::TypeDefinition>().value(),
printer);
printer.new_indent_line();
break;
case 2: // FunctionDefinition
print_function_definition(
*statement.get<nodes::FunctionDefinition>().value(), printer);
printer.new_indent_line();
break;
case 3: // Extra
print_extra(*statement.get<nodes::Extra>().value(), printer);
printer.new_indent_line();
break;
case 4: // EmptyLines
print_empty_lines(*statement.get<nodes::EmptyLines>().value(), printer);
break;
}
}
void print_import(const nodes::Import &statement, Printer &printer) {
printer.print(":: "); printer.print(":: ");
print_identifier(*statement.get_import_name(), printer); print(*statement.get_import_name(), printer);
if (*statement.get_import_name()->get() != if (*statement.get_import_name()->get() !=
*statement.get_module_name()->get()) { *statement.get_module_name()->get()) {
printer.print(" = "); printer.print(" = ");
print_identifier(*statement.get_module_name(), printer); print(*statement.get_module_name(), printer);
} }
if (statement.symbols_size() > 0) { if (statement.symbols_size() > 0) {
@ -66,7 +45,7 @@ void print_import(const nodes::Import &statement, Printer &printer) {
printer.print("( "); printer.print("( ");
} }
print_identifier(*statement.get_symbol(i), printer); print(*statement.get_symbol(i), printer);
if (identifier_is_operator) { if (identifier_is_operator) {
printer.print(" )"); printer.print(" )");
@ -76,25 +55,24 @@ void print_import(const nodes::Import &statement, Printer &printer) {
printer.print(";"); printer.print(";");
} // IN PROGRESS } // IN PROGRESS
void print_constraint(const nodes::Constraint &statement, Printer &printer) { void print(const nodes::Constraint &statement, Printer &printer) {
printer.print("? "); printer.print("? ");
print_expression(*statement.get_expression(), printer); print(*statement.get_expression(), printer);
printer.print(";"); printer.print(";");
} }
void print_type_definition(const nodes::TypeDefinition &statement, void print(const nodes::TypeDefinition &statement, Printer &printer) {
Printer &printer) { print(*statement.get_docs(), printer);
print_docs(*statement.get_docs(), printer);
if (statement.is_on_heap()) { if (statement.is_on_heap()) {
printer.print("<> "); printer.print("<> ");
} }
print_identifier(*statement.get_name(), printer); print(*statement.get_name(), printer);
for (size_t i = 0; i < statement.arguments_size(); ++i) { for (size_t i = 0; i < statement.arguments_size(); ++i) {
printer.space(); printer.space();
print_identifier(*statement.get_argument(i), printer); print(*statement.get_argument(i), printer);
} }
if (statement.get_type().has_value()) { if (statement.get_type().has_value()) {
@ -104,7 +82,7 @@ void print_type_definition(const nodes::TypeDefinition &statement,
printer.set_indentation_level(printer.get_current_position() - 2); printer.set_indentation_level(printer.get_current_position() - 2);
print_type(*statement.get_type().value().get(), printer); print(*statement.get_type().value().get(), printer);
printer.set_indentation_level(previous_indentation_level); printer.set_indentation_level(previous_indentation_level);
} }
@ -112,12 +90,11 @@ void print_type_definition(const nodes::TypeDefinition &statement,
} // IN PROGRESS } // IN PROGRESS
// TODO: do not print prefix type for names // TODO: do not print prefix type for names
void print_function_definition(const nodes::FunctionDefinition &statement, void print(const nodes::FunctionDefinition &statement, Printer &printer) {
Printer &printer) { print(*statement.get_docs(), printer);
print_docs(*statement.get_docs(), printer);
for (size_t i = 0; i < statement.constraints_size(); ++i) { for (size_t i = 0; i < statement.constraints_size(); ++i) {
print_constraint(*statement.get_constraint(i), printer); print(*statement.get_constraint(i), printer);
printer.new_indent_line(); printer.new_indent_line();
} }
@ -132,13 +109,13 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
printer.print("( "); printer.print("( ");
} }
print_identifier(*statement.get_name(), printer); print(*statement.get_name(), printer);
if (identifier_is_operator) { if (identifier_is_operator) {
printer.print(" )"); printer.print(" )");
} }
print_modifier(statement.get_return_modifier(), printer); // ! or ? print(statement.get_return_modifier(), printer); // ! or ?
for (size_t i = 0; i < statement.arguments_size(); ++i) { for (size_t i = 0; i < statement.arguments_size(); ++i) {
if (!statement.get_argument(i)->get_name().has_value()) { if (!statement.get_argument(i)->get_name().has_value()) {
@ -158,15 +135,14 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
printer.space(); printer.space();
} }
print_modifier(statement.get_argument(i)->get_before_modifier(), printer, print(statement.get_argument(i)->get_before_modifier(), printer, true);
true);
} }
print_identifier(*statement.get_argument(i)->get_name().value(), printer); print(*statement.get_argument(i)->get_name().value(), printer);
// all arguments are typed or are untyped in the same time // all arguments are typed or are untyped in the same time
if (!statement.get_argument(i)->get_type().has_value()) { if (!statement.get_argument(i)->get_type().has_value()) {
print_modifier(statement.get_argument(i)->get_after_modifier(), printer); print(statement.get_argument(i)->get_after_modifier(), printer);
} }
} }
@ -184,10 +160,9 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
printer.space(); printer.space();
} }
print_modifier(statement.get_argument(i)->get_before_modifier(), printer, print(statement.get_argument(i)->get_before_modifier(), printer, true);
true);
print_type(*statement.get_argument(i)->get_type().value(), printer); print(*statement.get_argument(i)->get_type().value(), printer);
} }
} }
@ -201,7 +176,7 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
if (!expression_is_container) { if (!expression_is_container) {
printer.set_indentation_level(printer.current_position()); printer.set_indentation_level(printer.current_position());
} }
print_expression(*statement.get_expression().value(), printer); print(*statement.get_expression().value(), printer);
if (!expression_is_container) { if (!expression_is_container) {
printer.set_indentation_level(previous_indentation_level); printer.set_indentation_level(previous_indentation_level);
printer.print(";"); printer.print(";");

View file

@ -6,22 +6,22 @@
namespace printers { namespace printers {
// TODO: better printing format for builtin types // TODO: better printing format for builtin types
void print_type(const nodes::Type &type, printers::Printer &printer) { void print(const nodes::Type &type, printers::Printer &printer) {
if (type.has_annotation()) { if (type.has_annotation()) {
print_annotation(*type.get_annotation().value(), printer); print_annotation(*type.get_annotation().value(), printer);
printer.space(); printer.space();
} }
if (type.get_modifier() != nodes::Modifier::CONST) { if (type.get_modifier() != nodes::Modifier::CONST) {
print_modifier(type.get_modifier(), printer); print(type.get_modifier(), printer);
} }
print_identifier(*type.get_name(), printer); print(*type.get_name(), printer);
if (type.parameters_size() > 0) { if (type.parameters_size() > 0) {
printer.print("["); printer.print("[");
for (size_t i = 0; i < type.parameters_size(); ++i) { for (size_t i = 0; i < type.parameters_size(); ++i) {
print_type(*type.get_parameter(i), printer); print(*type.get_parameter(i), printer);
if (i + 1 < type.parameters_size()) { if (i + 1 < type.parameters_size()) {
printer.space(); printer.space();
} }

View file

@ -18,8 +18,7 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
type_check_error(message, node, sources_manager, handle_errors); type_check_error(message, node, sources_manager, handle_errors);
} }
return sources_manager.get_type_storage()->primitive_type( return sources_manager.types()->primitive(builtin::Type::BOOL);
builtin::types::Type::BOOL);
} }
bool check_no_pass_type_in_arguments(const Arguments &arguments, bool check_no_pass_type_in_arguments(const Arguments &arguments,
@ -35,14 +34,14 @@ bool check_no_pass_type_in_arguments(const Arguments &arguments,
return true; return true;
} }
nodes::TypeCheckResult Result type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
const nodes::Node &node, SourcesManager &sources_manager, SourcesManager &sources_manager,
const std::string &message, bool handle_errors) { const std::string &message, bool handle_errors) {
const auto &expected = arguments.get_expected(); const auto &expected = arguments.get_expected();
if (expected.empty()) { if (expected.empty()) {
return nodes::TypeCheckResult{type}; return Result{type};
} }
// TODO: use 'can cast to' (for modifiers), instead '==' // TODO: use 'can cast to' (for modifiers), instead '=='
@ -53,15 +52,15 @@ type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
type_check_error(message, node, sources_manager, handle_errors); type_check_error(message, node, sources_manager, handle_errors);
} }
return nodes::TypeCheckResult{expected.front()}; // any can be choosen return Result{expected.front()}; // any can be choosen
} }
template <typename T> template <typename T>
std::optional<const T *> find_statement_handle_errors( std::optional<const T *> find_statement(
const std::string &name, const nodes::Node &node, const std::string &name, const nodes::Node &node,
SourcesManager &sources_manager, const std::string &message_not_found, SourcesManager &sources_manager, const std::string &message_not_found,
const std::string &message_different_statement, bool handle_errors) { const std::string &message_different_statement, bool handle_errors) {
const auto maybe_any_statement = sources_manager.get_name_tree()->find(name); const auto maybe_any_statement = sources_manager.names()->find(name);
if (!maybe_any_statement.has_value()) { if (!maybe_any_statement.has_value()) {
type_check_error(message_not_found, node, sources_manager, handle_errors); type_check_error(message_not_found, node, sources_manager, handle_errors);
return std::nullopt; return std::nullopt;
@ -77,28 +76,26 @@ std::optional<const T *> find_statement_handle_errors(
return maybe_statement.value(); return maybe_statement.value();
} }
std::optional<const nodes::TypeDefinition *> find_type_definition_handle_errors( std::optional<const nodes::TypeDefinition *>
const std::string &name, const nodes::Node &node, find_type_definition(const std::string &name, const nodes::Node &node,
SourcesManager &sources_manager, bool handle_errors) { SourcesManager &sources_manager, bool handle_errors) {
return find_statement_handle_errors<nodes::TypeDefinition>( return find_statement_handle_errors<nodes::TypeDefinition>(
name, node, sources_manager, "No type definition found in name tree", name, node, sources_manager, "No type definition found in name tree",
"Node in name tree is not type definition", handle_errors); "Node in name tree is not type definition", handle_errors);
} }
std::optional<const nodes::FunctionDefinition *> std::optional<const nodes::FunctionDefinition *>
find_name_definition_handle_errors(const std::string &name, find_name_definition(const std::string &name, const nodes::Node &node,
const nodes::Node &node, SourcesManager &sources_manager, bool handle_errors) {
SourcesManager &sources_manager,
bool handle_errors) {
return find_statement_handle_errors<nodes::FunctionDefinition>( return find_statement_handle_errors<nodes::FunctionDefinition>(
name, node, sources_manager, "No name definition found in name tree", name, node, sources_manager, "No name definition found in name tree",
"Node in name tree is not name definition", handle_errors); "Node in name tree is not name definition", handle_errors);
} }
std::optional<nodes::TypeProxy> unfold_user_defined_type_handle_errors( std::optional<nodes::TypeProxy>
nodes::TypeProxy type, const nodes::Node &node, unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node,
SourcesManager &sources_manager, bool handle_errors) { SourcesManager &sources_manager, bool handle_errors) {
const auto maybe_type_definition = find_type_definition_handle_errors( const auto maybe_type_definition = find_type_definition(
*type.get()->get_name()->get(), node, sources_manager, handle_errors); *type.get()->get_name()->get(), node, sources_manager, handle_errors);
if (!maybe_type_definition.has_value()) { if (!maybe_type_definition.has_value()) {
@ -120,11 +117,12 @@ std::optional<nodes::TypeProxy> unfold_user_defined_type_handle_errors(
return maybe_type_definition.value()->get_type().value(); return maybe_type_definition.value()->get_type().value();
} }
std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors( std::optional<nodes::TypeProxy>
nodes::TypeProxy type, const std::string &field, const nodes::Node &node, get_field_type_by_name(nodes::TypeProxy type, const std::string &field,
SourcesManager &sources_manager, bool handle_errors) { const nodes::Node &node, SourcesManager &sources_manager,
bool handle_errors) {
switch (type.get()->to_builtin()) { switch (type.get()->to_builtin()) {
case builtin::types::Type::TUPLE: { // access field case builtin::Type::TUPLE: { // access field
const auto maybe_field = type.get()->get_parameter_proxy_by_name(field); const auto maybe_field = type.get()->get_parameter_proxy_by_name(field);
@ -136,19 +134,18 @@ std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors(
} }
return maybe_field.value(); return maybe_field.value();
} }
case builtin::types::Type::NONE: { // user defined type, trying to unfold, and case builtin::Type::NONE: { // user defined type, trying to unfold, and
// then repeat access // then repeat access
// remove recursion ?? // remove recursion ??
const auto maybe_internal_type = unfold_user_defined_type_handle_errors( const auto maybe_internal_type =
type, node, sources_manager, handle_errors); unfold_user_defined_type(type, node, sources_manager, handle_errors);
if (!maybe_internal_type.has_value()) { if (!maybe_internal_type.has_value()) {
return std::nullopt; return std::nullopt;
} }
return get_field_type_by_name_handle_errors(maybe_internal_type.value(), return get_field_type_by_name(maybe_internal_type.value(), field, node,
field, node, sources_manager, sources_manager, handle_errors);
handle_errors);
} }
default: // variant, function, optional, result, error (TODO: add message default: // variant, function, optional, result, error (TODO: add message
// field?), array (TODO: add length field ?), basic types // field?), array (TODO: add length field ?), basic types
@ -167,9 +164,8 @@ void type_check_error(const std::string &message, const nodes::Node &node,
return; return;
} }
sources_manager.get_error_log()->add_error( sources_manager.errors()->add_error(error_handling::ErrorLog::ErrorMessage(
error_handling::ErrorLog::ErrorMessage( node, message, error_handling::ErrorType::TYPE_CHECK));
node, message, error_handling::ErrorType::TYPE_CHECK));
} }
} // namespace type_check } // namespace type_check