type check utils: optional error handling, name expression type check part

This commit is contained in:
ProgramSnail 2024-04-11 22:34:45 +03:00
parent c969dac7cc
commit 57b1172a4f
3 changed files with 117 additions and 112 deletions

View file

@ -239,7 +239,8 @@ private:
nodes::TypeProxy check_same_to_pass_type_in_arguments(
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
SourcesManager &sources_manager,
const std::string &message = "Different type with passed one");
const std::string &message = "Different type with passed one",
bool handle_errors = true);
// bool check_no_pass_type_in_arguments(
// const Arguments &arguments, const nodes::Node &node,
@ -249,33 +250,35 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
nodes::TypeCheckResult 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");
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);
nodes::TypeCheckResult 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_handle_errors(const std::string &name,
const nodes::Node &node,
SourcesManager &sources_manager);
find_type_definition(const std::string &name, const nodes::Node &node,
SourcesManager &sources_manager,
bool handle_errors = true);
std::optional<const nodes::FunctionDefinition *>
find_name_definition_handle_errors(const std::string &name,
const nodes::Node &node,
SourcesManager &sources_manager);
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_handle_errors(nodes::TypeProxy type,
const nodes::Node &node,
SourcesManager &sources_manager);
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_handle_errors(
nodes::TypeProxy type, const std::string &field, const nodes::Node &node,
SourcesManager &sources_manager);
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);
void type_check_error(const std::string &message, const nodes::Node &node,
SourcesManager &sources_manager);
SourcesManager &sources_manager,
bool handle_error = true);
} // namespace type_check

View file

@ -549,38 +549,49 @@ type_check_name_expression(const nodes::NameExpression &expression,
nodes::Identifier current_prefix = fragments.front();
std::optional<State::VariableInfo> maybe_variable;
size_t i = 0;
for (; i < fragments.size(); ++i) { // go in prefixes and try to find matching var namei
if (i > 0) {
current_prefix.append_after(fragments[i]);
}
for (; i < fragments.size(); ++i) {
// go in prefixes and try to find matching var namei
if (i > 0) {
current_prefix.append_after(fragments[i]);
}
maybe_variable = state.find_variable(*current_prefix.get());
maybe_variable = state.find_variable(*current_prefix.get());
if (maybe_variable.has_value()) {
break;
}
if (maybe_variable.has_value()) {
break;
}
}
if (maybe_variable.has_value()) {
auto& type = maybe_variable.value().type;
for (size_t j = i + 1; j < fragments.size(); ++i) {
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)
}
// TODO: fields from several fragments ? (not acceptable fors methods /
// functions)
// <- in typecheck utils method
// TODO: switch by type types: Variant, Tuple, ...
// Tuple -> try to find field
// Others -> try to open / builtin fields ?
const auto maybe_field = type.get()->get_parameter_proxy_by_name(*fragments[j].get());
const auto maybe_field_type = get_field_type_by_name(
type, *fragments[i].get(), expression, sources_manager);
if (maybe_field.has_value()) {
type = maybe_field.value();
continue;
}
if (j + 1 == fragments.size()) { // then this can be method call
// TODO: try to fond method or local function
}
// fields for the names should be found
// last segment can be function name
if (maybe_field_type.has_value()) {
type = maybe_field_type.value();
// TODO
continue;
}
// TODO
// fields for the names should be found
// last segment can be function name
}
}
}
@ -603,17 +614,14 @@ type_check_name_expression(const nodes::NameExpression &expression,
const auto arguments_given = expression.arguments_size();
const auto arguments_defined = function_definition->arguments_size();
if (arguments_given + 1 < arguments_defined ||
arguments_given >
arguments_defined) { // other, when there is passed type
arguments_given > arguments_defined) { // other, when there is passed type
type_check_error(
"Number of function arguments is different from expected (" +
std::to_string(arguments_given) + " instead of " +
std::to_string(arguments_defined) +
std::string{
arguments_defined > 0
? (" or " + std::to_string(
arguments_defined - 1))
: ""} +
std::string{arguments_defined > 0
? (" or " + std::to_string(arguments_defined - 1))
: ""} +
")",
expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result();
@ -973,11 +981,9 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
"Number of function arguments is different from expected (" +
std::to_string(arguments_given) + " instead of " +
std::to_string(arguments_defined) +
std::string{
arguments_defined > 0
? (" or " + std::to_string(
arguments_defined - 1))
: ""} +
std::string{arguments_defined > 0
? (" or " + std::to_string(arguments_defined - 1))
: ""} +
")",
expression, sources_manager);
}
@ -996,8 +1002,10 @@ 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)));
type_check_expression(
*expression.get_expression(), sources_manager, state,
Arguments{}.expect(
expected_type.get()->get_parameter_proxy(arguments_defined - 1)));
}
// TODO: needed ?? (only passed type check required ??)

View file

@ -8,13 +8,14 @@ namespace type_check {
// no pass type -> return type
nodes::TypeProxy check_same_to_pass_type_in_arguments(
nodes::TypeProxy type, const Arguments &arguments, const nodes::Node &node,
SourcesManager &sources_manager, const std::string &message) {
SourcesManager &sources_manager, const std::string &message,
bool handle_errors) {
if (!arguments.get_passed().has_value()) {
return type;
}
if (type != arguments.get_passed().value()) {
type_check_error(message, node, sources_manager);
type_check_error(message, node, sources_manager, handle_errors);
}
return sources_manager.get_type_storage()->primitive_type(
@ -24,20 +25,20 @@ nodes::TypeProxy check_same_to_pass_type_in_arguments(
bool check_no_pass_type_in_arguments(const Arguments &arguments,
const nodes::Node &node,
SourcesManager &sources_manager,
const std::string &message) {
const std::string &message,
bool handle_errors) {
if (arguments.get_passed().has_value()) {
type_check_error(message, node, sources_manager);
type_check_error(message, node, sources_manager, handle_errors);
return false;
}
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) {
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) {
const auto &expected = arguments.get_expected();
if (expected.empty()) {
@ -49,74 +50,66 @@ nodes::TypeCheckResult type_same_to_expected(nodes::TypeProxy type,
[type](nodes::TypeProxy expected_type) {
return type != expected_type;
})) {
type_check_error(message, node, sources_manager);
type_check_error(message, node, sources_manager, handle_errors);
}
return nodes::TypeCheckResult{expected.front()}; // any can be choosen
}
template <typename T>
std::optional<const T *>
find_statement_handle_errors(const std::string &name, const nodes::Node &node,
SourcesManager &sources_manager,
const std::string &message_not_found,
const std::string &message_different_statement) {
std::optional<const T *> find_statement_handle_errors(
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);
if (!maybe_any_statement.has_value()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node, message_not_found, error_handling::ErrorType::TYPE_CHECK));
type_check_error(message_not_found, node, sources_manager, handle_errors);
return std::nullopt;
}
const auto maybe_statement = maybe_any_statement.value().get()->get<T>();
if (!maybe_statement.has_value()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node, message_different_statement,
error_handling::ErrorType::TYPE_CHECK));
type_check_error(message_different_statement, node, sources_manager,
handle_errors);
return std::nullopt;
}
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) {
std::optional<const nodes::TypeDefinition *> find_type_definition_handle_errors(
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");
"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) {
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");
"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) {
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(
*type.get()->get_name()->get(), node, sources_manager);
*type.get()->get_name()->get(), node, sources_manager, handle_errors);
if (!maybe_type_definition.has_value()) {
return std::nullopt;
}
if (maybe_type_definition.value()->get_type().has_value()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node,
"Only type declaration found for type " +
*type.get()->get_name()->get() + " (type is not defined)",
error_handling::ErrorType::TYPE_CHECK));
type_check_error("Only type declaration found for type " +
*type.get()->get_name()->get() +
" (type is not defined)",
node, sources_manager, handle_errors);
return std::nullopt;
}
@ -129,7 +122,7 @@ unfold_user_defined_type_handle_errors(nodes::TypeProxy type,
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) {
SourcesManager &sources_manager, bool handle_errors) {
switch (type.get()->to_builtin()) {
case builtin::types::Type::TUPLE: { // access field
@ -138,10 +131,8 @@ std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors(
if (!maybe_field.has_value()) {
// TODO: pass unfolded type name to log it ??
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node, "Type has no defined field " + field,
error_handling::ErrorType::TYPE_CHECK));
type_check_error("Type has no defined field " + field, node,
sources_manager, handle_errors);
}
return maybe_field.value();
}
@ -149,30 +140,33 @@ std::optional<nodes::TypeProxy> get_field_type_by_name_handle_errors(
// then repeat access
// remove recursion ??
const auto maybe_internal_type =
unfold_user_defined_type_handle_errors(type, node, sources_manager);
const auto maybe_internal_type = unfold_user_defined_type_handle_errors(
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);
field, node, sources_manager,
handle_errors);
}
default: // variant, function, optional, result, error (TODO: add message
// field?), array (TODO: add length field ?), basic types
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node,
"Type " + builtin::types::to_string(type.get()->to_builtin()) +
" has no accessible fields by definition",
error_handling::ErrorType::TYPE_CHECK));
type_check_error("Type " +
builtin::types::to_string(type.get()->to_builtin()) +
" has no accessible fields by definition",
node, sources_manager, handle_errors);
return std::nullopt;
}
}
void type_check_error(const std::string &message, const nodes::Node &node,
SourcesManager &sources_manager) {
SourcesManager &sources_manager, bool handle_error) {
if (!handle_error) {
return;
}
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
node, message, error_handling::ErrorType::TYPE_CHECK));