harec

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

commit 440f489eb0b70733552aad5d2c3a4dc0421cdffc
parent 3f1e08ba7ad9bc236a8fcdf5573845dd2a35fd53
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Fri, 22 Jan 2021 12:34:22 -0500

check: implement allocations

Diffstat:
Minclude/ast.h | 8+-------
Minclude/expr.h | 24++++++++++++++++++++++++
Msrc/check.c | 69++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/eval.c | 1+
Msrc/gen.c | 3+++
Msrc/parse.c | 9++++++---
6 files changed, 103 insertions(+), 11 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -117,12 +117,6 @@ struct ast_expression_access { }; }; -enum alloc_kind { - ALLOC_KIND_ALLOC, - ALLOC_KIND_APPEND, - ALLOC_KIND_FREE, -}; - struct ast_append_values { struct ast_expression *value; struct ast_append_values *next; @@ -133,10 +127,10 @@ struct ast_expression_allocation { struct ast_expression *expr; // For allocs only struct ast_type *type; + struct ast_expression *cap; // For appends only bool variadic; struct ast_append_values *values; - struct ast_expression *cap; }; struct ast_expression_assert { diff --git a/include/expr.h b/include/expr.h @@ -9,6 +9,7 @@ struct scope_object; enum expr_type { EXPR_ACCESS, + EXPR_ALLOC, EXPR_ASSERT, EXPR_ASSIGN, EXPR_BINARITHM, @@ -52,6 +53,28 @@ struct expression_access { }; }; +enum alloc_kind { + AKIND_ALLOC, + AKIND_APPEND, + AKIND_FREE, +}; + +struct append_values { + struct expression *value; + struct append_values *next; +}; + +struct expression_alloc { + enum alloc_kind kind; + struct expression *expr; + // For allocs only + // Allocated type goes in expr->result + struct expression *cap; + // For appends only + bool variadic; + struct append_values *values; +}; + struct expression_assert { struct expression *cond; struct expression *message; @@ -238,6 +261,7 @@ struct expression { bool terminates; union { struct expression_access access; + struct expression_alloc alloc; struct expression_assert assert; struct expression_assign assign; struct expression_binarithm binarithm; diff --git a/src/check.c b/src/check.c @@ -57,7 +57,7 @@ lower_implicit_cast(const struct type *to, struct expression *expr) void check_expression(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr, - const struct type *type); + const struct type *hint); static void check_expr_access(struct context *ctx, @@ -135,6 +135,70 @@ check_expr_access(struct context *ctx, } static void +check_alloc(struct context *ctx, const struct ast_expression *aexpr, + struct expression *expr) +{ + expr->alloc.expr = xcalloc(sizeof(struct expression), 1); + expr->result = + type_store_lookup_atype(ctx->store, aexpr->alloc.type); + check_expression(ctx, aexpr->alloc.expr, expr->alloc.expr, expr->result); + enum type_storage storage = type_dealias(expr->result)->storage; + switch (storage) { + case TYPE_STORAGE_POINTER: + if (aexpr->alloc.cap != NULL) { + // We can't just expect(aexpr->alloc.cap != NULL) + // because we want to use aexpr->alloc.cap->loc + expect(&aexpr->alloc.cap->loc, false, + "Allocation with capacity must be of slice type, not %s", + type_storage_unparse(storage)); + } + break; + case TYPE_STORAGE_SLICE: + if (aexpr->alloc.cap != NULL) { + expr->alloc.cap = xcalloc(sizeof(struct expression), 1); + check_expression(ctx, aexpr->alloc.cap, expr->alloc.cap, + &builtin_type_size); + expect(&aexpr->alloc.cap->loc, + type_is_assignable(ctx->store, + &builtin_type_size, + expr->alloc.cap->result), + "Allocation capacity must be assignable to size"); + } + break; + default: + expect(&aexpr->loc, false, + "Allocation type must be pointer or slice, not %s", + type_storage_unparse(storage)); + } +} + +static void +check_expr_alloc(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr, + const struct type *hint) +{ + assert(aexpr->type == EXPR_ALLOC); + expr->type = EXPR_ALLOC; + expr->alloc.kind = aexpr->alloc.kind; + switch (expr->alloc.kind) { + case AKIND_ALLOC: + trace(TR_CHECK, "alloc"); + check_alloc(ctx, aexpr, expr); + break; + case AKIND_APPEND: + trace(TR_CHECK, "append"); + assert(0); // TODO + case AKIND_FREE: + trace(TR_CHECK, "free"); + expr->alloc.expr = xcalloc(sizeof(struct expression), 1); + check_expression(ctx, aexpr->alloc.expr, expr->alloc.expr, NULL); + expr->result = &builtin_type_void; + break; + } +} + +static void check_expr_assert(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr, @@ -1114,6 +1178,9 @@ check_expression(struct context *ctx, case EXPR_ACCESS: check_expr_access(ctx, aexpr, expr, hint); break; + case EXPR_ALLOC: + check_expr_alloc(ctx, aexpr, expr, hint); + break; case EXPR_ASSERT: check_expr_assert(ctx, aexpr, expr, hint); break; diff --git a/src/eval.c b/src/eval.c @@ -380,6 +380,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_STRUCT: case EXPR_UNARITHM: assert(0); // TODO + case EXPR_ALLOC: case EXPR_ASSERT: case EXPR_ASSIGN: case EXPR_BINDING: diff --git a/src/gen.c b/src/gen.c @@ -1596,6 +1596,9 @@ gen_expression(struct gen_context *ctx, case EXPR_ACCESS: gen_expr_access(ctx, expr, out); break; + case EXPR_ALLOC: + assert(0); // TODO + break; case EXPR_ASSERT: gen_expr_assert(ctx, expr, out); break; diff --git a/src/parse.c b/src/parse.c @@ -1159,7 +1159,8 @@ parse_allocation_expression(struct lexer *lexer) switch (lex(lexer, &tok)) { case T_ALLOC: trace(TR_PARSE, "alloc"); - exp->alloc.kind = ALLOC_KIND_ALLOC; + exp->type = EXPR_ALLOC; + exp->alloc.kind = AKIND_ALLOC; want(lexer, T_LPAREN, NULL); exp->alloc.type = parse_type(lexer); want(lexer, T_COMMA, NULL); @@ -1177,7 +1178,8 @@ parse_allocation_expression(struct lexer *lexer) break; case T_APPEND: trace(TR_PARSE, "append"); - exp->alloc.kind = ALLOC_KIND_APPEND; + exp->type = EXPR_ALLOC; + exp->alloc.kind = AKIND_APPEND; want(lexer, T_LPAREN, NULL); exp->alloc.expr = parse_simple_expression(lexer); want(lexer, T_COMMA, NULL); @@ -1204,7 +1206,8 @@ parse_allocation_expression(struct lexer *lexer) break; case T_FREE: trace(TR_PARSE, "free"); - exp->alloc.kind = ALLOC_KIND_FREE; + exp->type = EXPR_ALLOC; + exp->alloc.kind = AKIND_FREE; want(lexer, T_LPAREN, NULL); exp->alloc.expr = parse_simple_expression(lexer); want(lexer, T_RPAREN, NULL);