mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
fixes, refactoring (shorter names, visitor)
This commit is contained in:
parent
57b1172a4f
commit
f58bfd938c
20 changed files with 564 additions and 764 deletions
|
|
@ -7,9 +7,7 @@
|
|||
namespace type_check {
|
||||
|
||||
// IN PROGRESS: modifiers ??
|
||||
nodes::TypeCheckResult
|
||||
type_check_literal(const nodes::Literal &literal,
|
||||
SourcesManager &sources_manager,
|
||||
const Arguments& arguments);
|
||||
Result check(const nodes::Literal &literal, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments);
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
|
|
@ -5,7 +5,33 @@
|
|||
|
||||
#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
|
||||
|
||||
|
|
@ -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) {
|
||||
switch (type) {
|
||||
// -- containers
|
||||
|
|
@ -202,4 +204,6 @@ inline std::optional<size_t> get_parameters_count(Type type) {
|
|||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
} // namespace builtin::types
|
||||
} // namespace types
|
||||
|
||||
} // namespace builtin
|
||||
|
|
|
|||
|
|
@ -12,77 +12,66 @@
|
|||
|
||||
namespace type_check {
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_expression(const nodes::Expression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Expression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
// --- flow control
|
||||
|
||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Match &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Loop &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments);
|
||||
|
||||
// --- containers
|
||||
|
||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
// --- modifiers
|
||||
|
||||
nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Return &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Access &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_loop_control(const nodes::LoopControl &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::LoopControl &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::ModifierExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
// --- other
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_expression(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_constructor(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments);
|
||||
|
||||
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments);
|
||||
Result check(const nodes::Lambda &expression, SourcesManager &sources_manager,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ public:
|
|||
bool operator>=(const Type &other) const { return !operator<(other); }
|
||||
|
||||
// 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_parameters_count =
|
||||
|
|
@ -226,15 +226,13 @@ public:
|
|||
// for fixed parameter counts
|
||||
if (builtin_type_parameters_count.has_value() &&
|
||||
builtin_type_parameters_count.value() != parameters_.size()) {
|
||||
return builtin::types::Type::NONE;
|
||||
return builtin::Type::NONE;
|
||||
}
|
||||
|
||||
return builtin_type;
|
||||
}
|
||||
|
||||
bool is_builtin(builtin::types::Type type) const {
|
||||
return to_builtin() == type;
|
||||
}
|
||||
bool is_builtin(builtin::Type type) const { return to_builtin() == type; }
|
||||
|
||||
private:
|
||||
Identifier name_;
|
||||
|
|
@ -247,7 +245,7 @@ class TypeStorage {
|
|||
friend TypeProxy;
|
||||
|
||||
public:
|
||||
TypeProxy primitive_type(builtin::types::Type type) {
|
||||
TypeProxy primitive(builtin::Type type) {
|
||||
auto iter = primitive_type_ids_.find(type);
|
||||
if (iter != primitive_type_ids_.end()) {
|
||||
return TypeProxy(*this, iter->second);
|
||||
|
|
@ -289,7 +287,7 @@ public:
|
|||
}
|
||||
|
||||
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &¶meters,
|
||||
builtin::types::Type container,
|
||||
builtin::Type container,
|
||||
Node node = Node()) {
|
||||
for (auto ¶meter : parameters) {
|
||||
if (parameter.type_storage_ != this) {
|
||||
|
|
@ -343,7 +341,7 @@ public:
|
|||
if (type.is_generic()) {
|
||||
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
|
||||
// cyclic deps allowed (do check ??)
|
||||
if (iter != resolved_generic_names_.end()) {
|
||||
|
|
@ -471,7 +469,7 @@ private:
|
|||
|
||||
private:
|
||||
// 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
|
||||
std::unordered_map<std::string, size_t> resolved_generic_names_;
|
||||
|
|
@ -485,46 +483,4 @@ private:
|
|||
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
|
||||
|
|
|
|||
|
|
@ -124,17 +124,24 @@ private:
|
|||
size_t indentation_level_ = 0;
|
||||
};
|
||||
|
||||
void print_modifier(const nodes::Modifier &modifier, Printer &printer,
|
||||
bool const_is_none = false);
|
||||
void print(const nodes::Modifier &modifier, Printer &printer,
|
||||
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_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
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print_docs(const nodes::SymbolDocs &docs, Printer &printer);
|
||||
void print(const nodes::SymbolDocs &docs, Printer &printer);
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -4,48 +4,41 @@
|
|||
#include "expression_nodes.hpp"
|
||||
namespace printers {
|
||||
|
||||
void print_expression(const nodes::Expression &expression,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::Expression &expression, printers::Printer &printer);
|
||||
|
||||
// --- 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,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::Condition &expression, printers::Printer &printer);
|
||||
|
||||
void print_loop(const nodes::Loop &expression, printers::Printer &printer);
|
||||
void print(const nodes::Loop &expression, printers::Printer &printer);
|
||||
|
||||
// --- containers
|
||||
|
||||
void print_container(const nodes::Container &expression,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::Container &expression, printers::Printer &printer);
|
||||
|
||||
// --- 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,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::NameDefinition &expression, 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,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::LoopControl &expression, printers::Printer &printer);
|
||||
|
||||
void print_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer);
|
||||
|
||||
// --- other
|
||||
|
||||
void print_name_expression(const nodes::NameExpression &expression,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::NameExpression &expression, printers::Printer &printer);
|
||||
|
||||
void print_constructor(const nodes::Constructor &expression,
|
||||
printers::Printer &printer);
|
||||
void print(const nodes::Constructor &expression, printers::Printer &printer);
|
||||
|
||||
void print_lambda(const nodes::Lambda &expression, printers::Printer &printer);
|
||||
void print(const nodes::Lambda &expression, printers::Printer &printer);
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -7,19 +7,17 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print_source_file(const std::vector<nodes::Statement> &statements,
|
||||
Printer &printer);
|
||||
// void print_source_file(const std::vector<nodes::Statement> &statements,
|
||||
// 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,
|
||||
Printer &printer);
|
||||
void print(const nodes::TypeDefinition &statement, Printer &printer);
|
||||
|
||||
void print_function_definition(const nodes::FunctionDefinition &statement,
|
||||
Printer &printer);
|
||||
void print(const nodes::FunctionDefinition &statement, Printer &printer);
|
||||
|
||||
} // namespace printers
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
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
|
||||
// &printer);
|
||||
|
|
|
|||
|
|
@ -49,44 +49,42 @@ public:
|
|||
|
||||
void print(std::ostream &out) {
|
||||
printers::Printer printer(out, 2, 80, true);
|
||||
printers::print_source_file(statements_, printer);
|
||||
printers::print(statements_, printer);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
nodes::ExpressionStorage *get_expression_storage() {
|
||||
return &expression_storage_;
|
||||
}
|
||||
nodes::ExpressionStorage *expressions() { return &expression_storage_; }
|
||||
|
||||
const nodes::ExpressionStorage *get_expression_storage() const {
|
||||
const nodes::ExpressionStorage *expressions() const {
|
||||
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(); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,23 +145,23 @@ public:
|
|||
std::vector<Context> contexts_ = {{}};
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
class Arguments {
|
||||
public:
|
||||
Arguments() = default;
|
||||
|
||||
Arguments expect_builtin(builtin::types::Type type,
|
||||
Arguments expect_builtin(builtin::Type type,
|
||||
SourcesManager &sources_manager) const {
|
||||
Arguments copy(*this);
|
||||
copy.expected_types_ = {
|
||||
sources_manager.get_type_storage()->primitive_type(type)};
|
||||
copy.expected_types_ = {sources_manager.types()->primitive(type)};
|
||||
return copy;
|
||||
}
|
||||
|
||||
Arguments pass_builtin(builtin::types::Type type,
|
||||
Arguments pass_builtin(builtin::Type type,
|
||||
SourcesManager &sources_manager) const {
|
||||
Arguments copy(*this);
|
||||
copy.passed_type_ =
|
||||
sources_manager.get_type_storage()->primitive_type(type);
|
||||
copy.passed_type_ = sources_manager.types()->primitive(type);
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
|
@ -208,6 +208,8 @@ private:
|
|||
nodes::MaybeTypeProxy passed_type_;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
class ContextHolder {
|
||||
public:
|
||||
ContextHolder(State &state, const nodes::Node &node,
|
||||
|
|
@ -236,6 +238,52 @@ private:
|
|||
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 type, const Arguments &arguments, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
@ -247,15 +295,17 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
|
|||
// SourcesManager &sources_manager,
|
||||
// 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,
|
||||
SourcesManager &sources_manager,
|
||||
const std::string &message = "Different type with expected one",
|
||||
bool handle_errors = true);
|
||||
|
||||
nodes::TypeCheckResult type_check_from_arguments(
|
||||
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors = true);
|
||||
Result type_check_from_arguments(nodes::TypeProxy type,
|
||||
const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
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,
|
||||
bool handle_errors = true);
|
||||
|
||||
std::optional<nodes::TypeProxy>
|
||||
unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
nodes::MaybeTypeProxy unfold_user_defined_type(nodes::TypeProxy type,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
|
||||
std::optional<nodes::TypeProxy>
|
||||
get_field_type_by_name(nodes::TypeProxy type, const std::string &field,
|
||||
const nodes::Node &node, SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
nodes::MaybeTypeProxy get_field_type_by_name(nodes::TypeProxy type,
|
||||
const std::string &field,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors = true);
|
||||
|
||||
void type_check_error(const std::string &message, const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
|
|||
|
|
@ -6,52 +6,39 @@ nodes::TypeProxy get_literal_type(const nodes::Literal &literal,
|
|||
SourcesManager &sources_manager) {
|
||||
switch (literal.get_any()->index()) {
|
||||
case 0: // float
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::FLOAT);
|
||||
return sources_manager.types()->primitive(builtin::Type::FLOAT);
|
||||
case 1: // double
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::DOUBLE);
|
||||
return sources_manager.types()->primitive(builtin::Type::DOUBLE);
|
||||
case 2: // int32_t
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::INT);
|
||||
return sources_manager.types()->primitive(builtin::Type::INT);
|
||||
case 3: // int64_t
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::LONG);
|
||||
return sources_manager.types()->primitive(builtin::Type::LONG);
|
||||
case 4: // size_t
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::INDEX);
|
||||
return sources_manager.types()->primitive(builtin::Type::INDEX);
|
||||
case 5: // std::string
|
||||
return sources_manager.get_type_storage()->add_array_of(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::CHAR));
|
||||
return sources_manager.types()->add_array_of(
|
||||
sources_manager.types()->primitive(builtin::Type::CHAR));
|
||||
case 6: // unicode_string
|
||||
return sources_manager.get_type_storage()->add_array_of(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNICODE));
|
||||
return sources_manager.types()->add_array_of(
|
||||
sources_manager.types()->primitive(builtin::Type::UNICODE));
|
||||
case 7: // char
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::CHAR);
|
||||
return sources_manager.types()->primitive(builtin::Type::CHAR);
|
||||
case 8: // unicode
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNICODE);
|
||||
return sources_manager.types()->primitive(builtin::Type::UNICODE);
|
||||
case 9: // bool
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::BOOL);
|
||||
return sources_manager.types()->primitive(builtin::Type::BOOL);
|
||||
case 10: // unit
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT);
|
||||
return sources_manager.types()->primitive(builtin::Type::UNIT);
|
||||
case 11: // null
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::NULL_OPTION);
|
||||
return sources_manager.types()->primitive(builtin::Type::NULL_OPTION);
|
||||
}
|
||||
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_literal(const nodes::Literal &literal,
|
||||
SourcesManager &sources_manager,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Literal &literal, SourcesManager &sources_manager,
|
||||
State &, const Arguments &arguments) {
|
||||
auto const type = get_literal_type(literal, sources_manager);
|
||||
return type_same_to_expected(type, arguments, literal, sources_manager);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ collect_parameters(parser::ParseTree::Node first_node,
|
|||
|
||||
nodes::TypeProxy build_container_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage,
|
||||
builtin::types::Type container) {
|
||||
builtin::Type container) {
|
||||
std::vector<nodes::TypeProxy> parameters =
|
||||
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::TypeStorage &type_storage) {
|
||||
return build_container_type(parser_node, type_storage,
|
||||
builtin::types::Type::VARIANT);
|
||||
builtin::Type::VARIANT);
|
||||
}
|
||||
|
||||
// '&'? annotation? type ('&' annotation? type)+
|
||||
nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_container_type(parser_node, type_storage,
|
||||
builtin::types::Type::TUPLE);
|
||||
return build_container_type(parser_node, type_storage, builtin::Type::TUPLE);
|
||||
}
|
||||
|
||||
// _reference_ type
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "expression_type_check.hpp"
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
#include "basic_type_check.hpp"
|
||||
#include "builtin_types.hpp"
|
||||
|
|
@ -15,89 +14,29 @@
|
|||
|
||||
namespace type_check {
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_expression(const nodes::Expression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
switch (expression.get_any()->index()) {
|
||||
// --- flow control
|
||||
case 0: // Match
|
||||
return type_check_match(*expression.get<nodes::Match>().value(),
|
||||
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();
|
||||
Result type_check_expression(const nodes::Expression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
return std::visit(
|
||||
[&sources_manager, &state, &arguments](const auto &arg) -> Result {
|
||||
return check(arg, sources_manager, state, arguments);
|
||||
},
|
||||
*expression.get_any());
|
||||
}
|
||||
|
||||
// --- flow control
|
||||
|
||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
nodes::TypeCheckResult value_result = type_check_expression(
|
||||
*expression.get_value(), sources_manager, state, Arguments{});
|
||||
Result check(const nodes::Match &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments) {
|
||||
Result value_result =
|
||||
check(*expression.get_value(), sources_manager, state, Arguments{});
|
||||
|
||||
// x :=/=: ...
|
||||
if (value_result.is_invalid()) {
|
||||
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_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);
|
||||
|
||||
// :=/=: x ...
|
||||
type_check_expression(
|
||||
*current_case->get_value(), sources_manager, state,
|
||||
Arguments{}
|
||||
.expect_builtin(builtin::types::Type::BOOL, sources_manager)
|
||||
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{}
|
||||
: expression_result.value().get()));
|
||||
check(*current_case->get_value(), sources_manager, state,
|
||||
Arguments{}
|
||||
.expect_builtin(builtin::Type::BOOL, sources_manager)
|
||||
.pass(value_result.is_invalid()
|
||||
? nodes::MaybeTypeProxy{}
|
||||
: expression_result.value().get()));
|
||||
// TODO: use type modifiers ??
|
||||
|
||||
// ... ?? x ...
|
||||
if (current_case->get_condition().has_value()) {
|
||||
type_check_expression(*current_case->get_condition().value(),
|
||||
sources_manager, state,
|
||||
Arguments{}.expect_builtin(
|
||||
builtin::types::Type::BOOL, sources_manager));
|
||||
check(*current_case->get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
|
||||
}
|
||||
|
||||
// ... -> x
|
||||
if (current_case->get_expression().has_value()) {
|
||||
at_least_one_case_with_expression = true;
|
||||
nodes::TypeCheckResult case_result = type_check_expression(
|
||||
*current_case->get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
Result case_result =
|
||||
check(*current_case->get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
|
||||
if (!expression_result.has_value() && !case_result.is_invalid()) {
|
||||
expression_result = std::move(case_result);
|
||||
|
|
@ -144,38 +81,33 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
type_check_error(
|
||||
"All cases should be with or without expression at the same time",
|
||||
expression, sources_manager);
|
||||
expression_result = nodes::TypeCheckResult::construct_invalid_result();
|
||||
expression_result = Result::invalid();
|
||||
}
|
||||
|
||||
if (!expression_result.has_value()) {
|
||||
expression_result = nodes::TypeCheckResult{
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT)};
|
||||
expression_result =
|
||||
Result{sources_manager.types()->primitive(builtin::Type::UNIT)};
|
||||
}
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->add_array_of(
|
||||
expression_result.value().get()),
|
||||
sources_manager.types()->add_array_of(expression_result.value().get()),
|
||||
arguments, expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
|
||||
std::optional<nodes::TypeCheckResult> expression_result;
|
||||
Result check(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
MaybeResult expression_result;
|
||||
|
||||
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||
type_check_expression(*expression.get_case(i).first, sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
|
||||
sources_manager));
|
||||
check(*expression.get_case(i).first, sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
|
||||
|
||||
nodes::TypeCheckResult case_result = type_check_expression(
|
||||
*expression.get_case(i).first, sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
Result case_result =
|
||||
check(*expression.get_case(i).first, sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
|
||||
if (!expression_result.has_value() && !case_result.is_invalid()) {
|
||||
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()) {
|
||||
type_check_expression(
|
||||
*expression.get_else_case().value(), sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
check(*expression.get_else_case().value(), sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
? expression_result.value().get()
|
||||
: nodes::MaybeTypeProxy{}));
|
||||
}
|
||||
|
||||
if (!expression_result.has_value()) {
|
||||
type_check_error("There should be at least one case in if statement",
|
||||
expression, sources_manager);
|
||||
expression_result = nodes::TypeCheckResult::construct_invalid_result();
|
||||
expression_result = Result::invalid();
|
||||
}
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->add_array_of(
|
||||
expression_result.value().get()),
|
||||
sources_manager.types()->add_array_of(expression_result.value().get()),
|
||||
arguments, expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Loop &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments) {
|
||||
// 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(
|
||||
*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
Result expression_result =
|
||||
check(*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Loop::LOOP: // infinity loop, no params
|
||||
break;
|
||||
case nodes::Loop::WHILE:
|
||||
type_check_expression(*expression.get_condition().value(), sources_manager,
|
||||
state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
|
||||
sources_manager));
|
||||
check(*expression.get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::Type::BOOL, sources_manager));
|
||||
|
||||
// --- type check is independent from loop itself ---
|
||||
// if (condition_result.value().is_invalid()) {
|
||||
|
|
@ -232,10 +158,9 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
break;
|
||||
case nodes::Loop::FOR:
|
||||
// TODO: expect range ??
|
||||
interval_result = type_check_expression(
|
||||
interval_result = check(
|
||||
*expression.get_interval().value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::ARRAY,
|
||||
sources_manager));
|
||||
Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager));
|
||||
|
||||
if (interval_result.value().is_invalid()) {
|
||||
// --- type check is independent from loop itself ---
|
||||
|
|
@ -243,10 +168,10 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
break;
|
||||
}
|
||||
|
||||
variable_result = type_check_expression(
|
||||
*expression.get_variable().value(), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
interval_result.value().get().get()->get_parameter_proxy(0)));
|
||||
variable_result =
|
||||
check(*expression.get_variable().value(), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
interval_result.value().get().get()->get_parameter_proxy(0)));
|
||||
|
||||
// --- type check is independent from loop itself ---
|
||||
// if (variable_result.value().is_invalid()) {
|
||||
|
|
@ -262,22 +187,21 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
// TODO: modifier checks ??, modifiers ??
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->add_array_of(expression_result.get()),
|
||||
arguments, expression, sources_manager);
|
||||
sources_manager.types()->add_array_of(expression_result.get()), arguments,
|
||||
expression, sources_manager);
|
||||
} // IN PROGRESS
|
||||
|
||||
// --- containers
|
||||
|
||||
nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
std::optional<nodes::TypeCheckResult> last_expression_result;
|
||||
Result type_check_array(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
MaybeResult last_expression_result;
|
||||
|
||||
for (size_t i = 0; i < expression.expressions_size(); ++i) {
|
||||
// elements should have same type, but type is not expected
|
||||
auto expression_result = type_check_expression(
|
||||
*expression.get_expression(i), sources_manager, state, Arguments{});
|
||||
auto expression_result = check(*expression.get_expression(i),
|
||||
sources_manager, state, Arguments{});
|
||||
|
||||
if (!last_expression_result.has_value()) {
|
||||
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()) {
|
||||
type_check_error("Elements in array should have same type",
|
||||
*expression.get_expression(i), sources_manager);
|
||||
// return nodes::TypeCheckResult::construct_invalid_result(); // max
|
||||
// return TypeCheckResult::construct_invalid_result(); // max
|
||||
// possible checks, so no return
|
||||
}
|
||||
}
|
||||
|
|
@ -293,50 +217,43 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
|||
|
||||
if (!last_expression_result.has_value()) {
|
||||
type_check_error("Array with zero elements", expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->add_array_of(
|
||||
last_expression_result.value().get()),
|
||||
arguments, expression, sources_manager);
|
||||
return type_check_from_arguments(sources_manager.types()->add_array_of(
|
||||
last_expression_result.value().get()),
|
||||
arguments, expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result type_check_block(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
nodes::MaybeTypeProxy context_exit_type;
|
||||
|
||||
{
|
||||
ContextHolder context_holder(
|
||||
state, expression, *sources_manager.get_error_log(),
|
||||
state, expression, *sources_manager.errors(),
|
||||
&context_exit_type); // TODO: is brought type returned
|
||||
|
||||
for (size_t i = 0; i < expression.expressions_size(); ++i) {
|
||||
// result types in block are discarded
|
||||
type_check_expression(*expression.get_expression(i), sources_manager,
|
||||
state, Arguments{});
|
||||
check(*expression.get_expression(i), sources_manager, state, Arguments{});
|
||||
}
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult block_brought_type =
|
||||
Result block_brought_type =
|
||||
context_exit_type.has_value()
|
||||
? nodes::TypeCheckResult(context_exit_type.value())
|
||||
: nodes::TypeCheckResult(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT));
|
||||
? Result(context_exit_type.value())
|
||||
: Result(sources_manager.types()->primitive(builtin::Type::UNIT));
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->add_array_of(
|
||||
block_brought_type.get()),
|
||||
sources_manager.types()->add_array_of(block_brought_type.get()),
|
||||
arguments, expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Container::ARRAY:
|
||||
return type_check_array(expression, sources_manager, state, arguments);
|
||||
|
|
@ -347,12 +264,10 @@ nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
|||
|
||||
// --- modifiers
|
||||
|
||||
nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
auto returned_result = type_check_expression(
|
||||
*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
Result check(const nodes::Return &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments) {
|
||||
auto returned_result =
|
||||
check(*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
|
||||
if (returned_result.is_invalid()) {
|
||||
return returned_result;
|
||||
|
|
@ -363,29 +278,27 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
|||
if (state.bring_type(returned_result.get())) {
|
||||
type_check_error("Different brought type to current one", expression,
|
||||
sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
break;
|
||||
case nodes::Return::RETURN:
|
||||
if (!state.return_type(returned_result.get())) {
|
||||
type_check_error("Different returned type to current one", expression,
|
||||
sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT),
|
||||
arguments, expression, sources_manager);
|
||||
sources_manager.types()->primitive(builtin::Type::UNIT), arguments,
|
||||
expression, sources_manager);
|
||||
}
|
||||
|
||||
// TODO: warning if name is same to package prefix, function prefix, etc. ??
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
if (!arguments.get_passed().has_value()) {
|
||||
type_check_error("Can't deduce type of new variable from context",
|
||||
expression, sources_manager);
|
||||
|
|
@ -401,8 +314,8 @@ type_check_name_definition(const nodes::NameDefinition &expression,
|
|||
}
|
||||
|
||||
// variable accessible by reference by default ??
|
||||
sources_manager.get_type_storage()->add_modification_of(variable_type,
|
||||
nodes::Modifier::REF);
|
||||
sources_manager.types()->add_modification_of(variable_type,
|
||||
nodes::Modifier::REF);
|
||||
|
||||
if (!state.insert_variable(*expression.get_name()->get(), variable_type,
|
||||
expression.get_modifier())) {
|
||||
|
|
@ -412,23 +325,20 @@ type_check_name_definition(const nodes::NameDefinition &expression,
|
|||
|
||||
// Return BOOL as any := / =: expression
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::BOOL),
|
||||
arguments, expression, sources_manager);
|
||||
sources_manager.types()->primitive(builtin::Type::BOOL), arguments,
|
||||
expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result type_check_array_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
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(
|
||||
*expression.get_index(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::INDEX, sources_manager));
|
||||
|
||||
auto value_result = type_check_expression(
|
||||
*expression.get_value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::ARRAY, sources_manager));
|
||||
auto value_result =
|
||||
check(*expression.get_value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::Type::ARRAY, sources_manager));
|
||||
|
||||
if (index_result.is_invalid()) {
|
||||
return index_result;
|
||||
|
|
@ -445,13 +355,12 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
|
|||
sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
auto value_result = type_check_expression(
|
||||
*expression.get_value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::TUPLE, sources_manager));
|
||||
Result type_check_tuple_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
auto value_result =
|
||||
check(*expression.get_value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::Type::TUPLE, sources_manager));
|
||||
|
||||
if (value_result.is_invalid()) {
|
||||
return value_result;
|
||||
|
|
@ -470,10 +379,8 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression,
|
|||
expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Access &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments) {
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Access::ARRAY:
|
||||
return type_check_array_access(expression, sources_manager, state,
|
||||
|
|
@ -484,48 +391,47 @@ nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
|||
}
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_loop_control(const nodes::LoopControl &expression,
|
||||
SourcesManager &sources_manager, State &,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::LoopControl &expression,
|
||||
SourcesManager &sources_manager, State &,
|
||||
const Arguments &arguments) {
|
||||
return type_check_from_arguments(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT),
|
||||
arguments, expression, sources_manager);
|
||||
sources_manager.types()->primitive(builtin::Type::UNIT), arguments,
|
||||
expression, sources_manager);
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
auto modified_result = type_check_expression(
|
||||
*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
Result check(const nodes::ModifierExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
auto modified_result =
|
||||
check(*expression.get_expression(), sources_manager, state, Arguments{});
|
||||
|
||||
if (modified_result.is_invalid()) {
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
|
||||
if (nodes::utils::is_suffix_modifier(
|
||||
expression.get_modifier())) { // optional, result
|
||||
// '?' - open optional / result in -> (execute or not execute pattern
|
||||
// matching expression) / (value / return) (TODO: alternative for bring)
|
||||
// '?' - open optional / result in ->
|
||||
// (execute or not execute pattern
|
||||
// matching expression) / (value /
|
||||
// return) (TODO: alternative for bring)
|
||||
|
||||
// '!' - open optional / result -> value / panic
|
||||
|
||||
switch (modified_result.get().get()->to_builtin()) {
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::Type::OPTIONAL:
|
||||
case builtin::Type::RESULT:
|
||||
// TODO: how to unwrap external modifier ??
|
||||
modified_result.set(modified_result.get().get()->get_parameter_proxy(0));
|
||||
break;
|
||||
default:
|
||||
type_check_error("Can unwrap only Optional or Result", expression,
|
||||
sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
} else {
|
||||
// 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()));
|
||||
}
|
||||
|
||||
|
|
@ -536,10 +442,9 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
|||
// --- other
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_expression(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
// TODO: constraints ??
|
||||
|
||||
const auto name = expression.get_name();
|
||||
|
|
@ -565,10 +470,11 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
if (maybe_variable.has_value()) {
|
||||
auto &type = maybe_variable.value().type;
|
||||
for (size_t j = i + 1; j < fragments.size(); ++i) {
|
||||
|
||||
if (j + 1 == fragments.size()) { // then this can be method call
|
||||
// TODO: try to find method or local function
|
||||
// if found, search to field (without error handling)
|
||||
if (j + 1 ==
|
||||
fragments
|
||||
.size()) { // then this can be method call
|
||||
// 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 /
|
||||
|
|
@ -600,10 +506,10 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
|
||||
// TODO: check, if there is variable with this name
|
||||
// TODO: check var + fields
|
||||
const auto maybe_function_definition = find_name_definition_handle_errors(
|
||||
*name->get(), expression, sources_manager);
|
||||
const auto maybe_function_definition =
|
||||
find_name_definition(*name->get(), expression, sources_manager);
|
||||
if (!maybe_function_definition.has_value()) {
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
const nodes::FunctionDefinition *function_definition =
|
||||
maybe_function_definition.value();
|
||||
|
|
@ -624,13 +530,13 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
: ""} +
|
||||
")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
// TODO: try return correct type (function return type), when possible
|
||||
}
|
||||
|
||||
// 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;
|
||||
++i) { // TODO: pass types with oud modifier
|
||||
const nodes::FunctionDefinition::Argument *argument =
|
||||
|
|
@ -647,7 +553,6 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
const auto expected_annotation = argument->get_annotation();
|
||||
|
||||
if (annotation.has_value() != expected_annotation.has_value()) {
|
||||
|
||||
type_check_error("Wrong function argument annotation: should be " +
|
||||
std::string{expected_annotation.has_value()
|
||||
? *expected_annotation.value()
|
||||
|
|
@ -663,16 +568,16 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
*expression.get_argument_value(i), sources_manager);
|
||||
}
|
||||
|
||||
function_argument_results.push_back(type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(argument->get_type_proxy().value())));
|
||||
function_argument_results.push_back(
|
||||
check(*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(argument->get_type_proxy().value())));
|
||||
}
|
||||
|
||||
if (function_definition->arguments_size() == 0) {
|
||||
type_check_error(
|
||||
"Function arguments size is zero. Returned type is not defined",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
|
||||
// TODO: check condition
|
||||
|
|
@ -687,7 +592,7 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
type_check_error(
|
||||
"Function argument type is not defined for returned type", expression,
|
||||
sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
|
||||
// TODO: invert modifier ??
|
||||
|
|
@ -697,20 +602,21 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
}
|
||||
|
||||
// checks for universal call syntax ??
|
||||
|
||||
// TODO: riturn result
|
||||
} // IN PROGRESS
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult
|
||||
type_check_constructor(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
// TODO: constraints ??
|
||||
|
||||
// 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);
|
||||
if (!maybe_type_definition.has_value()) {
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
const nodes::TypeDefinition *type_definition = maybe_type_definition.value();
|
||||
|
||||
|
|
@ -718,7 +624,7 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
type_check_error(
|
||||
"Type defenition for constructor type not found (declaration only)",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
}
|
||||
|
||||
// TODO: deal with anniotations, recursive annotations
|
||||
|
|
@ -732,7 +638,7 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
if (expression.arguments_size() == 0) {
|
||||
type_check_error("Number of type constructor arguments should be > 0",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
// TODO: try return correct type (constructor's type), when possible (not
|
||||
// generic)
|
||||
}
|
||||
|
|
@ -743,7 +649,7 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
|
||||
{ // check arguments size, ets.
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
case builtin::Type::TUPLE:
|
||||
if (expression.arguments_size() != type.get()->parameters_size()) {
|
||||
type_check_error(
|
||||
"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(type.get()->parameters_size()) + ")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
// TODO: try return correct type (constructor's type), when possible
|
||||
// (not generic)
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::types::Type::ERROR:
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
case builtin::Type::VARIANT:
|
||||
case builtin::Type::OPTIONAL:
|
||||
case builtin::Type::RESULT:
|
||||
case builtin::Type::ERROR:
|
||||
case builtin::Type::FUNCTION:
|
||||
case builtin::Type::NONE:
|
||||
if (expression.arguments_size() != 1) { // TODO: better to_string
|
||||
type_check_error("Number of type constructor arguments should be = 1 "
|
||||
"(builtin type " +
|
||||
std::to_string(uint(builtin_type)) + ")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
// TODO: try return correct type (constructor's type), when possible
|
||||
// (not generic)
|
||||
}
|
||||
|
|
@ -776,13 +682,13 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
break;
|
||||
}
|
||||
|
||||
if (get_parameters_count(builtin_type).has_value() &&
|
||||
if (builtin::types::get_parameters_count(builtin_type).has_value() &&
|
||||
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",
|
||||
expression, sources_manager);
|
||||
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
return Result::invalid();
|
||||
// TODO: try return correct type (constructor's type), when possible (not
|
||||
// generic)
|
||||
}
|
||||
|
|
@ -841,13 +747,13 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
};
|
||||
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
case builtin::Type::TUPLE:
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
check_same_annotation(i, type.get()->get_parameter(i)->get_annotation(),
|
||||
true /*log errors*/);
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
case builtin::Type::VARIANT:
|
||||
// more then one same annotation ??
|
||||
for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
|
||||
if (check_same_annotation(
|
||||
|
|
@ -865,14 +771,14 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
*expression.get_argument_value(0), sources_manager);
|
||||
}
|
||||
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(),
|
||||
true /*log errors*/);
|
||||
break;
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
case builtin::Type::OPTIONAL:
|
||||
case builtin::Type::RESULT:
|
||||
case builtin::Type::FUNCTION:
|
||||
case builtin::Type::NONE:
|
||||
check_no_annotation(0, true /*log errors*/);
|
||||
break;
|
||||
default: // array, basic types
|
||||
|
|
@ -882,58 +788,51 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
|
||||
{ // type check arguments
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
case builtin::Type::TUPLE:
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
|
||||
check(*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
case builtin::Type::VARIANT:
|
||||
if (chosen_variant_option.has_value()) {
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(
|
||||
chosen_variant_option.value())));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(
|
||||
chosen_variant_option.value())));
|
||||
} else { // TODO: error, if there is more then one possible variant in
|
||||
// answer
|
||||
nodes::TypeProxies possible_options;
|
||||
for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
|
||||
possible_options.push_back(type.get()->get_parameter_proxy(i));
|
||||
}
|
||||
type_check_expression(*expression.get_argument_value(0),
|
||||
sources_manager, state,
|
||||
Arguments{}.expect(possible_options));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(possible_options));
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::Type::OPTIONAL:
|
||||
// first parameter or NULL
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
{type.get()->get_parameter_proxy(0),
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::NULL_OPTION)}));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect({type.get()->get_parameter_proxy(0),
|
||||
sources_manager.types()->primitive(
|
||||
builtin::Type::NULL_OPTION)}));
|
||||
break;
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::Type::RESULT:
|
||||
// first parameter or ERROR[second parameter]
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect({type.get()->get_parameter_proxy(0),
|
||||
sources_manager.get_type_storage()->add_error_of(
|
||||
type.get()->get_parameter_proxy(1))}));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect({type.get()->get_parameter_proxy(0),
|
||||
sources_manager.types()->add_error_of(
|
||||
type.get()->get_parameter_proxy(1))}));
|
||||
break;
|
||||
case builtin::types::Type::ERROR:
|
||||
case builtin::Type::ERROR:
|
||||
// first parameter
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(0)));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(0)));
|
||||
break;
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
case builtin::Type::FUNCTION:
|
||||
case builtin::Type::NONE:
|
||||
// type itself
|
||||
type_check_expression(*expression.get_argument_value(0), sources_manager,
|
||||
state, Arguments{}.expect(type));
|
||||
check(*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type));
|
||||
break;
|
||||
default: // array, basic types
|
||||
type_check_error("Type can't be constructed", expression,
|
||||
|
|
@ -950,10 +849,8 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
} // IN PROGRESS
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
Result check(const nodes::Lambda &expression, SourcesManager &sources_manager,
|
||||
State &state, const Arguments &arguments) {
|
||||
if (arguments.get_expected().empty()) {
|
||||
type_check_error("Can't deduce type of lambda function from context: no "
|
||||
"one type expected",
|
||||
|
|
@ -968,7 +865,7 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
|||
}
|
||||
|
||||
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,
|
||||
sources_manager);
|
||||
}
|
||||
|
|
@ -1002,10 +899,9 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
|||
|
||||
// TODO: out type is can be not last
|
||||
if (arguments_given + 1 == arguments_defined) {
|
||||
type_check_expression(
|
||||
*expression.get_expression(), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
expected_type.get()->get_parameter_proxy(arguments_defined - 1)));
|
||||
check(*expression.get_expression(), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
expected_type.get()->get_parameter_proxy(arguments_defined - 1)));
|
||||
}
|
||||
|
||||
// TODO: needed ?? (only passed type check required ??)
|
||||
|
|
@ -1013,4 +909,16 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
|||
sources_manager);
|
||||
} // 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
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print_modifier(const nodes::Modifier &modifier, Printer &printer,
|
||||
bool const_is_none) {
|
||||
void print(const nodes::Modifier &modifier, Printer &printer,
|
||||
bool const_is_none) {
|
||||
switch (modifier) {
|
||||
case nodes::Modifier::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()) {
|
||||
case 0: // float
|
||||
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
|
||||
}
|
||||
|
||||
void print_identifier(const nodes::Identifier &identifier, Printer &printer) {
|
||||
void print(const nodes::Identifier &identifier, Printer &printer) {
|
||||
printer.print(*identifier.get());
|
||||
}
|
||||
|
||||
|
|
@ -150,11 +150,11 @@ void print_annotation(const std::string &annotation, Printer &printer) {
|
|||
printer.print(annotation);
|
||||
}
|
||||
|
||||
void print_extra(const nodes::Extra &extra, Printer &printer) {
|
||||
void print(const nodes::Extra &extra, Printer &printer) {
|
||||
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) {
|
||||
printer.new_indent_line();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace printers {
|
|||
|
||||
// TODO
|
||||
|
||||
void print_docs(const nodes::SymbolDocs &docs, Printer &printer) {
|
||||
void print(const nodes::SymbolDocs &docs, Printer &printer) {
|
||||
auto description = docs.get_description();
|
||||
|
||||
if (description.has_value()) {
|
||||
|
|
|
|||
|
|
@ -16,68 +16,13 @@ bool is_block_expression(const nodes::Expression &expression) {
|
|||
|
||||
} // namespace utils
|
||||
|
||||
void print_expression(const nodes::Expression &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::Expression &expression, printers::Printer &printer) {
|
||||
if (expression.is_scoped()) {
|
||||
printer.print("(");
|
||||
}
|
||||
|
||||
switch (expression.get_any()->index()) {
|
||||
// --- flow control
|
||||
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;
|
||||
}
|
||||
std::visit([&printer](const auto &arg) -> void { print(arg, printer); },
|
||||
*expression.get_any());
|
||||
|
||||
if (expression.is_scoped()) {
|
||||
printer.print(")");
|
||||
|
|
@ -86,7 +31,7 @@ void print_expression(const nodes::Expression &expression,
|
|||
|
||||
// --- 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()) {
|
||||
case nodes::Match::Case::PATTERN_VALUE:
|
||||
|
|
@ -99,21 +44,21 @@ void print_case(const nodes::Match::Case &expression, Printer &printer) {
|
|||
|
||||
printer.space();
|
||||
|
||||
print_expression(*expression.get_value(), printer);
|
||||
print(*expression.get_value(), printer);
|
||||
|
||||
if (expression.get_condition().has_value()) {
|
||||
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()) {
|
||||
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => ");
|
||||
print_expression(*expression.get_expression().value(), printer);
|
||||
print(*expression.get_expression().value(), printer);
|
||||
}
|
||||
} // IN PROGRESS
|
||||
|
||||
void print_match(const nodes::Match &expression, printers::Printer &printer) {
|
||||
print_expression(*expression.get_value(), printer);
|
||||
void print(const nodes::Match &expression, printers::Printer &printer) {
|
||||
print(*expression.get_value(), printer);
|
||||
|
||||
printer.space();
|
||||
|
||||
|
|
@ -122,7 +67,7 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) {
|
|||
printer.set_indentation_level(printer.current_position());
|
||||
|
||||
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()) {
|
||||
printer.new_indent_line();
|
||||
|
|
@ -133,8 +78,7 @@ void print_match(const nodes::Match &expression, printers::Printer &printer) {
|
|||
|
||||
} // IN PROGRESS
|
||||
|
||||
void print_condition(const nodes::Condition &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::Condition &expression, printers::Printer &printer) {
|
||||
|
||||
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||
if (i > 0) {
|
||||
|
|
@ -151,11 +95,11 @@ void print_condition(const nodes::Condition &expression,
|
|||
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 " : " => ");
|
||||
|
||||
print_expression(*expression.get_case(i).second, printer);
|
||||
print(*expression.get_case(i).second, printer);
|
||||
}
|
||||
|
||||
if (expression.cases_size() == 0) {
|
||||
|
|
@ -171,11 +115,11 @@ void print_condition(const nodes::Condition &expression,
|
|||
printer.new_indent_line();
|
||||
}
|
||||
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" : "@");
|
||||
|
||||
switch (expression.get_type()) {
|
||||
|
|
@ -184,27 +128,26 @@ void print_loop(const nodes::Loop &expression, printers::Printer &printer) {
|
|||
break;
|
||||
case nodes::Loop::WHILE:
|
||||
printer.space();
|
||||
print_expression(*expression.get_condition().value(), printer);
|
||||
print(*expression.get_condition().value(), printer);
|
||||
printer.space();
|
||||
break;
|
||||
case nodes::Loop::FOR:
|
||||
printer.space();
|
||||
print_expression(*expression.get_variable().value(), printer);
|
||||
print(*expression.get_variable().value(), printer);
|
||||
printer.print(" : ");
|
||||
print_expression(*expression.get_interval().value(), printer);
|
||||
print(*expression.get_interval().value(), printer);
|
||||
printer.space();
|
||||
break;
|
||||
}
|
||||
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
|
||||
|
||||
print_expression(*expression.get_expression(), printer);
|
||||
print(*expression.get_expression(), printer);
|
||||
} // IN PROGRESS
|
||||
|
||||
// --- containers
|
||||
|
||||
void print_container(const nodes::Container &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::Container &expression, printers::Printer &printer) {
|
||||
bool is_array = expression.get_type() == nodes::Container::ARRAY;
|
||||
|
||||
if (is_array) {
|
||||
|
|
@ -224,7 +167,7 @@ void print_container(const nodes::Container &expression,
|
|||
if (!is_array && !is_empty_lines) {
|
||||
printer.new_indent_line();
|
||||
}
|
||||
print_expression(*expression.get_expression(i), printer);
|
||||
print(*expression.get_expression(i), printer);
|
||||
if (is_array) {
|
||||
if (i + 1 < expression.expressions_size()) {
|
||||
printer.space();
|
||||
|
|
@ -247,7 +190,7 @@ void print_container(const nodes::Container &expression,
|
|||
|
||||
// --- modifiers
|
||||
|
||||
void print_return(const nodes::Return &expression, printers::Printer &printer) {
|
||||
void print(const nodes::Return &expression, printers::Printer &printer) {
|
||||
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Return::RETURN:
|
||||
|
|
@ -260,11 +203,11 @@ void print_return(const nodes::Return &expression, printers::Printer &printer) {
|
|||
break;
|
||||
}
|
||||
|
||||
print_expression(*expression.get_expression(), printer);
|
||||
print(*expression.get_expression(), printer);
|
||||
}
|
||||
|
||||
void print_name_definition(const nodes::NameDefinition &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::NameDefinition &expression,
|
||||
printers::Printer &printer) {
|
||||
|
||||
if (printer.print_words_instead_of_symbols()) {
|
||||
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) {
|
||||
print_expression(*expression.get_value(), printer);
|
||||
void print(const nodes::Access &expression, printers::Printer &printer) {
|
||||
print(*expression.get_value(), printer);
|
||||
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Access::ARRAY:
|
||||
|
|
@ -307,7 +250,7 @@ void print_access(const nodes::Access &expression, printers::Printer &printer) {
|
|||
break;
|
||||
}
|
||||
|
||||
print_expression(*expression.get_index(), printer);
|
||||
print(*expression.get_index(), printer);
|
||||
|
||||
switch (expression.get_type()) {
|
||||
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,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::LoopControl &expression, printers::Printer &printer) {
|
||||
switch (expression.get_type()) {
|
||||
case nodes::LoopControl::BREAK:
|
||||
printer.print("break");
|
||||
|
|
@ -334,30 +276,30 @@ void print_loop_control(const nodes::LoopControl &expression,
|
|||
}
|
||||
}
|
||||
|
||||
void print_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
if (expression.get_modifier() != nodes::Modifier::OPTIONAL &&
|
||||
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 ||
|
||||
expression.get_modifier() == nodes::Modifier::RESULT) {
|
||||
print_modifier(expression.get_modifier(), printer);
|
||||
print(expression.get_modifier(), printer);
|
||||
}
|
||||
}
|
||||
|
||||
// --- other
|
||||
|
||||
void print_name_expression(const nodes::NameExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
void print(const nodes::NameExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
bool is_comma_operator = (*expression.get_name()->get() == ",");
|
||||
bool is_range_operator = (*expression.get_name()->get() == "..");
|
||||
|
||||
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()) {
|
||||
printer.print(".");
|
||||
|
||||
|
|
@ -366,7 +308,7 @@ void print_name_expression(const nodes::NameExpression &expression,
|
|||
printer.space();
|
||||
}
|
||||
} else if (expression.get_prefix().has_value()) {
|
||||
print_type(*expression.get_prefix().value(), printer);
|
||||
print(*expression.get_prefix().value(), printer);
|
||||
printer.print(".");
|
||||
}
|
||||
|
||||
|
|
@ -380,7 +322,7 @@ void print_name_expression(const nodes::NameExpression &expression,
|
|||
printer.print("( ");
|
||||
}
|
||||
|
||||
print_identifier(*expression.get_name(), printer);
|
||||
print(*expression.get_name(), printer);
|
||||
|
||||
if (operator_called_as_function) {
|
||||
printer.print(" )");
|
||||
|
|
@ -399,14 +341,13 @@ void print_name_expression(const nodes::NameExpression &expression,
|
|||
print_annotation(*expression.get_argument_annotation(i).value(), printer);
|
||||
printer.space();
|
||||
}
|
||||
print_expression(*expression.get_argument_value(i), printer);
|
||||
print(*expression.get_argument_value(i), printer);
|
||||
}
|
||||
|
||||
} // IN PROGRESS
|
||||
|
||||
void print_constructor(const nodes::Constructor &expression,
|
||||
printers::Printer &printer) {
|
||||
print_type(*expression.get_type(), printer);
|
||||
void print(const nodes::Constructor &expression, printers::Printer &printer) {
|
||||
print(*expression.get_type(), printer);
|
||||
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
printer.space();
|
||||
|
|
@ -416,22 +357,22 @@ void print_constructor(const nodes::Constructor &expression,
|
|||
printer.space();
|
||||
}
|
||||
|
||||
print_expression(*expression.get_argument_value(i), printer);
|
||||
print(*expression.get_argument_value(i), printer);
|
||||
}
|
||||
|
||||
} // 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 " : "\\ ");
|
||||
|
||||
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.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
|
||||
|
||||
print_expression(*expression.get_expression(), printer);
|
||||
print(*expression.get_expression(), printer);
|
||||
|
||||
} // IN PROGRESS
|
||||
|
||||
|
|
|
|||
|
|
@ -10,48 +10,27 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print_source_file(const std::vector<nodes::Statement> &statements,
|
||||
Printer &printer) {
|
||||
for (auto &statement : statements) {
|
||||
print_statement(statement, printer);
|
||||
}
|
||||
// void print_source_file(const std::vector<nodes::Statement> &statements,
|
||||
// Printer &printer) {
|
||||
// for (const auto &statement : statements) {
|
||||
// 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) {
|
||||
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) {
|
||||
void print(const nodes::Import &statement, Printer &printer) {
|
||||
printer.print(":: ");
|
||||
|
||||
print_identifier(*statement.get_import_name(), printer);
|
||||
print(*statement.get_import_name(), printer);
|
||||
|
||||
if (*statement.get_import_name()->get() !=
|
||||
*statement.get_module_name()->get()) {
|
||||
printer.print(" = ");
|
||||
print_identifier(*statement.get_module_name(), printer);
|
||||
print(*statement.get_module_name(), printer);
|
||||
}
|
||||
|
||||
if (statement.symbols_size() > 0) {
|
||||
|
|
@ -66,7 +45,7 @@ void print_import(const nodes::Import &statement, Printer &printer) {
|
|||
printer.print("( ");
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_symbol(i), printer);
|
||||
print(*statement.get_symbol(i), printer);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print(" )");
|
||||
|
|
@ -76,25 +55,24 @@ void print_import(const nodes::Import &statement, Printer &printer) {
|
|||
printer.print(";");
|
||||
} // IN PROGRESS
|
||||
|
||||
void print_constraint(const nodes::Constraint &statement, Printer &printer) {
|
||||
void print(const nodes::Constraint &statement, Printer &printer) {
|
||||
printer.print("? ");
|
||||
print_expression(*statement.get_expression(), printer);
|
||||
print(*statement.get_expression(), printer);
|
||||
printer.print(";");
|
||||
}
|
||||
|
||||
void print_type_definition(const nodes::TypeDefinition &statement,
|
||||
Printer &printer) {
|
||||
print_docs(*statement.get_docs(), printer);
|
||||
void print(const nodes::TypeDefinition &statement, Printer &printer) {
|
||||
print(*statement.get_docs(), printer);
|
||||
|
||||
if (statement.is_on_heap()) {
|
||||
printer.print("<> ");
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_name(), printer);
|
||||
print(*statement.get_name(), printer);
|
||||
|
||||
for (size_t i = 0; i < statement.arguments_size(); ++i) {
|
||||
printer.space();
|
||||
print_identifier(*statement.get_argument(i), printer);
|
||||
print(*statement.get_argument(i), printer);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
print_type(*statement.get_type().value().get(), printer);
|
||||
print(*statement.get_type().value().get(), printer);
|
||||
|
||||
printer.set_indentation_level(previous_indentation_level);
|
||||
}
|
||||
|
|
@ -112,12 +90,11 @@ void print_type_definition(const nodes::TypeDefinition &statement,
|
|||
} // IN PROGRESS
|
||||
|
||||
// TODO: do not print prefix type for names
|
||||
void print_function_definition(const nodes::FunctionDefinition &statement,
|
||||
Printer &printer) {
|
||||
print_docs(*statement.get_docs(), printer);
|
||||
void print(const nodes::FunctionDefinition &statement, Printer &printer) {
|
||||
print(*statement.get_docs(), printer);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
@ -132,13 +109,13 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
|
|||
printer.print("( ");
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_name(), printer);
|
||||
print(*statement.get_name(), printer);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
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) {
|
||||
if (!statement.get_argument(i)->get_name().has_value()) {
|
||||
|
|
@ -158,15 +135,14 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
|
|||
printer.space();
|
||||
}
|
||||
|
||||
print_modifier(statement.get_argument(i)->get_before_modifier(), printer,
|
||||
true);
|
||||
print(statement.get_argument(i)->get_before_modifier(), printer, 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
|
||||
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();
|
||||
}
|
||||
|
||||
print_modifier(statement.get_argument(i)->get_before_modifier(), printer,
|
||||
true);
|
||||
print(statement.get_argument(i)->get_before_modifier(), printer, 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) {
|
||||
printer.set_indentation_level(printer.current_position());
|
||||
}
|
||||
print_expression(*statement.get_expression().value(), printer);
|
||||
print(*statement.get_expression().value(), printer);
|
||||
if (!expression_is_container) {
|
||||
printer.set_indentation_level(previous_indentation_level);
|
||||
printer.print(";");
|
||||
|
|
|
|||
|
|
@ -6,22 +6,22 @@
|
|||
namespace printers {
|
||||
|
||||
// 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()) {
|
||||
print_annotation(*type.get_annotation().value(), printer);
|
||||
printer.space();
|
||||
}
|
||||
|
||||
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) {
|
||||
printer.print("[");
|
||||
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()) {
|
||||
printer.space();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
|
|||
type_check_error(message, node, sources_manager, handle_errors);
|
||||
}
|
||||
|
||||
return sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::BOOL);
|
||||
return sources_manager.types()->primitive(builtin::Type::BOOL);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
|
||||
const nodes::Node &node, SourcesManager &sources_manager,
|
||||
const std::string &message, bool handle_errors) {
|
||||
Result type_same_to_expected(nodes::TypeProxy type, const Arguments &arguments,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
const std::string &message, bool handle_errors) {
|
||||
const auto &expected = arguments.get_expected();
|
||||
|
||||
if (expected.empty()) {
|
||||
return nodes::TypeCheckResult{type};
|
||||
return Result{type};
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
return nodes::TypeCheckResult{expected.front()}; // any can be choosen
|
||||
return Result{expected.front()}; // any can be choosen
|
||||
}
|
||||
|
||||
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,
|
||||
SourcesManager &sources_manager, const std::string &message_not_found,
|
||||
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()) {
|
||||
type_check_error(message_not_found, node, sources_manager, handle_errors);
|
||||
return std::nullopt;
|
||||
|
|
@ -77,28 +76,26 @@ std::optional<const T *> find_statement_handle_errors(
|
|||
return maybe_statement.value();
|
||||
}
|
||||
|
||||
std::optional<const nodes::TypeDefinition *> find_type_definition_handle_errors(
|
||||
const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
std::optional<const nodes::TypeDefinition *>
|
||||
find_type_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
return find_statement_handle_errors<nodes::TypeDefinition>(
|
||||
name, node, sources_manager, "No type definition found in name tree",
|
||||
"Node in name tree is not type definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition_handle_errors(const std::string &name,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager,
|
||||
bool handle_errors) {
|
||||
find_name_definition(const std::string &name, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
return find_statement_handle_errors<nodes::FunctionDefinition>(
|
||||
name, node, sources_manager, "No name definition found in name tree",
|
||||
"Node in name tree is not name definition", handle_errors);
|
||||
}
|
||||
|
||||
std::optional<nodes::TypeProxy> unfold_user_defined_type_handle_errors(
|
||||
nodes::TypeProxy type, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
const auto maybe_type_definition = find_type_definition_handle_errors(
|
||||
std::optional<nodes::TypeProxy>
|
||||
unfold_user_defined_type(nodes::TypeProxy type, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
const auto maybe_type_definition = find_type_definition(
|
||||
*type.get()->get_name()->get(), node, sources_manager, handle_errors);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors(
|
||||
nodes::TypeProxy type, const std::string &field, const nodes::Node &node,
|
||||
SourcesManager &sources_manager, bool handle_errors) {
|
||||
std::optional<nodes::TypeProxy>
|
||||
get_field_type_by_name(nodes::TypeProxy type, const std::string &field,
|
||||
const nodes::Node &node, SourcesManager &sources_manager,
|
||||
bool handle_errors) {
|
||||
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);
|
||||
|
||||
|
|
@ -136,19 +134,18 @@ std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors(
|
|||
}
|
||||
return maybe_field.value();
|
||||
}
|
||||
case builtin::types::Type::NONE: { // user defined type, trying to unfold, and
|
||||
// then repeat access
|
||||
case builtin::Type::NONE: { // user defined type, trying to unfold, and
|
||||
// then repeat access
|
||||
|
||||
// remove recursion ??
|
||||
const auto maybe_internal_type = unfold_user_defined_type_handle_errors(
|
||||
type, node, sources_manager, handle_errors);
|
||||
const auto maybe_internal_type =
|
||||
unfold_user_defined_type(type, node, sources_manager, handle_errors);
|
||||
if (!maybe_internal_type.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return get_field_type_by_name_handle_errors(maybe_internal_type.value(),
|
||||
field, node, sources_manager,
|
||||
handle_errors);
|
||||
return get_field_type_by_name(maybe_internal_type.value(), field, node,
|
||||
sources_manager, handle_errors);
|
||||
}
|
||||
default: // variant, function, optional, result, error (TODO: add message
|
||||
// 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;
|
||||
}
|
||||
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
node, message, error_handling::ErrorType::TYPE_CHECK));
|
||||
sources_manager.errors()->add_error(error_handling::ErrorLog::ErrorMessage(
|
||||
node, message, error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue