xgo/symbol_table_test.go
daniel 15494e1691
fix local symbol resolution bug (#316)
* fix local symbol resolution bug

* 1
2020-09-13 19:33:48 -07:00

133 lines
3.3 KiB
Go

package tengo_test
import (
"testing"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/require"
)
func TestSymbolTable(t *testing.T) {
/*
GLOBAL
[0] a
[1] b
LOCAL 1
[0] d
LOCAL 2
[0] e
[1] f
LOCAL 2 BLOCK 1
[2] g
[3] h
LOCAL 2 BLOCK 2
[2] i
[3] j
[4] k
LOCAL 1 BLOCK 1
[1] l
[2] m
[3] n
[4] o
[5] p
LOCAL 3
[0] q
[1] r
*/
global := symbolTable()
require.Equal(t, globalSymbol("a", 0), global.Define("a"))
require.Equal(t, globalSymbol("b", 1), global.Define("b"))
local1 := global.Fork(false)
require.Equal(t, localSymbol("d", 0), local1.Define("d"))
local1Block1 := local1.Fork(true)
require.Equal(t, localSymbol("l", 1), local1Block1.Define("l"))
require.Equal(t, localSymbol("m", 2), local1Block1.Define("m"))
require.Equal(t, localSymbol("n", 3), local1Block1.Define("n"))
require.Equal(t, localSymbol("o", 4), local1Block1.Define("o"))
require.Equal(t, localSymbol("p", 5), local1Block1.Define("p"))
local2 := local1.Fork(false)
require.Equal(t, localSymbol("e", 0), local2.Define("e"))
require.Equal(t, localSymbol("f", 1), local2.Define("f"))
local2Block1 := local2.Fork(true)
require.Equal(t, localSymbol("g", 2), local2Block1.Define("g"))
require.Equal(t, localSymbol("h", 3), local2Block1.Define("h"))
local2Block2 := local2.Fork(true)
require.Equal(t, localSymbol("i", 2), local2Block2.Define("i"))
require.Equal(t, localSymbol("j", 3), local2Block2.Define("j"))
require.Equal(t, localSymbol("k", 4), local2Block2.Define("k"))
local3 := local1Block1.Fork(false)
require.Equal(t, localSymbol("q", 0), local3.Define("q"))
require.Equal(t, localSymbol("r", 1), local3.Define("r"))
require.Equal(t, 2, global.MaxSymbols())
require.Equal(t, 6, local1.MaxSymbols())
require.Equal(t, 6, local1Block1.MaxSymbols())
require.Equal(t, 5, local2.MaxSymbols())
require.Equal(t, 4, local2Block1.MaxSymbols())
require.Equal(t, 5, local2Block2.MaxSymbols())
require.Equal(t, 2, local3.MaxSymbols())
resolveExpect(t, global, "a", globalSymbol("a", 0), 0)
resolveExpect(t, local1, "d", localSymbol("d", 0), 0)
resolveExpect(t, local1, "a", globalSymbol("a", 0), 1)
resolveExpect(t, local3, "a", globalSymbol("a", 0), 3)
resolveExpect(t, local3, "d", freeSymbol("d", 0), 2)
resolveExpect(t, local3, "r", localSymbol("r", 1), 0)
resolveExpect(t, local2Block2, "k", localSymbol("k", 4), 0)
resolveExpect(t, local2Block2, "e", localSymbol("e", 0), 1)
resolveExpect(t, local2Block2, "b", globalSymbol("b", 1), 3)
}
func symbol(
name string,
scope tengo.SymbolScope,
index int,
) *tengo.Symbol {
return &tengo.Symbol{
Name: name,
Scope: scope,
Index: index,
}
}
func globalSymbol(name string, index int) *tengo.Symbol {
return symbol(name, tengo.ScopeGlobal, index)
}
func localSymbol(name string, index int) *tengo.Symbol {
return symbol(name, tengo.ScopeLocal, index)
}
func freeSymbol(name string, index int) *tengo.Symbol {
return symbol(name, tengo.ScopeFree, index)
}
func symbolTable() *tengo.SymbolTable {
return tengo.NewSymbolTable()
}
func resolveExpect(
t *testing.T,
symbolTable *tengo.SymbolTable,
name string,
expectedSymbol *tengo.Symbol,
expectedDepth int,
) {
actualSymbol, actualDepth, ok := symbolTable.Resolve(name, true)
require.True(t, ok)
require.Equal(t, expectedSymbol, actualSymbol)
require.Equal(t, expectedDepth, actualDepth)
}