mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2026-01-03 04:38: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);
|
size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0);
|
||||||
|
|
||||||
// handle arguments
|
// handle arguments
|
||||||
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
|
bool all_arguments = function_declaration->type->types.size() <= node->arguments.size() + 1 - index_shift;
|
||||||
Visitor::Visit(node->arguments[i].second);
|
|
||||||
|
|
||||||
// function arguments can't be changed inside function
|
{
|
||||||
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
size_t i = index_shift; // function call argument id
|
||||||
if (!context_manager_.DefineVariable(function_definition->definition->arguments[i - index_shift],
|
size_t j = 0; // actual argument id
|
||||||
current_value_)) {
|
for (; j + 1 < function_declaration->type->types.size(); ++j) { // last type in function declaration is return type
|
||||||
error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base);
|
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
|
// check & collect parmeters
|
||||||
if (function_declaration->parameters.size() != node->parameters.size()) {
|
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);
|
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) {
|
for (size_t i = 0; i < node->parameters.size(); ++i) {
|
||||||
Visit(node->parameters[i].get());
|
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);
|
size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0);
|
||||||
|
|
||||||
// check arguments
|
// 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);
|
error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
|
bool all_arguments = function_declaration->type->types.size() <= node->arguments.size() + 1 - index_shift;
|
||||||
Visit(function_declaration->type->types[i - index_shift].second.get());
|
|
||||||
utils::IdType argument_type = TypeInContext(current_type_, context);
|
|
||||||
|
|
||||||
if (node->arguments[i].first.has_value()) {
|
{
|
||||||
if (!function_declaration->type->types[i - index_shift].first.has_value()) {
|
size_t i = index_shift; // function call argument id
|
||||||
error_handling::HandleTypecheckError("Declared argument has no annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
|
size_t j = 0; // actual argument id
|
||||||
} else if (node->arguments[i].first.value() != function_declaration->type->types[i - index_shift].first.value()) {
|
for (; i < node->arguments.size() && j + 1 < function_declaration->type->types.size(); ++j) { // last type in function declaration is return type
|
||||||
error_handling::HandleTypecheckError("Wrong argument annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
|
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 (i < node->arguments.size()) {
|
||||||
if (!context_manager_.AddValueRequirement(current_type_, argument_type)) {
|
error_handling::HandleTypecheckError("More arguments then needed in function call expression", node->base);
|
||||||
error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,9 +213,15 @@ def ( -- ) : begin end = {
|
||||||
decl scan-int : -> \int
|
decl scan-int : -> \int
|
||||||
def scan-int = \int..read: (\io..scan:)
|
def scan-int = \int..read: (\io..scan:)
|
||||||
|
|
||||||
decl print-int : ::x \int -> \unit
|
decl print-int : \int -> \unit
|
||||||
def print-int : x = \io..print: (x..show:)
|
def print-int : x = \io..print: (x..show:)
|
||||||
|
|
||||||
|
decl print-int-with-comment : ::i \int -> \string? -> \unit
|
||||||
|
def print-int-with-comment : i maybe-comment = {
|
||||||
|
; \io..print: (i..show:)
|
||||||
|
var comment? = maybe-comment in \io..print: comment
|
||||||
|
}
|
||||||
|
|
||||||
decl scan-anything 'a[#read] : -> 'a
|
decl scan-anything 'a[#read] : -> 'a
|
||||||
def scan-anything = 'a..read: (\io..scan:)
|
def scan-anything = 'a..read: (\io..scan:)
|
||||||
|
|
||||||
|
|
@ -272,7 +278,7 @@ exec main {
|
||||||
|
|
||||||
; print-anything:[int] n
|
; print-anything:[int] n
|
||||||
|
|
||||||
; print-int: ::x 123
|
; print-int-with-comment: ::i 123
|
||||||
|
|
||||||
var & a & b & c = scan-three-t:
|
var & a & b & c = scan-three-t:
|
||||||
; \io..print: b
|
; \io..print: b
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue