diff --git a/env.go b/env.go index 6841404a..dd1859c4 100644 --- a/env.go +++ b/env.go @@ -5,8 +5,8 @@ import "context" type env struct { pc int stack *stack - scopes *stack paths *stack + scopes *scopeStack values []interface{} codes []*code codeinfos []codeinfo @@ -22,8 +22,8 @@ type env struct { func newEnv(ctx context.Context) *env { return &env{ stack: newStack(), - scopes: newStack(), paths: newStack(), + scopes: newScopeStack(), ctx: ctx, } } diff --git a/execute.go b/execute.go index 2e1e0869..e9509574 100644 --- a/execute.go +++ b/execute.go @@ -212,7 +212,7 @@ loop: env.scopes.index = index } if outerindex = index; outerindex >= 0 { - if s := env.scopes.data[outerindex].value.(scope); s.id == xs[0] { + if s := env.scopes.data[outerindex].value; s.id == xs[0] { outerindex = s.outerindex } } @@ -349,7 +349,7 @@ func (env *env) pop() interface{} { func (env *env) popscope() (int, int) { free := env.scopes.index > env.scopes.limit - s := env.scopes.pop().(scope) + s := env.scopes.pop() if free { env.offset = s.offset } @@ -377,7 +377,7 @@ func (env *env) popfork() int { func (env *env) index(v [2]int) int { for id, i := v[0], env.scopes.index; i >= 0; { - s := env.scopes.data[i].value.(scope) + s := env.scopes.data[i].value if s.id == id { return s.offset + v[1] } diff --git a/scope_stack.go b/scope_stack.go new file mode 100644 index 00000000..82d620be --- /dev/null +++ b/scope_stack.go @@ -0,0 +1,51 @@ +package gojq + +type scopeStack struct { + data []scopeBlock + index int + limit int +} + +type scopeBlock struct { + value scope + next int +} + +func newScopeStack() *scopeStack { + return &scopeStack{index: -1, limit: -1} +} + +func (s *scopeStack) push(v scope) { + b := scopeBlock{v, s.index} + i := s.index + 1 + if i <= s.limit { + i = s.limit + 1 + } + s.index = i + if i < len(s.data) { + s.data[i] = b + } else { + s.data = append(s.data, b) + } +} + +func (s *scopeStack) pop() scope { + b := s.data[s.index] + s.index = b.next + return b.value +} + +func (s *scopeStack) empty() bool { + return s.index < 0 +} + +func (s *scopeStack) save(index, limit *int) { + *index, *limit = s.index, s.limit + if s.index > s.limit { + s.limit = s.index + } +} + +func (s *scopeStack) restore(index, limit int) { + s.index, s.limit = index, limit +}