aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-06-14 15:40:52 +0100
committergingerBill <bill@gingerbill.org>2023-06-14 15:40:52 +0100
commit242d3b3c4d7e269b04c96a81dbf6e5f5fbeb5e8b (patch)
treeb24f839cf92e18eb1a2f48ef5cf45d83d9ae74c2 /src/check_expr.cpp
parentc66ac9725ee89df82b70a1109ee1988360d5ab6d (diff)
Begin work allowing mixture of named and unnamed
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp73
1 files changed, 45 insertions, 28 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index d3e287ba4..52ab5092e 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -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,
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);
@@ -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 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 {
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;
}
@@ -5873,7 +5872,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco
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;
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();
- 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);
- for_array(i, args) {
- Ast *arg = args[i];
+ for_array(i, ce->args) {
+ Ast *arg = ce->args[i];
ast_node(fv, FieldValue, arg);
Ast *field = fv->field;
@@ -5938,15 +5937,15 @@ gb_internal CallArgumentError check_order_of_call_arguments(CheckerContext *c, T
if (a > b) {
err = CallArgumentError_OutOfOrderParameters;
if (show_error) {
- Ast *arg_a = args[i+0];
- Ast *arg_b = args[i+1];
+ Ast *arg_a = ce->args[i+0];
+ Ast *arg_b = ce->args[i+1];
isize curr_a_order = a;
for (isize j = i; j >= 0; j--) {
isize j_order = arg_order_indices[j];
if (b < j_order && j_order < curr_a_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);
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
Array<Operand> operands = {};
defer (array_free(&operands));
+
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)) {
Type *ptype = nullptr;
bool single_case = true;
@@ -5991,7 +5993,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
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 = {};
data.result_type = t_invalid;
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
-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;
if (args.count > 0) {
- bool first_is_field_value = (args[0]->kind == Ast_FieldValue);
- for (Ast *arg : args) {
- bool mix = false;
- if (first_is_field_value) {
- mix = arg->kind != Ast_FieldValue;
- } else {
- mix = arg->kind == Ast_FieldValue;
+ if (allow_mixed) {
+ bool was_named = false;
+ for (Ast *arg : args) {
+ if (was_named && arg->kind != Ast_FieldValue) {
+ error(arg, "Non-named parameter is not allowed to follow named parameter i.e. 'field = value' in a %s", context);
+ failure = true;
+ }
+ was_named = was_named || arg->kind == Ast_FieldValue;
}
- if (mix) {
- error(arg, "Mixture of 'field = value' and value elements in a %s is not allowed", context);
- failure = true;
+ } else {
+ bool first_is_field_value = (args[0]->kind == Ast_FieldValue);
+ 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;
}
-#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->expr = call; \
return Expr_Stmt; \
@@ -7021,6 +7034,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
return builtin_procs[id].kind;
}
+ // CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call", true);
CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("procedure call");
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) {
+ Type *proc_type = base_type(operand->type);
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
bool valid_mode = is_operand_value(*operand);
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;
gb_zero_item(operand);
operand->expr = call;
@@ -7064,7 +7078,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
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 (operand->expr != nullptr && operand->expr->kind == Ast_CallExpr) {
pt = type_of_expr(operand->expr->CallExpr.proc);