harec

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

commit 8978c6eae3accde2f7fc75204a9e18958e12c360
parent e6e8f8824d2d9eb8388e5580ae630c1bcadac90e
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 12 Jan 2021 12:02:07 -0500

Implement logical AND and logical OR

Diffstat:
Msrc/gen.c | 29+++++++++++++++++++++++++++++
Atests/10-binarithms.ha | 35+++++++++++++++++++++++++++++++++++
Mtests/configure | 3++-
3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/src/gen.c b/src/gen.c @@ -527,6 +527,35 @@ gen_expr_binarithm(struct gen_context *ctx, const struct qbe_type *etype = qtype_for_type(ctx, expr->result, false); assert(ltype == rtype); // TODO: Type promotion + if (expr->binarithm.op == BIN_LAND || expr->binarithm.op == BIN_LOR) { + struct qbe_statement rlabel = {0}, slabel = {0}; + struct qbe_value rbranch = {0}, sbranch = {0}, result = {0}; + rbranch.kind = QV_LABEL; + rbranch.name = strdup(genl(&rlabel, &ctx->id, "rvalue.%d")); + sbranch.kind = QV_LABEL; + sbranch.name = strdup(genl(&slabel, &ctx->id, "short_circuit.%d")); + gen_temp(ctx, &result, etype, "result.%d"); + + gen_expression(ctx, expr->binarithm.lvalue, &result); + if (expr->binarithm.op == BIN_LAND) { + pushi(ctx->current, NULL, Q_JNZ, &result, &rbranch, + &sbranch, NULL); + } else { + pushi(ctx->current, NULL, Q_JNZ, &result, &sbranch, + &rbranch, NULL); + } + + push(&ctx->current->body, &rlabel); + gen_expression(ctx, expr->binarithm.rvalue, &result); + if (!expr->binarithm.rvalue->terminates) { + pushi(ctx->current, NULL, Q_JMP, &sbranch, NULL); + } + + push(&ctx->current->body, &slabel); + gen_store(ctx, out, &result); + return; + } + struct qbe_value lvalue = {0}, rvalue = {0}, result = {0}; gen_temp(ctx, &lvalue, ltype, "lvalue.%d"); gen_temp(ctx, &rvalue, rtype, "rvalue.%d"); diff --git a/tests/10-binarithms.ha b/tests/10-binarithms.ha @@ -0,0 +1,35 @@ + +fn error() bool = { + abort(); + return false; +}; + +fn set(x: *int) bool = { + *x = 42; + return true; +}; + +fn andor() void = { + assert((false || false) == false); + assert((false || true) == true); + assert((true || false) == true); + assert((true || true) == true); + assert((true || error()) == true); + let x = 0; + assert((false || set(&x)) == true); + assert(x == 42); + + assert((false && false) == false); + assert((false && true) == false); + assert((true && false) == false); + assert((true && true) == true); + assert((false && error()) == false); + x = 0; + assert((true && set(&x)) == true); + assert(x == 42); +}; + +export fn main() void = { + // TODO: other binarithms + andor(); +}; diff --git a/tests/configure b/tests/configure @@ -12,7 +12,8 @@ tests() { 06-structs \ 07-aliases \ 08-slices \ - 09-funcs + 09-funcs \ + 10-binarithms do cat <<EOF tests/$t: libhart.a tests/$t.ha