aboutsummaryrefslogtreecommitdiff
path: root/src/check_type.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_type.cpp')
-rw-r--r--src/check_type.cpp45
1 files changed, 32 insertions, 13 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp
index befe56711..fe9c9c4ae 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1210,7 +1210,7 @@ Type *determine_type_from_polymorphic(Checker *c, Type *poly_type, Operand opera
}
-Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
+Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
if (_params == nullptr) {
return nullptr;
}
@@ -1250,6 +1250,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
bool is_variadic = false;
+ isize variadic_index = -1;
bool is_c_vararg = false;
Array<Entity *> variables = {};
array_init(&variables, c->allocator, variable_count);
@@ -1270,7 +1271,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
bool detemine_type_from_operand = false;
Type *specialization = nullptr;
- bool is_using = (p->flags&FieldFlag_using) != 0;
+ bool is_using = (p->flags&FieldFlag_using) != 0;
bool is_constant_value = (p->flags&FieldFlag_const) != 0;
@@ -1304,6 +1305,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
add_entity_use(c, e->identifier, e);
} else {
error(default_value, "Default parameter must be a constant");
+ continue;
}
}
} else {
@@ -1315,12 +1317,21 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
} else {
if (type_expr->kind == AstNode_Ellipsis) {
type_expr = type_expr->Ellipsis.expr;
+ #if 1
+ is_variadic = true;
+ variadic_index = variables.count;
+ if (p->names.count != 1) {
+ error(param, "Invalid AST: Invalid variadic parameter with multiple names");
+ success = false;
+ }
+ #else
if (i+1 == params.count) {
is_variadic = true;
} else {
error(param, "Invalid AST: Invalid variadic parameter");
success = false;
}
+ #endif
}
if (type_expr->kind == AstNode_TypeType) {
ast_node(tt, TypeType, type_expr);
@@ -1360,8 +1371,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (default_value != nullptr) {
if (type_expr->kind == AstNode_TypeType) {
error(default_value, "A type parameter may not have a default value");
+ continue;
} else if (is_constant_value) {
error(default_value, "A constant parameter may not have a default value");
+ continue;
} else {
Operand o = {};
if (default_value->kind == AstNode_BasicDirective &&
@@ -1404,23 +1417,22 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
check_is_assignable_to(c, &o, type);
}
}
-
}
if (type == nullptr) {
- error(params[i], "Invalid parameter type");
+ error(param, "Invalid parameter type");
type = t_invalid;
}
if (is_type_untyped(type)) {
if (is_type_untyped_undef(type)) {
- error(params[i], "Cannot determine parameter type from ---");
+ error(param, "Cannot determine parameter type from ---");
} else {
- error(params[i], "Cannot determine parameter type from a nil");
+ error(param, "Cannot determine parameter type from a nil");
}
type = t_invalid;
}
if (is_type_empty_union(type)) {
gbString str = type_to_string(type);
- error(params[i], "Invalid use of an empty union `%s`", str);
+ error(param, "Invalid use of an empty union `%s`", str);
gb_string_free(str);
type = t_invalid;
}
@@ -1429,7 +1441,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (p->flags&FieldFlag_c_vararg) {
if (p->type == nullptr ||
p->type->kind != AstNode_Ellipsis) {
- error(params[i], "`#c_vararg` can only be applied to variadic type fields");
+ error(param, "`#c_vararg` can only be applied to variadic type fields");
p->flags &= ~FieldFlag_c_vararg; // Remove the flag
} else {
is_c_vararg = true;
@@ -1438,10 +1450,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (is_constant_value) {
if (is_type_param) {
- error(p->type, "`$` is not needed for a `type` parameter");
+ error(param, "`$` is not needed for a `type` parameter");
}
if (p->flags&FieldFlag_no_alias) {
- error(p->type, "`#no_alias` can only be applied to variable fields of pointer type");
+ error(param, "`#no_alias` can only be applied to variable fields of pointer type");
p->flags &= ~FieldFlag_no_alias; // Remove the flag
}
@@ -1505,7 +1517,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (p->flags&FieldFlag_no_alias) {
if (!is_type_pointer(type)) {
- error(params[i], "`#no_alias` can only be applied to fields of pointer type");
+ error(name, "`#no_alias` can only be applied to fields of pointer type");
p->flags &= ~FieldFlag_no_alias; // Remove the flag
}
}
@@ -1550,10 +1562,14 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (is_variadic) {
+ GB_ASSERT(variadic_index >= 0);
+ }
+
+ if (is_variadic) {
GB_ASSERT(params.count > 0);
// NOTE(bill): Change last variadic parameter to be a slice
// Custom Calling convention for variadic parameters
- Entity *end = variables[variable_count-1];
+ Entity *end = variables[variadic_index];
end->type = make_type_slice(c->allocator, end->type);
end->flags |= EntityFlag_Ellipsis;
if (is_c_vararg) {
@@ -1581,6 +1597,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (success_) *success_ = success;
if (specialization_count_) *specialization_count_ = specialization_count;
if (is_variadic_) *is_variadic_ = is_variadic;
+ if (variadic_index_) *variadic_index_ = variadic_index;
return tuple;
}
@@ -1904,9 +1921,10 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
}
bool variadic = false;
+ isize variadic_index = -1;
bool success = true;
isize specialization_count = 0;
- Type *params = check_get_params(c, c->context.scope, pt->params, &variadic, &success, &specialization_count, operands);
+ Type *params = check_get_params(c, c->context.scope, pt->params, &variadic, &variadic_index, &success, &specialization_count, operands);
Type *results = check_get_results(c, c->context.scope, pt->results);
@@ -1941,6 +1959,7 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
type->Proc.results = results;
type->Proc.result_count = cast(i32)result_count;
type->Proc.variadic = variadic;
+ type->Proc.variadic_index = variadic_index;
type->Proc.calling_convention = cc;
type->Proc.is_polymorphic = pt->generic;
type->Proc.specialization_count = specialization_count;