mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
part of constuctor typecheck (constructors for different types)
This commit is contained in:
parent
005fb6aaf3
commit
d7f1b6c377
3 changed files with 217 additions and 59 deletions
|
|
@ -177,9 +177,10 @@ inline std::optional<size_t> get_parameters_count(Type type) {
|
|||
return std::nullopt;
|
||||
case Type::ARRAY:
|
||||
case Type::OPTIONAL:
|
||||
case Type::RESULT:
|
||||
case Type::ERROR:
|
||||
return 1;
|
||||
case Type::RESULT: // RESULT[T E] = T | Error[E]
|
||||
return 2;
|
||||
// -- basic types
|
||||
case Type::FLOAT:
|
||||
case Type::DOUBLE:
|
||||
|
|
|
|||
|
|
@ -243,6 +243,21 @@ public:
|
|||
std::move(parameters)));
|
||||
}
|
||||
|
||||
TypeProxy add_error_of(TypeProxy type, Node node = Node()) {
|
||||
if (type.type_storage_ != this) {
|
||||
error_handling::handle_general_error(
|
||||
"TypeStorage: Can't add error of type from another type "
|
||||
"storage");
|
||||
}
|
||||
|
||||
std::vector<nodes::TypeProxy> parameters;
|
||||
parameters.push_back(type);
|
||||
|
||||
return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE,
|
||||
builtin::types::ERROR_IDENTIFIER),
|
||||
std::move(parameters)));
|
||||
}
|
||||
|
||||
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &¶meters,
|
||||
builtin::types::Type container,
|
||||
Node node = Node()) {
|
||||
|
|
|
|||
|
|
@ -541,7 +541,8 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
const Arguments &arguments) {
|
||||
// TODO: constraints ??
|
||||
|
||||
// TODO: deal with passed type
|
||||
// --- TODO --- deal with passed type --- TODO --- (additional argument)
|
||||
// TODO: deal with given ->(out) Args (type not expected, but passed into)
|
||||
|
||||
// TODO: check, if there is variable with this name
|
||||
const auto maybe_function_definition = find_name_definition_handle_errors(
|
||||
|
|
@ -665,13 +666,9 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
|
||||
// TODO: work with different parametric types: tuple, variant, ...
|
||||
|
||||
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);
|
||||
if (expression.arguments_size() == 0) {
|
||||
type_check_error("Number of type constructor arguments should be > 0",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// TODO: try return correct type (constructor's type), when possible (not
|
||||
// generic)
|
||||
|
|
@ -681,60 +678,205 @@ type_check_constructor(const nodes::Constructor &expression,
|
|||
|
||||
const auto builtin_type = type.get()->to_builtin();
|
||||
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
// for tuple
|
||||
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();
|
||||
|
||||
if (annotation.has_value() != expected_annotation.has_value()) {
|
||||
|
||||
{ // check arguments size, ets.
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
if (expression.arguments_size() != type.get()->parameters_size()) {
|
||||
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);
|
||||
"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)
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::types::Type::ERROR:
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
if (expression.arguments_size() != 1) { // TODO: better to_string
|
||||
type_check_error("Number of type constructor arguments should be = 1 "
|
||||
"(builtin type " +
|
||||
std::to_string(uint(builtin_type)) + ")",
|
||||
expression, sources_manager);
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// TODO: try return correct type (constructor's type), when possible
|
||||
// (not generic)
|
||||
}
|
||||
|
||||
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 ??
|
||||
break;
|
||||
default: // array, basic types
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_parameters_count(builtin_type).has_value() &&
|
||||
type.get()->parameters_size() !=
|
||||
get_parameters_count(builtin_type).value()) {
|
||||
type_check_error("Wrong amount of parametars for builtin type",
|
||||
expression, sources_manager);
|
||||
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// TODO: try return correct type (constructor's type), when possible (not
|
||||
// generic)
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<size_t> chosen_variant_option; // for VARIANT
|
||||
|
||||
{ // check annotations
|
||||
const auto check_same_annotation =
|
||||
[&expression, &sources_manager](
|
||||
size_t i, std::optional<const std::string *> expected_annotation,
|
||||
bool log_errors) {
|
||||
bool is_same = true;
|
||||
|
||||
const auto annotation = expression.get_argument_annotation(i);
|
||||
|
||||
if (annotation.has_value() != expected_annotation.has_value()) {
|
||||
if (log_errors) {
|
||||
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);
|
||||
}
|
||||
is_same = false;
|
||||
}
|
||||
|
||||
if (annotation.has_value() &&
|
||||
*annotation.value() != *expected_annotation.value()) {
|
||||
if (log_errors) {
|
||||
type_check_error("Wrong function argument type annotation: " +
|
||||
*annotation.value() + " instead of " +
|
||||
*expected_annotation.value(),
|
||||
*expression.get_argument_value(i),
|
||||
sources_manager);
|
||||
}
|
||||
|
||||
is_same = false;
|
||||
}
|
||||
|
||||
return is_same;
|
||||
};
|
||||
|
||||
const auto check_no_annotation =
|
||||
[&expression, &sources_manager](size_t i, bool log_errors) {
|
||||
if (expression.get_argument_annotation(i).has_value()) {
|
||||
if (log_errors) {
|
||||
type_check_error(
|
||||
"Type constructor argument annotation not expected there",
|
||||
*expression.get_argument_value(i), sources_manager);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
check_same_annotation(i, type.get()->get_parameter(i)->get_annotation(),
|
||||
true /*log errors*/);
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
// more then one same annotation ??
|
||||
for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
|
||||
if (check_same_annotation(
|
||||
0, type.get()->get_parameter(i)->get_annotation(),
|
||||
false /*do not log errors*/)) {
|
||||
chosen_variant_option = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chosen_variant_option.has_value() &&
|
||||
!check_no_annotation(0, false /*do not log errors*/)) {
|
||||
type_check_error("Wrong type constructor argument annotation in "
|
||||
"constructor of variant type",
|
||||
*expression.get_argument_value(0), sources_manager);
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::ERROR: // no anotations ??
|
||||
check_same_annotation(0, type.get()->get_parameter(0)->get_annotation(),
|
||||
true /*log errors*/);
|
||||
break;
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
case builtin::types::Type::RESULT:
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
check_no_annotation(0, true /*log errors*/);
|
||||
break;
|
||||
default: // array, basic types
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{ // type check arguments
|
||||
switch (builtin_type) {
|
||||
case builtin::types::Type::TUPLE:
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(i)));
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
if (chosen_variant_option.has_value()) {
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(
|
||||
chosen_variant_option.value())));
|
||||
} else { // TODO: error, if there is more then one possible variant in
|
||||
// answer
|
||||
nodes::TypeProxies possible_options;
|
||||
for (size_t i = 0; i < type.get()->parameters_size(); ++i) {
|
||||
possible_options.push_back(type.get()->get_parameter_proxy(i));
|
||||
}
|
||||
type_check_expression(*expression.get_argument_value(0),
|
||||
sources_manager, state,
|
||||
Arguments{}.expect(possible_options));
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
// first parameter or NULL
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(
|
||||
{type.get()->get_parameter_proxy(0),
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::NULL_OPTION)}));
|
||||
break;
|
||||
case builtin::types::Type::RESULT:
|
||||
// first parameter or ERROR[second parameter]
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect({type.get()->get_parameter_proxy(0),
|
||||
sources_manager.get_type_storage()->add_error_of(
|
||||
type.get()->get_parameter_proxy(1))}));
|
||||
break;
|
||||
case builtin::types::Type::ERROR:
|
||||
// first parameter
|
||||
type_check_expression(
|
||||
*expression.get_argument_value(0), sources_manager, state,
|
||||
Arguments{}.expect(type.get()->get_parameter_proxy(0)));
|
||||
break;
|
||||
case builtin::types::Type::FUNCTION:
|
||||
case builtin::types::Type::NONE:
|
||||
// type itself
|
||||
type_check_expression(*expression.get_argument_value(0), sources_manager,
|
||||
state, Arguments{}.expect(type));
|
||||
break;
|
||||
default: // array, basic types
|
||||
type_check_error("Type can't be constructed", expression,
|
||||
sources_manager);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case builtin::types::Type::VARIANT:
|
||||
// TODO: expect one of types
|
||||
break;
|
||||
case builtin::types::Type::OPTIONAL:
|
||||
// TODO: expect type (generic) or NULL
|
||||
break;
|
||||
case builtin::types::Type::RESULT:
|
||||
// TODO: expect ERROR or type (generic)
|
||||
break;
|
||||
case builtin::types::Type::ERROR:
|
||||
// TODO: expect type (generic)
|
||||
break;
|
||||
case builtin::types::Type::FUNCTION:
|
||||
// TODO: built from one value (function)
|
||||
break;
|
||||
case builtin::types::Type::NONE:
|
||||
// TODO: built from one value
|
||||
break;
|
||||
default: // array, basic types
|
||||
type_check_error("Type can't be constructed", expression, sources_manager);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: deduce generic parts in type
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue