v.gen.c: fix error of if_expr in infix_expr (#11200)

pull/11208/head
yuyi 2021-08-16 16:23:19 +08:00 committed by GitHub
parent d7490abe19
commit 90b052b1db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 23 deletions

View File

@ -168,13 +168,14 @@ mut:
// TypeOne, TypeTwo {}
// where an aggregate (at least two types) is generated
// sum type deref needs to know which index to deref because unions take care of the correct field
aggregate_type_idx int
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
timers &util.Timers = util.new_timers(false)
force_main_console bool // true when [console] used on fn main()
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
obf_table map[string]string
aggregate_type_idx int
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
infix_left_var_name string // a && if expr
timers &util.Timers = util.new_timers(false)
force_main_console bool // true when [console] used on fn main()
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
obf_table map[string]string
// main_fn_decl_node ast.FnDecl
expected_cast_type ast.Type // for match expr of sumtypes
defer_vars []string
@ -4626,6 +4627,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
cur_line = g.go_before_stmt(0)
g.empty_line = true
g.writeln('$styp $tmp; /* if prepend */')
if g.infix_left_var_name.len > 0 {
g.writeln('if ($g.infix_left_var_name) {')
g.indent++
}
} else if node.is_expr || g.inside_ternary != 0 {
g.inside_ternary++
g.write('(')
@ -4739,6 +4744,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
}
g.writeln('}')
if needs_tmp_var {
if g.infix_left_var_name.len > 0 {
g.indent--
g.writeln('}')
}
g.empty_line = false
g.write('$cur_line $tmp')
}

View File

@ -33,6 +33,9 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
.left_shift {
g.infix_expr_left_shift_op(node)
}
.and, .logical_or {
g.infix_expr_and_or_op(node)
}
else {
// `x & y == 0` => `(x & y) == 0` in C
need_par := node.op in [.amp, .pipe, .xor]
@ -499,28 +502,34 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
}
}
// infix_expr_and_or_op generates code for `&&` and `||`
fn (mut g Gen) infix_expr_and_or_op(node ast.InfixExpr) {
if node.right is ast.IfExpr {
// b := a && if true { a = false ...} else {...}
if g.need_tmp_var_in_if(node.right) {
tmp := g.new_tmp_var()
cur_line := g.go_before_stmt(0).trim_space()
g.empty_line = true
g.write('bool $tmp = (')
g.expr(node.left)
g.writeln(');')
g.stmt_path_pos << g.out.len
g.write('$cur_line $tmp $node.op.str() ')
g.infix_left_var_name = if node.op == .and { tmp } else { '!$tmp' }
g.expr(node.right)
g.infix_left_var_name = ''
return
}
}
g.gen_plain_infix_expr(node)
}
// gen_plain_infix_expr generates basic code for infix expressions,
// without any overloading of any kind
// i.e. v`a + 1` => c`a + 1`
// It handles auto dereferencing of variables, as well as automatic casting
// (see Gen.expr_with_cast for more details)
fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) {
if node.left is ast.Ident && node.right is ast.IfExpr {
// b := a && if true { a = false ...} else {...}
if g.need_tmp_var_in_if(node.right) {
tmp := g.new_tmp_var()
styp := g.typ(node.left_type)
cur_line := g.go_before_stmt(0)
g.empty_line = true
g.write('$styp $tmp = ')
g.expr(node.left)
g.writeln(';')
g.stmt_path_pos << g.out.len
g.write('$cur_line $tmp $node.op.str() ')
g.expr(node.right)
return
}
}
if node.left_type.is_ptr() && node.left.is_auto_deref_var() {
g.write('*')
}

View File

@ -0,0 +1,13 @@
fn main() {
mut a := false
b := a && if true {
a = true
true
} else {
false
}
println(b)
assert b == false
println(a)
assert a == false
}