cgen: fix array of fns index call with embeded array index (fix #17381) (#22198)

This commit is contained in:
yuyi 2024-09-12 00:33:48 +08:00 committed by GitHub
parent 62ab1be572
commit 1c992de86d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 3 deletions

View File

@ -234,6 +234,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
}
} else {
is_direct_array_access := g.is_direct_array_access || node.is_direct
is_fn_index_call := g.is_fn_index_call && elem_sym.info is ast.FnType
// do not clone inside `opt_ok(opt_ok(&(string[]) {..})` before returns
needs_clone := info.elem_type == ast.string_type_idx && g.is_autofree && !(g.inside_return
&& g.fn_decl != unsafe { nil } && g.fn_decl.return_type.has_flag(.option))
@ -257,7 +258,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
if needs_clone {
g.write('/*2*/string_clone(')
}
if g.is_fn_index_call {
if is_fn_index_call {
if elem_sym.info is ast.FnType {
g.write('((')
g.write_fn_ptr_decl(&elem_sym.info, '')
@ -297,13 +298,13 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
g.write('data)[')
g.expr(node.index)
g.write(']')
if g.is_fn_index_call {
if is_fn_index_call {
g.write(')')
}
} else {
g.write(', ')
g.expr(node.index)
if g.is_fn_index_call {
if is_fn_index_call {
g.write(')))')
} else {
g.write('))')

View File

@ -0,0 +1,64 @@
fn max_speed(functions []fn (int) int, g fn (int) int, end_time int) int {
mut s := [0]
mut gears := []int{len: end_time, init: 0}
for t in 0 .. end_time {
stay_in_gear_speed := if t - 1 >= 0 { functions[gears[t - 1]](s[t - 1]) } else { 0 }
shift_gear_speed := if t - 2 >= 0 { functions[gears[t - 2] + 1](g(s[t - 2])) } else { 0 }
if stay_in_gear_speed > shift_gear_speed {
gears[t] = if t - 1 >= 0 { gears[t - 1] } else { 0 }
s << stay_in_gear_speed
} else {
gears[t] = if t - 2 >= 0 { gears[t - 2] } else { 0 } + 1
s << shift_gear_speed
}
}
return s[end_time]
}
@[direct_array_access]
fn max_speed_direct_access(functions []fn (int) int, g fn (int) int, end_time int) int {
mut s := [0]
mut gears := []int{len: end_time, init: 0}
for t in 0 .. end_time {
stay_in_gear_speed := if t - 1 >= 0 { functions[gears[t - 1]](s[t - 1]) } else { 0 }
shift_gear_speed := if t - 2 >= 0 { functions[gears[t - 2] + 1](g(s[t - 2])) } else { 0 }
if stay_in_gear_speed > shift_gear_speed {
gears[t] = if t - 1 >= 0 { gears[t - 1] } else { 0 }
s << stay_in_gear_speed
} else {
gears[t] = if t - 2 >= 0 { gears[t - 2] } else { 0 } + 1
s << shift_gear_speed
}
}
return s[end_time]
}
fn first_gear(speed int) int {
return speed + 1
}
fn second_gear(speed int) int {
return speed + 1
}
fn third_gear(speed int) int {
return speed + 1
}
fn decelerate(speed int) int {
return speed - 3
}
fn test_array_of_fns_index_call_with_embeded_array_call() {
funcs := [first_gear, second_gear, third_gear]
speed1 := max_speed(funcs, decelerate, 3)
println(speed1)
assert speed1 == 1
speed2 := max_speed_direct_access(funcs, decelerate, 3)
println(speed2)
assert speed2 == 1
}