compiler: variadic fn - improve error, fix bug when only arg is varg
parent
ceee2923dd
commit
282cd44cec
|
@ -747,7 +747,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||||
t := p.get_type()
|
t := p.get_type()
|
||||||
vargs_struct := '_V_FnVargs_$f.name'
|
vargs_struct := '_V_FnVargs_$f.name'
|
||||||
// register varg struct, incase function is never called
|
// 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'
|
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
|
||||||
typ = '...$t'
|
typ = '...$t'
|
||||||
} else {
|
} else {
|
||||||
|
@ -1029,7 +1029,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
||||||
return f // TODO is return f right?
|
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'
|
vargs_struct := '_V_FnVargs_$f.name'
|
||||||
varg_type := Type{
|
varg_type := Type{
|
||||||
cat: TypeCategory.struct_,
|
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 {
|
if values.len > 0 {
|
||||||
p.table.rewrite_type(varg_type)
|
p.table.rewrite_type(varg_type)
|
||||||
p.cgen.gen(',&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}')
|
|
||||||
} else {
|
} else {
|
||||||
p.table.register_type2(varg_type)
|
p.table.register_type2(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[$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) {
|
fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) {
|
||||||
last_arg := f.args.last()
|
last_arg := f.args.last()
|
||||||
varg_def_type := last_arg.typ.right(3)
|
varg_def_type := last_arg.typ.right(3)
|
||||||
mut varg_values := []string
|
mut values := []string
|
||||||
for p.tok != .rpar {
|
for p.tok != .rpar {
|
||||||
if p.tok == .comma {
|
if p.tok == .comma {
|
||||||
p.check(.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('*') { '&' }
|
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('*') { '*' }
|
||||||
else { '' }
|
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"
|
// "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_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*')
|
||||||
is_indexer := p.tok == .lsbr
|
is_indexer := p.tok == .lsbr
|
||||||
mut close_bracket := false
|
mut close_bracket := false
|
||||||
|
index_error_tok_pos := p.token_idx
|
||||||
if is_indexer {
|
if is_indexer {
|
||||||
is_fixed_arr := typ[0] == `[`
|
is_fixed_arr := typ[0] == `[`
|
||||||
if !is_str && !is_arr && !is_map && !is_ptr && !is_fixed_arr && !is_variadic_arg {
|
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.cgen.resetln(l.left(fn_ph))
|
||||||
p.table.varg_access << VargAccess{
|
p.table.varg_access << VargAccess{
|
||||||
fn_name: p.cur_fn.name,
|
fn_name: p.cur_fn.name,
|
||||||
tok_idx: p.token_idx,
|
tok_idx: index_error_tok_pos,
|
||||||
index: index_val.int()
|
index: index_val.int()
|
||||||
}
|
}
|
||||||
p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')
|
p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')
|
||||||
|
|
Loading…
Reference in New Issue