commit f9dbf4981add935413649f0b8e77c7edd189648a
parent 9823d8cae6542d9ff805c089395ba19511537f10
Author: Eyal Sawady <ecs@d2evs.net>
Date: Fri, 3 Sep 2021 22:13:01 +0000
ast: simplify embedded struct literals
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
3 files changed, 31 insertions(+), 55 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -300,15 +300,9 @@ struct ast_expression_switch {
struct ast_expression_struct;
struct ast_field_value {
- bool is_embedded;
- union {
- struct {
- char *name;
- struct ast_type *type;
- struct ast_expression *initializer;
- } field;
- struct ast_expression *embedded;
- };
+ char *name;
+ struct ast_type *type;
+ struct ast_expression *initializer;
struct ast_field_value *next;
};
diff --git a/src/check.c b/src/check.c
@@ -2249,27 +2249,23 @@ check_expr_struct(struct context *ctx,
struct ast_field_value *afield = aexpr->_struct.fields;
while (afield) {
- assert(!afield->is_embedded); // TODO
-
const struct type *ftype;
if (!stype) {
- tfield->name = afield->field.name;
- tfield->type = afield->field.type;
+ assert(afield->name); // TODO
+ if (!afield->type) {
+ error(ctx, aexpr->loc, expr,
+ "Unnamed struct must specify field type");
+ return;
+ }
+ tfield->name = afield->name;
+ tfield->type = afield->type;
ftype = type_store_lookup_atype(
ctx->store, tfield->type);
} else {
- if (!afield->field.name) {
- error(ctx, afield->field.initializer->loc,
- expr,
- "Anonymous fields are not permitted for named struct type");
- return;
- // XXX: ^ Is that correct?
- }
sexpr->field = type_get_field(type_dealias(stype),
- afield->field.name);
+ afield->name);
if (!sexpr->field) {
- error(ctx, afield->field.initializer->loc,
- expr,
+ error(ctx, afield->initializer->loc, expr,
"No field by this name exists for this type");
return;
}
@@ -2277,12 +2273,11 @@ check_expr_struct(struct context *ctx,
}
sexpr->value = xcalloc(1, sizeof(struct expression));
- check_expression(ctx, afield->field.initializer, sexpr->value, ftype);
+ check_expression(ctx, afield->initializer, sexpr->value, ftype);
if (stype) {
if (!type_is_assignable(sexpr->field->type, sexpr->value->result)) {
- error(ctx, afield->field.initializer->loc,
- expr,
+ error(ctx, afield->initializer->loc, expr,
"Initializer is not assignable to struct field");
return;
}
@@ -3182,19 +3177,11 @@ expr_is_specified(struct context *ctx, const struct ast_expression *aexpr)
case EXPR_STRUCT:
for (struct ast_field_value *field = aexpr->_struct.fields;
field; field = field->next) {
- if (field->is_embedded) {
- if (!expr_is_specified(ctx, field->embedded)) {
- return false;
- }
- } else {
- if (!type_is_specified(ctx,
- field->field.type)) {
- return false;
- }
- if (!expr_is_specified(ctx,
- field->field.initializer)) {
- return false;
- }
+ if (field->type && !type_is_specified(ctx, field->type)) {
+ return false;
+ }
+ if (!expr_is_specified(ctx, field->initializer)) {
+ return false;
}
}
if (aexpr->_struct.type.name) {
diff --git a/src/parse.c b/src/parse.c
@@ -876,47 +876,42 @@ parse_field_value(struct lexer *lexer)
xcalloc(sizeof(struct ast_field_value), 1);
char *name;
struct token tok = {0};
+ struct identifier ident = {0};
+ struct identifier *i;
switch (lex(lexer, &tok)) {
case T_NAME:
name = tok.name;
switch (lex(lexer, &tok)) {
case T_COLON:
- exp->is_embedded = false;
- exp->field.name = name;
- exp->field.type = parse_type(lexer);
+ exp->name = name;
+ exp->type = parse_type(lexer);
want(lexer, T_EQUAL, NULL);
- exp->field.initializer = parse_expression(lexer);
+ exp->initializer = parse_expression(lexer);
break;
case T_EQUAL:
- exp->is_embedded = false;
- exp->field.name = name;
- exp->field.initializer = parse_expression(lexer);
+ exp->name = name;
+ exp->initializer = parse_expression(lexer);
break;
case T_DOUBLE_COLON:
- exp->is_embedded = true;
- struct identifier ident = {0};
- struct identifier *i = &ident;
+ i = &ident;
parse_identifier(lexer, i, false);
while (i->ns != NULL) {
i = i->ns;
}
i->ns = xcalloc(sizeof(struct identifier), 1);
i->ns->name = name;
- exp->embedded = parse_struct_literal(lexer, ident);
+ exp->initializer = parse_struct_literal(lexer, ident);
break;
default:
unlex(lexer, &tok);
- exp->is_embedded = true;
ident.name = name;
ident.ns = NULL;
- exp->embedded = parse_struct_literal(lexer, ident);
+ exp->initializer = parse_struct_literal(lexer, ident);
break;
}
break;
case T_STRUCT:
- exp->is_embedded = true;
- struct identifier id = {0};
- exp->embedded = parse_struct_literal(lexer, id);
+ exp->initializer = parse_struct_literal(lexer, ident);
break;
default:
assert(0);