From 1ed65518e63a9a7d7ddd860fffae2fe5b340cf71 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Mon, 6 Nov 2017 11:14:28 +0100 Subject: [PATCH] simplify build time pending check --- Makefile | 3 +- choice.go | 6 +-- context.go | 100 +++--------------------------------------------- context_test.go | 4 +- notes.txt | 1 + registry.go | 2 - results.go | 50 ++++++++++++++++++++++++ sequence.go | 6 +-- 8 files changed, 66 insertions(+), 106 deletions(-) diff --git a/Makefile b/Makefile index 23b7424..141c7ea 100644 --- a/Makefile +++ b/Makefile @@ -52,9 +52,10 @@ precommit: fmt build check-full clean: @rm -f *.test @rm -f cpu.out + @rm -f .coverprofile @go clean -i ./... -ci-trigger: deps build check-full check-fmt +ci-trigger: deps check-fmt build check-full ifeq ($(TRAVIS_BRANCH)_$(TRAVIS_PULL_REQUEST), master_false) make publish-coverage endif diff --git a/choice.go b/choice.go index e35fccc..fbbd061 100644 --- a/choice.go +++ b/choice.go @@ -204,11 +204,11 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) { if parsed { c.results.dropMatchTo(c.offset, b.id, to) } else { - if c.buildPending(c.offset, b.id, to) { + if c.pending(c.offset, b.id) { return nil, false } - c.markBuildPending(c.offset, b.id, to) + c.markPending(c.offset, b.id) } var option builder @@ -221,7 +221,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) { n, _ := option.build(c) if !parsed { - c.unmarkBuildPending(from, b.id, to) + c.unmarkPending(from, b.id) } if b.commit&Alias != 0 { diff --git a/context.go b/context.go index 9450087..4b29c29 100644 --- a/context.go +++ b/context.go @@ -63,101 +63,6 @@ func (c *context) token() (rune, bool) { return c.tokens[c.offset], true } -func (c *context) pending(offset, id int) bool { - if len(c.isPending) <= id { - return false - } - - for i := range c.isPending[id] { - if c.isPending[id][i] == offset { - return true - } - } - - return false -} - -func (c *context) markPending(offset, id int) { - if len(c.isPending) <= id { - if cap(c.isPending) > id { - c.isPending = c.isPending[:id+1] - } else { - c.isPending = c.isPending[:cap(c.isPending)] - for i := cap(c.isPending); i <= id; i++ { - c.isPending = append(c.isPending, nil) - } - } - } - - for i := range c.isPending[id] { - if c.isPending[id][i] == -1 { - c.isPending[id][i] = offset - return - } - } - - c.isPending[id] = append(c.isPending[id], offset) -} - -func (c *context) unmarkPending(offset, id int) { - for i := range c.isPending[id] { - if c.isPending[id][i] == offset { - c.isPending[id][i] = -1 - break - } - } -} - -func (c *context) resetPending() { - c.isPending = nil -} - -func (c *context) buildPending(offset, id, to int) bool { - if len(c.isPending) <= id { - return false - } - - for i := 0; i < len(c.isPending[id]); i += 2 { - if c.isPending[id][i] == offset && c.isPending[id][i+1] == to { - return true - } - } - - return false -} - -func (c *context) markBuildPending(offset, id, to int) { - if len(c.isPending) <= id { - if cap(c.isPending) > id { - c.isPending = c.isPending[:id+1] - } else { - c.isPending = c.isPending[:cap(c.isPending)] - for i := cap(c.isPending); i <= id; i++ { - c.isPending = append(c.isPending, nil) - } - } - } - - for i := 0; i < len(c.isPending[id]); i += 2 { - if c.isPending[id][i] == -1 { - c.isPending[id][i] = offset - c.isPending[id][i+1] = to - return - } - } - - c.isPending[id] = append(c.isPending[id], offset, to) -} - -func (c *context) unmarkBuildPending(offset, id, to int) { - for i := 0; i < len(c.isPending[id]); i += 2 { - if c.isPending[id][i] == offset && c.isPending[id][i+1] == to { - c.isPending[id][i] = -1 - break - } - } -} - func (c *context) fromResults(id int) bool { to, m, ok := c.results.longestResult(c.offset, id) if !ok { @@ -173,6 +78,11 @@ func (c *context) fromResults(id int) bool { return true } +// TODO: +// - try to move this to the parsers +// - try to move more +// - if doens't help performance, try move more from there to here + func (c *context) success(to int) { c.offset = to c.matchLast = true diff --git a/context_test.go b/context_test.go index d0d4354..a2288dc 100644 --- a/context_test.go +++ b/context_test.go @@ -86,11 +86,11 @@ func TestPendingWithinCap(t *testing.T) { t.Run("parse", func(t *testing.T) { for i := 0; i < 16; i++ { - c.markBuildPending(0, i, 0) + c.markPending(0, i) } for i := 0; i < 16; i++ { - if !c.buildPending(0, i, 0) { + if !c.pending(0, i) { t.Error("failed to mark build pending") } } diff --git a/notes.txt b/notes.txt index ab3f664..cae8e21 100644 --- a/notes.txt +++ b/notes.txt @@ -4,6 +4,7 @@ error reporting - print the line - print the deepest non-alias node name - print the documentation of the node name +- make it work with custom tokens read, with error reporting what was the bug with the large json from eskip? diff --git a/registry.go b/registry.go index eee1910..e420dad 100644 --- a/registry.go +++ b/registry.go @@ -5,7 +5,6 @@ type registry struct { ids map[string]int names map[int]string definitions map[string]definition - parsers map[string]parser } func newRegistry(defs ...definition) *registry { @@ -13,7 +12,6 @@ func newRegistry(defs ...definition) *registry { ids: make(map[string]int), names: make(map[int]string), definitions: make(map[string]definition), - parsers: make(map[string]parser), } for _, def := range defs { diff --git a/results.go b/results.go index c53e3ce..d1a3c22 100644 --- a/results.go +++ b/results.go @@ -23,6 +23,7 @@ func (r *results) ensureOffset(offset int) { func (r *results) setMatch(offset, id, to int) { r.ensureOffset(offset) + for i := 0; i < len(r.match[offset]); i += 2 { if r.match[offset][i] != id || r.match[offset][i+1] != to { continue @@ -124,3 +125,52 @@ func (r *results) dropMatchTo(offset, id, to int) { } } } + +func (c *context) resetPending() { + c.isPending = nil +} + +func (c *context) pending(offset, id int) bool { + if len(c.isPending) <= id { + return false + } + + for i := range c.isPending[id] { + if c.isPending[id][i] == offset { + return true + } + } + + return false +} + +func (c *context) markPending(offset, id int) { + if len(c.isPending) <= id { + if cap(c.isPending) > id { + c.isPending = c.isPending[:id+1] + } else { + c.isPending = c.isPending[:cap(c.isPending)] + for i := cap(c.isPending); i <= id; i++ { + c.isPending = append(c.isPending, nil) + } + } + } + + for i := range c.isPending[id] { + if c.isPending[id][i] == -1 { + c.isPending[id][i] = offset + return + } + } + + c.isPending[id] = append(c.isPending[id], offset) +} + +func (c *context) unmarkPending(offset, id int) { + for i := range c.isPending[id] { + if c.isPending[id][i] == offset { + c.isPending[id][i] = -1 + break + } + } +} diff --git a/sequence.go b/sequence.go index 5d63293..b5ff16c 100644 --- a/sequence.go +++ b/sequence.go @@ -258,11 +258,11 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { } else if parsed { c.results.dropMatchTo(c.offset, b.id, to) } else { - if c.buildPending(c.offset, b.id, to) { + if c.pending(c.offset, b.id) { return nil, false } - c.markBuildPending(c.offset, b.id, to) + c.markPending(c.offset, b.id) } var ( @@ -303,7 +303,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { } if !parsed { - c.unmarkBuildPending(from, b.id, to) + c.unmarkPending(from, b.id) } if b.commit&Alias != 0 {