all: fix generic functions with pointer args (#10686)
parent
9eee6631cc
commit
d14de5fdaf
|
@ -1180,7 +1180,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
typ := concrete_types[index]
|
typ := concrete_types[index]
|
||||||
return typ.derive(generic_type).clear_flag(.generic)
|
return typ.derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
match mut sym.info {
|
match mut sym.info {
|
||||||
Array {
|
Array {
|
||||||
|
@ -1195,7 +1195,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
}
|
}
|
||||||
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
|
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
|
||||||
idx := t.find_or_register_array_with_dims(typ, dims)
|
idx := t.find_or_register_array_with_dims(typ, dims)
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayFixed {
|
ArrayFixed {
|
||||||
|
@ -1203,7 +1203,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
concrete_types)
|
concrete_types)
|
||||||
{
|
{
|
||||||
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{})
|
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{})
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Chan {
|
Chan {
|
||||||
|
@ -1211,7 +1211,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
concrete_types)
|
concrete_types)
|
||||||
{
|
{
|
||||||
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FnType {
|
FnType {
|
||||||
|
@ -1234,7 +1234,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx := t.find_or_register_fn_type('', func, true, false)
|
idx := t.find_or_register_fn_type('', func, true, false)
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
MultiReturn {
|
MultiReturn {
|
||||||
mut types := []Type{}
|
mut types := []Type{}
|
||||||
|
@ -1249,7 +1249,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_multi_return(types)
|
idx := t.find_or_register_multi_return(types)
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map {
|
Map {
|
||||||
|
@ -1270,7 +1270,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Struct {
|
Struct {
|
||||||
|
@ -1292,7 +1292,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
idx = t.add_placeholder_type(nrt, .v)
|
idx = t.add_placeholder_type(nrt, .v)
|
||||||
}
|
}
|
||||||
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
|
|
@ -252,6 +252,12 @@ pub fn (t Type) derive(t_from Type) Type {
|
||||||
return (0xffff0000 & t_from) | u16(t)
|
return (0xffff0000 & t_from) | u16(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy flags from `t_from` to `t` and return `t`
|
||||||
|
[inline]
|
||||||
|
pub fn (t Type) derive_add_muls(t_from Type) Type {
|
||||||
|
return Type((0xff000000 & t_from) | u16(t)).set_nr_muls(t.nr_muls() + t_from.nr_muls())
|
||||||
|
}
|
||||||
|
|
||||||
// return new type with TypeSymbol idx set to `idx`
|
// return new type with TypeSymbol idx set to `idx`
|
||||||
[inline]
|
[inline]
|
||||||
pub fn new_type(idx int) Type {
|
pub fn new_type(idx int) Type {
|
||||||
|
|
|
@ -1677,9 +1677,8 @@ fn (mut f Fmt) write_generic_if_require(node ast.CallExpr) {
|
||||||
if node.concrete_types.len > 0 {
|
if node.concrete_types.len > 0 {
|
||||||
f.write('<')
|
f.write('<')
|
||||||
for i, concrete_type in node.concrete_types {
|
for i, concrete_type in node.concrete_types {
|
||||||
is_last := i == node.concrete_types.len - 1
|
f.write(f.table.type_to_str_using_aliases(concrete_type, f.mod2alias))
|
||||||
f.write(f.table.type_to_str(concrete_type))
|
if i != node.concrete_types.len - 1 {
|
||||||
if !is_last {
|
|
||||||
f.write(', ')
|
f.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1824,7 +1823,7 @@ pub fn (mut f Fmt) ident(node ast.Ident) {
|
||||||
// Force usage of full path to const in the same module:
|
// Force usage of full path to const in the same module:
|
||||||
// `println(minute)` => `println(time.minute)`
|
// `println(minute)` => `println(time.minute)`
|
||||||
// This makes it clear that a module const is being used
|
// This makes it clear that a module const is being used
|
||||||
// (since V's conts are no longer ALL_CAP).
|
// (since V's consts are no longer ALL_CAP).
|
||||||
// ^^^ except for `main`, where consts are allowed to not have a `main.` prefix.
|
// ^^^ except for `main`, where consts are allowed to not have a `main.` prefix.
|
||||||
if !node.name.contains('.') && !f.inside_const {
|
if !node.name.contains('.') && !f.inside_const {
|
||||||
mod := f.cur_mod
|
mod := f.cur_mod
|
||||||
|
|
|
@ -582,6 +582,23 @@ fn (mut g Gen) base_type(t ast.Type) string {
|
||||||
return styp
|
return styp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) generic_fn_name(types []ast.Type, before string, is_decl bool) string {
|
||||||
|
if types.len == 0 {
|
||||||
|
return before
|
||||||
|
}
|
||||||
|
// Using _T_ to differentiate between get<string> and get_string
|
||||||
|
// `foo<int>()` => `foo_T_int()`
|
||||||
|
mut name := before + '_T'
|
||||||
|
for typ in types {
|
||||||
|
nr_muls := typ.nr_muls()
|
||||||
|
if is_decl && nr_muls > 0 {
|
||||||
|
name = strings.repeat(`*`, nr_muls) + name
|
||||||
|
}
|
||||||
|
name += '_' + strings.repeat_string('__ptr__', nr_muls) + g.typ(typ.set_nr_muls(0))
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) expr_string(expr ast.Expr) string {
|
fn (mut g Gen) expr_string(expr ast.Expr) string {
|
||||||
pos := g.out.len
|
pos := g.out.len
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
|
|
|
@ -190,15 +190,9 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
|
||||||
name = c_name(name)
|
name = c_name(name)
|
||||||
}
|
}
|
||||||
mut type_name := g.typ(node.return_type)
|
mut type_name := g.typ(node.return_type)
|
||||||
if g.table.cur_concrete_types.len > 0 {
|
|
||||||
// foo<T>() => foo_T_int(), foo_T_string() etc
|
name = g.generic_fn_name(g.table.cur_concrete_types, name, true)
|
||||||
// Using _T_ to differentiate between get<string> and get_string
|
|
||||||
name += '_T'
|
|
||||||
for concrete_type in g.table.cur_concrete_types {
|
|
||||||
gen_name := g.typ(concrete_type)
|
|
||||||
name += '_' + gen_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
|
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
|
||||||
&& name != 'main__main' && node.name != 'str' {
|
&& name != 'main__main' && node.name != 'str' {
|
||||||
mut key := node.name
|
mut key := node.name
|
||||||
|
@ -726,16 +720,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, concrete_type in node.concrete_types {
|
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||||
if concrete_type != ast.void_type && concrete_type != 0 {
|
|
||||||
// Using _T_ to differentiate between get<string> and get_string
|
|
||||||
// `foo<int>()` => `foo_T_int()`
|
|
||||||
if i == 0 {
|
|
||||||
name += '_T'
|
|
||||||
}
|
|
||||||
name += '_' + g.typ(concrete_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO2
|
// TODO2
|
||||||
// g.generate_tmp_autofree_arg_vars(node, name)
|
// g.generate_tmp_autofree_arg_vars(node, name)
|
||||||
//
|
//
|
||||||
|
@ -923,14 +908,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
panic('cgen: obf name "$key" not found, this should never happen')
|
panic('cgen: obf name "$key" not found, this should never happen')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, concrete_type in node.concrete_types {
|
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||||
// Using _T_ to differentiate between get<string> and get_string
|
|
||||||
// `foo<int>()` => `foo_T_int()`
|
|
||||||
if i == 0 {
|
|
||||||
name += '_T'
|
|
||||||
}
|
|
||||||
name += '_' + g.typ(concrete_type)
|
|
||||||
}
|
|
||||||
// TODO2
|
// TODO2
|
||||||
// cgen shouldn't modify ast nodes, this should be moved
|
// cgen shouldn't modify ast nodes, this should be moved
|
||||||
// g.generate_tmp_autofree_arg_vars(node, name)
|
// g.generate_tmp_autofree_arg_vars(node, name)
|
||||||
|
|
|
@ -1852,7 +1852,8 @@ fn (p &Parser) is_typename(t token.Token) bool {
|
||||||
// otherwise it is not generic because it may be multi-value (e.g. `return f < foo, 0`).
|
// otherwise it is not generic because it may be multi-value (e.g. `return f < foo, 0`).
|
||||||
// 5. `f<mod.Foo>` is same as case 3
|
// 5. `f<mod.Foo>` is same as case 3
|
||||||
// 6. `f<mod.Foo,` is same as case 4
|
// 6. `f<mod.Foo,` is same as case 4
|
||||||
// 7. otherwise, it's not generic
|
// 7. if there is a &, ignore the & and see if it is a type
|
||||||
|
// 10. otherwise, it's not generic
|
||||||
// see also test_generic_detection in vlib/v/tests/generics_test.v
|
// see also test_generic_detection in vlib/v/tests/generics_test.v
|
||||||
fn (p &Parser) is_generic_call() bool {
|
fn (p &Parser) is_generic_call() bool {
|
||||||
lit0_is_capital := if p.tok.kind != .eof && p.tok.lit.len > 0 {
|
lit0_is_capital := if p.tok.kind != .eof && p.tok.lit.len > 0 {
|
||||||
|
@ -1863,11 +1864,21 @@ fn (p &Parser) is_generic_call() bool {
|
||||||
if lit0_is_capital || p.peek_tok.kind != .lt {
|
if lit0_is_capital || p.peek_tok.kind != .lt {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
tok2 := p.peek_token(2)
|
mut tok2 := p.peek_token(2)
|
||||||
tok3 := p.peek_token(3)
|
mut tok3 := p.peek_token(3)
|
||||||
tok4 := p.peek_token(4)
|
mut tok4 := p.peek_token(4)
|
||||||
tok5 := p.peek_token(5)
|
mut tok5 := p.peek_token(5)
|
||||||
kind2, kind3, kind4, kind5 := tok2.kind, tok3.kind, tok4.kind, tok5.kind
|
mut kind2, mut kind3, mut kind4, mut kind5 := tok2.kind, tok3.kind, tok4.kind, tok5.kind
|
||||||
|
if kind2 == .amp { // if there is a & in front, shift everything left
|
||||||
|
tok2 = tok3
|
||||||
|
kind2 = kind3
|
||||||
|
tok3 = tok4
|
||||||
|
kind3 = kind4
|
||||||
|
tok4 = tok5
|
||||||
|
kind4 = kind5
|
||||||
|
tok5 = p.peek_token(6)
|
||||||
|
kind5 = tok5.kind
|
||||||
|
}
|
||||||
|
|
||||||
if kind2 == .lsbr {
|
if kind2 == .lsbr {
|
||||||
// case 1
|
// case 1
|
||||||
|
|
|
@ -15,7 +15,8 @@ fn test_identity() {
|
||||||
'a': 'b'
|
'a': 'b'
|
||||||
})['a'] == 'b'
|
})['a'] == 'b'
|
||||||
|
|
||||||
assert simple<simplemodule.Data>(simplemodule.Data{ value: 0 }).value == 0
|
assert simple<simplemodule.Data>(simplemodule.Data{ value: 8 }).value == 8
|
||||||
|
assert simple<&simplemodule.Data>(&simplemodule.Data{ value: 123 }).value == 123
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plus<T>(xxx T, b T) T {
|
fn plus<T>(xxx T, b T) T {
|
||||||
|
|
Loading…
Reference in New Issue