Skip to content

Commit

Permalink
optimize variable lookup by tracking outer scope indices (fix #86)
Browse files Browse the repository at this point in the history
  • Loading branch information
itchyny committed Aug 17, 2021
1 parent b96316e commit 932c65e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 25 deletions.
7 changes: 7 additions & 0 deletions cli/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,13 @@
3
2
- name: function declaration and recursive call
args:
- '100000 as $x | def f: if . == $x then . else . + 1 | f end; f'
input: '0'
expected: |
100000
- name: function declaration with duplicate function names
args:
- 'def f(g): def f: def g: 3; g * 2; g * f; def f: . * 5; f(f)'
Expand Down
9 changes: 5 additions & 4 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ func newEnv(ctx context.Context) *env {
}

type scope struct {
id int
offset int
pc int
saveindex int
id int
offset int
pc int
saveindex int
outerindex int
}

type fork struct {
Expand Down
30 changes: 18 additions & 12 deletions execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,24 @@ loop:
goto loop
case opscope:
xs := code.v.([3]int)
var i, l int
var saveindex, outerindex, limit int
if index == env.scopes.index {
if callpc >= 0 {
i = index
saveindex = index
} else {
callpc = -callpc
i = env.scopes.top().(scope).saveindex
saveindex = env.scopes.top().(scope).saveindex
}
} else {
env.scopes.save(&i, &l)
env.scopes.save(&saveindex, &limit)
env.scopes.index = index
}
env.scopes.push(scope{xs[0], env.offset, callpc, i})
if outerindex = index; outerindex >= 0 {
if s := env.scopes.data[outerindex].value.(scope); s.id == xs[0] {
outerindex = s.outerindex
}
}
env.scopes.push(scope{xs[0], env.offset, callpc, saveindex, outerindex})
env.offset += xs[1]
if env.offset > len(env.values) {
vs := make([]interface{}, env.offset*2)
Expand Down Expand Up @@ -363,14 +368,15 @@ func (env *env) popfork() *fork {
return f
}

func (env *env) scopeOffset(id int) int {
return env.scopes.lookup(func(v interface{}) bool {
return v.(scope).id == id
}).(scope).offset
}

func (env *env) index(v [2]int) int {
return env.scopeOffset(v[0]) + v[1]
for id, i := v[0], env.scopes.index; i >= 0; {
if s := env.scopes.data[i].value.(scope); s.id == id {
return s.offset + v[1]
} else {
i = s.outerindex
}
}
panic("env.index")
}

type pathValue struct {
Expand Down
9 changes: 0 additions & 9 deletions stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ func (s *stack) empty() bool {
return s.index < 0
}

func (s *stack) lookup(f func(v interface{}) bool) interface{} {
for i := s.index; i >= 0; i = s.data[i].next {
if f(s.data[i].value) {
return s.data[i].value
}
}
panic("stack.lookup")
}

func (s *stack) save(index, limit *int) {
if s.index >= s.limit {
s.limit = s.index
Expand Down

0 comments on commit 932c65e

Please sign in to comment.