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
|
f.is_variadic = true
|
||||||
t := p.get_type()
|
t := p.get_type()
|
||||||
// register varg struct, incase function is never called
|
// register varg struct, incase function is never called
|
||||||
if p.first_pass() && !f.is_generic {
|
if p.first_pass() && !f.is_generic && !f.is_c{
|
||||||
p.fn_register_vargs_stuct(f, t, []string)
|
p.register_vargs_stuct(t, 0)
|
||||||
}
|
}
|
||||||
typ = '...$t'
|
typ = '...$t'
|
||||||
} else {
|
} else {
|
||||||
@ -1205,21 +1205,25 @@ fn (p mut Parser) replace_type_params(f &Fn, ti TypeInst) []string {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) string {
|
fn (p mut Parser) register_vargs_stuct(typ string, len int) string {
|
||||||
vargs_struct := '_V_FnVargs_$f.name'
|
vargs_struct := '_V_FnVargs_$typ'
|
||||||
varg_type := Type{
|
varg_type := Type{
|
||||||
cat: TypeCategory.struct_,
|
cat: TypeCategory.struct_,
|
||||||
name: vargs_struct,
|
name: vargs_struct,
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
}
|
}
|
||||||
|
mut varg_len := len
|
||||||
if !p.table.known_type(vargs_struct) {
|
if !p.table.known_type(vargs_struct) {
|
||||||
p.table.register_type2(varg_type)
|
p.table.register_type2(varg_type)
|
||||||
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
|
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
|
||||||
} else {
|
} 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.rewrite_type(varg_type)
|
||||||
}
|
}
|
||||||
p.table.add_field(vargs_struct, 'len', 'int', false, '', .public)
|
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
|
return vargs_struct
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,6 +1242,10 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
|
|||||||
p.cgen.start_tmp()
|
p.cgen.start_tmp()
|
||||||
mut varg_type := p.bool_expression()
|
mut varg_type := p.bool_expression()
|
||||||
varg_value := p.cgen.end_tmp()
|
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 {
|
if !f.is_generic {
|
||||||
p.check_types(last_arg.typ, varg_type)
|
p.check_types(last_arg.typ, varg_type)
|
||||||
} else {
|
} else {
|
||||||
@ -1246,7 +1254,6 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
|
|||||||
p.check_types(varg_type, t)
|
p.check_types(varg_type, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
varg_def_type = varg_type
|
|
||||||
}
|
}
|
||||||
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' }
|
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' }
|
||||||
else 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 {
|
if !f.is_method && f.args.len > 1 {
|
||||||
p.cgen.gen(',')
|
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) {
|
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(',')+'}}')
|
p.cgen.gen('&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) register_multi_return_stuct(types []string) string {
|
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('...') {
|
else if arg.typ.starts_with('...') {
|
||||||
s += '_V_FnVargs_$f.name *$arg.name'
|
s += '_V_FnVargs_${arg.typ[3..]} *$arg.name'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// s += '$arg.typ $arg.name'
|
// s += '$arg.typ $arg.name'
|
||||||
|
@ -2,6 +2,7 @@ struct VaTestGroup {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// basic
|
||||||
fn variadic_test(name string, groups ...VaTestGroup) {
|
fn variadic_test(name string, groups ...VaTestGroup) {
|
||||||
assert groups.len == 2
|
assert groups.len == 2
|
||||||
assert groups[0].name == 'users'
|
assert groups[0].name == 'users'
|
||||||
@ -14,6 +15,7 @@ fn test_fn_variadic() {
|
|||||||
variadic_test('joe', group1, group2)
|
variadic_test('joe', group1, group2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generic
|
||||||
fn variadic_test_generic<T>(a int, b ...T) T {
|
fn variadic_test_generic<T>(a int, b ...T) T {
|
||||||
b1 := b[0]
|
b1 := b[0]
|
||||||
b2 := b[1]
|
b2 := b[1]
|
||||||
@ -23,3 +25,19 @@ fn variadic_test_generic<T>(a int, b ...T) T {
|
|||||||
fn test_fn_variadic_generic() {
|
fn test_fn_variadic_generic() {
|
||||||
assert variadic_test_generic(111, 'hello', 'v') == '111 hello v'
|
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