mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-04 10:57:50 +08:00
96752afa4d
Struct map is a mechanism to let Go code expose simple structs to Elvish code. The difference between struct maps and maps is convenience for Go code; they also have different performance characteristics, but since struct maps are always quite small, the difference is not meaningful for Elvish's use cases. As a result, there is no good reason that Elvish code needs to be aware of the difference between struct maps and normal maps. Making them indistinguishable to Elvish code simplifies the language. This commit does the following: - Change Equal, Hash, Kind and Repr to treat struct maps like maps. - Change Assoc and Dissoc to "promote" struct maps to maps. - Remove the custom Repr method of parse.Source. - Update documentation to reflect this change.
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package vals
|
|
|
|
import (
|
|
"errors"
|
|
)
|
|
|
|
// Assocer wraps the Assoc method.
|
|
type Assocer interface {
|
|
// Assoc returns a slightly modified version of the receiver with key k
|
|
// associated with value v.
|
|
Assoc(k, v any) (any, error)
|
|
}
|
|
|
|
var (
|
|
errAssocUnsupported = errors.New("assoc is not supported")
|
|
errReplacementMustBeString = errors.New("replacement must be string")
|
|
errAssocWithSlice = errors.New("assoc with slice not yet supported")
|
|
)
|
|
|
|
// Assoc takes a container, a key and value, and returns a modified version of
|
|
// the container, in which the key associated with the value. It is implemented
|
|
// for the builtin type string, List and Map types, StructMap types, and types
|
|
// satisfying the Assocer interface. For other types, it returns an error.
|
|
func Assoc(a, k, v any) (any, error) {
|
|
switch a := a.(type) {
|
|
case string:
|
|
return assocString(a, k, v)
|
|
case List:
|
|
return assocList(a, k, v)
|
|
case Map:
|
|
return a.Assoc(k, v), nil
|
|
case StructMap:
|
|
return promoteToMap(a).Assoc(k, v), nil
|
|
case Assocer:
|
|
return a.Assoc(k, v)
|
|
}
|
|
return nil, errAssocUnsupported
|
|
}
|
|
|
|
func assocString(s string, k, v any) (any, error) {
|
|
i, j, err := convertStringIndex(k, s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
repl, ok := v.(string)
|
|
if !ok {
|
|
return nil, errReplacementMustBeString
|
|
}
|
|
return s[:i] + repl + s[j:], nil
|
|
}
|
|
|
|
func assocList(l List, k, v any) (any, error) {
|
|
index, err := ConvertListIndex(k, l.Len())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if index.Slice {
|
|
return nil, errAssocWithSlice
|
|
}
|
|
return l.Assoc(index.Lower, v), nil
|
|
}
|