Assert a try will unwrap. #271

This commit is contained in:
Christoffer Lerno
2021-08-18 18:14:55 +02:00
committed by Christoffer Lerno
parent f180a0d44a
commit b4be829c71
5 changed files with 64 additions and 21 deletions

View File

@@ -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 )
*

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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
}