harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit c944388851200927212f4f113b53132881cbf3a9
parent 644e974b9969d2d0065bbf4ac6f2227db1f3f783
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 10 Jan 2021 09:44:45 -0500

check: basic struct expression implementation

Missing a few things:
- Named struct types
	-> Out-of-order initialization
	-> Testing for exhaustive initialization
	-> Autofill
- Embedded structs

Diffstat:
Minclude/expr.h | 7+++++++
Minclude/types.h | 2++
Msrc/check.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/type_store.c | 2++
Msrc/types.c | 18++++++++++++++++++
5 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -177,6 +177,12 @@ struct expression_return { struct expression *value; }; +struct expression_struct { + const struct type_struct_union *field; + struct expression *value; + struct expression_struct *next; +}; + enum unarithm_operator { UN_ADDRESS, // & UN_BNOT, // ~ @@ -209,6 +215,7 @@ struct expression { struct expression_list list; struct expression_measure measure; struct expression_return _return; + struct expression_struct _struct; struct expression_unarithm unarithm; }; }; diff --git a/include/types.h b/include/types.h @@ -104,6 +104,8 @@ struct type { }; const struct type *type_dereference(const struct type *type); +const struct type_struct_union *type_lookup_field( + const struct type *type, const char *name); const char *type_storage_unparse(enum type_storage storage); bool type_is_signed(const struct type *type); diff --git a/src/check.c b/src/check.c @@ -643,6 +643,70 @@ check_expr_return(struct context *ctx, } static void +check_expr_struct(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "struct"); + assert(!aexpr->_struct.autofill); // TODO + assert(!aexpr->_struct.type.name); // TODO + expr->type = EXPR_STRUCT; + + struct ast_type stype = { + .storage = TYPE_STORAGE_STRUCT, + .flags = TYPE_CONST, + }; + struct ast_struct_union_type *tfield = &stype.struct_union; + struct ast_struct_union_type **tnext = &tfield->next; + struct expression_struct *sexpr = &expr->_struct; + struct expression_struct **snext = &sexpr->next; + + struct ast_field_value *afield = aexpr->_struct.fields; + while (afield) { + assert(!afield->is_embedded); // TODO + + tfield->member_type = MEMBER_TYPE_FIELD; + tfield->field.name = afield->field.name; + tfield->field.type = afield->field.type; + sexpr->value = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, afield->field.initializer, sexpr->value); + + if (afield->next) { + *tnext = tfield = xcalloc( + 1, sizeof(struct ast_struct_union_type)); + tnext = &tfield->next; + *snext = sexpr = xcalloc( + 1, sizeof(struct expression_struct)); + snext = &sexpr->next; + } + + afield = afield->next; + } + + expr->result = type_store_lookup_atype(&ctx->store, &stype); + + tfield = stype.struct_union.next; + sexpr = &expr->_struct; + while (tfield) { + const struct type_struct_union *field = type_lookup_field( + expr->result, tfield->field.name); + // TODO: Use more specific error location + expect(&aexpr->loc, + type_is_assignable(&ctx->store, field->type, sexpr->value->result), + "Cannot initialize struct field from value of this type"); + sexpr->field = field; + sexpr->value = lower_implicit_cast(field->type, sexpr->value); + + struct ast_struct_union_type *next = tfield->next; + free(tfield); + tfield = next; + sexpr = sexpr->next; + } + + trleave(TR_CHECK, NULL); +} + +static void check_expr_unarithm(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -753,7 +817,10 @@ check_expression(struct context *ctx, check_expr_return(ctx, aexpr, expr); break; case EXPR_SLICE: + assert(0); // TODO case EXPR_STRUCT: + check_expr_struct(ctx, aexpr, expr); + break; case EXPR_SWITCH: assert(0); // TODO case EXPR_UNARITHM: diff --git a/src/type_store.c b/src/type_store.c @@ -646,6 +646,8 @@ type_init_from_type(struct type_store *store, type_store_lookup_type(store, ofield->type); field->offset = ofield->offset; } + new->size = old->size; + new->align = old->align; break; case TYPE_STORAGE_TAGGED_UNION: assert(0); // TODO diff --git a/src/types.c b/src/types.c @@ -1,5 +1,6 @@ #include <assert.h> #include <stdbool.h> +#include <string.h> #include "types.h" const struct type * @@ -11,6 +12,23 @@ type_dereference(const struct type *type) return type_dereference(type->pointer.referent); } +const struct type_struct_union * +type_lookup_field(const struct type *type, const char *name) +{ + // TODO: We should consider lowering unions into structs with explicit + // offsets + assert(type->storage == TYPE_STORAGE_STRUCT + || type->storage == TYPE_STORAGE_UNION); + struct type_struct_union *typesu = type->struct_union; + while (typesu) { + if (strcmp(typesu->name, name) == 0) { + return typesu; + } + typesu = typesu->next; + } + return NULL; +} + const char * type_storage_unparse(enum type_storage storage) {