type check: lambda fixes, name expression part

This commit is contained in:
ProgramSnail 2024-02-24 00:01:18 +03:00
parent d8ef39b2bd
commit 5afbaf06ae

View file

@ -545,6 +545,7 @@ type_check_name_expression(const nodes::NameExpression &expression,
// TODO: deal with given ->(out) Args (type not expected, but passed into)
// TODO: check, if there is variable with this name
// TODO: check var + fields
const auto maybe_function_definition = find_name_definition_handle_errors(
*expression.get_name()->get(), expression, sources_manager);
if (!maybe_function_definition.has_value()) {
@ -553,14 +554,24 @@ type_check_name_expression(const nodes::NameExpression &expression,
const nodes::FunctionDefinition *function_definition =
maybe_function_definition.value();
// + 1 - returned type
if (expression.arguments_size() + 1 !=
function_definition
->arguments_size()) { // other, when there is passed type
// TODO: count passed type, if needed
// TODO: manage situation with one out type at any position
// TODO + 1 - returned type - somtimes (can be ==)
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
type_check_error(
"Number of function arguments is different from expected (" +
std::to_string(expression.arguments_size()) + " instead of " +
std::to_string(function_definition->arguments_size()) + ")",
std::to_string(arguments_given) + " instead of " +
std::to_string(arguments_defined) +
std::string{
arguments_defined > 0
? (" or " + std::to_string(
arguments_defined - 1))
: ""} +
")",
expression, sources_manager);
return nodes::TypeCheckResult::construct_invalid_result();
// TODO: try return correct type (function return type), when possible
@ -569,8 +580,8 @@ type_check_name_expression(const nodes::NameExpression &expression,
// TODO: define types for generic function
std::vector<nodes::TypeCheckResult> function_argument_results;
for (size_t i = 0; i < expression.arguments_size();
++i) { // TODO: arguments reordering, based on annotations
for (size_t i = 0; i < arguments_given;
++i) { // TODO: pass types with oud modifier
const nodes::FunctionDefinition::Argument *argument =
function_definition->get_argument(i);
@ -613,7 +624,8 @@ type_check_name_expression(const nodes::NameExpression &expression,
return nodes::TypeCheckResult::construct_invalid_result();
}
{
// TODO: check condition
if (arguments_given + 1 == arguments_defined) {
// returned type
const nodes::FunctionDefinition::Argument *returned =
function_definition->get_argument(
@ -897,7 +909,8 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
expression, sources_manager);
}
if (arguments.get_expected().size() != 1) {
if (arguments.get_expected().size() !=
1) { // TODO: check if only one function argument
type_check_error("Can't deduce type of lambda function from context; too "
"much possible types",
expression, sources_manager);
@ -909,17 +922,44 @@ nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
sources_manager);
}
// TODO: define vars
// TODO: expect returned type as type of internal expression
// TODO: merge returned and brought type
// TODO: add context
// auto returned_type = type_check_expression(
// *expression.get_expression(), sources_manager, state, Arguments{});
// TODO: deal with return type (+1 sometimes), etc
const auto arguments_given = expression.arguments_size();
const auto arguments_defined = expected_type.get()->parameters_size();
if (arguments_given != arguments_defined) {
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))
: ""} +
")",
expression, sources_manager);
}
// TODO: set another context (for expression typecheck and vars)
for (size_t i = 0; i < arguments_given; ++i) {
if (!state.insert_variable(*expression.get_argument(i)->get(),
expected_type.get()->get_parameter_proxy(i),
nodes::NameDefinition::Modifier::LET)) {
// TODO: which modifier ??
type_check_error("Variable is already defined in this context",
expression, sources_manager);
}
}
// 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)));
}
// TODO: needed ?? (only passed type check required ??)
return type_check_from_arguments(
expected_type, arguments, expression,
sources_manager); // TODO: same to expected ??
return type_check_from_arguments(expected_type, arguments, expression,
sources_manager);
} // IN PROGRESS
} // namespace type_check