package symbols
import "fmt"
type Scope struct {
Parent *Scope
Symbols map[string]*Symbol
}
func NewScope(parent *Scope) *Scope {
return &Scope{
Parent: parent,
Symbols: make(map[string]*Symbol),
}
}
func (s *Scope) NewChild() *Scope {
return NewScope(s)
}
func (s *Scope) Define(sym *Symbol) error {
if _, exists := s.Symbols[sym.Name]; exists {
return fmt.Errorf("symbol '%v' already defined in this scope", sym.Name)
}
for sc := s.Parent; sc != nil; sc = sc.Parent {
if _, exists := sc.Symbols[sym.Name]; exists {
return fmt.Errorf("symbol '%v' would shadow symbol from parent scope", sym.Name)
}
}
s.Symbols[sym.Name] = sym
return nil
}
func (s *Scope) Resolve(name string) (*Symbol, bool) {
for sc := s; sc != nil; sc = sc.Parent {
if sym, ok := sc.Symbols[name]; ok {
return sym, true
}
}
return nil, false
}