// Copyright 2013 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 interp // Values // // All interpreter values are "boxed" in the empty interface, value. // The range of possible dynamic types within value are: // // - bool // - numbers (all built-in int/float/complex types are distinguished) // - string // - map[value]value --- maps for which usesBuiltinMap(keyType) // *hashmap --- maps for which !usesBuiltinMap(keyType) // - chan value // - []value --- slices // - iface --- interfaces. // - structure --- structs. Fields are ordered and accessed by numeric indices. // - array --- arrays. // - *value --- pointers. Careful: *value is a distinct type from *array etc. // - *ssa.Function \ // *ssa.Builtin } --- functions. A nil 'func' is always of type *ssa.Function. // *closure / // - tuple --- as returned by Return, Next, "value,ok" modes, etc. // - iter --- iterators from 'range' over map or string. // - bad --- a poison pill for locals that have gone out of scope. // - rtype -- the interpreter's concrete implementation of reflect.Type // // Note that nil is not on this list. // // Pay close attention to whether or not the dynamic type is a pointer. // The compiler cannot help you since value is an empty interface. import ( "bytes" "fmt" "go/types" "io" "reflect" "strings" "sync" "unsafe" "golang.org/x/tools/go/ssa" "golang.org/x/tools/go/types/typeutil" ) type value interface{} type tuple []value type array []value type iface struct { t types.Type // never an "untyped" type v value } type structure []value // For map, array, *array, slice, string or channel. type iter interface { // next returns a Tuple (key, value, ok). // key and value are unaliased, e.g. copies of the sequence element. next() tuple } type closure struct { Fn *ssa.Function Env []value } type bad struct{} type rtype struct { t types.Type } // Hash functions and equivalence relation: // hashString computes the FNV hash of s. func hashString(s string) int { var h uint32 for i := 0; i < len(s); i++ { h ^= uint32(s[i]) h *= 16777619 } return int(h) } var ( mu sync.Mutex hasher = typeutil.MakeHasher() ) // hashType returns a hash for t such that // types.Identical(x, y) => hashType(x) == hashType(y). func hashType(t types.Type) int { mu.Lock() h := int(hasher.Hash(t)) mu.Unlock() return h } // usesBuiltinMap returns true if the built-in hash function and // equivalence relation for type t are consistent with those of the // interpreter's representation of type t. Such types are: all basic // types (bool, numbers, string), pointers and channels. // // usesBuiltinMap returns false for types that require a custom map // implementation: interfaces, arrays and structs. // // Panic ensues if t is an invalid map key type: function, map or slice. func usesBuiltinMap(t types.Type) bool { switch t := t.(type) { case *types.Basic, *types.Chan, *types.Pointer: return true case *types.Named: return usesBuiltinMap(t.Underlying()) case *types.Interface, *types.Array, *types.Struct: return false } panic(fmt.Sprintf("invalid map key type: %T", t)) } func (x array) eq(t types.Type, _y interface{}) bool { y := _y.(array) tElt := t.Underlying().(*types.Array).Elem() for i, xi := range x { if !equals(tElt, xi, y[i]) { return false } } return true } func (x array) hash(t types.Type) int { h := 0 tElt := t.Underlying().(*types.Array).Elem() for _, xi := range x { h += hash(tElt, xi) } return h } func (x structure) eq(t types.Type, _y interface{}) bool { y := _y.(structure) tStruct := t.Underlying().(*types.Struct) for i, n := 0, tStruct.NumFields(); i < n; i++ { if f := tStruct.Field(i); !f.Anonymous() { if !equals(f.Type(), x[i], y[i]) { return false } } } return true } func (x structure) hash(t types.Type) int { tStruct := t.Underlying().(*types.Struct) h := 0 for i, n := 0, tStruct.NumFields(); i < n; i++ { if f := tStruct.Field(i); !f.Anonymous() { h += hash(f.Type(), x[i]) } } return h } // nil-tolerant variant of types.Identical. func sameType(x, y types.Type) bool { if x == nil { return y == nil } return y != nil && types.Identical(x, y) } func (x iface) eq(t types.Type, _y interface{}) bool { y := _y.(iface) return sameType(x.t, y.t) && (x.t == nil || equals(x.t, x.v, y.v)) } func (x iface) hash(_ types.Type) int { return hashType(x.t)*8581 + hash(x.t, x.v) } func (x rtype) hash(_ types.Type) int { return hashType(x.t) } func (x rtype) eq(_ types.Type, y interface{}) bool { return types.Identical(x.t, y.(rtype).t) } // equals returns true iff x and y are equal according to Go's // linguistic equivalence relation for type t. // In a well-typed program, the dynamic types of x and y are // guaranteed equal. func equals(t types.Type, x, y value) bool { switch x := x.(type) { case bool: return x == y.(bool) case int: return x == y.(int) case int8: return x == y.(int8) case int16: return x == y.(int16) case int32: return x == y.(int32) case int64: return x == y.(int64) case uint: return x == y.(uint) case uint8: return x == y.(uint8) case uint16: return x == y.(uint16) case uint32: return x == y.(uint32) case uint64: return x == y.(uint64) case uintptr: return x == y.(uintptr) case float32: return x == y.(float32) case float64: return x == y.(float64) case complex64: return x == y.(complex64) case complex128: return x == y.(complex128) case string: return x == y.(string) case *value: return x == y.(*value) case chan value: return x == y.(chan value) case structure: return x.eq(t, y) case array: return x.eq(t, y) case iface: return x.eq(t, y) case rtype: return x.eq(t, y) } // Since map, func and slice don't support comparison, this // case is only reachable if one of x or y is literally nil // (handled in eqnil) or via interface{} values. panic(fmt.Sprintf("comparing uncomparable type %s", t)) } // Returns an integer hash of x such that equals(x, y) => hash(x) == hash(y). func hash(t types.Type, x value) int { switch x := x.(type) { case bool: if x { return 1 } return 0 case int: return x case int8: return int(x) case int16: return int(x) case int32: return int(x) case int64: return int(x) case uint: return int(x) case uint8: return int(x) case uint16: return int(x) case uint32: return int(x) case uint64: return int(x) case uintptr: return int(x) case float32: return int(x) case float64: return int(x) case complex64: return int(real(x)) case complex128: return int(real(x)) case string: return hashString(x) case *value: return int(uintptr(unsafe.Pointer(x))) case chan value: return int(uintptr(reflect.ValueOf(x).Pointer())) case structure: return x.hash(t) case array: return x.hash(t) case iface: return x.hash(t) case rtype: return x.hash(t) } panic(fmt.Sprintf("%T is unhashable", x)) } // reflect.Value struct values don't have a fixed shape, since the // payload can be a scalar or an aggregate depending on the instance. // So store (and load) can't simply use recursion over the shape of the // rhs value, or the lhs, to copy the value; we need the static type // information. (We can't make reflect.Value a new basic data type // because its "structness" is exposed to Go programs.) // load returns the value of type T in *addr. func load(T types.Type, addr *value) value { switch T := T.Underlying().(type) { case *types.Struct: v := (*addr).(structure) a := make(structure, len(v)) for i := range a { a[i] = load(T.Field(i).Type(), &v[i]) } return a case *types.Array: v := (*addr).(array) a := make(array, len(v)) for i := range a { a[i] = load(T.Elem(), &v[i]) } return a default: return *addr } } // store stores value v of type T into *addr. func store(T types.Type, addr *value, v value) { switch T := T.Underlying().(type) { case *types.Struct: lhs := (*addr).(structure) rhs := v.(structure) for i := range lhs { store(T.Field(i).Type(), &lhs[i], rhs[i]) } case *types.Array: lhs := (*addr).(array) rhs := v.(array) for i := range lhs { store(T.Elem(), &lhs[i], rhs[i]) } default: *addr = v } } // Prints in the style of built-in println. // (More or less; in gc println is actually a compiler intrinsic and // can distinguish println(1) from println(interface{}(1)).) func writeValue(buf *bytes.Buffer, v value) { switch v := v.(type) { case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string: fmt.Fprintf(buf, "%v", v) case map[value]value: buf.WriteString("map[") sep := "" for k, e := range v { buf.WriteString(sep) sep = " " writeValue(buf, k) buf.WriteString(":") writeValue(buf, e) } buf.WriteString("]") case *hashmap: buf.WriteString("map[") sep := " " for _, e := range v.entries() { for e != nil { buf.WriteString(sep) sep = " " writeValue(buf, e.key) buf.WriteString(":") writeValue(buf, e.value) e = e.next } } buf.WriteString("]") case chan value: fmt.Fprintf(buf, "%v", v) // (an address) case *value: if v == nil { buf.WriteString("") } else { fmt.Fprintf(buf, "%p", v) } case iface: fmt.Fprintf(buf, "(%s, ", v.t) writeValue(buf, v.v) buf.WriteString(")") case structure: buf.WriteString("{") for i, e := range v { if i > 0 { buf.WriteString(" ") } writeValue(buf, e) } buf.WriteString("}") case array: buf.WriteString("[") for i, e := range v { if i > 0 { buf.WriteString(" ") } writeValue(buf, e) } buf.WriteString("]") case []value: buf.WriteString("[") for i, e := range v { if i > 0 { buf.WriteString(" ") } writeValue(buf, e) } buf.WriteString("]") case *ssa.Function, *ssa.Builtin, *closure: fmt.Fprintf(buf, "%p", v) // (an address) case rtype: buf.WriteString(v.t.String()) case tuple: // Unreachable in well-formed Go programs buf.WriteString("(") for i, e := range v { if i > 0 { buf.WriteString(", ") } writeValue(buf, e) } buf.WriteString(")") default: fmt.Fprintf(buf, "<%T>", v) } } // Implements printing of Go values in the style of built-in println. func toString(v value) string { var b bytes.Buffer writeValue(&b, v) return b.String() } // ------------------------------------------------------------------------ // Iterators type stringIter struct { *strings.Reader i int } func (it *stringIter) next() tuple { okv := make(tuple, 3) ch, n, err := it.ReadRune() ok := err != io.EOF okv[0] = ok if ok { okv[1] = it.i okv[2] = ch } it.i += n return okv } type mapIter struct { iter *reflect.MapIter ok bool } func (it *mapIter) next() tuple { it.ok = it.iter.Next() if !it.ok { return []value{false, nil, nil} } k, v := it.iter.Key().Interface(), it.iter.Value().Interface() return []value{true, k, v} } type hashmapIter struct { iter *reflect.MapIter ok bool cur *entry } func (it *hashmapIter) next() tuple { for { if it.cur != nil { k, v := it.cur.key, it.cur.value it.cur = it.cur.next return []value{true, k, v} } it.ok = it.iter.Next() if !it.ok { return []value{false, nil, nil} } it.cur = it.iter.Value().Interface().(*entry) } }