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
}