symbol_table_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package tengo_test
  2. import (
  3. "testing"
  4. "github.com/d5/tengo/v2"
  5. "github.com/d5/tengo/v2/require"
  6. )
  7. func TestSymbolTable(t *testing.T) {
  8. /*
  9. GLOBAL
  10. [0] a
  11. [1] b
  12. LOCAL 1
  13. [0] d
  14. LOCAL 2
  15. [0] e
  16. [1] f
  17. LOCAL 2 BLOCK 1
  18. [2] g
  19. [3] h
  20. LOCAL 2 BLOCK 2
  21. [2] i
  22. [3] j
  23. [4] k
  24. LOCAL 1 BLOCK 1
  25. [1] l
  26. [2] m
  27. [3] n
  28. [4] o
  29. [5] p
  30. LOCAL 3
  31. [0] q
  32. [1] r
  33. */
  34. global := symbolTable()
  35. require.Equal(t, globalSymbol("a", 0), global.Define("a"))
  36. require.Equal(t, globalSymbol("b", 1), global.Define("b"))
  37. local1 := global.Fork(false)
  38. require.Equal(t, localSymbol("d", 0), local1.Define("d"))
  39. local1Block1 := local1.Fork(true)
  40. require.Equal(t, localSymbol("l", 1), local1Block1.Define("l"))
  41. require.Equal(t, localSymbol("m", 2), local1Block1.Define("m"))
  42. require.Equal(t, localSymbol("n", 3), local1Block1.Define("n"))
  43. require.Equal(t, localSymbol("o", 4), local1Block1.Define("o"))
  44. require.Equal(t, localSymbol("p", 5), local1Block1.Define("p"))
  45. local2 := local1.Fork(false)
  46. require.Equal(t, localSymbol("e", 0), local2.Define("e"))
  47. require.Equal(t, localSymbol("f", 1), local2.Define("f"))
  48. local2Block1 := local2.Fork(true)
  49. require.Equal(t, localSymbol("g", 2), local2Block1.Define("g"))
  50. require.Equal(t, localSymbol("h", 3), local2Block1.Define("h"))
  51. local2Block2 := local2.Fork(true)
  52. require.Equal(t, localSymbol("i", 2), local2Block2.Define("i"))
  53. require.Equal(t, localSymbol("j", 3), local2Block2.Define("j"))
  54. require.Equal(t, localSymbol("k", 4), local2Block2.Define("k"))
  55. local3 := local1Block1.Fork(false)
  56. require.Equal(t, localSymbol("q", 0), local3.Define("q"))
  57. require.Equal(t, localSymbol("r", 1), local3.Define("r"))
  58. require.Equal(t, 2, global.MaxSymbols())
  59. require.Equal(t, 6, local1.MaxSymbols())
  60. require.Equal(t, 6, local1Block1.MaxSymbols())
  61. require.Equal(t, 5, local2.MaxSymbols())
  62. require.Equal(t, 4, local2Block1.MaxSymbols())
  63. require.Equal(t, 5, local2Block2.MaxSymbols())
  64. require.Equal(t, 2, local3.MaxSymbols())
  65. resolveExpect(t, global, "a", globalSymbol("a", 0), 0)
  66. resolveExpect(t, local1, "d", localSymbol("d", 0), 0)
  67. resolveExpect(t, local1, "a", globalSymbol("a", 0), 1)
  68. resolveExpect(t, local3, "a", globalSymbol("a", 0), 3)
  69. resolveExpect(t, local3, "d", freeSymbol("d", 0), 2)
  70. resolveExpect(t, local3, "r", localSymbol("r", 1), 0)
  71. resolveExpect(t, local2Block2, "k", localSymbol("k", 4), 0)
  72. resolveExpect(t, local2Block2, "e", localSymbol("e", 0), 1)
  73. resolveExpect(t, local2Block2, "b", globalSymbol("b", 1), 3)
  74. }
  75. func symbol(
  76. name string,
  77. scope tengo.SymbolScope,
  78. index int,
  79. ) *tengo.Symbol {
  80. return &tengo.Symbol{
  81. Name: name,
  82. Scope: scope,
  83. Index: index,
  84. }
  85. }
  86. func globalSymbol(name string, index int) *tengo.Symbol {
  87. return symbol(name, tengo.ScopeGlobal, index)
  88. }
  89. func localSymbol(name string, index int) *tengo.Symbol {
  90. return symbol(name, tengo.ScopeLocal, index)
  91. }
  92. func freeSymbol(name string, index int) *tengo.Symbol {
  93. return symbol(name, tengo.ScopeFree, index)
  94. }
  95. func symbolTable() *tengo.SymbolTable {
  96. return tengo.NewSymbolTable()
  97. }
  98. func resolveExpect(
  99. t *testing.T,
  100. symbolTable *tengo.SymbolTable,
  101. name string,
  102. expectedSymbol *tengo.Symbol,
  103. expectedDepth int,
  104. ) {
  105. actualSymbol, actualDepth, ok := symbolTable.Resolve(name, true)
  106. require.True(t, ok)
  107. require.Equal(t, expectedSymbol, actualSymbol)
  108. require.Equal(t, expectedDepth, actualDepth)
  109. }