package valsimport ()// Conversion between native and Elvish values.//// Elvish uses native Go types most of the time - string, bool, hashmap.Map,// vector.Vector, etc., and there is no need for any conversions. There are some// exceptions, for instance int and rune, since Elvish currently lacks integer// types.//// There is a many-to-one relationship between Go types and Elvish types. A// Go value can always be converted to an Elvish value unambiguously, but to// convert an Elvish value into a Go value one must know the destination type// first. For example, all of the Go values int(1), rune('1') and string("1")// convert to Elvish "1"; conversely, Elvish "1" may be converted to any of the// aforementioned three possible values, depending on the destination type.//// In future, Elvish may gain distinct types for integers and characters, making// the examples above unnecessary; however, the conversion logic may not// entirely go away, as there might always be some mismatch between Elvish's// type system and Go's.typewrongTypestruct {wantKindstringgotKindstring}func ( wrongType) () string {returnfmt.Sprintf("wrong type: need %s, got %s", .wantKind, .gotKind)}typecannotParseAsstruct {wantstringreprstring}func ( cannotParseAs) () string {returnfmt.Sprintf("cannot parse as %s: %s", .want, .repr)}var (errMustBeString = errors.New("must be string")errMustBeValidUTF8 = errors.New("must be valid UTF-8")errMustHaveSingleRune = errors.New("must have a single rune")errMustBeNumber = errors.New("must be number")errMustBeInteger = errors.New("must be integer"))// ScanToGo converts an Elvish value to a Go value. the pointer points to. It// uses the type of the pointer to determine the destination type, and puts the// converted value in the location the pointer points to. Conversion only// happens when the destination type is int, float64 or rune; in other cases,// this function just checks that the source value is already assignable to the// destination.func ( interface{}, interface{}) error {switch ptr := .(type) {case *int: , := elvToInt()if == nil { * = }returncase *float64: , := elvToFloat()if == nil { * = }returncase *Num: , := elvToNum()if == nil { * = }returncase *rune: , := elvToRune()if == nil { * = }returndefault:// Do a generic `*ptr = src` via reflection := TypeOf()if .Kind() != reflect.Ptr {returnfmt.Errorf("internal bug: need pointer to scan to, got %T", ) } := .Elem()if !TypeOf().AssignableTo() {returnwrongType{Kind(reflect.Zero().Interface()), Kind()} }ValueOf().Elem().Set(ValueOf())returnnil }}// FromGo converts a Go value to an Elvish value. Most types are returned as// is, but exact numerical types are normalized to one of int, *big.Int and// *big.Rat, using the small representation that can hold the value, and runes// are converted to strings.func ( interface{}) interface{} {switch a := .(type) {case *big.Int:returnNormalizeBigInt()case *big.Rat:returnNormalizeBigRat()caserune:returnstring()default:return }}func ( interface{}) (float64, error) {switch arg := .(type) {casefloat64:return , nilcasestring: , := strconv.ParseFloat(, 64)if == nil {return , nil } , := strconv.ParseInt(, 0, 64)if == nil {returnfloat64(), }return0, cannotParseAs{"number", Repr(, -1)}default:return0, errMustBeNumber }}func ( interface{}) (int, error) {switch arg := .(type) {caseint:return , nilcasestring: , := strconv.ParseInt(, 0, 0)if == nil {returnint(), nil }return0, cannotParseAs{"integer", Repr(, -1)}default:return0, errMustBeInteger }}func ( interface{}) (Num, error) {switch arg := .(type) {caseint, *big.Int, *big.Rat, float64:return , nilcasestring: := ParseNum()if == nil {return0, cannotParseAs{"number", Repr(, -1)} }return , nildefault:return0, errMustBeNumber }}func ( interface{}) (rune, error) { , := .(string)if ! {return -1, errMustBeString } := , := utf8.DecodeRuneInString()if == utf8.RuneError {return -1, errMustBeValidUTF8 }if != len() {return -1, errMustHaveSingleRune }return , nil}
The pages are generated with Goldsv0.2.8-preview. (GOOS=darwin GOARCH=arm64)