| // 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("<nil>") | |
| } 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) | |
| } | |
| } |