harec

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

commit 028fd82fb5d9f1bcf9fb7eef42d651bd6906cd8a
parent 8796dcfafea729c7aa2f1f05975a8cc28d66768e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 23 Jan 2021 16:41:35 -0500

Add match test

Diffstat:
Msrc/check.c | 29+++++++++++++++--------------
Msrc/gen.c | 7++++---
Atests/18-match.ha | 37+++++++++++++++++++++++++++++++++++++
Mtests/configure | 3++-
4 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -887,34 +887,34 @@ check_expr_match(struct context *ctx, _case = *next = xcalloc(1, sizeof(struct match_case)); next = &_case->next; - const struct type *ctype = type_store_lookup_atype( - ctx->store, acase->type); + const struct type *ctype = NULL; + if (acase->type) { + ctype = type_store_lookup_atype(ctx->store, acase->type); - // TODO: Figure out alias semantics properly - if (is_ptr) { + // TODO: Figure out alias semantics properly switch (ctype->storage) { case TYPE_STORAGE_POINTER: + expect(&acase->type->loc, is_ptr, + "Not matching on pointer type"); expect(&acase->type->loc, type->pointer.referent == ctype->pointer.referent, "Match case of incompatible pointer type"); break; case TYPE_STORAGE_NULL: - // No additional tests required + expect(&acase->type->loc, is_ptr, + "Not matching on pointer type"); break; - default: - expect(&acase->type->loc, false, - "Invalid type for match case"); - break; - } - } else { - bool valid = false; - switch (ctype->storage) { case TYPE_STORAGE_TAGGED_UNION: + expect(&acase->type->loc, !is_ptr, + "Not matching on tagged union type"); expect(&acase->type->loc, type_is_assignable( ctx->store, type, ctype), "Invalid type for match case"); break; default: + expect(&acase->type->loc, !is_ptr, + "Not matching on tagged union type"); + bool valid = false; for (const struct type_tagged_union *tu = &type->tagged; tu; tu = tu->next) { if (tu->type == ctype) { @@ -929,6 +929,7 @@ check_expr_match(struct context *ctx, } if (acase->name) { + assert(ctype); struct identifier ident = { .name = acase->name, }; @@ -940,7 +941,7 @@ check_expr_match(struct context *ctx, _case->value = xcalloc(1, sizeof(struct expression)); _case->type = ctype; - check_expression(ctx, acase->value, _case->value, type); + check_expression(ctx, acase->value, _case->value, NULL); if (acase->name) { scope_pop(&ctx->scope, TR_CHECK); diff --git a/src/gen.c b/src/gen.c @@ -1397,10 +1397,11 @@ gen_expr_match(struct gen_context *ctx, const struct type *mtype = expr->match.value->result; struct qbe_value mval = {0}, tag = {0}, match = {0}, temp = {0}; - gen_temp(ctx, &mval, qtype_for_type(ctx, mtype, false), "match.%d"); - gen_temp(ctx, &temp, &qbe_word, "temp.%d"); - qval_address(&mval); + // Kill me + alloc_temp(ctx, &mval, mtype, "match.%d"); + qval_deref(&mval); gen_expression(ctx, expr->match.value, &mval); + gen_temp(ctx, &temp, &qbe_word, "temp.%d"); gen_temp(ctx, &tag, &qbe_word, "tag.%d"); pushi(ctx->current, &tag, Q_LOADUW, &mval, NULL); diff --git a/tests/18-match.ha b/tests/18-match.ha @@ -0,0 +1,37 @@ +fn tagged() void = { + let cases: [](int | uint | str) = [10, 10u, "hello"]; + let expected = [1z, 2z, 5z]; + for (let i = 0z; i < len(cases); i += 1z) { + let y: size = match (cases[i]) { + int => 1z, + uint => 2z, + s: str => len(s), + }; + assert(y == expected[i]); + }; +}; + +fn termination() void = { + let x: (int | uint | str) = 1337; + let y: int = match (x) { + int => 42, + uint => abort(), + str => abort(), + }; + assert(y == 42); +}; + +fn default() void = { + let x: (int | uint | str) = 1337u; + let y: int = match (x) { + int => 42, + * => 24, + }; + assert(y == 24); +}; + +export fn main() void = { + tagged(); + termination(); + default(); +}; diff --git a/tests/configure b/tests/configure @@ -20,7 +20,8 @@ tests() { 14-switch \ 15-enums \ 16-defer \ - 17-alloc + 17-alloc \ + 18-match do cat <<EOF tests/$t: libhart.a tests/$t.ha