diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index f8d4bdd1fa42cf..e9a47820df23b6 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -21,6 +21,8 @@ pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDe GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlStmt | StructDecl | TypeDecl +// NB: when you add a new Expr or Stmt type with a .pos field, remember to update +// the .position() token.Position methods too. pub type ScopeObject = ConstField | GlobalField | Var pub struct Type { @@ -276,7 +278,8 @@ pub mut: // break, continue pub struct BranchStmt { pub: - tok token.Token + kind token.Kind + pos token.Position } pub struct CallExpr { @@ -591,6 +594,7 @@ pub: val_var string stmts []Stmt kind CompForKind + pos token.Position pub mut: // expr Expr typ table.Type @@ -738,6 +742,7 @@ pub: pub struct DeferStmt { pub: stmts []Stmt + pos token.Position pub mut: ifdef string } @@ -746,21 +751,25 @@ pub mut: pub struct ParExpr { pub: expr Expr + pos token.Position } pub struct GoStmt { pub: call_expr Expr + pos token.Position } pub struct GotoLabel { pub: name string + pos token.Position } pub struct GotoStmt { pub: name string + pos token.Position } pub struct ArrayInit { @@ -813,6 +822,7 @@ pub: high Expr has_high bool has_low bool + pos token.Position } // NB: &string(x) gets parsed as ast.PrefixExpr{ right: ast.CastExpr{...} } @@ -848,6 +858,7 @@ pub struct IfGuardExpr { pub: var_name string expr Expr + pos token.Position pub mut: expr_type table.Type } @@ -905,6 +916,7 @@ pub: pub struct TypeOf { pub: expr Expr + pos token.Position pub mut: expr_type table.Type } @@ -920,6 +932,7 @@ pub: pub struct ConcatExpr { pub: vals []Expr + pos token.Position pub mut: return_type table.Type } @@ -1006,9 +1019,15 @@ pub fn (expr Expr) position() token.Position { AnonFn { return expr.decl.pos } - ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, CharLiteral, Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr, IntegerLiteral, MapInit, MatchExpr, None, PostfixExpr, PrefixExpr, SelectExpr, SelectorExpr, SizeOf, StringLiteral, StringInterLiteral, StructInit, Likely { + ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, ChanInit, CharLiteral, ConcatExpr, Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, MatchExpr, None, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf, UnsafeExpr { return expr.pos } + IfGuardExpr { + return expr.expr.position() + } + ComptimeCall { + return expr.left.position() + } InfixExpr { left_pos := expr.left.position() right_pos := expr.right.position() @@ -1021,17 +1040,12 @@ pub fn (expr Expr) position() token.Position { len: right_pos.pos - left_pos.pos + right_pos.len } } - /* - ast.Ident {} - ast.IfGuardExpr {} - ast.None {} - ast.ParExpr {} - ast.Type {} - ast.TypeOf {} - */ - else { + CTempVar { return token.Position{} } + // Please, do NOT use else{} here. + // This match is exhaustive *on purpose*, to help force + // maintaining/implementing proper .pos fields. } } @@ -1083,13 +1097,14 @@ pub: pub fn (stmt Stmt) position() token.Position { match stmt { - AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl, GlobalDecl, HashStmt, InterfaceDecl, Module { return stmt.pos } + AssertStmt, AssignStmt, Block, BranchStmt, CompFor, ConstDecl, DeferStmt, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, GotoLabel, GotoStmt, Import, Return, StructDecl, GlobalDecl, HashStmt, InterfaceDecl, Module, SqlStmt { return stmt.pos } GoStmt { return stmt.call_expr.position() } - BranchStmt { return token.Position{stmt.tok.len, stmt.tok.line_nr, stmt.tok.pos} } TypeDecl { match stmt { AliasTypeDecl, FnTypeDecl, SumTypeDecl { return stmt.pos } } } - else { return token.Position{} } + // Please, do NOT use else{} here. + // This match is exhaustive *on purpose*, to help force + // maintaining/implementing proper .pos fields. } } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e22b40399ccd79..e10b6ddccac99d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1667,9 +1667,9 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type, ex return } ast.BranchStmt { - if last_stmt.tok.kind !in [.key_continue, .key_break] { + if last_stmt.kind !in [.key_continue, .key_break] { c.error('only break/continue is allowed as a branch statement in the end of an `or {}` block', - last_stmt.tok.position()) + last_stmt.pos) return } } @@ -2324,7 +2324,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { } ast.BranchStmt { if c.in_for_count == 0 { - c.error('$node.tok.lit statement not within a loop', node.tok.position()) + c.error('$node.kind.str() statement not within a loop', node.pos) } } ast.CompFor { diff --git a/vlib/v/checker/tests/prefix_expr_decl_assign_err.out b/vlib/v/checker/tests/prefix_expr_decl_assign_err.out index f18057d0ac20bb..00bb16b5bb1a68 100644 --- a/vlib/v/checker/tests/prefix_expr_decl_assign_err.out +++ b/vlib/v/checker/tests/prefix_expr_decl_assign_err.out @@ -1,11 +1,12 @@ -vlib/v/checker/tests/prefix_expr_decl_assign_err.vv:2:5: error: non-name on the left side of `:=` - 1 | fn main() { - 2 | &a := 12 - | ^ - 3 | (*d) := 14 - 4 | } -vlib/v/checker/tests/prefix_expr_decl_assign_err.vv:1:1: error: non-name `(*d)` on left side of `:=` - 1 | fn main() { - | ^ - 2 | &a := 12 - 3 | (*d) := 14 +vlib/v/checker/tests/prefix_expr_decl_assign_err.vv:2:5: error: non-name on the left side of `:=` + 1 | fn main() { + 2 | &a := 12 + | ^ + 3 | (*d) := 14 + 4 | } +vlib/v/checker/tests/prefix_expr_decl_assign_err.vv:3:10: error: non-name `(*d)` on left side of `:=` + 1 | fn main() { + 2 | &a := 12 + 3 | (*d) := 14 + | ~~ + 4 | } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 51be07d37c6e73..c4f037a1fcb224 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -301,7 +301,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) { f.writeln('}') } ast.BranchStmt { - match node.tok.kind { + match node.kind { .key_break { f.writeln('break') } .key_continue { f.writeln('continue') } else {} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 8b8a0d8b8dc96c..654e80eba291d1 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -794,9 +794,9 @@ fn (mut g Gen) stmt(node ast.Stmt) { g.writeln('}') } ast.BranchStmt { - g.write_v_source_line_info(node.tok.position()) + g.write_v_source_line_info(node.pos) // continue or break - g.write(node.tok.kind.str()) + g.write(node.kind.str()) g.writeln(';') } ast.ConstDecl { diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 02aaccba104970..e324c48eb1ca2b 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -771,7 +771,7 @@ fn (mut g JsGen) gen_block(it ast.Block) { fn (mut g JsGen) gen_branch_stmt(it ast.BranchStmt) { // continue or break - g.write(it.tok.kind.str()) + g.write(it.kind.str()) g.writeln(';') } diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 5ee33fe3efeae0..dc471efa3055ce 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -139,12 +139,14 @@ fn (mut p Parser) comp_for() ast.CompFor { } else { p.error('unknown kind `$for_val`, available are: `methods` or `fields`') } + spos := p.tok.position() stmts := p.parse_block() return ast.CompFor{ val_var: val_var stmts: stmts kind: kind typ: typ + pos: spos.extend(p.tok.position()) } } diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 13ace8394fee76..6012451edf56fd 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -230,6 +230,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr { types << parsed_type exprs << ast.Type{ typ: parsed_type + pos: p.tok.position() } if p.tok.kind != .comma { break @@ -298,6 +299,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr { high: expr2 has_low: true has_high: true + pos: p.tok.position() } } else { exprs << expr diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index bf1762f2255b4a..dca6afc6015d4c 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -585,10 +585,12 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { } if p.peek_tok.kind == .colon { // `label:` + spos := p.tok.position() name := p.check_name() p.next() return ast.GotoLabel{ name: name + pos: spos.extend(p.tok.position()) } } else if p.peek_tok.kind == .name { p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position()) @@ -624,7 +626,8 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { tok := p.tok p.next() return ast.BranchStmt{ - tok: tok + kind: tok.kind + pos: tok.position() } } .key_unsafe { @@ -635,25 +638,31 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { } .key_defer { p.next() + spos := p.tok.position() stmts := p.parse_block() return ast.DeferStmt{ stmts: stmts + pos: spos.extend(p.tok.position()) } } .key_go { p.next() + spos := p.tok.position() expr := p.expr(0) // mut call_expr := &ast.CallExpr(0) // TODO // { call_expr = it } return ast.GoStmt{ call_expr: expr + pos: spos.extend(p.tok.position()) } } .key_goto { p.next() + spos := p.tok.position() name := p.check_name() return ast.GotoStmt{ name: name + pos: spos } } .key_const { @@ -766,27 +775,6 @@ fn (mut p Parser) parse_attr() table.Attr { } } -/* -fn (mut p Parser) range_expr(low ast.Expr) ast.Expr { - // ,table.Type) { - if p.tok.kind != .dotdot { - p.next() - } - p.check(.dotdot) - mut high := ast.Expr{} - if p.tok.kind != .rsbr { - high = p.expr(0) - // if typ.typ.kind != .int { - // p.error('non-integer index `$typ.typ.name`') - // } - } - node := ast.RangeExpr{ - low: low - high: high - } - return node -} -*/ pub fn (mut p Parser) error(s string) { p.error_with_pos(s, p.tok.position()) } @@ -877,6 +865,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt { return ast.ExprStmt{ expr: ast.ConcatExpr{ vals: left + pos: tok.position() } pos: tok.position() comments: left_comments @@ -967,6 +956,7 @@ pub fn (mut p Parser) name_expr() ast.Expr { } return ast.MapInit{ typ: map_type + pos: p.tok.position() } } // `chan typ{...}` @@ -1153,6 +1143,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr { low: ast.Expr{} high: high has_high: true + pos: pos } } } @@ -1176,6 +1167,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr { high: high has_high: has_high has_low: has_low + pos: pos } } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index d32d5c1ee8eaa8..084e6b3c738341 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -85,6 +85,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { p.check(.rpar) node = ast.ParExpr{ expr: node + pos: p.tok.position() } } .key_if { @@ -151,12 +152,14 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { p.check(.rpar) } .key_typeof { + spos := p.tok.position() p.next() p.check(.lpar) expr := p.expr(0) p.check(.rpar) node = ast.TypeOf{ expr: expr + pos: spos.extend(p.tok.position()) } } .key_likely, .key_unlikely {