mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
parent
04936b00c5
commit
aad95ac818
@ -1710,10 +1710,14 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||||||
t_generic_names = sym.info.generic_types.map(t.sym(it).name)
|
t_generic_names = sym.info.generic_types.map(t.sym(it).name)
|
||||||
t_concrete_types = []
|
t_concrete_types = []
|
||||||
for t_typ in sym.generic_types {
|
for t_typ in sym.generic_types {
|
||||||
tname := t.sym(t_typ).name
|
if !t_typ.has_flag(.generic) {
|
||||||
index := generic_names.index(tname)
|
t_concrete_types << t_typ
|
||||||
if index >= 0 && index < concrete_types.len {
|
} else {
|
||||||
t_concrete_types << concrete_types[index]
|
tname := t.sym(t_typ).name
|
||||||
|
index := generic_names.index(tname)
|
||||||
|
if index >= 0 && index < concrete_types.len {
|
||||||
|
t_concrete_types << concrete_types[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1801,7 +1805,7 @@ pub fn (mut t Table) generic_type_names(generic_type Type) []string {
|
|||||||
if sym.info.is_generic {
|
if sym.info.is_generic {
|
||||||
if sym.generic_types.len > 0 {
|
if sym.generic_types.len > 0 {
|
||||||
// Foo[U] (declaration: Foo[T])
|
// Foo[U] (declaration: Foo[T])
|
||||||
names << sym.generic_types.map(t.sym(it).name)
|
names << sym.generic_types.filter(it.has_flag(.generic)).map(t.sym(it).name)
|
||||||
} else {
|
} else {
|
||||||
names << sym.info.generic_types.map(t.sym(it).name)
|
names << sym.info.generic_types.map(t.sym(it).name)
|
||||||
}
|
}
|
||||||
@ -1862,10 +1866,14 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
|
|||||||
t_generic_names = ts.info.generic_types.map(t.sym(it).name)
|
t_generic_names = ts.info.generic_types.map(t.sym(it).name)
|
||||||
t_concrete_types = []
|
t_concrete_types = []
|
||||||
for t_typ in ts.generic_types {
|
for t_typ in ts.generic_types {
|
||||||
tname := t.sym(t_typ).name
|
if !t_typ.has_flag(.generic) {
|
||||||
index := generic_names.index(tname)
|
t_concrete_types << t_typ
|
||||||
if index >= 0 && index < concrete_types.len {
|
} else {
|
||||||
t_concrete_types << concrete_types[index]
|
tname := t.sym(t_typ).name
|
||||||
|
index := generic_names.index(tname)
|
||||||
|
if index >= 0 && index < concrete_types.len {
|
||||||
|
t_concrete_types << concrete_types[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,6 +277,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||||||
node.pos)
|
node.pos)
|
||||||
} else if node.generic_types.len > 0 && c.table.cur_fn != unsafe { nil } {
|
} else if node.generic_types.len > 0 && c.table.cur_fn != unsafe { nil } {
|
||||||
for gtyp in node.generic_types {
|
for gtyp in node.generic_types {
|
||||||
|
if !gtyp.has_flag(.generic) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
gtyp_name := c.table.sym(gtyp).name
|
gtyp_name := c.table.sym(gtyp).name
|
||||||
if gtyp_name !in c.table.cur_fn.generic_names {
|
if gtyp_name !in c.table.cur_fn.generic_names {
|
||||||
cur_generic_names := '(' + c.table.cur_fn.generic_names.join(',') + ')'
|
cur_generic_names := '(' + c.table.cur_fn.generic_names.join(',') + ')'
|
||||||
|
@ -109,6 +109,10 @@ fn (mut g Gen) final_gen_str(typ StrType) {
|
|||||||
}
|
}
|
||||||
styp := typ.styp
|
styp := typ.styp
|
||||||
str_fn_name := styp_to_str_fn_name(styp)
|
str_fn_name := styp_to_str_fn_name(styp)
|
||||||
|
if str_fn_name in g.str_fn_names {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.str_fn_names << str_fn_name
|
||||||
if typ.typ.has_flag(.optional) {
|
if typ.typ.has_flag(.optional) {
|
||||||
g.gen_str_for_option(typ.typ, styp, str_fn_name)
|
g.gen_str_for_option(typ.typ, styp, str_fn_name)
|
||||||
return
|
return
|
||||||
|
@ -157,6 +157,7 @@ mut:
|
|||||||
defer_vars []string
|
defer_vars []string
|
||||||
str_types []StrType // types that need automatic str() generation
|
str_types []StrType // types that need automatic str() generation
|
||||||
generated_str_fns []StrType // types that already have a str() function
|
generated_str_fns []StrType // types that already have a str() function
|
||||||
|
str_fn_names []string // remove duplicate function names
|
||||||
threaded_fns shared []string // for generating unique wrapper types and fns for `go xxx()`
|
threaded_fns shared []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
waiter_fns shared []string // functions that wait for `go xxx()` to finish
|
waiter_fns shared []string // functions that wait for `go xxx()` to finish
|
||||||
needed_equality_fns []ast.Type
|
needed_equality_fns []ast.Type
|
||||||
@ -5363,6 +5364,7 @@ fn (mut g Gen) write_sorted_types() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
|
mut struct_names := []string{cap: 16}
|
||||||
for sym in symbols {
|
for sym in symbols {
|
||||||
if sym.name.starts_with('C.') {
|
if sym.name.starts_with('C.') {
|
||||||
continue
|
continue
|
||||||
@ -5377,7 +5379,10 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
|||||||
mut name := sym.cname
|
mut name := sym.cname
|
||||||
match sym.info {
|
match sym.info {
|
||||||
ast.Struct {
|
ast.Struct {
|
||||||
g.struct_decl(sym.info, name, false)
|
if name !in struct_names {
|
||||||
|
g.struct_decl(sym.info, name, false)
|
||||||
|
struct_names << name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.Alias {
|
ast.Alias {
|
||||||
// ast.Alias { TODO
|
// ast.Alias { TODO
|
||||||
@ -5401,9 +5406,10 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SumType {
|
ast.SumType {
|
||||||
if sym.info.is_generic {
|
if sym.info.is_generic || name in struct_names {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
struct_names << name
|
||||||
g.typedefs.writeln('typedef struct ${name} ${name};')
|
g.typedefs.writeln('typedef struct ${name} ${name};')
|
||||||
g.type_definitions.writeln('')
|
g.type_definitions.writeln('')
|
||||||
g.type_definitions.writeln('// Union sum type ${name} = ')
|
g.type_definitions.writeln('// Union sum type ${name} = ')
|
||||||
|
@ -708,19 +708,19 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
|
|||||||
bs_name += '['
|
bs_name += '['
|
||||||
bs_cname += '_T_'
|
bs_cname += '_T_'
|
||||||
mut concrete_types := []ast.Type{}
|
mut concrete_types := []ast.Type{}
|
||||||
mut is_instance := false
|
mut is_instance := true
|
||||||
for p.tok.kind != .eof {
|
for p.tok.kind != .eof {
|
||||||
mut type_pos := p.tok.pos()
|
mut type_pos := p.tok.pos()
|
||||||
gt := p.parse_type()
|
gt := p.parse_type()
|
||||||
type_pos = type_pos.extend(p.prev_tok.pos())
|
type_pos = type_pos.extend(p.prev_tok.pos())
|
||||||
if !gt.has_flag(.generic) {
|
if gt.has_flag(.generic) {
|
||||||
is_instance = true
|
is_instance = false
|
||||||
}
|
}
|
||||||
gts := p.table.sym(gt)
|
gts := p.table.sym(gt)
|
||||||
if gts.kind == .multi_return {
|
if gts.kind == .multi_return {
|
||||||
p.error_with_pos('cannot use multi return as generic concrete type', type_pos)
|
p.error_with_pos('cannot use multi return as generic concrete type', type_pos)
|
||||||
}
|
}
|
||||||
if !is_instance && gts.name.len > 1 {
|
if gt.has_flag(.generic) && gts.name.len > 1 {
|
||||||
p.error_with_pos('the parameter type name of a generic struct, must be a single capital letter placeholder name, like T or X, or a non-generic type name like int, string, etc.',
|
p.error_with_pos('the parameter type name of a generic struct, must be a single capital letter placeholder name, like T or X, or a non-generic type name like int, string, etc.',
|
||||||
type_pos)
|
type_pos)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,165 @@
|
|||||||
|
struct Tuple1[A] {
|
||||||
|
a A
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tuple2[A, B] {
|
||||||
|
a A
|
||||||
|
b B
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tuple3[A, B, X] { // note: "C" is reserved for C language...
|
||||||
|
a A
|
||||||
|
b B
|
||||||
|
c X
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of key tuples
|
||||||
|
fn map_to_array1_k[K, V](m map[K]V) []Tuple1[K] {
|
||||||
|
mut r := []Tuple1[K]{cap: m.len}
|
||||||
|
for k, _ in m {
|
||||||
|
r << Tuple1[K]{k}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of value tuples
|
||||||
|
fn map_to_array1_v[K, V](m map[K]V) []Tuple1[V] {
|
||||||
|
mut r := []Tuple1[V]{cap: m.len}
|
||||||
|
for _, v in m {
|
||||||
|
r << Tuple1[V]{v}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of key-value tuples
|
||||||
|
fn map_to_array2_k_v[K, V](m map[K]V) []Tuple2[K, V] {
|
||||||
|
mut r := []Tuple2[K, V]{cap: m.len}
|
||||||
|
for k, v in m {
|
||||||
|
r << Tuple2[K, V]{k, v}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of value-key tuples
|
||||||
|
fn map_to_array2_v_k[K, V](m map[K]V) []Tuple2[V, K] {
|
||||||
|
mut r := []Tuple2[V, K]{cap: m.len}
|
||||||
|
for k, v in m {
|
||||||
|
r << Tuple2[V, K]{v, k}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of key-int tuples
|
||||||
|
fn map_to_array2_k_int[K, V](m map[K]V) []Tuple2[K, int] {
|
||||||
|
mut r := []Tuple2[K, int]{cap: m.len}
|
||||||
|
mut i := 0
|
||||||
|
for k, _ in m {
|
||||||
|
r << Tuple2[K, int]{k, i}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to array of value-int-key tuples
|
||||||
|
fn map_to_array3_v_int_k[K, V](m map[K]V) []Tuple3[V, int, K] {
|
||||||
|
mut r := []Tuple3[V, int, K]{cap: m.len}
|
||||||
|
mut i := 0
|
||||||
|
for k, v in m {
|
||||||
|
r << Tuple3[V, int, K]{v, i, k}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_generics_struct_init_with_inconsistent_generic_types() {
|
||||||
|
x := {
|
||||||
|
'one': 1
|
||||||
|
'two': 2
|
||||||
|
}
|
||||||
|
y := {
|
||||||
|
3: 'three'
|
||||||
|
4: 'four'
|
||||||
|
}
|
||||||
|
|
||||||
|
println(x)
|
||||||
|
rx1 := map_to_array1_k(x)
|
||||||
|
println(rx1)
|
||||||
|
assert rx1[0].a == 'one'
|
||||||
|
assert rx1[1].a == 'two'
|
||||||
|
|
||||||
|
rx2 := map_to_array1_v(x)
|
||||||
|
println(rx2)
|
||||||
|
assert rx2[0].a == 1
|
||||||
|
assert rx2[1].a == 2
|
||||||
|
|
||||||
|
rx3 := map_to_array2_k_v(x)
|
||||||
|
println(rx3)
|
||||||
|
assert rx3[0].a == 'one'
|
||||||
|
assert rx3[0].b == 1
|
||||||
|
assert rx3[1].a == 'two'
|
||||||
|
assert rx3[1].b == 2
|
||||||
|
|
||||||
|
rx4 := map_to_array2_v_k(x)
|
||||||
|
println(rx4)
|
||||||
|
assert rx4[0].a == 1
|
||||||
|
assert rx4[0].b == 'one'
|
||||||
|
assert rx4[1].a == 2
|
||||||
|
assert rx4[1].b == 'two'
|
||||||
|
|
||||||
|
rx5 := map_to_array2_k_int(x)
|
||||||
|
println(rx5)
|
||||||
|
assert rx5[0].a == 'one'
|
||||||
|
assert rx5[0].b == 0
|
||||||
|
assert rx5[1].a == 'two'
|
||||||
|
assert rx5[1].b == 1
|
||||||
|
|
||||||
|
rx6 := map_to_array3_v_int_k(x)
|
||||||
|
println(rx6)
|
||||||
|
assert rx6[0].a == 1
|
||||||
|
assert rx6[0].b == 0
|
||||||
|
assert rx6[0].c == 'one'
|
||||||
|
assert rx6[1].a == 2
|
||||||
|
assert rx6[1].b == 1
|
||||||
|
assert rx6[1].c == 'two'
|
||||||
|
|
||||||
|
println(y)
|
||||||
|
ry1 := map_to_array1_k(y)
|
||||||
|
println(ry1)
|
||||||
|
assert ry1[0].a == 3
|
||||||
|
assert ry1[1].a == 4
|
||||||
|
|
||||||
|
ry2 := map_to_array1_v(y)
|
||||||
|
println(ry2)
|
||||||
|
assert ry2[0].a == 'three'
|
||||||
|
assert ry2[1].a == 'four'
|
||||||
|
|
||||||
|
ry3 := map_to_array2_k_v(y)
|
||||||
|
println(ry3)
|
||||||
|
assert ry3[0].a == 3
|
||||||
|
assert ry3[0].b == 'three'
|
||||||
|
assert ry3[1].a == 4
|
||||||
|
assert ry3[1].b == 'four'
|
||||||
|
|
||||||
|
ry4 := map_to_array2_v_k(y)
|
||||||
|
println(ry4)
|
||||||
|
assert ry4[0].a == 'three'
|
||||||
|
assert ry4[0].b == 3
|
||||||
|
assert ry4[1].a == 'four'
|
||||||
|
assert ry4[1].b == 4
|
||||||
|
|
||||||
|
ry5 := map_to_array2_k_int(y)
|
||||||
|
println(ry5)
|
||||||
|
assert ry5[0].a == 3
|
||||||
|
assert ry5[0].b == 0
|
||||||
|
assert ry5[1].a == 4
|
||||||
|
assert ry5[1].b == 1
|
||||||
|
|
||||||
|
ry6 := map_to_array3_v_int_k(y)
|
||||||
|
println(ry6)
|
||||||
|
assert ry6[0].a == 'three'
|
||||||
|
assert ry6[0].b == 0
|
||||||
|
assert ry6[0].c == 3
|
||||||
|
assert ry6[1].a == 'four'
|
||||||
|
assert ry6[1].b == 1
|
||||||
|
assert ry6[1].c == 4
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user