| // 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) |
| } |
| } |