aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-12-14 14:35:23 +0000
committergingerBill <bill@gingerbill.org>2018-12-14 14:35:23 +0000
commitb54c35639b288b926192cdc6ad25ab985289d66b (patch)
treea01a86269d19d64e992a99741bfb79c7bfbfaa4b /src/check_expr.cpp
parent3bf01c8498b996fd18d26243f5dcaa2f3a84048e (diff)
Fix issue with mixture of named and unnamed parameters for a struct literal
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp181
1 files changed, 91 insertions, 90 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 86ff4f0cd..837505dff 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -5356,6 +5356,8 @@ bool ternary_compare_types(Type *x, Type *y) {
return are_types_identical(x, y);
}
+
+
ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Stmt;
@@ -5646,112 +5648,111 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
break;
}
- if (is_type_struct(t)) { // Checker values
- isize field_count = t->Struct.fields.count;
- isize min_field_count = t->Struct.fields.count;
- for (isize i = min_field_count-1; i >= 0; i--) {
- Entity *e = t->Struct.fields[i];
- GB_ASSERT(e->kind == Entity_Variable);
- if (e->Variable.param_value.kind != ParameterValue_Invalid) {
- min_field_count--;
- } else {
- break;
- }
- }
-
- if (cl->elems[0]->kind == Ast_FieldValue) {
- bool *fields_visited = gb_alloc_array(c->allocator, bool, field_count);
- for_array(i, cl->elems) {
- Ast *elem = cl->elems[i];
- if (elem->kind != Ast_FieldValue) {
- error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
- continue;
- }
- ast_node(fv, FieldValue, elem);
- if (fv->field->kind != Ast_Ident) {
- gbString expr_str = expr_to_string(fv->field);
- error(elem, "Invalid field name '%s' in structure literal", expr_str);
- gb_string_free(expr_str);
- continue;
- }
- String name = fv->field->Ident.token.string;
+ isize field_count = t->Struct.fields.count;
+ isize min_field_count = t->Struct.fields.count;
+ for (isize i = min_field_count-1; i >= 0; i--) {
+ Entity *e = t->Struct.fields[i];
+ GB_ASSERT(e->kind == Entity_Variable);
+ if (e->Variable.param_value.kind != ParameterValue_Invalid) {
+ min_field_count--;
+ } else {
+ break;
+ }
+ }
- Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
- bool is_unknown = sel.entity == nullptr;
- if (is_unknown) {
- error(elem, "Unknown field '%.*s' in structure literal", LIT(name));
- continue;
- }
+ if (cl->elems[0]->kind == Ast_FieldValue) {
+ bool *fields_visited = gb_alloc_array(c->allocator, bool, field_count);
- if (sel.index.count > 1) {
- error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name));
- continue;
- }
+ for_array(i, cl->elems) {
+ Ast *elem = cl->elems[i];
+ if (elem->kind != Ast_FieldValue) {
+ error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
+ continue;
+ }
+ ast_node(fv, FieldValue, elem);
+ if (fv->field->kind != Ast_Ident) {
+ gbString expr_str = expr_to_string(fv->field);
+ error(elem, "Invalid field name '%s' in structure literal", expr_str);
+ gb_string_free(expr_str);
+ continue;
+ }
+ String name = fv->field->Ident.token.string;
- Entity *field = t->Struct.fields[sel.index[0]];
- add_entity_use(c, fv->field, field);
+ Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
+ bool is_unknown = sel.entity == nullptr;
+ if (is_unknown) {
+ error(elem, "Unknown field '%.*s' in structure literal", LIT(name));
+ continue;
+ }
- if (fields_visited[sel.index[0]]) {
- error(elem, "Duplicate field '%.*s' in structure literal", LIT(name));
- continue;
- }
+ if (sel.index.count > 1) {
+ error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name));
+ continue;
+ }
- fields_visited[sel.index[0]] = true;
- check_expr_with_type_hint(c, o, fv->value, field->type);
+ Entity *field = t->Struct.fields[sel.index[0]];
+ add_entity_use(c, fv->field, field);
- if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type)) {
- is_constant = false;
- }
- if (is_constant) {
- is_constant = o->mode == Addressing_Constant;
- }
+ if (fields_visited[sel.index[0]]) {
+ error(elem, "Duplicate field '%.*s' in structure literal", LIT(name));
+ continue;
+ }
+ fields_visited[sel.index[0]] = true;
+ check_expr_with_type_hint(c, o, fv->value, field->type);
- check_assignment(c, o, field->type, str_lit("structure literal"));
+ if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type)) {
+ is_constant = false;
+ }
+ if (is_constant) {
+ is_constant = o->mode == Addressing_Constant;
}
- } else {
- bool seen_field_value = false;
- for_array(index, cl->elems) {
- Entity *field = nullptr;
- Ast *elem = cl->elems[index];
- if (elem->kind == Ast_FieldValue) {
- seen_field_value = true;
- // error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
- // continue;
- } else if (seen_field_value) {
- error(elem, "Value elements cannot be used after a 'field = value'");
- continue;
- }
- if (index >= field_count) {
- error(o->expr, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count);
- break;
- }
- if (field == nullptr) {
- field = t->Struct.fields[index];
- }
+ check_assignment(c, o, field->type, str_lit("structure literal"));
+ }
+ } else {
+ bool seen_field_value = false;
- check_expr_with_type_hint(c, o, elem, field->type);
+ for_array(index, cl->elems) {
+ Entity *field = nullptr;
+ Ast *elem = cl->elems[index];
+ if (elem->kind == Ast_FieldValue) {
+ seen_field_value = true;
+ error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
+ continue;
+ } else if (seen_field_value) {
+ error(elem, "Value elements cannot be used after a 'field = value'");
+ continue;
+ }
+ if (index >= field_count) {
+ error(o->expr, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count);
+ break;
+ }
- if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type)) {
- is_constant = false;
- }
- if (is_constant) {
- is_constant = o->mode == Addressing_Constant;
- }
+ if (field == nullptr) {
+ field = t->Struct.fields[index];
+ }
+
+ check_expr_with_type_hint(c, o, elem, field->type);
- check_assignment(c, o, field->type, str_lit("structure literal"));
+ if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type)) {
+ is_constant = false;
}
- if (cl->elems.count < field_count) {
- if (min_field_count < field_count) {
- if (cl->elems.count < min_field_count) {
- error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count);
- }
- } else {
- error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count);
- }
+ if (is_constant) {
+ is_constant = o->mode == Addressing_Constant;
+ }
+
+ check_assignment(c, o, field->type, str_lit("structure literal"));
+ }
+ if (cl->elems.count < field_count) {
+ if (min_field_count < field_count) {
+ if (cl->elems.count < min_field_count) {
+ error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count);
+ }
+ } else {
+ error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count);
}
}
}