mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-30 10:48:16 +00:00
optional arguments, fixes
This commit is contained in:
parent
8647918f37
commit
a208e2f42d
3 changed files with 90 additions and 24 deletions
|
|
@ -603,14 +603,32 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
|
|||
size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0);
|
||||
|
||||
// handle arguments
|
||||
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
|
||||
Visitor::Visit(node->arguments[i].second);
|
||||
bool all_arguments = function_declaration->type->types.size() <= node->arguments.size() + 1 - index_shift;
|
||||
|
||||
// function arguments can't be changed inside function
|
||||
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
if (!context_manager_.DefineVariable(function_definition->definition->arguments[i - index_shift],
|
||||
current_value_)) {
|
||||
error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base);
|
||||
{
|
||||
size_t i = index_shift; // function call argument id
|
||||
size_t j = 0; // actual argument id
|
||||
for (; j + 1 < function_declaration->type->types.size(); ++j) { // last type in function declaration is return type
|
||||
if (!all_arguments && i < node->arguments.size() && !node->arguments[i].first.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function call argument has no annotation (in function with part of arguments)", node->base);
|
||||
}
|
||||
|
||||
if (i < node->arguments.size() && (all_arguments || (function_declaration->type->types[j].first.has_value() && function_declaration->type->types[j].first.value() == node->arguments[i].first.value()))) {
|
||||
Visitor::Visit(node->arguments[i].second);
|
||||
++i;
|
||||
|
||||
// function arguments can't be changed inside function
|
||||
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
} else {
|
||||
current_value_ = context_manager_.AddValue(info::value::OptionalValue(std::nullopt,
|
||||
context_manager_.GetValueManager()),
|
||||
utils::ValueType::Const);
|
||||
}
|
||||
|
||||
if (!context_manager_.DefineVariable(function_definition->definition->arguments[j],
|
||||
current_value_)) {
|
||||
error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -794,10 +794,11 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
|||
|
||||
// check & collect parmeters
|
||||
if (function_declaration->parameters.size() != node->parameters.size()) {
|
||||
if (node->parameters.size() != 0) {
|
||||
// if (node->parameters.size() != 0) {
|
||||
error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base);
|
||||
}
|
||||
deduce_parameters = true;
|
||||
// }
|
||||
// deduce_parameters = true;
|
||||
// TODO: paramters deduction
|
||||
}
|
||||
for (size_t i = 0; i < node->parameters.size(); ++i) {
|
||||
Visit(node->parameters[i].get());
|
||||
|
|
@ -823,25 +824,66 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
|
|||
size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0);
|
||||
|
||||
// check arguments
|
||||
if (function_declaration->type->types.size() != node->arguments.size() + 1 - index_shift) {
|
||||
if (function_declaration->type->types.size() < node->arguments.size() + 1 - index_shift) {
|
||||
error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base);
|
||||
}
|
||||
|
||||
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
|
||||
Visit(function_declaration->type->types[i - index_shift].second.get());
|
||||
utils::IdType argument_type = TypeInContext(current_type_, context);
|
||||
bool all_arguments = function_declaration->type->types.size() <= node->arguments.size() + 1 - index_shift;
|
||||
|
||||
if (node->arguments[i].first.has_value()) {
|
||||
if (!function_declaration->type->types[i - index_shift].first.has_value()) {
|
||||
error_handling::HandleTypecheckError("Declared argument has no annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
|
||||
} else if (node->arguments[i].first.value() != function_declaration->type->types[i - index_shift].first.value()) {
|
||||
error_handling::HandleTypecheckError("Wrong argument annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
|
||||
{
|
||||
size_t i = index_shift; // function call argument id
|
||||
size_t j = 0; // actual argument id
|
||||
for (; i < node->arguments.size() && j + 1 < function_declaration->type->types.size(); ++j) { // last type in function declaration is return type
|
||||
if (!all_arguments) {
|
||||
if (!node->arguments[i].first.has_value()) { // function calls with part of arguments should have annotations for all arguments
|
||||
error_handling::HandleTypecheckError("Not all arguments annotated in function call expression with part of arguments (argument " + std::to_string(j + 1) + ")", node->base);
|
||||
}
|
||||
|
||||
if (!function_declaration->type->types[j].first.has_value() || function_declaration->type->types[j].first.value() != node->arguments[i].first.value()) {
|
||||
if (!function_declaration->type->types[j].second->references.empty() ||
|
||||
!std::holds_alternative<std::unique_ptr<TypeExpression>>(function_declaration->type->types[j].second->type) ||
|
||||
!std::get<std::unique_ptr<TypeExpression>>(function_declaration->type->types[j].second->type)->is_optional
|
||||
) {
|
||||
// TODO: make separated OptionalType ??
|
||||
error_handling::HandleTypecheckError("All missed arguments should be optionals in function call expression with part of arguments (argument " + std::to_string(j + 1) + ")", node->base);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Visit(function_declaration->type->types[j].second.get());
|
||||
utils::IdType argument_type = TypeInContext(current_type_, context);
|
||||
|
||||
if (node->arguments[i].first.has_value()) {
|
||||
if (!function_declaration->type->types[j].first.has_value()) {
|
||||
error_handling::HandleTypecheckError("Declared argument has no annotation (argument " + std::to_string(j + 1) + ")", node->base);
|
||||
} else if (node->arguments[i].first.value() != function_declaration->type->types[j].first.value()) {
|
||||
error_handling::HandleTypecheckError("Wrong argument annotation (argument " + std::to_string(j + 1) + ")", node->base);
|
||||
}
|
||||
}
|
||||
|
||||
Visitor::Visit(node->arguments[i].second);
|
||||
if (!context_manager_.AddValueRequirement(current_type_, argument_type)) {
|
||||
error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(j + 1) + ")", node->base);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
Visitor::Visit(node->arguments[i].second);
|
||||
if (!context_manager_.AddValueRequirement(current_type_, argument_type)) {
|
||||
error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
|
||||
if (i < node->arguments.size()) {
|
||||
error_handling::HandleTypecheckError("More arguments then needed in function call expression", node->base);
|
||||
}
|
||||
|
||||
if (j + 1 < function_declaration->type->types.size()) { // last type is return type
|
||||
for (; j + 1 < function_declaration->type->types.size(); ++j) {
|
||||
if (!function_declaration->type->types[j].second->references.empty() ||
|
||||
!std::holds_alternative<std::unique_ptr<TypeExpression>>(function_declaration->type->types[j].second->type) ||
|
||||
!std::get<std::unique_ptr<TypeExpression>>(function_declaration->type->types[j].second->type)->is_optional
|
||||
) {
|
||||
// TODO: make separated OptionalType ??
|
||||
error_handling::HandleTypecheckError("All missed arguments should be optionals in function call expression with part of arguments (after last argument)", node->base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue