Require all values from a procedure iterator if the procedure is marked with @(require_results)

This commit is contained in:
gingerBill
2026-02-11 14:05:06 +00:00
parent 9e547b4f82
commit b1633b9ebb
2 changed files with 33 additions and 2 deletions

View File

@@ -1724,6 +1724,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
bool is_range = false;
bool is_possibly_addressable = true;
isize max_val_count = 2;
if (is_ast_range(expr)) {
ast_node(ie, BinaryExpr, expr);
Operand x = {};
@@ -1884,7 +1885,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
error_line("\tMultiple return valued parameters in a range statement are limited to a minimum of 1 usable values with a trailing boolean for the conditional, got %td\n", count);
break;
}
enum : isize {MAXIMUM_COUNT = 100};
enum : isize {MAXIMUM_COUNT = 20};
if (count > MAXIMUM_COUNT) {
ERROR_BLOCK();
check_not_tuple(ctx, &operand);
@@ -1900,7 +1901,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
break;
}
max_val_count = count;
max_val_count = count-1;
for (Entity *e : t->Tuple.variables) {
array_add(&vals, e->type);
@@ -1920,6 +1921,20 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
if (is_reverse) {
error(node, "#reverse for is not supported for multiple return valued parameters");
}
Ast *expr = unparen_expr(operand.expr);
if (expr->kind == Ast_CallExpr) {
Type *p = base_type(type_of_expr(expr->CallExpr.proc));
if (p != nullptr && p->kind == Type_Proc) {
if (p->Proc.require_results) {
if (rs->vals.count < max_val_count) {
TokenPos start = ast_token(rs->vals[0]).pos;
TokenPos end = ast_end_pos(rs->vals[rs->vals.count-1]);
error_range(start, end, "Expected a %td identifier%s, got %td", max_val_count, max_val_count == 1 ? "" : "s", rs->vals.count);
}
}
}
}
}
break;

View File

@@ -514,6 +514,22 @@ gb_internal void error(Ast *node, char const *fmt, ...) {
}
}
gb_internal void error_range(TokenPos start, TokenPos end, char const *fmt, ...) {
GB_ASSERT(start.file_id == end.file_id);
GB_ASSERT(start.line == end.line);
GB_ASSERT(start.column <= end.column);
GB_ASSERT(start.offset <= end.offset);
va_list va;
va_start(va, fmt);
error_va(start, end, fmt, va);
va_end(va);
if (start.file_id != 0) {
AstFile *f = thread_safe_get_ast_file_from_id(start.file_id);
f->error_count += 1;
}
}
gb_internal void syntax_error_with_verbose(Ast *node, char const *fmt, ...) {
Token token = {};
TokenPos end_pos = {};