all: add .pos fields to all AST nodes, to avoid wrong positions in error messages

pull/6736/head
Delyan Angelov 2020-11-04 13:34:12 +02:00
parent 25912673a9
commit 9eb655e65c
10 changed files with 69 additions and 54 deletions

View File

@ -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.
}
}

View File

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

View File

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

View File

@ -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 {}

View File

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

View File

@ -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(';')
}

View File

@ -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())
}
}

View File

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

View File

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

View File

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