aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-03-24 12:11:00 +0000
committergingerBill <bill@gingerbill.org>2021-03-24 12:11:00 +0000
commit0e3ecc350abfce97029276d03a8c79c885784ae4 (patch)
tree2b3c4929bee17da673c5e561694b98caf59a85f7 /src/check_stmt.cpp
parent295c1550a8569f91ed1838b37426bd6f56383a82 (diff)
Make the parser support as many identifiers on the LHS in `for in` loops to improve error messages
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index c539da99b..3b5593516 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1666,7 +1666,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
Ast *expr = unparen_expr(rs->expr);
-
+ isize max_val_count = 2;
if (is_ast_range(expr)) {
ast_node(ie, BinaryExpr, expr);
Operand x = {};
@@ -1739,9 +1739,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
break;
case Type_Tuple:
- if (false) {
- check_not_tuple(ctx, &operand);
- } else {
+ {
isize count = t->Tuple.variables.count;
if (count < 1 || count > 3) {
check_not_tuple(ctx, &operand);
@@ -1759,14 +1757,14 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
if (count > 1) val0 = t->Tuple.variables[0]->type;
if (count > 2) val1 = t->Tuple.variables[1]->type;
- if (rs->val1 != nullptr && count < 3) {
+ if (rs->vals.count > 1 && rs->vals[1] != nullptr && count < 3) {
gbString s = type_to_string(t);
error(operand.expr, "Expected a 3-value tuple on the rhs, got (%s)", s);
gb_string_free(s);
break;
}
- if (rs->val0 != nullptr && count < 2) {
+ if (rs->vals.count > 0 && rs->vals[0] != nullptr && count < 2) {
gbString s = type_to_string(t);
error(operand.expr, "Expected at least a 2-values tuple on the rhs, got (%s)", s);
gb_string_free(s);
@@ -1776,6 +1774,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
break;
+ case Type_Struct:
+ if (t->Struct.soa_kind != StructSoa_None) {
+ error(operand.expr, "#soa structures do not yet support for in loop iteration");
+ }
+ break;
}
}
@@ -1787,9 +1790,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
error(operand.expr, "Cannot iterate over '%s' of type '%s'", s, t);
- if (rs->val0 != nullptr && rs->val1 == nullptr) {
+ if (rs->vals.count == 1) {
if (is_type_map(operand.type) || is_type_bit_set(operand.type)) {
- gbString v = expr_to_string(rs->val0);
+ gbString v = expr_to_string(rs->vals[0]);
defer (gb_string_free(v));
error_line("\tSuggestion: place parentheses around the expression\n");
error_line("\t for (%s in %s) {\n", v, s);
@@ -1800,8 +1803,14 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
skip_expr_range_stmt:; // NOTE(zhiayang): again, declaring a variable immediately after a label... weird.
- Ast * lhs[2] = {rs->val0, rs->val1};
+ if (rs->vals.count > max_val_count) {
+ error(rs->vals[max_val_count], "Expected a maximum of %td identifier%s, got %td", max_val_count, max_val_count == 1 ? "" : "s", rs->vals.count);
+ }
+
+ Ast * lhs[2] = {};
Type *rhs[2] = {val0, val1};
+ if (rs->vals.count > 1) { lhs[1] = rs->vals[1]; }
+ if (rs->vals.count > 0) { lhs[0] = rs->vals[0]; }
for (isize i = 0; i < 2; i++) {
if (lhs[i] == nullptr) {