package shared
type SymbolTable[T any] struct {
scopes []map[string]T
}
func NewSymbolTable[T any](_initial ...map[string]T) *SymbolTable[T] {
initial := map[string]T{}
if len(_initial) > 0 {
initial = _initial[0]
}
return &SymbolTable[T]{scopes: []map[string]T{initial}}
}
func (st *SymbolTable[T]) EnterScope() {
st.scopes = append(st.scopes, make(map[string]T))
}
func (st *SymbolTable[T]) ExitScope() {
if len(st.scopes) > 1 {
st.scopes = st.scopes[:len(st.scopes)-1]
} else {
panic("cannot exit global scope")
}
}
func (st *SymbolTable[T]) GetScope() map[string]T {
return st.scopes[len(st.scopes)-1]
}
func (st *SymbolTable[T]) Define(name string, value T) bool {
currentScope := st.scopes[len(st.scopes)-1]
if _, ok := st.Lookup(name); ok {
return false
}
currentScope[name] = value
return true
}
func (st *SymbolTable[T]) Lookup(name string) (T, bool) {
for i := len(st.scopes) - 1; i >= 0; i-- {
if value, found := st.scopes[i][name]; found {
return value, true
}
}
var zeroVal T
return zeroVal, false
}