]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.inline] cmd/compile/internal/syntax: simplified position code
authorRobert Griesemer <gri@golang.org>
Thu, 1 Dec 2016 23:25:07 +0000 (15:25 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 9 Dec 2016 01:35:00 +0000 (01:35 +0000)
Reviewed in and cherry-picked from https://go-review.googlesource.com/#/c/33805/.

Change-Id: I859d9bd5f2256ca78f7b24b330290f7ae600854d
Reviewed-on: https://go-review.googlesource.com/34234
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/syntax/pos.go
src/cmd/compile/internal/syntax/pos_test.go
src/cmd/compile/internal/syntax/scanner.go
src/cmd/compile/internal/syntax/scanner_test.go

index e9ec026af468de62bb8c81fdefb7312f9e331ffc..48bac7a42e406f64d73b99f4f958084572705331 100644 (file)
@@ -6,10 +6,11 @@
 
 package syntax
 
-import "fmt"
+import "strconv"
 
 // A Pos encodes a source position consisting of a (line, column) number pair
-// and a position base.
+// and a position base. A zero Pos is a ready to use "unknown" position (empty
+// filename, and unknown line and column 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
@@ -33,47 +34,36 @@ func MakePos(base *PosBase, line, col uint) Pos {
 }
 
 // Filename returns the name of the actual file containing this position.
-func (p *Pos) Filename() string {
-       if b := p.base; b != nil {
-               return b.pos.RelFilename()
-       }
-       return ""
-}
+func (p *Pos) Filename() string { return p.base.Pos().RelFilename() }
 
 // Base returns the position base.
 func (p *Pos) Base() *PosBase { return p.base }
 
 // RelFilename returns the filename recorded with the position's base.
-func (p *Pos) RelFilename() string {
-       if b := p.base; b != nil {
-               return b.filename
-       }
-       return ""
-}
+func (p *Pos) RelFilename() string { return p.base.Filename() }
 
 // RelLine returns the line number relative to the positions's base.
-func (p *Pos) RelLine() uint {
-       var line0 uint
-       if b := p.base; b != nil {
-               line0 = b.line - p.base.pos.Line()
-       }
-       return line0 + p.Line()
-}
+func (p *Pos) RelLine() uint { b := p.base; return b.Line() + p.Line() - b.Pos().Line() }
 
 func (p *Pos) String() string {
        b := p.base
 
-       if b == nil {
-               return p.lico.String()
-       }
-
-       if b == b.pos.base {
-               // base is file base
-               return fmt.Sprintf("%s:%s", b.filename, p.lico.String())
+       if b == b.Pos().base {
+               // base is file base (incl. nil)
+               return posString(b.Filename(), p.Line(), p.Col())
        }
 
        // base is relative
-       return fmt.Sprintf("%s:%s[%s]", b.filename, licoString(p.RelLine(), p.Col()), b.pos.String())
+       return posString(b.Filename(), p.RelLine(), p.Col()) + "[" + b.Pos().String() + "]"
+}
+
+// posString formats a (filename, line, col) tuple as a printable position.
+func posString(filename string, line, col uint) string {
+       s := filename + ":" + strconv.FormatUint(uint64(line), 10)
+       if col != 0 {
+               s += ":" + strconv.FormatUint(uint64(col), 10)
+       }
+       return s
 }
 
 // ----------------------------------------------------------------------------
@@ -91,9 +81,12 @@ type PosBase struct {
 
 // NewFileBase returns a new *PosBase for a file with the given filename.
 func NewFileBase(filename string) *PosBase {
-       base := &PosBase{filename: filename}
-       base.pos = MakePos(base, 0, 0)
-       return base
+       if filename != "" {
+               base := &PosBase{filename: filename}
+               base.pos = MakePos(base, 0, 0)
+               return base
+       }
+       return nil
 }
 
 // NewLinePragmaBase returns a new *PosBase for a line pragma of the form
@@ -106,7 +99,7 @@ func NewLinePragmaBase(pos Pos, filename string, line uint) *PosBase {
 var noPos Pos
 
 // Pos returns the position at which base is located.
-// If b == nil, the result is the empty position.
+// If b == nil, the result is the zero position.
 func (b *PosBase) Pos() *Pos {
        if b != nil {
                return &b.pos
@@ -144,29 +137,21 @@ type lico uint32
 // information as line numbers grow bigger; similar to what gcc
 // does.)
 const (
-       lineW, lineM = 24, 1<<lineW - 1
-       colW, colM   = 32 - lineW, 1<<colW - 1
+       lineBits, lineMax = 24, 1<<lineBits - 1
+       colBits, colMax   = 32 - lineBits, 1<<colBits - 1
 )
 
 func makeLico(line, col uint) lico {
-       if line > lineM {
+       if line > lineMax {
                // cannot represent line, use max. line so we have some information
-               line = lineM
+               line = lineMax
        }
-       if col > colM {
+       if col > colMax {
                // cannot represent column, use 0 to indicate unknown column
                col = 0
        }
-       return lico(line<<colW | col)
+       return lico(line<<colBits | col)
 }
 
-func (x lico) Line() uint     { return uint(x) >> colW }
-func (x lico) Col() uint      { return uint(x) & colM }
-func (x lico) String() string { return licoString(x.Line(), x.Col()) }
-
-func licoString(line, col uint) string {
-       if col == 0 {
-               return fmt.Sprintf("%d", line)
-       }
-       return fmt.Sprintf("%d:%d", line, col)
-}
+func (x lico) Line() uint { return uint(x) >> colBits }
+func (x lico) Col() uint  { return uint(x) & colMax }
index 65f84113aa16b25ea0a4cf8aecebe5a375b0c24a..ff29e7b0a3587250aa2db043d330bcd53f5dc85a 100644 (file)
@@ -10,6 +10,7 @@ import (
 )
 
 func TestPos(t *testing.T) {
+       f0 := NewFileBase("")
        f1 := NewFileBase("f1")
        f2 := NewLinePragmaBase(Pos{}, "f2", 10)
        f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", 100)
@@ -27,10 +28,11 @@ func TestPos(t *testing.T) {
                relFilename string
                relLine     uint
        }{
-               {Pos{}, "0", "", 0, 0, "", 0},
-               {MakePos(nil, 2, 3), "2:3", "", 2, 3, "", 2},
+               {Pos{}, ":0", "", 0, 0, "", 0},
+               {MakePos(nil, 2, 3), ":2:3", "", 2, 3, "", 2},
+               {MakePos(f0, 2, 3), ":2:3", "", 2, 3, "", 2},
                {MakePos(f1, 1, 1), "f1:1:1", "f1", 1, 1, "f1", 1},
-               {MakePos(f2, 7, 10), "f2:16:10[0]", "", 7, 10, "f2", 16},
+               {MakePos(f2, 7, 10), "f2:16:10[:0]", "", 7, 10, "f2", 16},
                {MakePos(f3, 12, 7), "f3:101:7[f1:10:1]", "f1", 12, 7, "f3", 101},
                {MakePos(f4, 25, 1), "f4:114:1[f3:99:1[f1:10:1]]", "f3", 25, 1, "f4", 114}, // doesn't occur in Go code
        } {
@@ -66,20 +68,20 @@ func TestLico(t *testing.T) {
                string    string
                line, col uint
        }{
-               {0, "0", 0, 0},
-               {makeLico(0, 0), "0", 0, 0},
-               {makeLico(0, 1), "0:1", 0, 1},
-               {makeLico(1, 0), "1", 1, 0},
-               {makeLico(1, 1), "1:1", 1, 1},
-               {makeLico(2, 3), "2:3", 2, 3},
-               {makeLico(lineM, 1), fmt.Sprintf("%d:1", lineM), lineM, 1},
-               {makeLico(lineM+1, 1), fmt.Sprintf("%d:1", lineM), lineM, 1}, // line too large, stick with max. line
-               {makeLico(1, colM), fmt.Sprintf("1:%d", colM), 1, colM},
-               {makeLico(1, colM+1), "1", 1, 0}, // column too large
-               {makeLico(lineM+1, colM+1), fmt.Sprintf("%d", lineM), lineM, 0},
+               {0, ":0", 0, 0},
+               {makeLico(0, 0), ":0", 0, 0},
+               {makeLico(0, 1), ":0:1", 0, 1},
+               {makeLico(1, 0), ":1", 1, 0},
+               {makeLico(1, 1), ":1:1", 1, 1},
+               {makeLico(2, 3), ":2:3", 2, 3},
+               {makeLico(lineMax, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1},
+               {makeLico(lineMax+1, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1}, // line too large, stick with max. line
+               {makeLico(1, colMax), fmt.Sprintf(":1:%d", colMax), 1, colMax},
+               {makeLico(1, colMax+1), ":1", 1, 0}, // column too large
+               {makeLico(lineMax+1, colMax+1), fmt.Sprintf(":%d", lineMax), lineMax, 0},
        } {
                x := test.x
-               if got := x.String(); got != test.string {
+               if got := posString("", x.Line(), x.Col()); got != test.string {
                        t.Errorf("%s: got %q", test.string, got)
                }
        }
index 6fdc0dc6dae678af267b4d61556f09208788d028..77d7a1beefaec107c5ac42a6fa855f4a3e181791 100644 (file)
@@ -577,7 +577,7 @@ func (s *scanner) lineComment() {
                }
                nstr := text[i+1:]
                n, err := strconv.Atoi(nstr)
-               if err != nil || n <= 0 || n > lineM {
+               if err != nil || n <= 0 || n > lineMax {
                        s.error_at(s.line0, s.col0-uint(len(nstr)), "invalid line number: "+nstr)
                        return
                }
index b319e2c354841da8efc2f329f2474ce8a84ef225..b8ec811c1831831c58b2f57ca003ad7340f396e5 100644 (file)
@@ -323,7 +323,7 @@ func TestScanErrors(t *testing.T) {
                {`//line foo:123abc`, "invalid line number: 123abc", 1, 12},
                {`/**///line foo:x`, "invalid line number: x", 1, 16},
                {`//line foo:0`, "invalid line number: 0", 1, 12},
-               {fmt.Sprintf(`//line foo:%d`, lineM+1), fmt.Sprintf("invalid line number: %d", lineM+1), 1, 12},
+               {fmt.Sprintf(`//line foo:%d`, lineMax+1), fmt.Sprintf("invalid line number: %d", lineMax+1), 1, 12},
 
                // former problem cases
                {"package p\n\n\xef", "invalid UTF-8 encoding", 3, 1},