simplify build time pending check

This commit is contained in:
Arpad Ryszka 2017-11-06 11:14:28 +01:00
parent 79fa303bed
commit 1ed65518e6
8 changed files with 66 additions and 106 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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")
}
}

View File

@ -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?

View File

@ -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 {

View File

@ -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
}
}
}

View File

@ -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 {