mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: variadic fn - improve error, fix bug when only arg is varg
This commit is contained in:
parent
ceee2923dd
commit
282cd44cec
@ -747,7 +747,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||
t := p.get_type()
|
||||
vargs_struct := '_V_FnVargs_$f.name'
|
||||
// register varg struct, incase function is never called
|
||||
p.fn_define_vargs_stuct(f, t, []string)
|
||||
p.fn_register_vargs_stuct(f, t, []string)
|
||||
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
|
||||
typ = '...$t'
|
||||
} else {
|
||||
@ -1029,7 +1029,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
||||
return f // TODO is return f right?
|
||||
}
|
||||
|
||||
fn (p mut Parser) fn_define_vargs_stuct(f &Fn, typ string, values []string) {
|
||||
fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) {
|
||||
vargs_struct := '_V_FnVargs_$f.name'
|
||||
varg_type := Type{
|
||||
cat: TypeCategory.struct_,
|
||||
@ -1038,24 +1038,17 @@ fn (p mut Parser) fn_define_vargs_stuct(f &Fn, typ string, values []string) {
|
||||
}
|
||||
if values.len > 0 {
|
||||
p.table.rewrite_type(varg_type)
|
||||
p.cgen.gen(',&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}')
|
||||
} else {
|
||||
p.table.register_type2(varg_type)
|
||||
}
|
||||
p.table.add_field(vargs_struct, 'len', 'int', false, '', .public)
|
||||
p.table.add_field(vargs_struct, 'args[$values.len]', typ, false, '', .public)
|
||||
for va in p.table.varg_access {
|
||||
if va.fn_name != f.name { continue }
|
||||
if va.index >= values.len {
|
||||
p.error_with_token_index('error accessing variadic arg, index `$va.index` out of range.', va.tok_idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) {
|
||||
last_arg := f.args.last()
|
||||
varg_def_type := last_arg.typ.right(3)
|
||||
mut varg_values := []string
|
||||
mut values := []string
|
||||
for p.tok != .rpar {
|
||||
if p.tok == .comma {
|
||||
p.check(.comma)
|
||||
@ -1067,9 +1060,19 @@ fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) {
|
||||
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' }
|
||||
else if !last_arg.typ.ends_with('*') && varg_type.ends_with('*') { '*' }
|
||||
else { '' }
|
||||
varg_values << '$ref_deref$varg_value'
|
||||
values << '$ref_deref$varg_value'
|
||||
}
|
||||
p.fn_define_vargs_stuct(f, varg_def_type, varg_values)
|
||||
for va in p.table.varg_access {
|
||||
if va.fn_name != f.name { continue }
|
||||
if va.index >= values.len {
|
||||
p.error_with_token_index('variadic arg index out of range: $va.index/${values.len-1}, vargs are 0 indexed', va.tok_idx)
|
||||
}
|
||||
}
|
||||
if f.args.len > 1 {
|
||||
p.cgen.gen(',')
|
||||
}
|
||||
p.cgen.gen('&(_V_FnVargs_$f.name){.len=$values.len,.args={'+values.join(',')+'}}')
|
||||
p.fn_register_vargs_stuct(f, varg_def_type, values)
|
||||
}
|
||||
|
||||
// "fn (int, string) int"
|
||||
|
@ -2106,6 +2106,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
|
||||
is_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*')
|
||||
is_indexer := p.tok == .lsbr
|
||||
mut close_bracket := false
|
||||
index_error_tok_pos := p.token_idx
|
||||
if is_indexer {
|
||||
is_fixed_arr := typ[0] == `[`
|
||||
if !is_str && !is_arr && !is_map && !is_ptr && !is_fixed_arr && !is_variadic_arg {
|
||||
@ -2202,7 +2203,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
|
||||
p.cgen.resetln(l.left(fn_ph))
|
||||
p.table.varg_access << VargAccess{
|
||||
fn_name: p.cur_fn.name,
|
||||
tok_idx: p.token_idx,
|
||||
tok_idx: index_error_tok_pos,
|
||||
index: index_val.int()
|
||||
}
|
||||
p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')
|
||||
|
Loading…
Reference in New Issue
Block a user