mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: fix forwarding vargs & multiple call varg len fix
This commit is contained in:
parent
de8297c983
commit
fe9d884d90
@ -813,8 +813,8 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||
f.is_variadic = true
|
||||
t := p.get_type()
|
||||
// register varg struct, incase function is never called
|
||||
if p.first_pass() && !f.is_generic {
|
||||
p.fn_register_vargs_stuct(f, t, []string)
|
||||
if p.first_pass() && !f.is_generic && !f.is_c{
|
||||
p.register_vargs_stuct(t, 0)
|
||||
}
|
||||
typ = '...$t'
|
||||
} else {
|
||||
@ -1205,21 +1205,25 @@ fn (p mut Parser) replace_type_params(f &Fn, ti TypeInst) []string {
|
||||
return r
|
||||
}
|
||||
|
||||
fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) string {
|
||||
vargs_struct := '_V_FnVargs_$f.name'
|
||||
fn (p mut Parser) register_vargs_stuct(typ string, len int) string {
|
||||
vargs_struct := '_V_FnVargs_$typ'
|
||||
varg_type := Type{
|
||||
cat: TypeCategory.struct_,
|
||||
name: vargs_struct,
|
||||
mod: p.mod
|
||||
}
|
||||
mut varg_len := len
|
||||
if !p.table.known_type(vargs_struct) {
|
||||
p.table.register_type2(varg_type)
|
||||
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
|
||||
} else {
|
||||
ex_typ := p.table.find_type(vargs_struct)
|
||||
ex_len := ex_typ.fields[1].name[5..ex_typ.fields[1].name.len-1].int()
|
||||
if ex_len > varg_len { varg_len = ex_len }
|
||||
p.table.rewrite_type(varg_type)
|
||||
}
|
||||
p.table.add_field(vargs_struct, 'len', 'int', false, '', .public)
|
||||
p.table.add_field(vargs_struct, 'args[$values.len]', typ, false, '', .public)
|
||||
p.table.add_field(vargs_struct, 'args[$varg_len]', typ, false, '', .public)
|
||||
return vargs_struct
|
||||
}
|
||||
|
||||
@ -1238,6 +1242,10 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
|
||||
p.cgen.start_tmp()
|
||||
mut varg_type := p.bool_expression()
|
||||
varg_value := p.cgen.end_tmp()
|
||||
if varg_type.starts_with('...') &&
|
||||
(values.len > 0 || p.tok == .comma) {
|
||||
p.error('You cannot pass additional vargs when forwarding vargs to another function/method')
|
||||
}
|
||||
if !f.is_generic {
|
||||
p.check_types(last_arg.typ, varg_type)
|
||||
} else {
|
||||
@ -1246,7 +1254,6 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
|
||||
p.check_types(varg_type, t)
|
||||
}
|
||||
}
|
||||
varg_def_type = varg_type
|
||||
}
|
||||
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' }
|
||||
else if !last_arg.typ.ends_with('*') && varg_type.ends_with('*') { '*' }
|
||||
@ -1263,12 +1270,17 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
|
||||
if !f.is_method && f.args.len > 1 {
|
||||
p.cgen.gen(',')
|
||||
}
|
||||
return varg_def_type, values
|
||||
return types[0], values
|
||||
}
|
||||
|
||||
fn (p mut Parser) fn_gen_caller_vargs(f &Fn, varg_type string, values []string) {
|
||||
vargs_struct := p.fn_register_vargs_stuct(f, varg_type, values)
|
||||
is_varg := varg_type.starts_with('...')
|
||||
if is_varg { // forwarding varg
|
||||
p.cgen.gen('${values[0]}')
|
||||
} else {
|
||||
vargs_struct := p.register_vargs_stuct(varg_type, values.len)
|
||||
p.cgen.gen('&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}')
|
||||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) register_multi_return_stuct(types []string) string {
|
||||
@ -1450,7 +1462,7 @@ fn (f &Fn) str_args(table &Table) string {
|
||||
}
|
||||
}
|
||||
else if arg.typ.starts_with('...') {
|
||||
s += '_V_FnVargs_$f.name *$arg.name'
|
||||
s += '_V_FnVargs_${arg.typ[3..]} *$arg.name'
|
||||
}
|
||||
else {
|
||||
// s += '$arg.typ $arg.name'
|
||||
|
@ -2,6 +2,7 @@ struct VaTestGroup {
|
||||
name string
|
||||
}
|
||||
|
||||
// basic
|
||||
fn variadic_test(name string, groups ...VaTestGroup) {
|
||||
assert groups.len == 2
|
||||
assert groups[0].name == 'users'
|
||||
@ -14,6 +15,7 @@ fn test_fn_variadic() {
|
||||
variadic_test('joe', group1, group2)
|
||||
}
|
||||
|
||||
// generic
|
||||
fn variadic_test_generic<T>(a int, b ...T) T {
|
||||
b1 := b[0]
|
||||
b2 := b[1]
|
||||
@ -23,3 +25,19 @@ fn variadic_test_generic<T>(a int, b ...T) T {
|
||||
fn test_fn_variadic_generic() {
|
||||
assert variadic_test_generic(111, 'hello', 'v') == '111 hello v'
|
||||
}
|
||||
|
||||
// forwarding
|
||||
fn variadic_forward_a(a ...string) string {
|
||||
return variadic_forward_b(a)
|
||||
}
|
||||
|
||||
fn variadic_forward_b(a ...string) string {
|
||||
a0 := a[0]
|
||||
a1 := a[1]
|
||||
a2 := a[2]
|
||||
return '$a0$a1$a2'
|
||||
}
|
||||
|
||||
fn test_fn_variadic_forward() {
|
||||
assert variadic_forward_a('a', 'b', 'c') == 'abc'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user