1
0
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:
joe-conigliaro 2019-10-01 21:48:19 +10:00 committed by Alexander Medvednikov
parent ceee2923dd
commit 282cd44cec
2 changed files with 17 additions and 13 deletions

View File

@ -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"

View File

@ -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]')