fix issues with symbols in global scope blocks (#318)
This commit is contained in:
parent
15494e1691
commit
2565e0553d
3 changed files with 98 additions and 1 deletions
|
@ -1180,7 +1180,7 @@ if a := 1; a {
|
||||||
tengo.MakeInstruction(parser.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
||||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
tengo.MakeInstruction(parser.OpSetGlobal, 1),
|
tengo.MakeInstruction(parser.OpSetGlobal, 2),
|
||||||
tengo.MakeInstruction(parser.OpSuspend)),
|
tengo.MakeInstruction(parser.OpSuspend)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
intObject(1),
|
intObject(1),
|
||||||
|
|
|
@ -44,6 +44,17 @@ func (t *SymbolTable) Define(name string) *Symbol {
|
||||||
|
|
||||||
if t.Parent(true) == nil {
|
if t.Parent(true) == nil {
|
||||||
symbol.Scope = ScopeGlobal
|
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 {
|
} else {
|
||||||
symbol.Scope = ScopeLocal
|
symbol.Scope = ScopeLocal
|
||||||
}
|
}
|
||||||
|
|
86
vm_test.go
86
vm_test.go
|
@ -1804,7 +1804,93 @@ out = (func() {
|
||||||
`, nil, 2)
|
`, nil, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBlocksInGlobalScope(t *testing.T) {
|
||||||
|
expectRun(t, `
|
||||||
|
f := undefined
|
||||||
|
if true {
|
||||||
|
a := 1
|
||||||
|
f = func() {
|
||||||
|
a = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := 3
|
||||||
|
f()
|
||||||
|
out = b`,
|
||||||
|
nil, 3)
|
||||||
|
|
||||||
|
expectRun(t, `
|
||||||
|
func() {
|
||||||
|
f := undefined
|
||||||
|
if true {
|
||||||
|
a := 10
|
||||||
|
f = func() {
|
||||||
|
a = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := 5
|
||||||
|
f()
|
||||||
|
out = b
|
||||||
|
}()
|
||||||
|
`,
|
||||||
|
nil, 5)
|
||||||
|
|
||||||
|
expectRun(t, `
|
||||||
|
f := undefined
|
||||||
|
if true {
|
||||||
|
a := 1
|
||||||
|
b := 2
|
||||||
|
f = func() {
|
||||||
|
a = 3
|
||||||
|
b = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := 5
|
||||||
|
d := 6
|
||||||
|
f()
|
||||||
|
out = c + d`,
|
||||||
|
nil, 11)
|
||||||
|
|
||||||
|
expectRun(t, `
|
||||||
|
fn := undefined
|
||||||
|
if true {
|
||||||
|
a := 1
|
||||||
|
b := 2
|
||||||
|
if true {
|
||||||
|
c := 3
|
||||||
|
d := 4
|
||||||
|
fn = func() {
|
||||||
|
a = 5
|
||||||
|
b = 6
|
||||||
|
c = 7
|
||||||
|
d = 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e := 9
|
||||||
|
f := 10
|
||||||
|
fn()
|
||||||
|
out = e + f`,
|
||||||
|
nil, 19)
|
||||||
|
|
||||||
|
expectRun(t, `
|
||||||
|
out = 0
|
||||||
|
func() {
|
||||||
|
for x in [1, 2, 3] {
|
||||||
|
out += x
|
||||||
|
}
|
||||||
|
}()`,
|
||||||
|
nil, 6)
|
||||||
|
|
||||||
|
expectRun(t, `
|
||||||
|
out = 0
|
||||||
|
for x in [1, 2, 3] {
|
||||||
|
out += x
|
||||||
|
}`,
|
||||||
|
nil, 6)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIf(t *testing.T) {
|
func TestIf(t *testing.T) {
|
||||||
|
|
||||||
expectRun(t, `if (true) { out = 10 }`, nil, 10)
|
expectRun(t, `if (true) { out = 10 }`, nil, 10)
|
||||||
expectRun(t, `if (false) { out = 10 }`, nil, tengo.UndefinedValue)
|
expectRun(t, `if (false) { out = 10 }`, nil, tengo.UndefinedValue)
|
||||||
expectRun(t, `if (false) { out = 10 } else { out = 20 }`, nil, 20)
|
expectRun(t, `if (false) { out = 10 } else { out = 20 }`, nil, 20)
|
||||||
|
|
Loading…
Reference in a new issue