488 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			488 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
// 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"
 | 
						|
	"io"
 | 
						|
	"reflect"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"unsafe"
 | 
						|
 | 
						|
	"code.google.com/p/go.tools/go/types"
 | 
						|
	"code.google.com/p/go.tools/go/types/typemap"
 | 
						|
	"code.google.com/p/go.tools/ssa"
 | 
						|
)
 | 
						|
 | 
						|
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 = typemap.MakeHasher()
 | 
						|
)
 | 
						|
 | 
						|
// hashType returns a hash for t such that
 | 
						|
// types.IsIdentical(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.IsIdentical.
 | 
						|
func sameType(x, y types.Type) bool {
 | 
						|
	if x == nil {
 | 
						|
		return y == nil
 | 
						|
	}
 | 
						|
	return y != nil && types.IsIdentical(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.IsIdentical(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))
 | 
						|
}
 | 
						|
 | 
						|
// copyVal returns a copy of value v.
 | 
						|
// TODO(adonovan): add tests of aliasing and mutation.
 | 
						|
func copyVal(v value) value {
 | 
						|
	if v == nil {
 | 
						|
		panic("copyVal(nil)")
 | 
						|
	}
 | 
						|
	switch v := v.(type) {
 | 
						|
	case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string, unsafe.Pointer:
 | 
						|
		return v
 | 
						|
	case map[value]value:
 | 
						|
		return v
 | 
						|
	case *hashmap:
 | 
						|
		return v
 | 
						|
	case chan value:
 | 
						|
		return v
 | 
						|
	case *value:
 | 
						|
		return v
 | 
						|
	case *ssa.Function, *ssa.Builtin, *closure:
 | 
						|
		return v
 | 
						|
	case iface:
 | 
						|
		return v
 | 
						|
	case []value:
 | 
						|
		return v
 | 
						|
	case structure:
 | 
						|
		a := make(structure, len(v))
 | 
						|
		copy(a, v)
 | 
						|
		return a
 | 
						|
	case array:
 | 
						|
		a := make(array, len(v))
 | 
						|
		copy(a, v)
 | 
						|
		return a
 | 
						|
	case tuple:
 | 
						|
		break
 | 
						|
	case rtype:
 | 
						|
		return v
 | 
						|
	}
 | 
						|
	panic(fmt.Sprintf("cannot copy %T", 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 toWriter(w io.Writer, 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(w, "%v", v)
 | 
						|
 | 
						|
	case map[value]value:
 | 
						|
		io.WriteString(w, "map[")
 | 
						|
		sep := ""
 | 
						|
		for k, e := range v {
 | 
						|
			io.WriteString(w, sep)
 | 
						|
			sep = " "
 | 
						|
			toWriter(w, k)
 | 
						|
			io.WriteString(w, ":")
 | 
						|
			toWriter(w, e)
 | 
						|
		}
 | 
						|
		io.WriteString(w, "]")
 | 
						|
 | 
						|
	case *hashmap:
 | 
						|
		io.WriteString(w, "map[")
 | 
						|
		sep := " "
 | 
						|
		for _, e := range v.table {
 | 
						|
			for e != nil {
 | 
						|
				io.WriteString(w, sep)
 | 
						|
				sep = " "
 | 
						|
				toWriter(w, e.key)
 | 
						|
				io.WriteString(w, ":")
 | 
						|
				toWriter(w, e.value)
 | 
						|
				e = e.next
 | 
						|
			}
 | 
						|
		}
 | 
						|
		io.WriteString(w, "]")
 | 
						|
 | 
						|
	case chan value:
 | 
						|
		fmt.Fprintf(w, "%v", v) // (an address)
 | 
						|
 | 
						|
	case *value:
 | 
						|
		if v == nil {
 | 
						|
			io.WriteString(w, "<nil>")
 | 
						|
		} else {
 | 
						|
			fmt.Fprintf(w, "%p", v)
 | 
						|
		}
 | 
						|
 | 
						|
	case iface:
 | 
						|
		fmt.Fprintf(w, "(%s, ", v.t)
 | 
						|
		toWriter(w, v.v)
 | 
						|
		io.WriteString(w, ")")
 | 
						|
 | 
						|
	case structure:
 | 
						|
		io.WriteString(w, "{")
 | 
						|
		for i, e := range v {
 | 
						|
			if i > 0 {
 | 
						|
				io.WriteString(w, " ")
 | 
						|
			}
 | 
						|
			toWriter(w, e)
 | 
						|
		}
 | 
						|
		io.WriteString(w, "}")
 | 
						|
 | 
						|
	case array:
 | 
						|
		io.WriteString(w, "[")
 | 
						|
		for i, e := range v {
 | 
						|
			if i > 0 {
 | 
						|
				io.WriteString(w, " ")
 | 
						|
			}
 | 
						|
			toWriter(w, e)
 | 
						|
		}
 | 
						|
		io.WriteString(w, "]")
 | 
						|
 | 
						|
	case []value:
 | 
						|
		io.WriteString(w, "[")
 | 
						|
		for i, e := range v {
 | 
						|
			if i > 0 {
 | 
						|
				io.WriteString(w, " ")
 | 
						|
			}
 | 
						|
			toWriter(w, e)
 | 
						|
		}
 | 
						|
		io.WriteString(w, "]")
 | 
						|
 | 
						|
	case *ssa.Function, *ssa.Builtin, *closure:
 | 
						|
		fmt.Fprintf(w, "%p", v) // (an address)
 | 
						|
 | 
						|
	case rtype:
 | 
						|
		io.WriteString(w, v.t.String())
 | 
						|
 | 
						|
	case tuple:
 | 
						|
		// Unreachable in well-formed Go programs
 | 
						|
		io.WriteString(w, "(")
 | 
						|
		for i, e := range v {
 | 
						|
			if i > 0 {
 | 
						|
				io.WriteString(w, ", ")
 | 
						|
			}
 | 
						|
			toWriter(w, e)
 | 
						|
		}
 | 
						|
		io.WriteString(w, ")")
 | 
						|
 | 
						|
	default:
 | 
						|
		fmt.Fprintf(w, "<%T>", v)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Implements printing of Go values in the style of built-in println.
 | 
						|
func toString(v value) string {
 | 
						|
	var b bytes.Buffer
 | 
						|
	toWriter(&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 chan [2]value
 | 
						|
 | 
						|
func (it mapIter) next() tuple {
 | 
						|
	kv, ok := <-it
 | 
						|
	return tuple{ok, kv[0], kv[1]}
 | 
						|
}
 |