harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

commit fe4556d224d5b26a65843dcc9fe1cd9ac98785a1
parent 6c11668244aa2a3ce4288c24c626ca2225df0156
Author: Sebastian <sebastian@sebsite.pw>
Date:   Wed, 11 Jan 2023 18:25:51 -0500

check: fix type reduction when yielding without value

Previously, using `yield` without a value didn't correctly add a `void`
expression to the list of yields for a scope. So, for instance, code
like this would incorrectly compile:

	let x: int = {
		if (true) yield 0;
		yield;
	};

If the above `yield` was changed to a `yield void` this would correctly
not compile. This has been fixed, by adding a `void` value to a yield
without a value during check.

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Msrc/check.c | 29++++++++++++++++++-----------
Mtests/30-reduction.c | 5+++++
2 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -1878,22 +1878,29 @@ check_expr_control(struct context *ctx, } expr->control.scope = scope; + if (expr->type != EXPR_YIELD) { + return; + } + + expr->control.value = xcalloc(1, sizeof(struct expression)); if (aexpr->control.value) { - expr->control.value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->control.value, expr->control.value, scope->hint); + } else { + expr->control.value->type = EXPR_CONSTANT; + expr->control.value->result = &builtin_type_void; + } - struct type_tagged_union *result = - xcalloc(1, sizeof(struct type_tagged_union)); - result->type = expr->control.value->result; - result->next = scope->results; - scope->results = result; + struct type_tagged_union *result = + xcalloc(1, sizeof(struct type_tagged_union)); + result->type = expr->control.value->result; + result->next = scope->results; + scope->results = result; - struct yield *yield = xcalloc(1, sizeof(struct yield)); - yield->expression = &expr->control.value; - yield->next = scope->yields; - scope->yields = yield; - } + struct yield *yield = xcalloc(1, sizeof(struct yield)); + yield->expression = &expr->control.value; + yield->next = scope->yields; + scope->yields = yield; } static void diff --git a/tests/30-reduction.c b/tests/30-reduction.c @@ -128,6 +128,11 @@ int main(void) { "if (true) null: *int " "else if (true) null: const nullable *int " "else null: nullable *int"); + test(&ctx, "(int | void)", + "{ " + "if (true) yield; " + "yield 0; " + "}"); test(&ctx, "", "if (true) null "