harec

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

commit f35adac4f375b7151ac10cf34f6dbaeacf12a958
parent 4e9d60660d0f026bbb29a9339d29662e1eb5e24f
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Wed,  3 Feb 2021 18:40:37 -0500

Refactor append and free out of EXPR_ALLOC

Diffstat:
Minclude/ast.h | 25++++++++++++++++---------
Minclude/expr.h | 26++++++++++++++------------
Msrc/check.c | 53++++++++++++++++++++++++++++++++---------------------
Msrc/dump.c | 6++++++
Msrc/eval.c | 2++
Msrc/gen.c | 69+++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/parse.c | 23+++++++++++------------
7 files changed, 118 insertions(+), 86 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -118,19 +118,20 @@ struct ast_expression_access { }; }; +struct ast_expression_alloc { + struct ast_expression *expr; + struct ast_type *type; + struct ast_expression *cap; +}; + struct ast_append_values { - struct ast_expression *value; + struct ast_expression *expr; struct ast_append_values *next; }; -struct ast_expression_allocation { - enum alloc_kind kind; +struct ast_expression_append { struct ast_expression *expr; - // For allocs only - struct ast_type *type; - struct ast_expression *cap; - // For appends only - bool variadic; + struct ast_expression *variadic; struct ast_append_values *values; }; @@ -215,6 +216,10 @@ struct ast_expression_for { struct ast_expression *body; }; +struct ast_expression_free { + struct ast_expression *expr; +}; + struct ast_expression_if { struct ast_expression *cond; struct ast_expression *true_branch, *false_branch; @@ -302,7 +307,8 @@ struct ast_expression { enum expr_type type; union { struct ast_expression_access access; - struct ast_expression_allocation alloc; + struct ast_expression_alloc alloc; + struct ast_expression_append append; struct ast_expression_assert assert; struct ast_expression_assign assign; struct ast_expression_binarithm binarithm; @@ -313,6 +319,7 @@ struct ast_expression { struct ast_expression_control control; struct ast_expression_defer defer; struct ast_expression_for _for; + struct ast_expression_free free; struct ast_expression_if _if; struct ast_expression_list list; struct ast_expression_match match; diff --git a/include/expr.h b/include/expr.h @@ -10,6 +10,7 @@ struct scope_object; enum expr_type { EXPR_ACCESS, EXPR_ALLOC, + EXPR_APPEND, EXPR_ASSERT, EXPR_ASSIGN, EXPR_BINARITHM, @@ -21,6 +22,7 @@ enum expr_type { EXPR_CONTINUE, EXPR_DEFER, EXPR_FOR, + EXPR_FREE, EXPR_IF, EXPR_LIST, EXPR_MATCH, @@ -53,25 +55,19 @@ struct expression_access { }; }; -enum alloc_kind { - AKIND_ALLOC, - AKIND_APPEND, - AKIND_FREE, +struct expression_alloc { + struct expression *expr; + struct expression *cap; }; struct append_values { - struct expression *value; + struct expression *expr; struct append_values *next; }; -struct expression_alloc { - enum alloc_kind kind; +struct expression_append { struct expression *expr; - // For allocs only - // Allocated type goes in expr->result - struct expression *cap; - // For appends only - bool variadic; + struct expression *variadic; struct append_values *values; }; @@ -187,6 +183,10 @@ struct expression_for { struct expression *body; }; +struct expression_free { + struct expression *expr; +}; + struct expression_if { struct expression *cond; struct expression *true_branch, *false_branch; @@ -286,6 +286,7 @@ struct expression { union { struct expression_access access; struct expression_alloc alloc; + struct expression_append append; struct expression_assert assert; struct expression_assign assign; struct expression_binarithm binarithm; @@ -296,6 +297,7 @@ struct expression { struct expression_defer defer; struct expression_control control; struct expression_for _for; + struct expression_free free; struct expression_if _if; struct expression_list list; struct expression_match match; diff --git a/src/check.c b/src/check.c @@ -150,9 +150,14 @@ check_expr_access(struct context *ctx, } static void -check_alloc(struct context *ctx, const struct ast_expression *aexpr, - struct expression *expr) +check_expr_alloc(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr, + const struct type *hint) { + assert(aexpr->type == EXPR_ALLOC); + trace(TR_CHECK, "alloc"); + expr->type = EXPR_ALLOC; expr->alloc.expr = xcalloc(sizeof(struct expression), 1); expr->result = type_store_lookup_atype(ctx->store, aexpr->alloc.type); @@ -187,29 +192,15 @@ check_alloc(struct context *ctx, const struct ast_expression *aexpr, } static void -check_expr_alloc(struct context *ctx, +check_expr_append(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; - } + assert(aexpr->type == EXPR_APPEND); + trace(TR_CHECK, "append"); + expr->type = EXPR_APPEND; + assert(0); // TODO } static void @@ -869,6 +860,20 @@ check_expr_for(struct context *ctx, } static void +check_expr_free(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr, + const struct type *hint) +{ + assert(aexpr->type == EXPR_FREE); + expr->type = EXPR_FREE; + trace(TR_CHECK, "free"); + expr->free.expr = xcalloc(sizeof(struct expression), 1); + check_expression(ctx, aexpr->free.expr, expr->free.expr, NULL); + expr->result = &builtin_type_void; +} + +static void check_expr_if(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr, @@ -1480,6 +1485,9 @@ check_expression(struct context *ctx, case EXPR_ALLOC: check_expr_alloc(ctx, aexpr, expr, hint); break; + case EXPR_APPEND: + check_expr_append(ctx, aexpr, expr, hint); + break; case EXPR_ASSERT: check_expr_assert(ctx, aexpr, expr, hint); break; @@ -1511,6 +1519,9 @@ check_expression(struct context *ctx, case EXPR_FOR: check_expr_for(ctx, aexpr, expr, hint); break; + case EXPR_FREE: + check_expr_free(ctx, aexpr, expr, hint); + break; case EXPR_IF: check_expr_if(ctx, aexpr, expr, hint); break; diff --git a/src/dump.c b/src/dump.c @@ -262,6 +262,9 @@ dump_expr(const struct expression *expr, int depth) case EXPR_ALLOC: fprintf(stderr, "alloc"); break; + case EXPR_APPEND: + fprintf(stderr, "append"); + break; case EXPR_ASSERT: fprintf(stderr, "assert"); break; @@ -331,6 +334,9 @@ dump_expr(const struct expression *expr, int depth) case EXPR_FOR: fprintf(stderr, "for"); break; + case EXPR_FREE: + fprintf(stderr, "free"); + break; case EXPR_IF: fprintf(stderr, "if"); break; diff --git a/src/eval.c b/src/eval.c @@ -509,6 +509,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_UNARITHM: assert(0); // TODO case EXPR_ALLOC: + case EXPR_APPEND: case EXPR_ASSERT: case EXPR_ASSIGN: case EXPR_BINDING: @@ -517,6 +518,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_CALL: case EXPR_DEFER: case EXPR_FOR: + case EXPR_FREE: case EXPR_IF: case EXPR_LIST: case EXPR_MATCH: diff --git a/src/gen.c b/src/gen.c @@ -495,11 +495,11 @@ gen_slice_alloc(struct gen_context *ctx, } static void -gen_alloc(struct gen_context *ctx, +gen_expr_alloc(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) { - assert(expr->type == EXPR_ALLOC && expr->alloc.kind == AKIND_ALLOC); + assert(expr->type == EXPR_ALLOC); if (type_dealias(expr->result)->storage == TYPE_STORAGE_SLICE) { gen_slice_alloc(ctx, expr, out); return; @@ -557,39 +557,12 @@ gen_alloc(struct gen_context *ctx, } static void -gen_expr_alloc(struct gen_context *ctx, +gen_expr_append(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) { - assert(expr->type == EXPR_ALLOC); - struct qbe_value val = {0}, rtfunc = {0}; - const struct type *type = type_dealias(expr->alloc.expr->result); - switch (expr->alloc.kind) { - case AKIND_ALLOC: - gen_alloc(ctx, expr, out); - break; - case AKIND_APPEND: - assert(0); // TODO - case AKIND_FREE: - if (type->storage == TYPE_STORAGE_SLICE - || type->storage == TYPE_STORAGE_STRING) { - alloc_temp(ctx, &val, type, "free.%d"); - val.type = &qbe_long; - gen_expression(ctx, expr->alloc.expr, &val); - val.type = &qbe_long; - pushi(ctx->current, &val, Q_LOADL, &val, NULL); - } else { - gen_temp(ctx, &val, - qtype_for_type(ctx, expr->alloc.expr->result, false), - "free.%d"); - gen_expression(ctx, expr->alloc.expr, &val); - } - rtfunc.kind = QV_GLOBAL; - rtfunc.name = strdup("rt.free"); - rtfunc.type = &qbe_long; - pushi(ctx->current, NULL, Q_CALL, &rtfunc, &val, NULL); - break; - } + assert(expr->type == EXPR_APPEND); + assert(0); // TODO } static void @@ -1444,6 +1417,32 @@ gen_expr_for(struct gen_context *ctx, } static void +gen_expr_free(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out) +{ + struct qbe_value val = {0}, rtfunc = {0}; + const struct type *type = type_dealias(expr->alloc.expr->result); + if (type->storage == TYPE_STORAGE_SLICE + || type->storage == TYPE_STORAGE_STRING) { + alloc_temp(ctx, &val, type, "free.%d"); + val.type = &qbe_long; + gen_expression(ctx, expr->alloc.expr, &val); + val.type = &qbe_long; + pushi(ctx->current, &val, Q_LOADL, &val, NULL); + } else { + gen_temp(ctx, &val, + qtype_for_type(ctx, expr->alloc.expr->result, false), + "free.%d"); + gen_expression(ctx, expr->alloc.expr, &val); + } + rtfunc.kind = QV_GLOBAL; + rtfunc.name = strdup("rt.free"); + rtfunc.type = &qbe_long; + pushi(ctx->current, NULL, Q_CALL, &rtfunc, &val, NULL); +} + +static void gen_expr_if(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -2087,6 +2086,9 @@ gen_expression(struct gen_context *ctx, case EXPR_ALLOC: gen_expr_alloc(ctx, expr, out); break; + case EXPR_APPEND: + gen_expr_append(ctx, expr, out); + break; case EXPR_ASSERT: gen_expr_assert(ctx, expr, out); break; @@ -2118,6 +2120,9 @@ gen_expression(struct gen_context *ctx, case EXPR_FOR: gen_expr_for(ctx, expr, out); break; + case EXPR_FREE: + gen_expr_free(ctx, expr, out); + break; case EXPR_IF: gen_expr_if(ctx, expr, out); break; diff --git a/src/parse.c b/src/parse.c @@ -1178,7 +1178,6 @@ parse_allocation_expression(struct lexer *lexer) case T_ALLOC: trace(TR_PARSE, "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); @@ -1196,25 +1195,26 @@ parse_allocation_expression(struct lexer *lexer) break; case T_APPEND: trace(TR_PARSE, "append"); - exp->type = EXPR_ALLOC; - exp->alloc.kind = AKIND_APPEND; + exp->type = EXPR_APPEND; want(lexer, T_LPAREN, NULL); - exp->alloc.expr = parse_simple_expression(lexer); + // Easier to parse a simple-expression and let check limit it to + // object-selector/*unary-expression + exp->append.expr = parse_simple_expression(lexer); want(lexer, T_COMMA, NULL); - struct ast_append_values **next = &exp->alloc.values; + struct ast_append_values **next = &exp->append.values; while (tok.token != T_RPAREN) { - *next = xcalloc(1, sizeof(struct ast_append_values)); if (lex(lexer, &tok) == T_ELLIPSIS) { - exp->alloc.variadic = true; - (*next)->value = parse_simple_expression(lexer); + exp->append.variadic = + parse_simple_expression(lexer); if (lex(lexer, &tok) != T_COMMA) { unlex(lexer, &tok); } want(lexer, T_RPAREN, &tok); break; } + *next = xcalloc(1, sizeof(struct ast_append_values)); unlex(lexer, &tok); - (*next)->value = parse_simple_expression(lexer); + (*next)->expr = parse_simple_expression(lexer); if (lex(lexer, &tok) != T_COMMA) { unlex(lexer, &tok); want(lexer, T_RPAREN, &tok); @@ -1224,10 +1224,9 @@ parse_allocation_expression(struct lexer *lexer) break; case T_FREE: trace(TR_PARSE, "free"); - exp->type = EXPR_ALLOC; - exp->alloc.kind = AKIND_FREE; + exp->type = EXPR_FREE; want(lexer, T_LPAREN, NULL); - exp->alloc.expr = parse_simple_expression(lexer); + exp->free.expr = parse_simple_expression(lexer); want(lexer, T_RPAREN, NULL); break; default: