mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
type check expressions: type_check_name_expression and type_check_constructor parts
This commit is contained in:
parent
ed4b984b81
commit
a5fc0c7ee7
4 changed files with 149 additions and 22 deletions
|
|
@ -219,6 +219,13 @@ public:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<TypeProxy> get_type_proxy() const {
|
||||
if (type_.has_value()) {
|
||||
return type_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Modifier get_before_modifier() const { return before_modifier_; }
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ find_type_definition_handle_errors(const std::string &name,
|
|||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager);
|
||||
|
||||
std::optional<const nodes::NameDefinition *>
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition_handle_errors(const std::string &name,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager);
|
||||
|
|
|
|||
|
|
@ -538,15 +538,112 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
|||
nodes::TypeCheckResult
|
||||
type_check_name_expression(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {} // IN PROGRESS
|
||||
const Arguments &arguments) {
|
||||
// TODO: constraints ??
|
||||
|
||||
// TODO: deal with passed type
|
||||
|
||||
// TODO: check, if there is variable with this name
|
||||
const auto maybe_function_definition = find_name_definition_handle_errors(
|
||||
*expression.get_name()->get(), expression, sources_manager);
|
||||
if (!maybe_function_definition.has_value()) {
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
}
|
||||
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
|
||||
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()) + ")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// TODO: try return correct type (function return type), when possible
|
||||
}
|
||||
|
||||
// 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
|
||||
const nodes::FunctionDefinition::Argument *argument =
|
||||
function_definition->get_argument(i);
|
||||
|
||||
if (!argument->get_type().has_value()) {
|
||||
type_check_error("Function argument type is not defined for argument " +
|
||||
std::to_string(i),
|
||||
expression, sources_manager);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto annotation = expression.get_argument_annotation(i);
|
||||
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()
|
||||
: "[none]"},
|
||||
*expression.get_argument_value(i), sources_manager);
|
||||
}
|
||||
|
||||
if (annotation.has_value() &&
|
||||
*annotation.value() != *expected_annotation.value()) {
|
||||
type_check_error(
|
||||
"Wrong function argument type annotation: " + *annotation.value() +
|
||||
" instead of " + *expected_annotation.value(),
|
||||
*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())));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
{
|
||||
// returned type
|
||||
const nodes::FunctionDefinition::Argument *returned =
|
||||
function_definition->get_argument(
|
||||
function_definition->arguments_size() - 1);
|
||||
|
||||
// TODO: invert modifier ??
|
||||
if (!returned->get_type().has_value()) {
|
||||
type_check_error(
|
||||
"Function argument type is not defined for returned type", expression,
|
||||
sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
}
|
||||
|
||||
// TODO: invert modifier ??
|
||||
// TODO: generic types should be deduced from arguments
|
||||
return type_same_to_expected(returned->get_type_proxy().value(),
|
||||
arguments.get_expected(), expression,
|
||||
*sources_manager.get_error_log());
|
||||
}
|
||||
|
||||
// checks for universal call syntax ??
|
||||
} // IN PROGRESS
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult
|
||||
type_check_constructor(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
check_no_pass_type_in_arguments(arguments, expression, sources_manager);
|
||||
// TODO: constraints ??
|
||||
|
||||
// TODO: use pass type
|
||||
const auto maybe_type_definition = find_type_definition_handle_errors(
|
||||
*expression.get_type()->get_name()->get(), expression, sources_manager);
|
||||
if (!maybe_type_definition.has_value()) {
|
||||
|
|
@ -561,37 +658,60 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
}
|
||||
|
||||
// TODO: chack that is not typeclass ??
|
||||
// TODO: deal with anniotations, recursive annotations
|
||||
|
||||
// TODO: type arguments substitution (deduce argument type values ??)
|
||||
for (size_t i = 0; i < type_definition->arguments_size(); ++i) {
|
||||
// TODO: ...
|
||||
}
|
||||
// TODO: check that is not typeclass ??
|
||||
|
||||
nodes::TypeProxy type = type_definition->get_type().value();
|
||||
|
||||
// TODO: work with different parametric types: tuple, variant, ...
|
||||
|
||||
if (type.get()->parameters_size() != expression.arguments_size()) {
|
||||
type_check_error("Constructor arguments count is " +
|
||||
std::string{expression.arguments_size() <
|
||||
type.get()->parameters_size()
|
||||
? "less"
|
||||
: "more"} +
|
||||
" then type fields count",
|
||||
if (expression.arguments_size() !=
|
||||
type.get()->parameters_size()) { // other, when there is passed type
|
||||
type_check_error(
|
||||
"Number of type constructor arguments is different from expected (" +
|
||||
std::to_string(expression.arguments_size()) + " instead of " +
|
||||
std::to_string(type.get()->parameters_size()) + ")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// TODO: try return correct type (constructor's type), when possible (not
|
||||
// generic)
|
||||
}
|
||||
|
||||
// TODO: work with generics (type_definition->arguments, ...)
|
||||
|
||||
// for tuple
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
for (size_t i = 0; i < expression.arguments_size();
|
||||
++i) { // TODO: deduce order by annotations
|
||||
const auto annotation = expression.get_argument_annotation(i);
|
||||
const auto expected_annotation =
|
||||
type.get()->get_parameter(i)->get_annotation();
|
||||
|
||||
auto argument_type = type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
/* TODO: type from definition by annotation */);
|
||||
if (annotation.has_value() != expected_annotation.has_value()) {
|
||||
|
||||
type_check_error(
|
||||
"Wrong type constructor argument annotation: should be " +
|
||||
std::string{expected_annotation.has_value()
|
||||
? *expected_annotation.value()
|
||||
: "[none]"},
|
||||
*expression.get_argument_value(i), sources_manager);
|
||||
}
|
||||
// TODO: expect types of arguments by type definition
|
||||
|
||||
if (annotation.has_value() &&
|
||||
*annotation.value() != *expected_annotation.value()) {
|
||||
type_check_error(
|
||||
"Wrong function argument type annotation: " + *annotation.value() +
|
||||
" instead of " + *expected_annotation.value(),
|
||||
*expression.get_argument_value(i), sources_manager);
|
||||
}
|
||||
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
|
||||
// TODO: do something with argument type ??
|
||||
}
|
||||
|
||||
// TODO: deduce generic parts in type
|
||||
return type_same_to_expected(expression.get_type_proxy(),
|
||||
arguments.get_expected(), expression,
|
||||
*sources_manager.get_error_log());
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@ find_type_definition_handle_errors(const std::string &name,
|
|||
"Node in name tree is not type definition");
|
||||
}
|
||||
|
||||
std::optional<const nodes::NameDefinition *>
|
||||
std::optional<const nodes::FunctionDefinition *>
|
||||
find_name_definition_handle_errors(const std::string &name,
|
||||
const nodes::Node &node,
|
||||
SourcesManager &sources_manager) {
|
||||
return find_statement_handle_errors<nodes::NameDefinition>(
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue