]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.inline] cmd/compile/internal/syntax: add predicates to syntax.Pos
authorRobert Griesemer <gri@golang.org>
Fri, 9 Dec 2016 23:38:23 +0000 (15:38 -0800)
committerRobert Griesemer <gri@golang.org>
Sat, 10 Dec 2016 01:21:20 +0000 (01:21 +0000)
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 <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/syntax/pos.go
src/cmd/compile/internal/syntax/pos_test.go

index 01a03ff30c127385f2eb87136bae60e56348fb76..98cdae9327c68993eb250df41acc2aa2d729682a 100644 (file)
@@ -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() }
 
index c9ecd3de68239e56ea5e08e1162a8e0e6dad48a8..bf2a0c1dfaeca2e0341fb6959569e854c5b0eeca 100644 (file)
@@ -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