diff options
Diffstat (limited to 'vendor/github.com/d5/tengo')
-rw-r--r-- | vendor/github.com/d5/tengo/v2/compiler.go | 4 | ||||
-rw-r--r-- | vendor/github.com/d5/tengo/v2/script.go | 2 | ||||
-rw-r--r-- | vendor/github.com/d5/tengo/v2/symbol_table.go | 56 |
3 files changed, 42 insertions, 20 deletions
diff --git a/vendor/github.com/d5/tengo/v2/compiler.go b/vendor/github.com/d5/tengo/v2/compiler.go index 1937a1d6..53cc7d38 100644 --- a/vendor/github.com/d5/tengo/v2/compiler.go +++ b/vendor/github.com/d5/tengo/v2/compiler.go @@ -323,7 +323,7 @@ func (c *Compiler) Compile(node parser.Node) error { return err } case *parser.Ident: - symbol, _, ok := c.symbolTable.Resolve(node.Name) + symbol, _, ok := c.symbolTable.Resolve(node.Name, false) if !ok { return c.errorf(node, "unresolved reference '%s'", node.Name) } @@ -659,7 +659,7 @@ func (c *Compiler) compileAssign( return c.errorf(node, "operator ':=' not allowed with selector") } - symbol, depth, exists := c.symbolTable.Resolve(ident) + symbol, depth, exists := c.symbolTable.Resolve(ident, false) if op == token.Define { if depth == 0 && exists { return c.errorf(node, "'%s' redeclared in this block", ident) diff --git a/vendor/github.com/d5/tengo/v2/script.go b/vendor/github.com/d5/tengo/v2/script.go index 4f9608c1..46e48029 100644 --- a/vendor/github.com/d5/tengo/v2/script.go +++ b/vendor/github.com/d5/tengo/v2/script.go @@ -116,7 +116,7 @@ func (s *Script) Compile() (*Compiled, error) { // global symbol names to indexes globalIndexes := make(map[string]int, len(globals)) for _, name := range symbolTable.Names() { - symbol, _, _ := symbolTable.Resolve(name) + symbol, _, _ := symbolTable.Resolve(name, false) if symbol.Scope == ScopeGlobal { globalIndexes[name] = symbol.Index } diff --git a/vendor/github.com/d5/tengo/v2/symbol_table.go b/vendor/github.com/d5/tengo/v2/symbol_table.go index 6ae5d7d3..73aaad3b 100644 --- a/vendor/github.com/d5/tengo/v2/symbol_table.go +++ b/vendor/github.com/d5/tengo/v2/symbol_table.go @@ -44,6 +44,17 @@ func (t *SymbolTable) Define(name string) *Symbol { if t.Parent(true) == nil { symbol.Scope = ScopeGlobal + + // if symbol is defined in a block of global scope, symbol index must + // be tracked at the root-level table instead. + if p := t.parent; p != nil { + for p.parent != nil { + p = p.parent + } + t.numDefinition-- + p.numDefinition++ + } + } else { symbol.Scope = ScopeLocal } @@ -71,25 +82,36 @@ func (t *SymbolTable) DefineBuiltin(index int, name string) *Symbol { // Resolve resolves a symbol with a given name. func (t *SymbolTable) Resolve( name string, -) (symbol *Symbol, depth int, ok bool) { - symbol, ok = t.store[name] - if !ok && t.parent != nil { - symbol, depth, ok = t.parent.Resolve(name) - if !ok { - return + recur bool, +) (*Symbol, int, bool) { + symbol, ok := t.store[name] + if ok { + // symbol can be used if + if symbol.Scope != ScopeLocal || // it's not of local scope, OR, + symbol.LocalAssigned || // it's assigned at least once, OR, + recur { // it's defined in higher level + return symbol, 0, true } - depth++ - - // if symbol is defined in parent table and if it's not global/builtin - // then it's free variable. - if !t.block && depth > 0 && - symbol.Scope != ScopeGlobal && - symbol.Scope != ScopeBuiltin { - return t.defineFree(symbol), depth, true - } - return } - return + + if t.parent == nil { + return nil, 0, false + } + + symbol, depth, ok := t.parent.Resolve(name, true) + if !ok { + return nil, 0, false + } + depth++ + + // if symbol is defined in parent table and if it's not global/builtin + // then it's free variable. + if !t.block && depth > 0 && + symbol.Scope != ScopeGlobal && + symbol.Scope != ScopeBuiltin { + return t.defineFree(symbol), depth, true + } + return symbol, depth, true } // Fork creates a new symbol table for a new scope. |