mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
generics: generic methods, cast to T
This commit is contained in:
parent
7d02eccbce
commit
280c7d396c
@ -392,8 +392,23 @@ fn (p mut Parser) fn_decl() {
|
||||
if f.is_generic {
|
||||
if p.first_pass() {
|
||||
f.body_idx = p.cur_tok_index()+1
|
||||
p.table.register_fn(f)
|
||||
if f.is_method {
|
||||
rcv := p.table.find_type(receiver_typ)
|
||||
if p.first_pass() && rcv.name == '' {
|
||||
r := Type {
|
||||
name: rcv.name.replace('*', '')
|
||||
mod: p.mod
|
||||
is_placeholder: true
|
||||
}
|
||||
p.table.register_type2(r)
|
||||
}
|
||||
// println('added generic method $rcv.name $f.name')
|
||||
p.add_method(rcv.name, f)
|
||||
} else {
|
||||
p.table.register_fn(f)
|
||||
}
|
||||
}
|
||||
if f.is_method { p.mark_var_changed(f.args[0]) }
|
||||
p.check_unused_variables()
|
||||
p.set_current_fn( EmptyFn )
|
||||
p.returns = false
|
||||
@ -692,9 +707,6 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
|
||||
// If we have a method placeholder,
|
||||
// we need to preappend "method(receiver, ...)"
|
||||
if f.is_method {
|
||||
if f.is_generic {
|
||||
p.error('generic methods are not yet implemented')
|
||||
}
|
||||
receiver := f.args.first()
|
||||
//println('r=$receiver.typ RT=$receiver_type')
|
||||
if receiver.is_mut && !p.expr_var.is_mut {
|
||||
@ -709,8 +721,8 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
|
||||
if !p.expr_var.is_changed {
|
||||
p.mark_var_changed(p.expr_var)
|
||||
}
|
||||
met_name := if f.is_generic { f.name } else { cgen_name }
|
||||
p.gen_method_call(receiver_type, f.typ, met_name, receiver, method_ph)
|
||||
met_call := p.gen_method_call(receiver, receiver_type, cgen_name, f.typ)
|
||||
p.cgen.set_placeholder(method_ph, met_call)
|
||||
} else {
|
||||
// Normal function call
|
||||
p.gen('$cgen_name (')
|
||||
@ -1082,8 +1094,8 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
|
||||
mut r := TypeInst{}
|
||||
mut i := 0
|
||||
mut args := args_
|
||||
args << f.typ
|
||||
for ai, e in args {
|
||||
if f.typ != 'void' { args << f.typ }
|
||||
for e in args {
|
||||
if e == '' { continue }
|
||||
tp := f.type_pars[i]
|
||||
mut ti := e
|
||||
@ -1118,6 +1130,11 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
|
||||
if r.inst[f.typ] == '' && f.typ in f.type_pars {
|
||||
r.inst[f.typ] = '_ANYTYPE_'
|
||||
}
|
||||
for tp in f.type_pars {
|
||||
if r.inst[tp] == '' {
|
||||
p.error_with_token_index('unused type parameter `$tp`', f.body_idx-2)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@ -1257,6 +1274,9 @@ fn (p mut Parser) register_multi_return_stuct(types []string) string {
|
||||
}
|
||||
|
||||
fn (p mut Parser) rename_generic_fn_instance(f mut Fn, ti TypeInst) {
|
||||
if f.is_method {
|
||||
f.name = f.receiver_typ + '_' + f.name
|
||||
}
|
||||
f.name = f.name + '_T'
|
||||
for k in ti.inst.keys() {
|
||||
f.name = f.name + '_' + type_to_safe_str(ti.inst[k].replace('...', ''))
|
||||
@ -1326,7 +1346,12 @@ fn (p mut Parser) dispatch_generic_fn_instance(f mut Fn, ti TypeInst) {
|
||||
if f.typ in ti.inst {
|
||||
f.typ = ti.inst[f.typ]
|
||||
}
|
||||
p.table.register_fn(f)
|
||||
|
||||
if f.is_method {
|
||||
p.add_method(f.args[0].name, f)
|
||||
} else {
|
||||
p.table.register_fn(f)
|
||||
}
|
||||
// println("generating gen inst $f.name(${f.str_args(p.table)}) $f.typ : $ti.inst")
|
||||
|
||||
p.cgen.is_tmp = false
|
||||
|
@ -247,11 +247,9 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
return name
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_method_call(receiver_type, ftyp string, cgen_name string,
|
||||
receiver Var,method_ph int)
|
||||
{
|
||||
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string, cgen_name string, ftyp string) string {
|
||||
//mut cgen_name := p.table.fn_gen_name(f)
|
||||
mut method_call := cgen_name + '('
|
||||
mut method_call := cgen_name + ' ('
|
||||
// if receiver is key_mut or a ref (&), generate & for the first arg
|
||||
if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) {
|
||||
method_call += '& /* ? */'
|
||||
@ -268,12 +266,11 @@ fn (p mut Parser) gen_method_call(receiver_type, ftyp string, cgen_name string,
|
||||
// array_int => int
|
||||
cast = receiver_type.all_after('array_')
|
||||
cast = '*($cast*) '
|
||||
}else{
|
||||
} else {
|
||||
cast = '(voidptr) '
|
||||
}
|
||||
}
|
||||
p.cgen.set_placeholder(method_ph, '$cast $method_call')
|
||||
//return method_call
|
||||
return '$cast $method_call'
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_array_at(typ_ string, is_arr0 bool, fn_ph int) {
|
||||
|
@ -1617,7 +1617,10 @@ fn (p mut Parser) name_expr() string {
|
||||
}
|
||||
p.gen('(')
|
||||
mut typ := name
|
||||
p.cast(name)
|
||||
if typ in p.cur_fn.dispatch_of.inst.keys() {
|
||||
typ = p.cur_fn.dispatch_of.inst[typ]
|
||||
}
|
||||
p.cast(typ)
|
||||
p.gen(')')
|
||||
for p.tok == .dot {
|
||||
typ = p.dot(typ, ph)
|
||||
|
@ -2,15 +2,15 @@ fn simple<T>(p T) T {
|
||||
return p
|
||||
}
|
||||
|
||||
fn sum<T>(l []T, nil T) T {
|
||||
mut r := nil
|
||||
fn sum<T>(l []T) T {
|
||||
mut r := T(0)
|
||||
for e in l {
|
||||
r += e
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
fn map_f<T,U,R>(l []T, f fn(T)U) []U {
|
||||
fn map_f<T,U>(l []T, f fn(T)U) []U {
|
||||
mut r := []U
|
||||
for e in l {
|
||||
r << f(e)
|
||||
@ -44,15 +44,39 @@ fn assert_eq<T>(a, b T) {
|
||||
assert r
|
||||
}
|
||||
|
||||
fn print_nice<T>(x T, indent int) {
|
||||
mut space := ''
|
||||
for i in 0..indent {
|
||||
space = space + ' '
|
||||
}
|
||||
println('$space$x')
|
||||
}
|
||||
|
||||
fn test_generic_fn() {
|
||||
assert_eq(simple(0+1), 1)
|
||||
assert_eq(simple('g') + 'h', 'gh')
|
||||
assert_eq(sum([5.1,6.2,7.0], 0.0), 18.3)
|
||||
assert_eq(sum([5.1,6.2,7.0]), 18.3)
|
||||
assert_eq(plus(i64(4), i64(6)), i64(10))
|
||||
a := [1,2,3,4]
|
||||
$if !windows {
|
||||
b := map_f(a, square)
|
||||
assert_eq(sum(b, 0), 30) // 1+4+9+16 = 30
|
||||
assert_eq(foldl(b, 1, mul_int), 576) // 1*4*9*16 = 576
|
||||
}
|
||||
b := map_f(a, square)
|
||||
assert_eq(sum(b), 30) // 1+4+9+16 = 30
|
||||
assert_eq(foldl(b, 1, mul_int), 576) // 1*4*9*16 = 576
|
||||
print_nice('str', 8)
|
||||
}
|
||||
|
||||
struct Point {
|
||||
mut:
|
||||
x f64
|
||||
y f64
|
||||
}
|
||||
|
||||
fn (p mut Point) translate<T>(x, y T) {
|
||||
p.x += x
|
||||
p.y += y
|
||||
}
|
||||
|
||||
fn test_generic_method() {
|
||||
mut p := Point{}
|
||||
p.translate(2, 1.0)
|
||||
assert p.x == 2.0 && p.y == 1.0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user