mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Begin work allowing mixture of named and unnamed
This commit is contained in:
+46
-29
@@ -101,8 +101,7 @@ gb_internal void check_struct_type (CheckerContext *c, Type *st
|
|||||||
gb_internal void check_union_type (CheckerContext *c, Type *union_type, Ast *node, Array<Operand> *poly_operands,
|
gb_internal void check_union_type (CheckerContext *c, Type *union_type, Ast *node, Array<Operand> *poly_operands,
|
||||||
Type *named_type = nullptr, Type *original_type_for_poly = nullptr);
|
Type *named_type = nullptr, Type *original_type_for_poly = nullptr);
|
||||||
|
|
||||||
gb_internal CallArgumentData check_call_arguments (CheckerContext *c, Operand *operand, Type *proc_type, Ast *call);
|
gb_internal Type * check_init_variable (CheckerContext *c, Entity *e, Operand *operand, String context_name);
|
||||||
gb_internal Type * check_init_variable (CheckerContext *c, Entity *e, Operand *operand, String context_name);
|
|
||||||
|
|
||||||
|
|
||||||
gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type);
|
gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type);
|
||||||
@@ -122,7 +121,7 @@ gb_internal void check_or_return_split_types(CheckerContext *c, Operand *x, Stri
|
|||||||
|
|
||||||
gb_internal bool is_diverging_expr(Ast *expr);
|
gb_internal bool is_diverging_expr(Ast *expr);
|
||||||
|
|
||||||
gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, Type *proc_type, Ast *call, Slice<Ast *> const &args, bool show_error);
|
gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, Type *proc_type, Ast *call, bool show_error);
|
||||||
|
|
||||||
enum LoadDirectiveResult {
|
enum LoadDirectiveResult {
|
||||||
LoadDirective_Success = 0,
|
LoadDirective_Success = 0,
|
||||||
@@ -5606,7 +5605,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (check_order_of_call_arguments(c, proc_type, call, ce->args, show_error)) {
|
if (check_order_of_call_arguments(c, proc_type, call, show_error)) {
|
||||||
return CallArgumentError_OutOfOrderParameters;
|
return CallArgumentError_OutOfOrderParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5873,7 +5872,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, Type *proc_type, Ast *call, Slice<Ast *> const &args, bool show_error) {
|
gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, Type *proc_type, Ast *call, bool show_error) {
|
||||||
CallArgumentError err = CallArgumentError_None;
|
CallArgumentError err = CallArgumentError_None;
|
||||||
|
|
||||||
if (proc_type == nullptr || !is_type_proc(proc_type)) {
|
if (proc_type == nullptr || !is_type_proc(proc_type)) {
|
||||||
@@ -5891,11 +5890,11 @@ gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, T
|
|||||||
|
|
||||||
TEMPORARY_ALLOCATOR_GUARD();
|
TEMPORARY_ALLOCATOR_GUARD();
|
||||||
|
|
||||||
auto arg_order_indices = slice_make<isize>(temporary_allocator(), args.count);
|
auto arg_order_indices = slice_make<isize>(temporary_allocator(), ce->args.count);
|
||||||
auto visited = slice_make<bool>(temporary_allocator(), param_count);
|
auto visited = slice_make<bool>(temporary_allocator(), param_count);
|
||||||
|
|
||||||
for_array(i, args) {
|
for_array(i, ce->args) {
|
||||||
Ast *arg = args[i];
|
Ast *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
|
|
||||||
Ast *field = fv->field;
|
Ast *field = fv->field;
|
||||||
@@ -5938,15 +5937,15 @@ gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, T
|
|||||||
if (a > b) {
|
if (a > b) {
|
||||||
err = CallArgumentError_OutOfOrderParameters;
|
err = CallArgumentError_OutOfOrderParameters;
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
Ast *arg_a = args[i+0];
|
Ast *arg_a = ce->args[i+0];
|
||||||
Ast *arg_b = args[i+1];
|
Ast *arg_b = ce->args[i+1];
|
||||||
|
|
||||||
isize curr_a_order = a;
|
isize curr_a_order = a;
|
||||||
for (isize j = i; j >= 0; j--) {
|
for (isize j = i; j >= 0; j--) {
|
||||||
isize j_order = arg_order_indices[j];
|
isize j_order = arg_order_indices[j];
|
||||||
if (b < j_order && j_order < curr_a_order) {
|
if (b < j_order && j_order < curr_a_order) {
|
||||||
curr_a_order = j_order;
|
curr_a_order = j_order;
|
||||||
arg_a = args[j];
|
arg_a = ce->args[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5967,15 +5966,18 @@ gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, Ast *call, Slice<Ast *> const &args) {
|
gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Ast *call) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
|
|
||||||
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
|
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
|
||||||
Array<Operand> operands = {};
|
Array<Operand> operands = {};
|
||||||
defer (array_free(&operands));
|
defer (array_free(&operands));
|
||||||
|
|
||||||
Type *result_type = t_invalid;
|
|
||||||
|
|
||||||
|
Type *result_type = t_invalid;
|
||||||
|
Type *proc_type = base_type(operand->type);
|
||||||
|
|
||||||
|
Slice<Ast *> const &args = ce->args;
|
||||||
if (is_call_expr_field_value(ce)) {
|
if (is_call_expr_field_value(ce)) {
|
||||||
Type *ptype = nullptr;
|
Type *ptype = nullptr;
|
||||||
bool single_case = true;
|
bool single_case = true;
|
||||||
@@ -5991,7 +5993,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
|
|||||||
ptype = proc_type;
|
ptype = proc_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_order_of_call_arguments(c, ptype, call, args, true)) {
|
if (check_order_of_call_arguments(c, ptype, call, true)) {
|
||||||
CallArgumentData data = {};
|
CallArgumentData data = {};
|
||||||
data.result_type = t_invalid;
|
data.result_type = t_invalid;
|
||||||
if (ptype && is_type_proc(ptype) && !is_type_polymorphic(ptype)) {
|
if (ptype && is_type_proc(ptype) && !is_type_polymorphic(ptype)) {
|
||||||
@@ -6850,20 +6852,31 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
|
|||||||
|
|
||||||
|
|
||||||
// returns true on failure
|
// returns true on failure
|
||||||
gb_internal bool check_call_parameter_mixture(Operand *operand, Slice<Ast *> const &args, char const *context) {
|
gb_internal bool check_call_parameter_mixture(Operand *operand, Slice<Ast *> const &args, char const *context, bool allow_mixed=false) {
|
||||||
bool failure = false;
|
bool failure = false;
|
||||||
if (args.count > 0) {
|
if (args.count > 0) {
|
||||||
bool first_is_field_value = (args[0]->kind == Ast_FieldValue);
|
if (allow_mixed) {
|
||||||
for (Ast *arg : args) {
|
bool was_named = false;
|
||||||
bool mix = false;
|
for (Ast *arg : args) {
|
||||||
if (first_is_field_value) {
|
if (was_named && arg->kind != Ast_FieldValue) {
|
||||||
mix = arg->kind != Ast_FieldValue;
|
error(arg, "Non-named parameter is not allowed to follow named parameter i.e. 'field = value' in a %s", context);
|
||||||
} else {
|
failure = true;
|
||||||
mix = arg->kind == Ast_FieldValue;
|
}
|
||||||
|
was_named = was_named || arg->kind == Ast_FieldValue;
|
||||||
}
|
}
|
||||||
if (mix) {
|
} else {
|
||||||
error(arg, "Mixture of 'field = value' and value elements in a %s is not allowed", context);
|
bool first_is_field_value = (args[0]->kind == Ast_FieldValue);
|
||||||
failure = true;
|
for (Ast *arg : args) {
|
||||||
|
bool mix = false;
|
||||||
|
if (first_is_field_value) {
|
||||||
|
mix = arg->kind != Ast_FieldValue;
|
||||||
|
} else {
|
||||||
|
mix = arg->kind == Ast_FieldValue;
|
||||||
|
}
|
||||||
|
if (mix) {
|
||||||
|
error(arg, "Mixture of 'field = value' and value elements in a %s is not allowed", context);
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6871,7 +6884,7 @@ gb_internal bool check_call_parameter_mixture(Operand *operand, Slice<Ast *> con
|
|||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN(context_) if (check_call_parameter_mixture(operand, args, "procedure call")) { \
|
#define CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN(context_, ...) if (check_call_parameter_mixture(operand, args, context_, ##__VA_ARGS__)) { \
|
||||||
operand->mode = Addressing_Invalid; \
|
operand->mode = Addressing_Invalid; \
|
||||||
operand->expr = call; \
|
operand->expr = call; \
|
||||||
return Expr_Stmt; \
|
return Expr_Stmt; \
|
||||||
@@ -7021,6 +7034,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
return builtin_procs[id].kind;
|
return builtin_procs[id].kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call", true);
|
||||||
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call");
|
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call");
|
||||||
|
|
||||||
Entity *initial_entity = entity_of_node(operand->expr);
|
Entity *initial_entity = entity_of_node(operand->expr);
|
||||||
@@ -7034,8 +7048,8 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *proc_type = base_type(operand->type);
|
|
||||||
if (operand->mode != Addressing_ProcGroup) {
|
if (operand->mode != Addressing_ProcGroup) {
|
||||||
|
Type *proc_type = base_type(operand->type);
|
||||||
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
|
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
|
||||||
bool valid_mode = is_operand_value(*operand);
|
bool valid_mode = is_operand_value(*operand);
|
||||||
if (!valid_type || !valid_mode) {
|
if (!valid_type || !valid_mode) {
|
||||||
@@ -7053,7 +7067,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallArgumentData data = check_call_arguments(c, operand, proc_type, call, args);
|
CallArgumentData data = check_call_arguments(c, operand, call);
|
||||||
Type *result_type = data.result_type;
|
Type *result_type = data.result_type;
|
||||||
gb_zero_item(operand);
|
gb_zero_item(operand);
|
||||||
operand->expr = call;
|
operand->expr = call;
|
||||||
@@ -7064,7 +7078,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
return Expr_Stmt;
|
return Expr_Stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *pt = base_type(proc_type);
|
Type *pt = base_type(operand->type);
|
||||||
|
if (pt == nullptr) {
|
||||||
|
pt = t_invalid;
|
||||||
|
}
|
||||||
if (pt == t_invalid) {
|
if (pt == t_invalid) {
|
||||||
if (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
|
if (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
|
||||||
pt = type_of_expr(operand->expr->CallExpr.proc);
|
pt = type_of_expr(operand->expr->CallExpr.proc);
|
||||||
|
|||||||
Reference in New Issue
Block a user