From 2d429f01bd917c42e66e1991eab9c2e33d813d16 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Dec 2016 15:38:23 -0800 Subject: [PATCH] [dev.inline] cmd/compile/internal/syntax: add predicates to syntax.Pos This moves syntax.Pos closer to cmd/internal/src.Pos so that we can more easily replace src.Pos with syntax.Pos going forward. Change-Id: I9f93a65fecb4c22591edca4b9d6cda39cf0e872e Reviewed-on: https://go-review.googlesource.com/34270 Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/syntax/pos.go | 30 +++++++++++++-- src/cmd/compile/internal/syntax/pos_test.go | 42 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/syntax/pos.go b/src/cmd/compile/internal/syntax/pos.go index 01a03ff30c..98cdae9327 100644 --- a/src/cmd/compile/internal/syntax/pos.go +++ b/src/cmd/compile/internal/syntax/pos.go @@ -9,12 +9,12 @@ package syntax import "strconv" // A Pos encodes a source position consisting of a (line, column) number pair -// and a position base. A zero Pos is a ready to use "unknown" position (empty -// filename, and unknown line and column number). +// and a position base. A zero Pos is a ready to use "unknown" position (nil +// position base and zero line number). // // The (line, column) values refer to a position in a file independent of any -// position base ("absolute" position). They start at 1, and they are unknown -// if 0. +// position base ("absolute" position). Line numbers start at 1, column values +// start at 0 and are byte offsets from the beginning of the line. // // The position base is used to determine the "relative" position, that is the // filename and line number relative to the position base. If the base refers @@ -27,12 +27,34 @@ type Pos struct { lico } +// NoPos is a valid unknown position. +var NoPos Pos + // MakePos creates a new Pos value with the given base, and (file-absolute) // line and column. func MakePos(base *PosBase, line, col uint) Pos { return Pos{base, makeLico(line, col)} } +// IsKnown reports whether the position p is known. +func (p Pos) IsKnown() bool { + return p.base != nil || p.Line() != 0 +} + +// Before reports whether the position p comes before q in the source. +// For positions in different files, ordering is by filename. +func (p Pos) Before(q Pos) bool { + n, m := p.Filename(), q.Filename() + return n < m || n == m && p.lico < q.lico +} + +// After reports whether the position p comes after q in the source. +// For positions in different files, ordering is by filename. +func (p Pos) After(q Pos) bool { + n, m := p.Filename(), q.Filename() + return n > m || n == m && p.lico > q.lico +} + // Filename returns the name of the actual file containing this position. func (p Pos) Filename() string { return p.base.Pos().RelFilename() } diff --git a/src/cmd/compile/internal/syntax/pos_test.go b/src/cmd/compile/internal/syntax/pos_test.go index c9ecd3de68..bf2a0c1dfa 100644 --- a/src/cmd/compile/internal/syntax/pos_test.go +++ b/src/cmd/compile/internal/syntax/pos_test.go @@ -62,6 +62,48 @@ func TestPos(t *testing.T) { } } +func TestPredicates(t *testing.T) { + b1 := NewFileBase("b1") + b2 := NewFileBase("b2") + for _, test := range []struct { + p, q Pos + known, before, after bool + }{ + {NoPos, NoPos, false, false, false}, + {NoPos, MakePos(nil, 1, 0), false, true, false}, + {MakePos(b1, 0, 0), NoPos, true, false, true}, + {MakePos(nil, 1, 0), NoPos, true, false, true}, + + {MakePos(nil, 1, 1), MakePos(nil, 1, 1), true, false, false}, + {MakePos(nil, 1, 1), MakePos(nil, 1, 2), true, true, false}, + {MakePos(nil, 1, 2), MakePos(nil, 1, 1), true, false, true}, + {MakePos(nil, 123, 1), MakePos(nil, 1, 123), true, false, true}, + + {MakePos(b1, 1, 1), MakePos(b1, 1, 1), true, false, false}, + {MakePos(b1, 1, 1), MakePos(b1, 1, 2), true, true, false}, + {MakePos(b1, 1, 2), MakePos(b1, 1, 1), true, false, true}, + {MakePos(b1, 123, 1), MakePos(b1, 1, 123), true, false, true}, + + {MakePos(b1, 1, 1), MakePos(b2, 1, 1), true, true, false}, + {MakePos(b1, 1, 1), MakePos(b2, 1, 2), true, true, false}, + {MakePos(b1, 1, 2), MakePos(b2, 1, 1), true, true, false}, + {MakePos(b1, 123, 1), MakePos(b2, 1, 123), true, true, false}, + + // special case: unknown column (column too large to represent) + {MakePos(nil, 1, colMax+10), MakePos(nil, 1, colMax+20), true, false, false}, + } { + if got := test.p.IsKnown(); got != test.known { + t.Errorf("%s known: got %v; want %v", test.p, got, test.known) + } + if got := test.p.Before(test.q); got != test.before { + t.Errorf("%s < %s: got %v; want %v", test.p, test.q, got, test.before) + } + if got := test.p.After(test.q); got != test.after { + t.Errorf("%s > %s: got %v; want %v", test.p, test.q, got, test.after) + } + } +} + func TestLico(t *testing.T) { for _, test := range []struct { x lico -- 2.48.1