diff --git a/vlib/compiler/aparser.v b/vlib/compiler/aparser.v index a21af38ab3..5966631001 100644 --- a/vlib/compiler/aparser.v +++ b/vlib/compiler/aparser.v @@ -1597,11 +1597,13 @@ fn ($v.name mut $v.typ) ${p.cur_fn.name}(...) { } else { p.gen(' ' + p.tok.str() + ' ') - }} + } + } p.fspace() p.next() p.fspace() pos := p.cgen.cur_line.len + expr_tok := p.cur_tok_index() p.is_var_decl = true expr_type := p.bool_expression() p.is_var_decl = false @@ -1609,8 +1611,8 @@ fn ($v.name mut $v.typ) ${p.cur_fn.name}(...) { // p.warn('expecting array got $expr_type') // } if expr_type == 'void' { - _,fn_name := p.is_expr_fn_call(p.token_idx - 3) - p.error_with_token_index('${fn_name}() $err_used_as_value', p.token_idx - 2) + _,fn_name := p.is_expr_fn_call(expr_tok+1) + p.error_with_token_index('${fn_name}() $err_used_as_value', expr_tok) } // Allow `num = 4` where `num` is an `?int` if p.assigned_type.starts_with('Option_') && expr_type == parse_pointer(p.assigned_type['Option_'.len..]) { @@ -1714,6 +1716,7 @@ fn (p mut Parser) var_decl() { else { p.error('expected `=` or `:=`') } + expr_tok := p.cur_tok_index() // all vars on left of `:=` already defined (or `_`) if is_decl_assign && var_names.len == 1 && var_names[0] == '_' { p.error_with_token_index('use `=` instead of `:=`', var_token_idxs.last()) @@ -1721,8 +1724,8 @@ fn (p mut Parser) var_decl() { p.var_decl_name = if var_names.len > 1 { '_V_mret_${p.token_idx}_' + var_names.join('_') } else { var_names[0] } t := p.gen_var_decl(p.var_decl_name, is_static) if t == 'void' { - _,fn_name := p.is_expr_fn_call(p.token_idx - 3) - p.error_with_token_index('${fn_name}() $err_used_as_value', p.token_idx - 2) + _,fn_name := p.is_expr_fn_call(expr_tok+1) + p.error_with_token_index('${fn_name}() $err_used_as_value', expr_tok) } mut var_types := [t] // multiple returns types diff --git a/vlib/compiler/compile_errors.v b/vlib/compiler/compile_errors.v index 7e0d4110ba..2e1f5ad904 100644 --- a/vlib/compiler/compile_errors.v +++ b/vlib/compiler/compile_errors.v @@ -197,6 +197,33 @@ fn (p mut Parser) print_error_context() { // p.scanner.debug_tokens() } +fn ienv_default(ename string, idefault int) int { + es := os.getenv(ename) + if es.len == 0 { return idefault } + return es.int() +} + +// print_current_tokens/1 pretty prints the current token context, like this: +// // Your label: tokens[ 32] = Token{ .line: 8, .pos: 93, .tok: 85 } = mut +// // Your label: tokens[> 33] = Token{ .line: 8, .pos: 95, .tok: 1 } = b +// // Your label: tokens[ 34] = Token{ .line: 8, .pos: 98, .tok: 31 } = := +// It is useful while debugging the v compiler itself. > marks p.token_idx +fn (p &Parser) print_current_tokens(label string){ + btokens := ienv_default('V_BTOKENS', 5) + atokens := ienv_default('V_ATOKENS', 5) + ctoken_idx := p.token_idx + stoken_idx := imax(0, ctoken_idx - btokens) + etoken_idx := imin( ctoken_idx + atokens + 1, p.tokens.len) + for i := stoken_idx; i < etoken_idx; i++ { + idx := if i == ctoken_idx { + '>${i:3d}' + } else { + ' ${i:3d}' + } + eprintln('$label: tokens[$idx] = ' + p.tokens[ i ].detailed_str()) + } +} + fn normalized_error(s string) string { mut res := s if !res.contains('__') { diff --git a/vlib/compiler/gen_c.v b/vlib/compiler/gen_c.v index 60b19a90f3..dc49332f76 100644 --- a/vlib/compiler/gen_c.v +++ b/vlib/compiler/gen_c.v @@ -65,10 +65,11 @@ fn (p mut Parser) gen_blank_identifier_assign() { is_indexer := p.peek() == .lsbr is_fn_call,next_expr := p.is_expr_fn_call(p.token_idx) pos := p.cgen.add_placeholder() + expr_tok := p.cur_tok_index() p.is_var_decl = true typ := p.bool_expression() if typ == 'void' { - p.error_with_token_index('${next_expr}() $err_used_as_value', p.token_idx - 2) + p.error_with_token_index('${next_expr}() $err_used_as_value', expr_tok) } p.is_var_decl = false if !is_indexer && !is_fn_call { diff --git a/vlib/compiler/token.v b/vlib/compiler/token.v index d1c1f687f2..6431a8a2bb 100644 --- a/vlib/compiler/token.v +++ b/vlib/compiler/token.v @@ -292,9 +292,16 @@ pub fn (t Token) str() string { if t.tok == .str { return "'$t.lit'" } + if t.tok == .eof { + return '.EOF' + } if t.tok < .plus { return t.lit // string, number etc } return t.tok.str() } +pub fn (t Token) detailed_str() string { + return 'Token{ .line:${t.line_nr:4d}, .pos:${t.pos:5d}, .tok: ${t.tok:3d} } = $t ' +} +