harec

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

commit fa2b3a43dd98f64d34ec4024aab48dad84798a14
parent cf8f62f69138171d5983ab35ddf2bd6dda989fa9
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sun, 31 Jan 2021 17:58:51 -0500

Implement static assertions

Diffstat:
Msrc/check.c | 23+++++++++++++++++++++++
Msrc/gen.c | 3+++
Msrc/parse.c | 9++-------
3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -211,6 +211,7 @@ check_expr_assert(struct context *ctx, trace(TR_CHECK, "assert"); expr->type = EXPR_ASSERT; expr->result = &builtin_type_void; + expr->assert.is_static = aexpr->assert.is_static; if (aexpr->assert.cond != NULL) { expr->assert.cond = xcalloc(1, sizeof(struct expression)); @@ -242,6 +243,28 @@ check_expr_assert(struct context *ctx, expr->assert.message->constant.string.value = s; expr->assert.message->constant.string.len = n; } + + if (expr->assert.is_static) { + bool cond; + if (expr->assert.cond != NULL) { + struct expression out = {0}; + enum eval_result r = + eval_expr(ctx, expr->assert.cond, &out); + expect(&aexpr->assert.cond->loc, r == EVAL_OK, + "Unable to evaluate static assertion at compile time"); + assert(out.result->storage == TYPE_STORAGE_BOOL); + cond = out.constant.bval; + } else { + cond = false; + } + if (aexpr->assert.message != NULL) { + expect(&aexpr->assert.cond->loc, cond, + "Static assertion failed: %s", + expr->assert.message->constant.string.value); + } else { + expect(&aexpr->loc, cond, "Static assertion failed"); + } + } } static void diff --git a/src/gen.c b/src/gen.c @@ -644,6 +644,9 @@ gen_expr_assert(struct gen_context *ctx, const struct qbe_value *out) { assert(expr->assert.message); // Invariant + if (expr->assert.is_static) { + return; + } struct qbe_statement failedl = {0}, passedl = {0}; struct qbe_value bfailed = {0}, bpassed = {0}; diff --git a/src/parse.c b/src/parse.c @@ -983,7 +983,7 @@ parse_plain_expression(struct lexer *lexer) static struct ast_expression * parse_assertion_expression(struct lexer *lexer, bool is_static) { - trace(TR_PARSE, "assertion"); + trace(TR_PARSE, is_static ? "static assertion" : "assertion"); struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_ASSERT; @@ -991,16 +991,11 @@ parse_assertion_expression(struct lexer *lexer, bool is_static) struct token tok; switch (lex(lexer, &tok)) { - case T_STATIC: - // XXX: The caller should deal with this for us - exp->assert.is_static = true; - lex(lexer, &tok); - break; case T_ASSERT: case T_ABORT: break; default: - synassert(false, &tok, T_STATIC, T_ASSERT, T_ABORT, T_EOF); + synassert(false, &tok, T_ASSERT, T_ABORT, T_EOF); } switch (tok.token) {