harec

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

commit 1dbd863cdf45ce1568ed935ff5289a1d03fa0edf
parent cd1031f472022d176d8a00ec00ab6b0d68db2ed7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 13 Jan 2021 10:16:48 -0500

check: implement slicing expressions

Diffstat:
Minclude/expr.h | 6++++++
Msrc/check.c | 51++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/type_store.c | 3++-
3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -185,6 +185,11 @@ struct expression_return { struct expression *value; }; +struct expression_slice { + struct expression *object; + struct expression *start, *end; +}; + struct expression_struct { const struct struct_field *field; struct expression *value; @@ -225,6 +230,7 @@ struct expression { struct expression_measure measure; struct expression_return _return; struct expression_struct _struct; + struct expression_slice slice; struct expression_unarithm unarithm; }; }; diff --git a/src/check.c b/src/check.c @@ -761,6 +761,54 @@ check_expr_return(struct context *ctx, } static void +check_expr_slice(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "slice"); + expr->type = EXPR_SLICE; + + expr->slice.object = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->slice.object, expr->slice.object); + const struct type *atype = + type_dereference(expr->slice.object->result); + expect(&aexpr->slice.object->loc, atype, + "Cannot dereference nullable pointer for slicing"); + expect(&aexpr->slice.object->loc, + expr->slice.object->result->storage == TYPE_STORAGE_SLICE || + expr->slice.object->result->storage == TYPE_STORAGE_ARRAY, + "Cannot slice non-array, non-slice object"); + + const struct type *itype; + if (aexpr->slice.start) { + expr->slice.start = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->slice.start, expr->slice.start); + itype = type_dealias(expr->slice.start->result); + expect(&aexpr->slice.start->loc, type_is_integer(itype), + "Cannot use non-integer %s type as slicing operand", + type_storage_unparse(itype->storage)); + expr->slice.start = lower_implicit_cast( + &builtin_type_size, expr->slice.start); + } + + if (aexpr->slice.end) { + expr->slice.end = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->slice.end, expr->slice.end); + itype = type_dealias(expr->slice.end->result); + expect(&aexpr->slice.end->loc, type_is_integer(itype), + "Cannot use non-integer %s type as slicing operand", + type_storage_unparse(itype->storage)); + expr->slice.end = lower_implicit_cast( + &builtin_type_size, expr->slice.end); + } + + expr->result = type_store_lookup_slice(&ctx->store, + expr->slice.object->result->array.members); + + trleave(TR_CHECK, NULL); +} + +static void check_expr_struct(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -938,7 +986,8 @@ check_expression(struct context *ctx, check_expr_return(ctx, aexpr, expr); break; case EXPR_SLICE: - assert(0); // TODO + check_expr_slice(ctx, aexpr, expr); + break; case EXPR_STRUCT: check_expr_struct(ctx, aexpr, expr); break; diff --git a/src/type_store.c b/src/type_store.c @@ -136,7 +136,8 @@ type_is_assignable(struct type_store *store, to->array.members, to->array.members->flags & ~TYPE_CONST); from_secondary = type_store_lookup_with_flags(store, from->array.members, from->array.members->flags & ~TYPE_CONST); - return from->storage == TYPE_STORAGE_ARRAY + return (from->storage == TYPE_STORAGE_ARRAY + || from->storage == TYPE_STORAGE_SLICE) && to_secondary == from_secondary; case TYPE_STORAGE_ARRAY: return to->array.length == SIZE_UNDEFINED