checker, cgen: fix for in iterator of generic struct (#12441)
parent
50a608aab3
commit
3bb1c3f930
|
@ -4816,7 +4816,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||||
sym := c.table.get_final_type_symbol(typ)
|
sym := c.table.get_final_type_symbol(typ)
|
||||||
if sym.kind == .struct_ {
|
if sym.kind == .struct_ {
|
||||||
// iterators
|
// iterators
|
||||||
next_fn := sym.find_method('next') or {
|
next_fn := sym.find_method_with_generic_parent('next') or {
|
||||||
c.error('a struct must have a `next()` method to be an iterator', node.cond.position())
|
c.error('a struct must have a `next()` method to be an iterator', node.cond.position())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2145,7 +2145,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
||||||
}
|
}
|
||||||
} else if node.kind == .struct_ {
|
} else if node.kind == .struct_ {
|
||||||
cond_type_sym := g.table.get_type_symbol(node.cond_type)
|
cond_type_sym := g.table.get_type_symbol(node.cond_type)
|
||||||
next_fn := cond_type_sym.find_method('next') or {
|
next_fn := cond_type_sym.find_method_with_generic_parent('next') or {
|
||||||
verror('`next` method not found')
|
verror('`next` method not found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2162,7 +2162,14 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
||||||
t_var := g.new_tmp_var()
|
t_var := g.new_tmp_var()
|
||||||
receiver_typ := next_fn.params[0].typ
|
receiver_typ := next_fn.params[0].typ
|
||||||
receiver_styp := g.typ(receiver_typ)
|
receiver_styp := g.typ(receiver_typ)
|
||||||
fn_name := receiver_styp.replace_each(['*', '', '.', '__']) + '_next'
|
mut fn_name := receiver_styp.replace_each(['*', '', '.', '__']) + '_next'
|
||||||
|
receiver_sym := g.table.get_type_symbol(receiver_typ)
|
||||||
|
if receiver_sym.info is ast.Struct {
|
||||||
|
if receiver_sym.info.concrete_types.len > 0 {
|
||||||
|
fn_name = g.generic_fn_name(receiver_sym.info.concrete_types, fn_name,
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
}
|
||||||
g.write('\t${g.typ(ret_typ)} $t_var = ${fn_name}(')
|
g.write('\t${g.typ(ret_typ)} $t_var = ${fn_name}(')
|
||||||
if !node.cond_type.is_ptr() && receiver_typ.is_ptr() {
|
if !node.cond_type.is_ptr() && receiver_typ.is_ptr() {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
struct Split<T> {
|
||||||
|
arr []T
|
||||||
|
pred fn (T) bool
|
||||||
|
mut:
|
||||||
|
idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut iter Split<T>) next() ?[]T {
|
||||||
|
start := iter.idx
|
||||||
|
for iter.idx < iter.arr.len {
|
||||||
|
if iter.pred(iter.arr[iter.idx]) {
|
||||||
|
iter.idx++
|
||||||
|
return iter.arr[start..iter.idx]
|
||||||
|
}
|
||||||
|
iter.idx++
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split<T>(arr []T, pred fn (T) bool) Split<T> {
|
||||||
|
return Split<T>{arr, pred, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_for_in_iterator_of_generic_struct() {
|
||||||
|
items := [0, 1, 2, 3, 4, 5, 6, 7, 8]
|
||||||
|
mut iter := split<int>(items, fn (item int) bool {
|
||||||
|
return item % 3 == 0
|
||||||
|
})
|
||||||
|
iter.next() or {}
|
||||||
|
mut ret_list := [][]int{}
|
||||||
|
for item in iter {
|
||||||
|
dump(item)
|
||||||
|
ret_list << item
|
||||||
|
}
|
||||||
|
println(ret_list)
|
||||||
|
assert ret_list.len == 2
|
||||||
|
assert ret_list[0] == [1, 2, 3]
|
||||||
|
assert ret_list[1] == [4, 5, 6]
|
||||||
|
}
|
Loading…
Reference in New Issue