// Package voc implements a generic vocabulary. Vocabularies may be nested // and are searched upwards using the parent vocabulary until this is nil. // Individual entries contain slices of values; the last item in a // slice is the current value. package voc import ( "git.sr.ht/~cco/go-scopes/common/funky" ) type VocData[V any] map[string][]V type Vocabulary[V any] struct { parent *Vocabulary[V] data VocData[V] } func NewVoc[V any](parent *Vocabulary[V]) *Vocabulary[V] { return &Vocabulary[V]{ parent: parent, data: VocData[V]{}, } } func (voc *Vocabulary[V]) Register(name string, it V) { vi, ok := voc.data[name] if ok { voc.data[name] = append(vi, it) } else { voc.data[name] = []V{it} } } func (voc *Vocabulary[V]) Lookup(name string) funky.Maybe[V] { vi, ok := voc.data[name] if ok { return funky.Just(vi[len(vi)-1]) } if voc.parent != nil { return voc.parent.Lookup(name) } return funky.Nothing[V]() }