Skip to content

Commit

Permalink
cgen: fix code generated for indexexpr with complex assigning (#22203)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Sep 14, 2024
1 parent 4c68f85 commit 8db2300
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
18 changes: 14 additions & 4 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
mut ident := ast.Ident{
scope: unsafe { nil }
}
mut cur_indexexpr := -1
left_sym := g.table.sym(g.unwrap_generic(var_type))
is_va_list = left_sym.language == .c && left_sym.name == 'C.va_list'
if mut left is ast.Ident {
Expand Down Expand Up @@ -696,14 +697,17 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.expr(left)
}
g.is_assign_lhs = false
if left is ast.IndexExpr && g.cur_indexexpr.len > 0 {
cur_indexexpr = g.cur_indexexpr.index(left.pos().pos)
}
if is_fixed_array_var || is_va_list {
if is_decl {
g.writeln(';')
if is_va_list {
continue
}
}
} else if !g.is_arraymap_set && !str_add && !op_overloaded {
} else if cur_indexexpr == -1 && !str_add && !op_overloaded {
g.write(' ${op} ')
} else if str_add || op_overloaded {
g.write(', ')
Expand Down Expand Up @@ -813,9 +817,10 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
if str_add || op_overloaded {
g.write(')')
}
if g.is_arraymap_set {
if cur_indexexpr != -1 {
g.cur_indexexpr.delete(cur_indexexpr)
g.write(' })')
g.is_arraymap_set = false
g.is_arraymap_set = g.cur_indexexpr.len > 0
}
g.is_shared = false
}
Expand All @@ -841,6 +846,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
g.writeln(';')
mr_types := (return_sym.info as ast.MultiReturn).types
for i, lx in node.left {
mut cur_indexexpr := -1
mut is_auto_heap := false
mut ident := ast.Ident{
scope: unsafe { nil }
Expand All @@ -854,6 +860,9 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
is_auto_heap = lx.obj.is_auto_heap
}
}
if lx is ast.IndexExpr && g.cur_indexexpr.len > 0 {
cur_indexexpr = g.cur_indexexpr.index(lx.pos.pos)
}
styp := if ident.name in g.defer_vars { '' } else { g.typ(node.left_types[i]) }
if node.op == .decl_assign {
g.write('${styp} ')
Expand Down Expand Up @@ -889,14 +898,15 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
g.writeln(';')
g.writeln('memcpy(&${g.expr_string(lx)}, &${mr_var_name}.arg${i}, sizeof(${styp}));')
} else {
if g.is_arraymap_set {
if cur_indexexpr != -1 {
if is_auto_heap {
g.writeln('HEAP${noscan}(${styp}, ${mr_var_name}.arg${i}) });')
} else if is_option {
g.writeln('(*((${g.base_type(return_type)}*)${mr_var_name}.data)).arg${i} });')
} else {
g.writeln('${mr_var_name}.arg${i} });')
}
g.cur_indexexpr.delete(cur_indexexpr)
} else {
if is_auto_heap {
g.writeln(' = HEAP${noscan}(${styp}, ${mr_var_name}.arg${i});')
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ mut:
mtxs string // array of mutexes if the `lock` has multiple variables
labeled_loops map[string]&ast.Stmt
inner_loop &ast.Stmt = unsafe { nil }
cur_indexexpr []int // list of nested indexexpr which generates array_set/map_set
shareds map[int]string // types with hidden mutex for which decl has been emitted
coverage_files map[u64]&CoverageInfo
inside_ternary int // ?: comma separated statements on a single line
Expand Down
2 changes: 2 additions & 0 deletions vlib/v/gen/c/index.v
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
g.write('*')
}
} else {
g.cur_indexexpr << node.pos.pos
g.is_arraymap_set = true // special handling of assign_op and closing with '})'
g.write('array_set(')
if !left_is_ptr || node.left_type.has_flag(.shared_f) {
Expand Down Expand Up @@ -398,6 +399,7 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) {
get_and_set_types := val_sym.kind in [.struct_, .map, .array, .array_fixed]
if g.is_assign_lhs && !g.is_arraymap_set && !get_and_set_types {
if g.assign_op == .assign || info.value_type == ast.string_type {
g.cur_indexexpr << node.pos.pos
g.is_arraymap_set = true
g.write('map_set(')
} else {
Expand Down
34 changes: 34 additions & 0 deletions vlib/v/tests/indexexpr_with_assign_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
fn test_1() {
mut test := []f64{}
test << 0
test[0] = if true {
sum := 1.2
sum
} else {
0
}
assert test == [1.2]
}

fn test_2() {
check := true
mut test := []f64{len: 100}
for i in 0 .. 100 {
test[i] = if check {
mut sum := 0.0
for x in 0 .. 100 {
if check {
sum += 1
}
if i <= x {
break
}
}
sum
} else {
0
}
}
assert test[0] == 1.0
assert test[99] == 100.0
}

0 comments on commit 8db2300

Please sign in to comment.