From b4be829c712076b399018510dc3d52181d8f1174 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 18 Aug 2021 18:14:55 +0200 Subject: [PATCH] Assert a try will unwrap. #271 --- src/compiler/parse_expr.c | 8 ++++ src/compiler/parse_stmt.c | 20 +-------- src/compiler/parser_internal.h | 1 + src/compiler/sema_stmts.c | 13 ++++-- .../errors/try_unwrap_using_assert.c3t | 43 +++++++++++++++++++ 5 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 test/test_suite/errors/try_unwrap_using_assert.c3t diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 212841377..1ed0d93dd 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -164,6 +164,14 @@ static inline Expr *parse_try_unwrap_chain(Context *context) return try_unwrap_chain; } +Expr *parse_assert_expr(Context *context) +{ + if (next_is_try_unwrap(context)) + { + return parse_try_unwrap_chain(context); + } + return parse_expr(context); +} /** * cond_list ::= ((expr | decl-expr) COMMA)* (expr | decl-expr | try_unwrap_chain | catch_unwrap ) * diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 61383c574..f2fd93016 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -832,22 +832,6 @@ static Ast *parse_volatile_stmt(Context *context) return ast; } -static inline bool is_valid_try_statement(TokenType type) -{ - switch (type) - { - case TOKEN_SWITCH: - case TOKEN_IF: - case TOKEN_FOR: - case TOKEN_WHILE: - case TOKEN_DO: - case TOKEN_RETURN: - case TOKEN_LBRACE: - return true; - default: - return false; - } -} @@ -930,10 +914,10 @@ static inline Ast *parse_assert_stmt(Context *context) Ast *ast = AST_NEW_TOKEN(AST_ASSERT_STMT, context->tok); advance_and_verify(context, TOKEN_ASSERT); TRY_CONSUME_OR(TOKEN_LPAREN, "'assert' needs a '(' here, did you forget it?", poisoned_ast); - ast->ct_assert_stmt.expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast); + ast->assert_stmt.expr = TRY_EXPR_OR(parse_assert_expr(context), poisoned_ast); if (try_consume(context, TOKEN_COMMA)) { - ast->ct_assert_stmt.message = TRY_EXPR_OR(parse_expr(context), poisoned_ast); + ast->assert_stmt.message = TRY_EXPR_OR(parse_expr(context), poisoned_ast); } TRY_CONSUME_OR(TOKEN_RPAREN, "The ending ')' was expected here.", poisoned_ast); TRY_CONSUME_EOS(); diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index b4bff8bad..5f7a724f3 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -46,6 +46,7 @@ void parse_imports(Context *context); Decl *parse_decl(Context *context); void recover_top_level(Context *context); Expr *parse_cond(Context *context); +Expr *parse_assert_expr(Context *context); Ast* parse_compound_stmt(Context *context); Ast *parse_jump_stmt_no_eos(Context *context); bool parse_attributes(Context *context, Attr ***attributes_ref); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 23a455b7d..0af5daae1 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -2204,8 +2204,8 @@ bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement) bool sema_analyse_assert_stmt(Context *context, Ast *statement) { - Expr *expr = statement->ct_assert_stmt.expr; - Expr *message = statement->ct_assert_stmt.message; + Expr *expr = statement->assert_stmt.expr; + Expr *message = statement->assert_stmt.message; if (message) { if (!sema_analyse_expr(context, type_compstr, message)) return false; @@ -2214,7 +2214,14 @@ bool sema_analyse_assert_stmt(Context *context, Ast *statement) SEMA_ERROR(message, "Expected a string as the error message."); } } - if (!sema_analyse_expr_of_required_type(context, type_bool, expr, false)) return false; + if (expr->expr_kind == EXPR_TRY_UNWRAP_CHAIN) + { + if (!sema_analyse_try_unwrap_chain(context, expr)) return false; + } + else + { + if (!sema_analyse_expr_of_required_type(context, type_bool, expr, false)) return false; + } return true; } diff --git a/test/test_suite/errors/try_unwrap_using_assert.c3t b/test/test_suite/errors/try_unwrap_using_assert.c3t new file mode 100644 index 000000000..5e220b592 --- /dev/null +++ b/test/test_suite/errors/try_unwrap_using_assert.c3t @@ -0,0 +1,43 @@ +// #target: x64-darwin +module test; + +extern func int! maybe(); + +func int tester(int n) +{ + int! num = maybe(); + assert(try num, "Hello"); + int x = num; + return num; +} + +// #expect: test.ll + +define i32 @test.tester(i32 %0) #0 { +entry: + %n = alloca i32, align 4 + %num = alloca i32, align 4 + %num.f = alloca i64, align 8 + %retparam = alloca i32, align 4 + %x = alloca i32, align 4 + store i32 %0, i32* %n, align 4 + %1 = call i64 @maybe(i32* %retparam) + %not_err = icmp eq i64 %1, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %1, i64* %num.f, align 8 + br label %after_assign + +after.errcheck: ; preds = %entry + %2 = load i32, i32* %retparam, align 4 + store i32 %2, i32* %num, align 4 + store i64 0, i64* %num.f, align 8 + br label %after_assign + +after_assign: ; preds = %after.errcheck, %error + %3 = load i32, i32* %num, align 4 + store i32 %3, i32* %x, align 4 + %4 = load i32, i32* %num, align 4 + ret i32 %4 +} \ No newline at end of file