commit 4ae764e204cb7d63f5653583c4823b7fd265032b
parent 000a268c4c1e348e613dec9545bb52cb64c9ab67
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 20 Jan 2021 09:46:49 -0500
check: implement defer
Diffstat:
5 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -210,7 +210,7 @@ struct ast_expression_control {
};
struct ast_expression_defer {
- struct ast_expression *expression;
+ struct ast_expression *deferred;
};
struct ast_expression_for {
diff --git a/include/check.h b/include/check.h
@@ -14,6 +14,7 @@ struct context {
struct identifier *ns;
struct scope *unit;
struct scope *scope;
+ bool deferring;
int id;
};
diff --git a/include/expr.h b/include/expr.h
@@ -144,6 +144,10 @@ struct expression_control {
char *label;
};
+struct expression_defer {
+ struct expression *deferred;
+};
+
struct expression_for {
char *label;
struct scope *scope;
@@ -241,6 +245,7 @@ struct expression {
struct expression_call call;
struct expression_cast cast;
union expression_constant constant;
+ struct expression_defer defer;
struct expression_control control;
struct expression_for _for;
struct expression_if _if;
diff --git a/src/check.c b/src/check.c
@@ -607,6 +607,22 @@ check_expr_constant(struct context *ctx,
}
static void
+check_expr_defer(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr,
+ const struct type *hint)
+{
+ expect(&aexpr->loc, !ctx->deferring,
+ "Cannot defer within another defer expression.");
+ expr->type = EXPR_DEFER;
+ expr->result = &builtin_type_void;
+ expr->defer.deferred = xcalloc(1, sizeof(struct expression));
+ ctx->deferring = true;
+ check_expression(ctx, aexpr->defer.deferred, expr->defer.deferred, NULL);
+ ctx->deferring = false;
+}
+
+static void
check_expr_control(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr,
@@ -1123,7 +1139,8 @@ check_expression(struct context *ctx,
check_expr_constant(ctx, aexpr, expr, hint);
break;
case EXPR_DEFER:
- assert(0);
+ check_expr_defer(ctx, aexpr, expr, hint);
+ break;
case EXPR_FOR:
check_expr_for(ctx, aexpr, expr, hint);
break;
diff --git a/src/parse.c b/src/parse.c
@@ -1045,7 +1045,7 @@ parse_defer_expression(struct lexer *lexer)
struct ast_expression *exp = mkexpr(&lexer->loc);
want(lexer, T_DEFER, NULL);
exp->type = EXPR_DEFER;
- exp->defer.expression = parse_scope_expression(lexer);
+ exp->defer.deferred = parse_scope_expression(lexer);
return exp;
}