From d0ff9a7c4abef1e33196e41dd4fa43c3237d04bb Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 3 Jun 2020 13:42:02 +0800 Subject: [PATCH] parser: correct fn arg position in error message --- .../checker/tests/function_arg_redefinition.out | 5 +++++ .../checker/tests/function_arg_redefinition.vv | 7 +++++++ .../tests/function_variadic_arg_non_final.out | 5 +++++ .../tests/function_variadic_arg_non_final.vv | 7 +++++++ vlib/v/parser/fn.v | 17 +++++++++++------ vlib/v/table/table.v | 2 ++ 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 vlib/v/checker/tests/function_arg_redefinition.out create mode 100644 vlib/v/checker/tests/function_arg_redefinition.vv create mode 100644 vlib/v/checker/tests/function_variadic_arg_non_final.out create mode 100644 vlib/v/checker/tests/function_variadic_arg_non_final.vv diff --git a/vlib/v/checker/tests/function_arg_redefinition.out b/vlib/v/checker/tests/function_arg_redefinition.out new file mode 100644 index 0000000000..b6a513dd9f --- /dev/null +++ b/vlib/v/checker/tests/function_arg_redefinition.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/function_arg_redefinition.v:1:17: error: redefinition of parameter `para1` + 1 | fn f(para1 int, para1 f32) int { + | ~~~~~ + 2 | return para1 + 3 | } diff --git a/vlib/v/checker/tests/function_arg_redefinition.vv b/vlib/v/checker/tests/function_arg_redefinition.vv new file mode 100644 index 0000000000..0618fbaab6 --- /dev/null +++ b/vlib/v/checker/tests/function_arg_redefinition.vv @@ -0,0 +1,7 @@ +fn f(para1 int, para1 f32) int { + return para1 +} + +fn main() { + a := f(11, 1.1) +} diff --git a/vlib/v/checker/tests/function_variadic_arg_non_final.out b/vlib/v/checker/tests/function_variadic_arg_non_final.out new file mode 100644 index 0000000000..38cc4481b4 --- /dev/null +++ b/vlib/v/checker/tests/function_variadic_arg_non_final.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/function_variadic_arg_non_final.v:1:6: error: cannot use ...(variadic) with non-final parameter para1 + 1 | fn f(para1 ...int, para2 f32) int { + | ~~~~~ + 2 | return 22 + 3 | } diff --git a/vlib/v/checker/tests/function_variadic_arg_non_final.vv b/vlib/v/checker/tests/function_variadic_arg_non_final.vv new file mode 100644 index 0000000000..f7ce72afb8 --- /dev/null +++ b/vlib/v/checker/tests/function_variadic_arg_non_final.vv @@ -0,0 +1,7 @@ +fn f(para1 ...int, para2 f32) int { + return 22 +} + +fn main() { + a := f(11, 1.1) +} diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 13d0fd943f..63b9b47fc1 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -204,7 +204,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { args << args2 for i, arg in args { if p.scope.known_var(arg.name) { - p.error('redefinition of parameter `$arg.name`') + p.error_with_pos('redefinition of parameter `$arg.name`', arg.pos) } p.scope.register(arg.name, ast.Var{ name: arg.name @@ -223,8 +223,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl { sym := p.table.get_type_symbol(arg.typ) if sym.kind !in [.array, .struct_, .map, .placeholder] && arg.typ != table.t_type && !arg.typ.is_ptr() { - p.error('mutable arguments are only allowed for arrays, maps, and structs\n' + - 'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`') + p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' + + 'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`', arg.pos) } } } @@ -382,6 +382,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { p.next() is_variadic = true } + pos := p.tok.position() mut arg_type := p.parse_type() if is_mut && arg_type != table.t_type { // if arg_type.is_ptr() { @@ -395,11 +396,12 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { } if p.tok.kind == .comma { if is_variadic { - p.error('cannot use ...(variadic) with non-final parameter no $arg_no') + p.error_with_pos('cannot use ...(variadic) with non-final parameter no $arg_no', pos) } p.next() } args << table.Arg{ + pos: pos name: arg_name is_mut: is_mut typ: arg_type @@ -412,10 +414,12 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { if is_mut { p.next() } + mut arg_pos := [p.tok.position()] mut arg_names := [p.check_name()] // `a, b, c int` for p.tok.kind == .comma { p.next() + arg_pos << p.tok.position() arg_names << p.check_name() } if p.tok.kind == .key_mut { @@ -437,15 +441,16 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { if is_variadic { typ = typ.set_flag(.variadic) } - for arg_name in arg_names { + for i, arg_name in arg_names { args << table.Arg{ + pos: arg_pos[i] name: arg_name is_mut: is_mut typ: typ } // if typ.typ.kind == .variadic && p.tok.kind == .comma { if is_variadic && p.tok.kind == .comma { - p.error('cannot use ...(variadic) with non-final parameter $arg_name') + p.error_with_pos('cannot use ...(variadic) with non-final parameter $arg_name', arg_pos[i]) } } if p.tok.kind != .rpar { diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 417247e3f0..ae3540d63c 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -5,6 +5,7 @@ module table import os import v.cflag +import v.token pub struct Table { pub mut: @@ -34,6 +35,7 @@ pub mut: pub struct Arg { pub: + pos token.Position name string is_mut bool typ Type