mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Fix trailing default argument checking
This commit is contained in:
+34
-12
@@ -2,6 +2,7 @@ void check_expr (Checker *c, Operand *operand, AstNode *
|
|||||||
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
||||||
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
||||||
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
|
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
|
||||||
|
void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t);
|
||||||
Type * check_type (Checker *c, AstNode *expression, Type *named_type = NULL);
|
Type * check_type (Checker *c, AstNode *expression, Type *named_type = NULL);
|
||||||
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
|
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
|
||||||
Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
|
Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
|
||||||
@@ -1051,20 +1052,23 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
||||||
isize variable_index = 0;
|
isize variable_index = 0;
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
if (params[i]->kind != AstNode_Field) {
|
AstNode *param = params[i];
|
||||||
|
if (param->kind != AstNode_Field) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(p, Field, params[i]);
|
ast_node(p, Field, param);
|
||||||
AstNode *type_expr = p->type;
|
AstNode *type_expr = p->type;
|
||||||
Type *type = NULL;
|
Type *type = NULL;
|
||||||
AstNode *default_value = p->default_value;
|
AstNode *default_value = p->default_value;
|
||||||
ExactValue value = {};
|
ExactValue value = {};
|
||||||
|
bool default_is_nil = false;
|
||||||
|
|
||||||
if (type_expr == NULL) {
|
if (type_expr == NULL) {
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(c, &o, default_value);
|
check_expr(c, &o, default_value);
|
||||||
|
if (is_operand_nil(o)) {
|
||||||
if (o.mode != Addressing_Constant) {
|
default_is_nil = true;
|
||||||
|
} else if (o.mode != Addressing_Constant) {
|
||||||
error_node(default_value, "Default parameter must be a constant");
|
error_node(default_value, "Default parameter must be a constant");
|
||||||
} else {
|
} else {
|
||||||
value = o.value;
|
value = o.value;
|
||||||
@@ -1077,7 +1081,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
if (i+1 == params.count) {
|
if (i+1 == params.count) {
|
||||||
is_variadic = true;
|
is_variadic = true;
|
||||||
} else {
|
} else {
|
||||||
error_node(params[i], "Invalid AST: Invalid variadic parameter");
|
error_node(param, "Invalid AST: Invalid variadic parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,9 +1089,11 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
|
|
||||||
if (default_value != NULL) {
|
if (default_value != NULL) {
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(c, &o, default_value);
|
check_expr_with_type_hint(c, &o, default_value, type);
|
||||||
|
|
||||||
if (o.mode != Addressing_Constant) {
|
if (is_operand_nil(o)) {
|
||||||
|
default_is_nil = true;
|
||||||
|
} else if (o.mode != Addressing_Constant) {
|
||||||
error_node(default_value, "Default parameter must be a constant");
|
error_node(default_value, "Default parameter must be a constant");
|
||||||
} else {
|
} else {
|
||||||
value = o.value;
|
value = o.value;
|
||||||
@@ -1101,6 +1107,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
error_node(params[i], "Invalid parameter type");
|
error_node(params[i], "Invalid parameter type");
|
||||||
type = t_invalid;
|
type = t_invalid;
|
||||||
}
|
}
|
||||||
|
if (is_type_untyped(type)) {
|
||||||
|
error_node(params[i], "Cannot determine parameter type from a nil");
|
||||||
|
type = t_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
if (p->flags&FieldFlag_no_alias) {
|
if (p->flags&FieldFlag_no_alias) {
|
||||||
if (!is_type_pointer(type)) {
|
if (!is_type_pointer(type)) {
|
||||||
@@ -1121,6 +1131,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
param->Variable.is_immutable = true;
|
param->Variable.is_immutable = true;
|
||||||
}
|
}
|
||||||
param->Variable.default_value = value;
|
param->Variable.default_value = value;
|
||||||
|
param->Variable.default_is_nil = default_is_nil;
|
||||||
|
|
||||||
add_entity(c, scope, name, param);
|
add_entity(c, scope, name, param);
|
||||||
variables[variable_index++] = param;
|
variables[variable_index++] = param;
|
||||||
@@ -4838,10 +4849,15 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
for (isize i = param_count-1; i >= 0; i--) {
|
for (isize i = param_count-1; i >= 0; i--) {
|
||||||
Entity *e = param_tuple->variables[i];
|
Entity *e = param_tuple->variables[i];
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
if (e->Variable.default_value.kind == ExactValue_Invalid) {
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
break;
|
param_count_excluding_defaults--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
param_count_excluding_defaults--;
|
if (e->Variable.default_is_nil) {
|
||||||
|
param_count_excluding_defaults--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4888,7 +4904,8 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
GB_ASSERT(proc_type->Proc.params != NULL);
|
GB_ASSERT(proc_type->Proc.params != NULL);
|
||||||
Entity **sig_params = param_tuple->variables;
|
Entity **sig_params = param_tuple->variables;
|
||||||
isize operand_index = 0;
|
isize operand_index = 0;
|
||||||
for (; operand_index < param_count_excluding_defaults; operand_index++) {
|
isize max_operand_count = gb_min(param_count, operands.count);
|
||||||
|
for (; operand_index < max_operand_count; operand_index++) {
|
||||||
Type *t = sig_params[operand_index]->type;
|
Type *t = sig_params[operand_index]->type;
|
||||||
Operand o = operands[operand_index];
|
Operand o = operands[operand_index];
|
||||||
if (variadic) {
|
if (variadic) {
|
||||||
@@ -5036,6 +5053,11 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->Variable.default_is_nil) {
|
||||||
|
score += assign_score_function(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString str = type_to_string(e->type);
|
gbString str = type_to_string(e->type);
|
||||||
error_node(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
error_node(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
||||||
@@ -5067,7 +5089,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
|||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
AstNode *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
check_expr(c, &operands[i], fv->value);
|
check_expr_or_type(c, &operands[i], fv->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ struct Entity {
|
|||||||
bool is_immutable;
|
bool is_immutable;
|
||||||
bool is_thread_local;
|
bool is_thread_local;
|
||||||
ExactValue default_value;
|
ExactValue default_value;
|
||||||
|
bool default_is_nil;
|
||||||
} Variable;
|
} Variable;
|
||||||
struct {
|
struct {
|
||||||
bool is_type_alias;
|
bool is_type_alias;
|
||||||
|
|||||||
+1
-1
@@ -2731,7 +2731,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
ev = exact_value_to_complex(ev);
|
ev = exact_value_to_complex(ev);
|
||||||
} else if (is_type_string(dst)) {
|
} else if (is_type_string(dst)) {
|
||||||
// Handled elsewhere
|
// Handled elsewhere
|
||||||
GB_ASSERT(ev.kind == ExactValue_String);
|
GB_ASSERT_MSG(ev.kind == ExactValue_String, "%d", ev.kind);
|
||||||
} else if (is_type_integer(dst)) {
|
} else if (is_type_integer(dst)) {
|
||||||
ev = exact_value_to_integer(ev);
|
ev = exact_value_to_integer(ev);
|
||||||
} else if (is_type_pointer(dst)) {
|
} else if (is_type_pointer(dst)) {
|
||||||
|
|||||||
+21
-18
@@ -1100,24 +1100,6 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *default_type(Type *type) {
|
|
||||||
if (type == NULL) {
|
|
||||||
return t_invalid;
|
|
||||||
}
|
|
||||||
if (type->kind == Type_Basic) {
|
|
||||||
switch (type->Basic.kind) {
|
|
||||||
case Basic_UntypedBool: return t_bool;
|
|
||||||
case Basic_UntypedInteger: return t_int;
|
|
||||||
case Basic_UntypedFloat: return t_f64;
|
|
||||||
case Basic_UntypedComplex: return t_complex128;
|
|
||||||
case Basic_UntypedString: return t_string;
|
|
||||||
case Basic_UntypedRune: return t_rune;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *default_bit_field_value_type(Type *type) {
|
Type *default_bit_field_value_type(Type *type) {
|
||||||
if (type == NULL) {
|
if (type == NULL) {
|
||||||
return t_invalid;
|
return t_invalid;
|
||||||
@@ -1138,6 +1120,27 @@ Type *default_bit_field_value_type(Type *type) {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type *default_type(Type *type) {
|
||||||
|
if (type == NULL) {
|
||||||
|
return t_invalid;
|
||||||
|
}
|
||||||
|
if (type->kind == Type_Basic) {
|
||||||
|
switch (type->Basic.kind) {
|
||||||
|
case Basic_UntypedBool: return t_bool;
|
||||||
|
case Basic_UntypedInteger: return t_int;
|
||||||
|
case Basic_UntypedFloat: return t_f64;
|
||||||
|
case Basic_UntypedComplex: return t_complex128;
|
||||||
|
case Basic_UntypedString: return t_string;
|
||||||
|
case Basic_UntypedRune: return t_rune;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type->kind == Type_BitFieldValue) {
|
||||||
|
return default_bit_field_value_type(type);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Valid Compile time execution #run type
|
// NOTE(bill): Valid Compile time execution #run type
|
||||||
bool is_type_cte_safe(Type *type) {
|
bool is_type_cte_safe(Type *type) {
|
||||||
type = default_type(base_type(type));
|
type = default_type(base_type(type));
|
||||||
|
|||||||
Reference in New Issue
Block a user