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;
|
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_; }
|
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,
|
const nodes::Node &node,
|
||||||
SourcesManager &sources_manager);
|
SourcesManager &sources_manager);
|
||||||
|
|
||||||
std::optional<const nodes::NameDefinition *>
|
std::optional<const nodes::FunctionDefinition *>
|
||||||
find_name_definition_handle_errors(const std::string &name,
|
find_name_definition_handle_errors(const std::string &name,
|
||||||
const nodes::Node &node,
|
const nodes::Node &node,
|
||||||
SourcesManager &sources_manager);
|
SourcesManager &sources_manager);
|
||||||
|
|
|
||||||
|
|
@ -538,15 +538,112 @@ type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_name_expression(const nodes::NameExpression &expression,
|
type_check_name_expression(const nodes::NameExpression &expression,
|
||||||
SourcesManager &sources_manager, State &state,
|
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
|
// TODO
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_constructor(const nodes::Constructor &expression,
|
type_check_constructor(const nodes::Constructor &expression,
|
||||||
SourcesManager &sources_manager, State &state,
|
SourcesManager &sources_manager, State &state,
|
||||||
const Arguments &arguments) {
|
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(
|
const auto maybe_type_definition = find_type_definition_handle_errors(
|
||||||
*expression.get_type()->get_name()->get(), expression, sources_manager);
|
*expression.get_type()->get_name()->get(), expression, sources_manager);
|
||||||
if (!maybe_type_definition.has_value()) {
|
if (!maybe_type_definition.has_value()) {
|
||||||
|
|
@ -561,37 +658,60 @@ type_check_constructor(const nodes::Constructor &expression,
|
||||||
return nodes::TypeCheckResult::construct_invalid_result();
|
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 ??)
|
// TODO: check that is not typeclass ??
|
||||||
for (size_t i = 0; i < type_definition->arguments_size(); ++i) {
|
|
||||||
// TODO: ...
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes::TypeProxy type = type_definition->get_type().value();
|
nodes::TypeProxy type = type_definition->get_type().value();
|
||||||
|
|
||||||
// TODO: work with different parametric types: tuple, variant, ...
|
// TODO: work with different parametric types: tuple, variant, ...
|
||||||
|
|
||||||
if (type.get()->parameters_size() != expression.arguments_size()) {
|
if (expression.arguments_size() !=
|
||||||
type_check_error("Constructor arguments count is " +
|
type.get()->parameters_size()) { // other, when there is passed type
|
||||||
std::string{expression.arguments_size() <
|
type_check_error(
|
||||||
type.get()->parameters_size()
|
"Number of type constructor arguments is different from expected (" +
|
||||||
? "less"
|
std::to_string(expression.arguments_size()) + " instead of " +
|
||||||
: "more"} +
|
std::to_string(type.get()->parameters_size()) + ")",
|
||||||
" then type fields count",
|
expression, sources_manager);
|
||||||
expression, sources_manager);
|
|
||||||
return nodes::TypeCheckResult::construct_invalid_result();
|
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 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 annotation = expression.get_argument_annotation(i);
|
||||||
|
const auto expected_annotation =
|
||||||
|
type.get()->get_parameter(i)->get_annotation();
|
||||||
|
|
||||||
auto argument_type = type_check_expression(
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
*expression.get_argument_value(i), sources_manager, state,
|
||||||
/* TODO: type from definition by annotation */);
|
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
|
||||||
|
// TODO: do something with argument type ??
|
||||||
}
|
}
|
||||||
// TODO: expect types of arguments by type definition
|
|
||||||
|
// TODO: deduce generic parts in type
|
||||||
return type_same_to_expected(expression.get_type_proxy(),
|
return type_same_to_expected(expression.get_type_proxy(),
|
||||||
arguments.get_expected(), expression,
|
arguments.get_expected(), expression,
|
||||||
*sources_manager.get_error_log());
|
*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");
|
"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,
|
find_name_definition_handle_errors(const std::string &name,
|
||||||
const nodes::Node &node,
|
const nodes::Node &node,
|
||||||
SourcesManager &sources_manager) {
|
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",
|
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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue