Skip to content

Commit

Permalink
all: add .pos fields to all AST nodes, to avoid wrong positions in er…
Browse files Browse the repository at this point in the history
…ror messages
  • Loading branch information
spytheman committed Nov 4, 2020
1 parent 2591267 commit 9eb655e
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 54 deletions.
43 changes: 29 additions & 14 deletions vlib/v/ast/ast.v
Expand Up @@ -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 {
Expand Down Expand Up @@ -276,7 +278,8 @@ pub mut:
// break, continue
pub struct BranchStmt {
pub:
tok token.Token
kind token.Kind
pos token.Position
}

pub struct CallExpr {
Expand Down Expand Up @@ -591,6 +594,7 @@ pub:
val_var string
stmts []Stmt
kind CompForKind
pos token.Position
pub mut:
// expr Expr
typ table.Type
Expand Down Expand Up @@ -738,6 +742,7 @@ pub:
pub struct DeferStmt {
pub:
stmts []Stmt
pos token.Position
pub mut:
ifdef string
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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{...} }
Expand Down Expand Up @@ -848,6 +858,7 @@ pub struct IfGuardExpr {
pub:
var_name string
expr Expr
pos token.Position
pub mut:
expr_type table.Type
}
Expand Down Expand Up @@ -905,6 +916,7 @@ pub:
pub struct TypeOf {
pub:
expr Expr
pos token.Position
pub mut:
expr_type table.Type
}
Expand All @@ -920,6 +932,7 @@ pub:
pub struct ConcatExpr {
pub:
vals []Expr
pos token.Position
pub mut:
return_type table.Type
}
Expand Down Expand Up @@ -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()
Expand All @@ -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.
}
}

Expand Down Expand Up @@ -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.
}
}

Expand Down
6 changes: 3 additions & 3 deletions vlib/v/checker/checker.v
Expand Up @@ -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
}
}
Expand Down Expand Up @@ -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 {
Expand Down
23 changes: 12 additions & 11 deletions 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 | }
2 changes: 1 addition & 1 deletion vlib/v/fmt/fmt.v
Expand Up @@ -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 {}
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/gen/cgen.v
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/js/js.v
Expand Up @@ -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(';')
}

Expand Down
2 changes: 2 additions & 0 deletions vlib/v/parser/comptime.v
Expand Up @@ -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())
}
}

Expand Down
2 changes: 2 additions & 0 deletions vlib/v/parser/if_match.v
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
36 changes: 14 additions & 22 deletions vlib/v/parser/parser.v
Expand Up @@ -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())
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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())
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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{...}`
Expand Down Expand Up @@ -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
}
}
}
Expand All @@ -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
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions vlib/v/parser/pratt.v
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 9eb655e

Please sign in to comment.