From ec2ca38adb9212e2f305f981a865d827065446d7 Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 9 Sep 2022 02:24:16 +0800 Subject: [PATCH] checker, cgen: fix match expr with result (#15706) --- vlib/v/checker/match.v | 1 + vlib/v/gen/c/cgen.v | 31 ++++++++++++++++++++-- vlib/v/gen/c/match.v | 20 +++++++++----- vlib/v/tests/match_expr_with_result_test.v | 23 ++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/match_expr_with_result_test.v diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index 1125f3afe9..c0ec9d708d 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -61,6 +61,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { expr_type := c.expr(stmt.expr) if first_iteration { if node.is_expr && (node.expected_type.has_flag(.optional) + || node.expected_type.has_flag(.result) || c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) { ret_type = node.expected_type } else { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index ea4f26cb54..f22da3429c 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -116,7 +116,9 @@ mut: inside_map_index bool inside_opt_data bool inside_if_optional bool + inside_if_result bool inside_match_optional bool + inside_match_result bool inside_vweb_tmpl bool inside_return bool inside_struct_init bool @@ -1592,6 +1594,29 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool { g.writeln(' }, ($c.option_name*)(&$tmp_var), sizeof($styp));') } } + } else if g.inside_if_result || g.inside_match_result { + g.set_current_pos_as_last_stmt_pos() + g.skip_stmt_pos = true + if stmt is ast.ExprStmt { + if stmt.typ == ast.error_type_idx { + g.writeln('${tmp_var}.is_error = true;') + g.write('${tmp_var}.err = ') + g.expr(stmt.expr) + g.writeln(';') + } else { + mut styp := g.base_type(stmt.typ) + $if tinyc && x32 && windows { + if stmt.typ == ast.int_literal_type { + styp = 'int' + } else if stmt.typ == ast.float_literal_type { + styp = 'f64' + } + } + g.write('opt_ok2(&($styp[]) { ') + g.stmt(stmt) + g.writeln(' }, ($c.result_name*)(&$tmp_var), sizeof($styp));') + } + } } else { g.set_current_pos_as_last_stmt_pos() g.skip_stmt_pos = true @@ -1609,7 +1634,8 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool { } } else { g.stmt(stmt) - if (g.inside_if_optional || g.inside_match_optional) && stmt is ast.ExprStmt { + if (g.inside_if_optional || g.inside_if_result || g.inside_match_optional + || g.inside_match_result) && stmt is ast.ExprStmt { g.writeln(';') } } @@ -1796,7 +1822,8 @@ fn (mut g Gen) stmt(node ast.Stmt) { // g.autofree_call_postgen() // } if g.inside_ternary == 0 && !g.inside_if_optional && !g.inside_match_optional - && !node.is_expr && node.expr !is ast.IfExpr { + && !g.inside_if_result && !g.inside_match_result && !node.is_expr + && node.expr !is ast.IfExpr { if node.expr is ast.MatchExpr { g.writeln('') } else { diff --git a/vlib/v/gen/c/match.v b/vlib/v/gen/c/match.v index e611b95098..09d60f831d 100644 --- a/vlib/v/gen/c/match.v +++ b/vlib/v/gen/c/match.v @@ -12,7 +12,7 @@ fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool { if g.table.type_kind(node.return_type) == .sum_type { return true } - if node.return_type.has_flag(.optional) { + if node.return_type.has_flag(.optional) || node.return_type.has_flag(.result) { return true } if sym.kind == .multi_return { @@ -52,12 +52,20 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { if is_expr && !need_tmp_var { g.inside_ternary++ } - if is_expr && node.return_type.has_flag(.optional) { - old := g.inside_match_optional - defer { - g.inside_match_optional = old + if is_expr { + if node.return_type.has_flag(.optional) { + old := g.inside_match_optional + defer { + g.inside_match_optional = old + } + g.inside_match_optional = true + } else if node.return_type.has_flag(.result) { + old := g.inside_match_result + defer { + g.inside_match_result = old + } + g.inside_match_result = true } - g.inside_match_optional = true } if node.cond in [ast.Ident, ast.SelectorExpr, ast.IntegerLiteral, ast.StringLiteral, ast.FloatLiteral] { cond_var = g.expr_string(node.cond) diff --git a/vlib/v/tests/match_expr_with_result_test.v b/vlib/v/tests/match_expr_with_result_test.v new file mode 100644 index 0000000000..d96e09605a --- /dev/null +++ b/vlib/v/tests/match_expr_with_result_test.v @@ -0,0 +1,23 @@ +fn foo(i int) ?bool { + return match true { + i == 0 { true } + else { none } + } +} + +fn bar(i int) !bool { + return match true { + i == 0 { true } + else { error('') } + } +} + +fn test_match_expr_with_result() { + r1 := foo(0) or { false } + println(r1) + assert r1 + + r2 := bar(0) or { false } + println(r2) + assert r2 +}