mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
This commit is contained in:
parent
38bfc482ba
commit
07997816d9
4 changed files with 114 additions and 9 deletions
|
@ -2190,16 +2190,15 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co
|
|||
Interface {
|
||||
// resolve generic types inside methods
|
||||
mut imethods := ts.info.methods.clone()
|
||||
gn_names := t.get_real_generic_names(typ, generic_names)
|
||||
for mut method in imethods {
|
||||
if unwrap_typ := t.convert_generic_type(method.return_type, generic_names,
|
||||
concrete_types)
|
||||
if unwrap_typ := t.convert_generic_type(method.return_type, gn_names,
|
||||
concrete_types[..gn_names.len])
|
||||
{
|
||||
method.return_type = unwrap_typ
|
||||
}
|
||||
for mut param in method.params {
|
||||
if unwrap_typ := t.convert_generic_type(param.typ, generic_names,
|
||||
concrete_types)
|
||||
{
|
||||
if unwrap_typ := t.convert_generic_type(param.typ, gn_names, concrete_types) {
|
||||
param.typ = unwrap_typ
|
||||
}
|
||||
}
|
||||
|
@ -2289,6 +2288,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
|||
fields[i].typ = t.unwrap_generic_type(fields[i].typ,
|
||||
generic_names, info.concrete_types)
|
||||
}
|
||||
|
||||
if t_typ := t.convert_generic_type(fields[i].typ, generic_names,
|
||||
info.concrete_types)
|
||||
{
|
||||
|
@ -2464,6 +2464,18 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
|||
}
|
||||
}
|
||||
|
||||
// Extracts all generic names from Type<A>[B] => B when <A>[B] is present
|
||||
// otherwise generic_names is returned
|
||||
pub fn (t &Table) get_real_generic_names(typ Type, generic_names []string) []string {
|
||||
if typ.has_flag(.generic) {
|
||||
typ_name := t.type_to_str(typ)
|
||||
if typ_name.contains('>[') {
|
||||
return typ_name.split('>[')[1].all_before_last(']').split(',')
|
||||
}
|
||||
}
|
||||
return generic_names
|
||||
}
|
||||
|
||||
// Extracts all type names from given types, notice that MultiReturn will be decompose
|
||||
// and will not included in returned string
|
||||
pub fn (t &Table) get_generic_names(generic_types []Type) []string {
|
||||
|
|
|
@ -1107,6 +1107,7 @@ pub fn (mut g Gen) get_sumtype_variant_name(typ ast.Type, sym ast.TypeSymbol) st
|
|||
pub fn (mut g Gen) write_typeof_functions() {
|
||||
g.writeln('')
|
||||
g.writeln('// >> typeof() support for sum types / interfaces')
|
||||
mut already_generated_ifaces := map[string]bool{}
|
||||
for ityp, sym in g.table.type_symbols {
|
||||
if sym.kind == .sum_type {
|
||||
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
|
||||
|
@ -1177,6 +1178,10 @@ pub fn (mut g Gen) write_typeof_functions() {
|
|||
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
|
||||
continue
|
||||
}
|
||||
if sym.cname in already_generated_ifaces {
|
||||
continue
|
||||
}
|
||||
already_generated_ifaces[sym.cname] = true
|
||||
g.definitions.writeln('${g.static_non_parallel}char * v_typeof_interface_${sym.cname}(int sidx);')
|
||||
if g.pref.parallel_cc {
|
||||
g.extern_out.writeln('extern char * v_typeof_interface_${sym.cname}(int sidx);')
|
||||
|
@ -1805,11 +1810,15 @@ static inline void __${sym.cname}_pushval(${sym.cname} ch, ${push_arg} val) {
|
|||
interface_non_generic_syms << sym
|
||||
}
|
||||
}
|
||||
mut already_generated_ifaces := map[string]bool{}
|
||||
for sym in interface_non_generic_syms {
|
||||
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
|
||||
continue
|
||||
}
|
||||
g.write_interface_typesymbol_declaration(sym)
|
||||
if sym.cname !in already_generated_ifaces {
|
||||
g.write_interface_typesymbol_declaration(sym)
|
||||
already_generated_ifaces[sym.cname] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7859,6 +7868,7 @@ fn (mut g Gen) interface_table() string {
|
|||
}
|
||||
mut sb := strings.new_builder(100)
|
||||
mut conversion_functions := strings.new_builder(100)
|
||||
mut already_generated_ifaces := map[string]bool{}
|
||||
interfaces := g.table.type_symbols.filter(it.kind == .interface && it.info is ast.Interface)
|
||||
for isym in interfaces {
|
||||
inter_info := isym.info as ast.Interface
|
||||
|
@ -7868,6 +7878,10 @@ fn (mut g Gen) interface_table() string {
|
|||
if g.pref.skip_unused && isym.idx !in g.table.used_features.used_syms {
|
||||
continue
|
||||
}
|
||||
if isym.cname in already_generated_ifaces {
|
||||
continue
|
||||
}
|
||||
already_generated_ifaces[isym.cname] = true
|
||||
// interface_name is for example Speaker
|
||||
interface_name := isym.cname
|
||||
// generate a struct that references interface methods
|
||||
|
|
|
@ -1298,9 +1298,6 @@ fn (mut w Walker) mark_resource_dependencies() {
|
|||
w.fn_by_name('strings.new_builder')
|
||||
w.uses_free[ast.string_type] = true
|
||||
}
|
||||
if w.uses_eq {
|
||||
w.fn_by_name('fast_string_eq')
|
||||
}
|
||||
if w.features.auto_str_ptr {
|
||||
w.fn_by_name('isnil')
|
||||
w.fn_by_name('tos4')
|
||||
|
@ -1597,6 +1594,9 @@ pub fn (mut w Walker) finalize(include_panic_deps bool) {
|
|||
w.mark_by_sym_name('StrIntpData')
|
||||
w.mark_by_sym_name('StrIntpMem')
|
||||
}
|
||||
if w.uses_eq {
|
||||
w.fn_by_name('fast_string_eq')
|
||||
}
|
||||
|
||||
// remove unused symbols
|
||||
w.remove_unused_fn_generic_types()
|
||||
|
|
79
vlib/v/tests/generics/generic_interface_field_test.v
Normal file
79
vlib/v/tests/generics/generic_interface_field_test.v
Normal file
|
@ -0,0 +1,79 @@
|
|||
pub struct Range[T] {
|
||||
pub:
|
||||
from T
|
||||
to T
|
||||
inclusive bool
|
||||
pub mut:
|
||||
step T = T(1)
|
||||
i T
|
||||
mut:
|
||||
started bool
|
||||
}
|
||||
|
||||
pub fn (mut r Range[T]) next[T]() ?T {
|
||||
if !r.started {
|
||||
r.started = true
|
||||
assert r.step > 0
|
||||
if r.from > r.to {
|
||||
r.step = -r.step
|
||||
}
|
||||
r.i = r.from
|
||||
}
|
||||
i := r.i
|
||||
next_i := i + r.step
|
||||
if r.inclusive {
|
||||
if r.step < 0 && i < r.to {
|
||||
return none
|
||||
}
|
||||
if r.step > 0 && i > r.to {
|
||||
return none
|
||||
}
|
||||
} else {
|
||||
if r.step < 0 && i <= r.to {
|
||||
return none
|
||||
}
|
||||
if r.step > 0 && i >= r.to {
|
||||
return none
|
||||
}
|
||||
}
|
||||
r.i = next_i
|
||||
return i
|
||||
}
|
||||
|
||||
pub interface Iterator[T] {
|
||||
mut:
|
||||
next() ?T
|
||||
}
|
||||
|
||||
pub struct Zip[A, B] {
|
||||
mut:
|
||||
a Iterator[A]
|
||||
b Iterator[B]
|
||||
}
|
||||
|
||||
pub struct Pair[A, B] {
|
||||
a A
|
||||
b B
|
||||
}
|
||||
|
||||
pub fn (mut z Zip[A, B]) next[A, B]() ?Pair[A, B] {
|
||||
a := z.a.next()?
|
||||
b := z.b.next()?
|
||||
return Pair[A, B]{a, b}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
mut r1 := Range{
|
||||
from: 5
|
||||
to: 10
|
||||
}
|
||||
_ := Iterator[int](r1)
|
||||
|
||||
mut r2 := Range{
|
||||
from: 10
|
||||
to: 5
|
||||
}
|
||||
_ := Iterator[int](r2)
|
||||
|
||||
_ := Zip[int, int]{}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue