cgen: fix return if true { 0 } else { none } (fix #9005) (#9030)

pull/9035/head
yuyi 2021-03-01 20:56:07 +08:00 committed by GitHub
parent 83a77542e3
commit f9c8d3d25c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 59 deletions

View File

@ -4913,9 +4913,14 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
if branch.stmts.len > 0 && branch.stmts[branch.stmts.len - 1] is ast.ExprStmt {
mut last_expr := branch.stmts[branch.stmts.len - 1] as ast.ExprStmt
c.expected_type = former_expected_type
if c.expected_type.has_flag(.optional) {
if node.typ == table.void_type {
node.is_expr = true
node.typ = c.expected_type
}
continue
}
last_expr.typ = c.expr(last_expr.expr)
// if last_expr.typ != node.typ {
// if !c.check_types(node.typ, last_expr.typ) {
if !c.check_types(last_expr.typ, node.typ) {
if node.typ == table.void_type {
// first branch of if expression

View File

@ -83,7 +83,7 @@ mut:
inside_map_infix bool // inside map<</+=/-= infix expr
inside_map_index bool
inside_opt_data bool
// inside_if_expr bool
inside_if_optional bool
ternary_names map[string]string
ternary_level_names map[string][]string
stmt_path_pos []int // positions of each statement start, for inserting C statements before the current statement
@ -913,11 +913,40 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) {
for i, stmt in stmts {
if i == stmts.len - 1 && tmp_var != '' {
// Handle if expressions, set the value of the last expression to the temp var.
if g.inside_if_optional {
g.stmt_path_pos << g.out.len
g.skip_stmt_pos = true
if stmt is ast.ExprStmt {
sym := g.table.get_type_symbol(stmt.typ)
if sym.name in ['Option', 'Option2'] || stmt.expr is ast.None {
tmp := g.new_tmp_var()
g.write('Option2 $tmp = ')
g.expr(stmt.expr)
g.writeln(';')
g.writeln('memcpy(&$tmp_var, &$tmp, sizeof(Option2));')
} else {
mut styp := g.base_type(stmt.typ)
$if tinyc && x32 && windows {
if stmt.typ == table.int_literal_type {
styp = 'int'
} else if stmt.typ == table.float_literal_type {
styp = 'f64'
}
}
g.write('opt_ok(&($styp[]) { ')
g.stmt(stmt)
g.writeln(' }, (Option2*)(&$tmp_var), sizeof($styp));')
}
}
} else {
g.stmt_path_pos << g.out.len
g.skip_stmt_pos = true
g.write('$tmp_var = ')
}
g.stmt(stmt)
}
} else {
g.stmt(stmt)
}
g.skip_stmt_pos = false
if g.inside_ternary > 0 && i < stmts.len - 1 {
g.write(',')
@ -1076,7 +1105,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
// if af {
// g.autofree_call_postgen()
// }
if g.inside_ternary == 0 && !node.is_expr && node.expr !is ast.IfExpr {
if g.inside_ternary == 0 && !g.inside_if_optional && !node.is_expr
&& node.expr !is ast.IfExpr {
g.writeln(';')
}
}
@ -4039,7 +4069,7 @@ fn (mut g Gen) concat_expr(node ast.ConcatExpr) {
fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool {
if node.is_expr && g.inside_ternary == 0 {
if g.is_autofree {
if g.is_autofree || node.typ.has_flag(.optional) {
return true
}
for branch in node.branches {
@ -4076,6 +4106,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
mut cur_line := ''
if needs_tmp_var {
if node.typ.has_flag(.optional) {
g.inside_if_optional = true
}
g.write('/*experimental if expr*/')
styp := g.typ(node.typ)
// g.insert_before_stmt('$styp $tmp;')
@ -4181,6 +4214,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
// g.writeln('$cur_line $tmp; /*Z*/')
g.write('$cur_line $tmp /*Z*/')
}
if node.typ.has_flag(.optional) {
g.inside_if_optional = false
}
}
fn (mut g Gen) index_expr(node ast.IndexExpr) {

View File

@ -0,0 +1,25 @@
fn foo1() ?int {
return if true { 0 } else { none }
}
fn foo2() ?int {
return if true { 1 } else { error('foo2 error') }
}
fn foo3() ?int {
return if true { 2 } else { 0 }
}
fn test_if_expr_of_optional() {
a1 := foo1() or { panic('error') }
println(a1)
assert a1 == 0
a2 := foo2() or { panic('error') }
println(a2)
assert a2 == 1
a3 := foo3() or { panic('error') }
println(a3)
assert a3 == 2
}