harec

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

commit d3e678086ae45b9297075860ec28a4a360dc7d98
parent 92bd3f55a9a6e09da69b59bffeb7ef80a74f616c
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 29 Dec 2020 12:23:01 -0500

check: implement if expressions

Diffstat:
Minclude/expr.h | 6++++++
Msrc/check.c | 41++++++++++++++++++++++++++++++++++++++++-
2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/expr.h b/include/expr.h @@ -118,6 +118,11 @@ union expression_constant { // TODO: Struct constants }; +struct expression_if { + struct expression *cond; + struct expression *true_branch, *false_branch; +}; + struct expressions { struct expression *expr; struct expressions *next; @@ -172,6 +177,7 @@ struct expression { struct expression_binding binding; struct expression_call call; union expression_constant constant; + struct expression_if _if; struct expression_list list; struct expression_measure measure; struct expression_return _return; diff --git a/src/check.c b/src/check.c @@ -355,6 +355,43 @@ check_expr_constant(struct context *ctx, } static void +check_expr_if(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "if"); + expr->type = EXPR_IF; + + struct expression *cond, *true_branch, *false_branch = NULL; + + cond = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_if.cond, cond); + + true_branch = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_if.true_branch, true_branch); + + if (aexpr->_if.false_branch) { + false_branch = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_if.false_branch, false_branch); + + // TODO: Tagged unions: + assert(true_branch->result == false_branch->result); + expr->result = true_branch->result; + } else { + expr->result = &builtin_type_void; + } + + expect(cond->result->storage == TYPE_STORAGE_BOOL, + "Expected if condition to be boolean"); + + expr->_if.cond = cond; + expr->_if.true_branch = true_branch; + expr->_if.false_branch = false_branch; + + trleave(TR_CHECK, NULL); +} + +static void check_expr_list(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -524,8 +561,10 @@ check_expression(struct context *ctx, break; case EXPR_CONTINUE: case EXPR_FOR: - case EXPR_IF: assert(0); // TODO + case EXPR_IF: + check_expr_if(ctx, aexpr, expr); + break; case EXPR_LIST: check_expr_list(ctx, aexpr, expr); break;