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:
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: