// Copyright 2022 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package types import "sync" // methodList holds a list of methods that may be lazily resolved by a provided // resolution method. type methodList struct { methods []*Func // guards synchronizes the instantiation of lazy methods. For lazy method // lists, guards is non-nil and of the length passed to newLazyMethodList. // For non-lazy method lists, guards is nil. guards *[]sync.Once } // newMethodList creates a non-lazy method list holding the given methods. func newMethodList(methods []*Func) *methodList { return &methodList{methods: methods} } // newLazyMethodList creates a lazy method list of the given length. Methods // may be resolved lazily for a given index by providing a resolver function. func newLazyMethodList(length int) *methodList { guards := make([]sync.Once, length) return &methodList{ methods: make([]*Func, length), guards: &guards, } } // isLazy reports whether the receiver is a lazy method list. func (l *methodList) isLazy() bool { return l != nil && l.guards != nil } // Add appends a method to the method list if not not already present. Add // panics if the receiver is lazy. func (l *methodList) Add(m *Func) { assert(!l.isLazy()) if i, _ := lookupMethod(l.methods, m.pkg, m.name, false); i < 0 { l.methods = append(l.methods, m) } } // Lookup looks up the method identified by pkg and name in the receiver. // Lookup panics if the receiver is lazy. If foldCase is true, method names // are considered equal if they are equal with case folding. func (l *methodList) Lookup(pkg *Package, name string, foldCase bool) (int, *Func) { assert(!l.isLazy()) if l == nil { return -1, nil } return lookupMethod(l.methods, pkg, name, foldCase) } // Len returns the length of the method list. func (l *methodList) Len() int { if l == nil { return 0 } return len(l.methods) } // At returns the i'th method of the method list. At panics if i is out of // bounds, or if the receiver is lazy and resolve is nil. func (l *methodList) At(i int, resolve func() *Func) *Func { if !l.isLazy() { return l.methods[i] } assert(resolve != nil) (*l.guards)[i].Do(func() { l.methods[i] = resolve() }) return l.methods[i] }