Make position comparison generally available.
Change-Id: I94b6f658fa19a15b30574dbb2181879115c131a8
Reviewed-on: https://go-review.googlesource.com/c/go/+/307215
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
return pos.Col()
}
+// Cmp compares the positions p and q and returns a result r as follows:
+//
+// r < 0: p is before q
+// r == 0: p and q are the same position (but may not be identical)
+// r > 0: p is after q
+//
+// If p and q are in different files, p is before q if the filename
+// of p sorts lexicographically before the filename of q.
+func (p Pos) Cmp(q Pos) int {
+ pname := p.RelFilename()
+ qname := q.RelFilename()
+ switch {
+ case pname < qname:
+ return -1
+ case pname > qname:
+ return +1
+ }
+
+ pline := p.Line()
+ qline := q.Line()
+ switch {
+ case pline < qline:
+ return -1
+ case pline > qline:
+ return +1
+ }
+
+ pcol := p.Col()
+ qcol := q.Col()
+ switch {
+ case pcol < qcol:
+ return -1
+ case pcol > qcol:
+ return +1
+ }
+
+ return 0
+}
+
func (pos Pos) String() string {
rel := position_{pos.RelFilename(), pos.RelLine(), pos.RelCol()}
abs := position_{pos.Base().Pos().RelFilename(), pos.Line(), pos.Col()}
// for each Error is the position of the token immediately preceding
// the comment, the Error message is the message msg extracted from
// the comment, with all errors that are on the same line collected
-// in a slice. If there is no preceding token (the `ERROR` comment
-// appears in the beginning of the file), then the recorded position
-// is unknown (line, col = 0, 0). If there are no ERROR comments, the
-// result is nil.
+// in a slice, in source order. If there is no preceding token (the
+// `ERROR` comment appears in the beginning of the file), then the
+// recorded position is unknown (line, col = 0, 0). If there are no
+// ERROR comments, the result is nil.
func ErrorMap(src io.Reader) (errmap map[uint][]Error) {
// position of previous token
var base *PosBase
check.report(&err)
}
-// TODO(gri) This functionality should probably be with the Pos implementation.
-func cmpPos(p, q syntax.Pos) int {
- // TODO(gri) is RelFilename correct here?
- pname := p.RelFilename()
- qname := q.RelFilename()
- switch {
- case pname < qname:
- return -1
- case pname > qname:
- return +1
- }
-
- pline := p.Line()
- qline := q.Line()
- switch {
- case pline < qline:
- return -1
- case pline > qline:
- return +1
- }
-
- pcol := p.Col()
- qcol := q.Col()
- switch {
- case pcol < qcol:
- return -1
- case pcol > qcol:
- return +1
- }
-
- return 0
-}
-
// firstInSrc reports the index of the object with the "smallest"
// source position in path. path must not be empty.
func firstInSrc(path []Object) int {
fst, pos := 0, path[0].Pos()
for i, t := range path[1:] {
- if cmpPos(t.Pos(), pos) < 0 {
+ if t.Pos().Cmp(pos) < 0 {
fst, pos = i+1, t.Pos()
}
}
// whose scope is the scope of the package that exported them.
func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) {
for ; s != nil; s = s.parent {
- if obj := s.elems[name]; obj != nil && (!pos.IsKnown() || cmpPos(obj.scopePos(), pos) <= 0) {
+ if obj := s.elems[name]; obj != nil && (!pos.IsKnown() || obj.scopePos().Cmp(pos) <= 0) {
return s, obj
}
}
// The result is guaranteed to be valid only if the type-checked
// AST has complete position information.
func (s *Scope) Contains(pos syntax.Pos) bool {
- return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
+ return s.pos.Cmp(pos) <= 0 && pos.Cmp(s.end) < 0
}
// Innermost returns the innermost (child) scope containing
}
}
sort.Slice(unused, func(i, j int) bool {
- return cmpPos(unused[i].pos, unused[j].pos) < 0
+ return unused[i].pos.Cmp(unused[j].pos) < 0
})
for _, v := range unused {
check.softErrorf(v.pos, "%s declared but not used", v.name)