mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
type check utils: optional error handling, name expression type check part
This commit is contained in:
parent
c969dac7cc
commit
57b1172a4f
3 changed files with 117 additions and 112 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -549,7 +549,8 @@ 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
|
||||
for (; i < fragments.size(); ++i) {
|
||||
// go in prefixes and try to find matching var namei
|
||||
if (i > 0) {
|
||||
current_prefix.append_after(fragments[i]);
|
||||
}
|
||||
|
|
@ -564,19 +565,29 @@ 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)
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (maybe_field_type.has_value()) {
|
||||
type = maybe_field_type.value();
|
||||
// TODO
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j + 1 == fragments.size()) { // then this can be method call
|
||||
// TODO: try to fond method or local function
|
||||
}
|
||||
// TODO
|
||||
|
||||
// fields for the names should be found
|
||||
// last segment can be function name
|
||||
|
|
@ -603,16 +614,13 @@ 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);
|
||||
|
|
@ -973,10 +981,8 @@ 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 ??)
|
||||
|
|
|
|||
|
|
@ -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()) +
|
||||
type_check_error("Type " +
|
||||
builtin::types::to_string(type.get()->to_builtin()) +
|
||||
" has no accessible fields by definition",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue