Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(259)

Unified Diff: src/pkg/exp/eval/type.go

Issue 4695047: code review 4695047: exp/eval, exp/ogle: remove packages eval and ogle (Closed)
Patch Set: diff -r 7f39a0541e03 https://go.googlecode.com/hg/ Created 13 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pkg/exp/eval/test.bash ('k') | src/pkg/exp/eval/typec.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pkg/exp/eval/type.go
===================================================================
deleted file mode 100644
--- a/src/pkg/exp/eval/type.go
+++ /dev/null
@@ -1,1252 +0,0 @@
-// Copyright 2009 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 eval
-
-import (
- "big"
- "go/ast"
- "go/token"
- "log"
- "reflect"
- "sort"
- "unsafe" // For Sizeof
-)
-
-
-// XXX(Spec) The type compatibility section is very confusing because
-// it makes it seem like there are three distinct types of
-// compatibility: plain compatibility, assignment compatibility, and
-// comparison compatibility. As I understand it, there's really only
-// assignment compatibility and comparison and conversion have some
-// restrictions and have special meaning in some cases where the types
-// are not otherwise assignment compatible. The comparison
-// compatibility section is almost all about the semantics of
-// comparison, not the type checking of it, so it would make much more
-// sense in the comparison operators section. The compatibility and
-// assignment compatibility sections should be rolled into one.
-
-type Type interface {
- // compat returns whether this type is compatible with another
- // type. If conv is false, this is normal compatibility,
- // where two named types are compatible only if they are the
- // same named type. If conv if true, this is conversion
- // compatibility, where two named types are conversion
- // compatible if their definitions are conversion compatible.
- //
- // TODO(austin) Deal with recursive types
- compat(o Type, conv bool) bool
- // lit returns this type's literal. If this is a named type,
- // this is the unnamed underlying type. Otherwise, this is an
- // identity operation.
- lit() Type
- // isBoolean returns true if this is a boolean type.
- isBoolean() bool
- // isInteger returns true if this is an integer type.
- isInteger() bool
- // isFloat returns true if this is a floating type.
- isFloat() bool
- // isIdeal returns true if this is an ideal int or float.
- isIdeal() bool
- // Zero returns a new zero value of this type.
- Zero() Value
- // String returns the string representation of this type.
- String() string
- // The position where this type was defined, if any.
- Pos() token.Pos
-}
-
-type BoundedType interface {
- Type
- // minVal returns the smallest value of this type.
- minVal() *big.Rat
- // maxVal returns the largest value of this type.
- maxVal() *big.Rat
-}
-
-var universePos = token.NoPos
-
-/*
- * Type array maps. These are used to memoize composite types.
- */
-
-type typeArrayMapEntry struct {
- key []Type
- v interface{}
- next *typeArrayMapEntry
-}
-
-type typeArrayMap map[uintptr]*typeArrayMapEntry
-
-func hashTypeArray(key []Type) uintptr {
- hash := uintptr(0)
- for _, t := range key {
- hash = hash * 33
- if t == nil {
- continue
- }
- addr := reflect.ValueOf(t).Pointer()
- hash ^= addr
- }
- return hash
-}
-
-func newTypeArrayMap() typeArrayMap { return make(map[uintptr]*typeArrayMapEntry) }
-
-func (m typeArrayMap) Get(key []Type) interface{} {
- ent, ok := m[hashTypeArray(key)]
- if !ok {
- return nil
- }
-
-nextEnt:
- for ; ent != nil; ent = ent.next {
- if len(key) != len(ent.key) {
- continue
- }
- for i := 0; i < len(key); i++ {
- if key[i] != ent.key[i] {
- continue nextEnt
- }
- }
- // Found it
- return ent.v
- }
-
- return nil
-}
-
-func (m typeArrayMap) Put(key []Type, v interface{}) interface{} {
- hash := hashTypeArray(key)
- ent := m[hash]
-
- new := &typeArrayMapEntry{key, v, ent}
- m[hash] = new
- return v
-}
-
-/*
- * Common type
- */
-
-type commonType struct{}
-
-func (commonType) isBoolean() bool { return false }
-
-func (commonType) isInteger() bool { return false }
-
-func (commonType) isFloat() bool { return false }
-
-func (commonType) isIdeal() bool { return false }
-
-func (commonType) Pos() token.Pos { return token.NoPos }
-
-/*
- * Bool
- */
-
-type boolType struct {
- commonType
-}
-
-var BoolType = universe.DefineType("bool", universePos, &boolType{})
-
-func (t *boolType) compat(o Type, conv bool) bool {
- _, ok := o.lit().(*boolType)
- return ok
-}
-
-func (t *boolType) lit() Type { return t }
-
-func (t *boolType) isBoolean() bool { return true }
-
-func (boolType) String() string {
- // Use angle brackets as a convention for printing the
- // underlying, unnamed type. This should only show up in
- // debug output.
- return "<bool>"
-}
-
-func (t *boolType) Zero() Value {
- res := boolV(false)
- return &res
-}
-
-/*
- * Uint
- */
-
-type uintType struct {
- commonType
-
- // 0 for architecture-dependent types
- Bits uint
- // true for uintptr, false for all others
- Ptr bool
- name string
-}
-
-var (
- Uint8Type = universe.DefineType("uint8", universePos, &uintType{commonType{}, 8, false, "uint8"})
- Uint16Type = universe.DefineType("uint16", universePos, &uintType{commonType{}, 16, false, "uint16"})
- Uint32Type = universe.DefineType("uint32", universePos, &uintType{commonType{}, 32, false, "uint32"})
- Uint64Type = universe.DefineType("uint64", universePos, &uintType{commonType{}, 64, false, "uint64"})
-
- UintType = universe.DefineType("uint", universePos, &uintType{commonType{}, 0, false, "uint"})
- UintptrType = universe.DefineType("uintptr", universePos, &uintType{commonType{}, 0, true, "uintptr"})
-)
-
-func (t *uintType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*uintType)
- return ok && t == t2
-}
-
-func (t *uintType) lit() Type { return t }
-
-func (t *uintType) isInteger() bool { return true }
-
-func (t *uintType) String() string { return "<" + t.name + ">" }
-
-func (t *uintType) Zero() Value {
- switch t.Bits {
- case 0:
- if t.Ptr {
- res := uintptrV(0)
- return &res
- } else {
- res := uintV(0)
- return &res
- }
- case 8:
- res := uint8V(0)
- return &res
- case 16:
- res := uint16V(0)
- return &res
- case 32:
- res := uint32V(0)
- return &res
- case 64:
- res := uint64V(0)
- return &res
- }
- panic("unexpected uint bit count")
-}
-
-func (t *uintType) minVal() *big.Rat { return big.NewRat(0, 1) }
-
-func (t *uintType) maxVal() *big.Rat {
- bits := t.Bits
- if bits == 0 {
- if t.Ptr {
- bits = uint(8 * unsafe.Sizeof(uintptr(0)))
- } else {
- bits = uint(8 * unsafe.Sizeof(uint(0)))
- }
- }
- numer := big.NewInt(1)
- numer.Lsh(numer, bits)
- numer.Sub(numer, idealOne)
- return new(big.Rat).SetInt(numer)
-}
-
-/*
- * Int
- */
-
-type intType struct {
- commonType
-
- // XXX(Spec) Numeric types: "There is also a set of
- // architecture-independent basic numeric types whose size
- // depends on the architecture." Should that be
- // architecture-dependent?
-
- // 0 for architecture-dependent types
- Bits uint
- name string
-}
-
-var (
- Int8Type = universe.DefineType("int8", universePos, &intType{commonType{}, 8, "int8"})
- Int16Type = universe.DefineType("int16", universePos, &intType{commonType{}, 16, "int16"})
- Int32Type = universe.DefineType("int32", universePos, &intType{commonType{}, 32, "int32"})
- Int64Type = universe.DefineType("int64", universePos, &intType{commonType{}, 64, "int64"})
-
- IntType = universe.DefineType("int", universePos, &intType{commonType{}, 0, "int"})
-)
-
-func (t *intType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*intType)
- return ok && t == t2
-}
-
-func (t *intType) lit() Type { return t }
-
-func (t *intType) isInteger() bool { return true }
-
-func (t *intType) String() string { return "<" + t.name + ">" }
-
-func (t *intType) Zero() Value {
- switch t.Bits {
- case 8:
- res := int8V(0)
- return &res
- case 16:
- res := int16V(0)
- return &res
- case 32:
- res := int32V(0)
- return &res
- case 64:
- res := int64V(0)
- return &res
-
- case 0:
- res := intV(0)
- return &res
- }
- panic("unexpected int bit count")
-}
-
-func (t *intType) minVal() *big.Rat {
- bits := t.Bits
- if bits == 0 {
- bits = uint(8 * unsafe.Sizeof(int(0)))
- }
- numer := big.NewInt(-1)
- numer.Lsh(numer, bits-1)
- return new(big.Rat).SetInt(numer)
-}
-
-func (t *intType) maxVal() *big.Rat {
- bits := t.Bits
- if bits == 0 {
- bits = uint(8 * unsafe.Sizeof(int(0)))
- }
- numer := big.NewInt(1)
- numer.Lsh(numer, bits-1)
- numer.Sub(numer, idealOne)
- return new(big.Rat).SetInt(numer)
-}
-
-/*
- * Ideal int
- */
-
-type idealIntType struct {
- commonType
-}
-
-var IdealIntType Type = &idealIntType{}
-
-func (t *idealIntType) compat(o Type, conv bool) bool {
- _, ok := o.lit().(*idealIntType)
- return ok
-}
-
-func (t *idealIntType) lit() Type { return t }
-
-func (t *idealIntType) isInteger() bool { return true }
-
-func (t *idealIntType) isIdeal() bool { return true }
-
-func (t *idealIntType) String() string { return "ideal integer" }
-
-func (t *idealIntType) Zero() Value { return &idealIntV{idealZero} }
-
-/*
- * Float
- */
-
-type floatType struct {
- commonType
-
- // 0 for architecture-dependent type
- Bits uint
-
- name string
-}
-
-var (
- Float32Type = universe.DefineType("float32", universePos, &floatType{commonType{}, 32, "float32"})
- Float64Type = universe.DefineType("float64", universePos, &floatType{commonType{}, 64, "float64"})
-)
-
-func (t *floatType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*floatType)
- return ok && t == t2
-}
-
-func (t *floatType) lit() Type { return t }
-
-func (t *floatType) isFloat() bool { return true }
-
-func (t *floatType) String() string { return "<" + t.name + ">" }
-
-func (t *floatType) Zero() Value {
- switch t.Bits {
- case 32:
- res := float32V(0)
- return &res
- case 64:
- res := float64V(0)
- return &res
- }
- panic("unexpected float bit count")
-}
-
-var maxFloat32Val *big.Rat
-var maxFloat64Val *big.Rat
-var minFloat32Val *big.Rat
-var minFloat64Val *big.Rat
-
-func (t *floatType) minVal() *big.Rat {
- bits := t.Bits
- switch bits {
- case 32:
- return minFloat32Val
- case 64:
- return minFloat64Val
- }
- log.Panicf("unexpected floating point bit count: %d", bits)
- panic("unreachable")
-}
-
-func (t *floatType) maxVal() *big.Rat {
- bits := t.Bits
- switch bits {
- case 32:
- return maxFloat32Val
- case 64:
- return maxFloat64Val
- }
- log.Panicf("unexpected floating point bit count: %d", bits)
- panic("unreachable")
-}
-
-/*
- * Ideal float
- */
-
-type idealFloatType struct {
- commonType
-}
-
-var IdealFloatType Type = &idealFloatType{}
-
-func (t *idealFloatType) compat(o Type, conv bool) bool {
- _, ok := o.lit().(*idealFloatType)
- return ok
-}
-
-func (t *idealFloatType) lit() Type { return t }
-
-func (t *idealFloatType) isFloat() bool { return true }
-
-func (t *idealFloatType) isIdeal() bool { return true }
-
-func (t *idealFloatType) String() string { return "ideal float" }
-
-func (t *idealFloatType) Zero() Value { return &idealFloatV{big.NewRat(0, 1)} }
-
-/*
- * String
- */
-
-type stringType struct {
- commonType
-}
-
-var StringType = universe.DefineType("string", universePos, &stringType{})
-
-func (t *stringType) compat(o Type, conv bool) bool {
- _, ok := o.lit().(*stringType)
- return ok
-}
-
-func (t *stringType) lit() Type { return t }
-
-func (t *stringType) String() string { return "<string>" }
-
-func (t *stringType) Zero() Value {
- res := stringV("")
- return &res
-}
-
-/*
- * Array
- */
-
-type ArrayType struct {
- commonType
- Len int64
- Elem Type
-}
-
-var arrayTypes = make(map[int64]map[Type]*ArrayType)
-
-// Two array types are identical if they have identical element types
-// and the same array length.
-
-func NewArrayType(len int64, elem Type) *ArrayType {
- ts, ok := arrayTypes[len]
- if !ok {
- ts = make(map[Type]*ArrayType)
- arrayTypes[len] = ts
- }
- t, ok := ts[elem]
- if !ok {
- t = &ArrayType{commonType{}, len, elem}
- ts[elem] = t
- }
- return t
-}
-
-func (t *ArrayType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*ArrayType)
- if !ok {
- return false
- }
- return t.Len == t2.Len && t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *ArrayType) lit() Type { return t }
-
-func (t *ArrayType) String() string { return "[]" + t.Elem.String() }
-
-func (t *ArrayType) Zero() Value {
- res := arrayV(make([]Value, t.Len))
- // TODO(austin) It's unfortunate that each element is
- // separately heap allocated. We could add ZeroArray to
- // everything, though that doesn't help with multidimensional
- // arrays. Or we could do something unsafe. We'll have this
- // same problem with structs.
- for i := int64(0); i < t.Len; i++ {
- res[i] = t.Elem.Zero()
- }
- return &res
-}
-
-/*
- * Struct
- */
-
-type StructField struct {
- Name string
- Type Type
- Anonymous bool
-}
-
-type StructType struct {
- commonType
- Elems []StructField
-}
-
-var structTypes = newTypeArrayMap()
-
-// Two struct types are identical if they have the same sequence of
-// fields, and if corresponding fields have the same names and
-// identical types. Two anonymous fields are considered to have the
-// same name.
-
-func NewStructType(fields []StructField) *StructType {
- // Start by looking up just the types
- fts := make([]Type, len(fields))
- for i, f := range fields {
- fts[i] = f.Type
- }
- tMapI := structTypes.Get(fts)
- if tMapI == nil {
- tMapI = structTypes.Put(fts, make(map[string]*StructType))
- }
- tMap := tMapI.(map[string]*StructType)
-
- // Construct key for field names
- key := ""
- for _, f := range fields {
- // XXX(Spec) It's not clear if struct { T } and struct
- // { T T } are either identical or compatible. The
- // "Struct Types" section says that the name of that
- // field is "T", which suggests that they are
- // identical, but it really means that it's the name
- // for the purpose of selector expressions and nothing
- // else. We decided that they should be neither
- // identical or compatible.
- if f.Anonymous {
- key += "!"
- }
- key += f.Name + " "
- }
-
- // XXX(Spec) Do the tags also have to be identical for the
- // types to be identical? I certainly hope so, because
- // otherwise, this is the only case where two distinct type
- // objects can represent identical types.
-
- t, ok := tMap[key]
- if !ok {
- // Create new struct type
- t = &StructType{commonType{}, fields}
- tMap[key] = t
- }
- return t
-}
-
-func (t *StructType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*StructType)
- if !ok {
- return false
- }
- if len(t.Elems) != len(t2.Elems) {
- return false
- }
- for i, e := range t.Elems {
- e2 := t2.Elems[i]
- // XXX(Spec) An anonymous and a non-anonymous field
- // are neither identical nor compatible.
- if e.Anonymous != e2.Anonymous ||
- (!e.Anonymous && e.Name != e2.Name) ||
- !e.Type.compat(e2.Type, conv) {
- return false
- }
- }
- return true
-}
-
-func (t *StructType) lit() Type { return t }
-
-func (t *StructType) String() string {
- s := "struct {"
- for i, f := range t.Elems {
- if i > 0 {
- s += "; "
- }
- if !f.Anonymous {
- s += f.Name + " "
- }
- s += f.Type.String()
- }
- return s + "}"
-}
-
-func (t *StructType) Zero() Value {
- res := structV(make([]Value, len(t.Elems)))
- for i, f := range t.Elems {
- res[i] = f.Type.Zero()
- }
- return &res
-}
-
-/*
- * Pointer
- */
-
-type PtrType struct {
- commonType
- Elem Type
-}
-
-var ptrTypes = make(map[Type]*PtrType)
-
-// Two pointer types are identical if they have identical base types.
-
-func NewPtrType(elem Type) *PtrType {
- t, ok := ptrTypes[elem]
- if !ok {
- t = &PtrType{commonType{}, elem}
- ptrTypes[elem] = t
- }
- return t
-}
-
-func (t *PtrType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*PtrType)
- if !ok {
- return false
- }
- return t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *PtrType) lit() Type { return t }
-
-func (t *PtrType) String() string { return "*" + t.Elem.String() }
-
-func (t *PtrType) Zero() Value { return &ptrV{nil} }
-
-/*
- * Function
- */
-
-type FuncType struct {
- commonType
- // TODO(austin) Separate receiver Type for methods?
- In []Type
- Variadic bool
- Out []Type
- builtin string
-}
-
-var funcTypes = newTypeArrayMap()
-var variadicFuncTypes = newTypeArrayMap()
-
-// Create singleton function types for magic built-in functions
-var (
- capType = &FuncType{builtin: "cap"}
- closeType = &FuncType{builtin: "close"}
- closedType = &FuncType{builtin: "closed"}
- lenType = &FuncType{builtin: "len"}
- makeType = &FuncType{builtin: "make"}
- newType = &FuncType{builtin: "new"}
- panicType = &FuncType{builtin: "panic"}
- printType = &FuncType{builtin: "print"}
- printlnType = &FuncType{builtin: "println"}
- copyType = &FuncType{builtin: "copy"}
-)
-
-// Two function types are identical if they have the same number of
-// parameters and result values and if corresponding parameter and
-// result types are identical. All "..." parameters have identical
-// type. Parameter and result names are not required to match.
-
-func NewFuncType(in []Type, variadic bool, out []Type) *FuncType {
- inMap := funcTypes
- if variadic {
- inMap = variadicFuncTypes
- }
-
- outMapI := inMap.Get(in)
- if outMapI == nil {
- outMapI = inMap.Put(in, newTypeArrayMap())
- }
- outMap := outMapI.(typeArrayMap)
-
- tI := outMap.Get(out)
- if tI != nil {
- return tI.(*FuncType)
- }
-
- t := &FuncType{commonType{}, in, variadic, out, ""}
- outMap.Put(out, t)
- return t
-}
-
-func (t *FuncType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*FuncType)
- if !ok {
- return false
- }
- if len(t.In) != len(t2.In) || t.Variadic != t2.Variadic || len(t.Out) != len(t2.Out) {
- return false
- }
- for i := range t.In {
- if !t.In[i].compat(t2.In[i], conv) {
- return false
- }
- }
- for i := range t.Out {
- if !t.Out[i].compat(t2.Out[i], conv) {
- return false
- }
- }
- return true
-}
-
-func (t *FuncType) lit() Type { return t }
-
-func typeListString(ts []Type, ns []*ast.Ident) string {
- s := ""
- for i, t := range ts {
- if i > 0 {
- s += ", "
- }
- if ns != nil && ns[i] != nil {
- s += ns[i].Name + " "
- }
- if t == nil {
- // Some places use nil types to represent errors
- s += "<none>"
- } else {
- s += t.String()
- }
- }
- return s
-}
-
-func (t *FuncType) String() string {
- if t.builtin != "" {
- return "built-in function " + t.builtin
- }
- args := typeListString(t.In, nil)
- if t.Variadic {
- if len(args) > 0 {
- args += ", "
- }
- args += "..."
- }
- s := "func(" + args + ")"
- if len(t.Out) > 0 {
- s += " (" + typeListString(t.Out, nil) + ")"
- }
- return s
-}
-
-func (t *FuncType) Zero() Value { return &funcV{nil} }
-
-type FuncDecl struct {
- Type *FuncType
- Name *ast.Ident // nil for function literals
- // InNames will be one longer than Type.In if this function is
- // variadic.
- InNames []*ast.Ident
- OutNames []*ast.Ident
-}
-
-func (t *FuncDecl) String() string {
- s := "func"
- if t.Name != nil {
- s += " " + t.Name.Name
- }
- s += funcTypeString(t.Type, t.InNames, t.OutNames)
- return s
-}
-
-func funcTypeString(ft *FuncType, ins []*ast.Ident, outs []*ast.Ident) string {
- s := "("
- s += typeListString(ft.In, ins)
- if ft.Variadic {
- if len(ft.In) > 0 {
- s += ", "
- }
- s += "..."
- }
- s += ")"
- if len(ft.Out) > 0 {
- s += " (" + typeListString(ft.Out, outs) + ")"
- }
- return s
-}
-
-/*
- * Interface
- */
-
-// TODO(austin) Interface values, types, and type compilation are
-// implemented, but none of the type checking or semantics of
-// interfaces are.
-
-type InterfaceType struct {
- commonType
- // TODO(austin) This should be a map from names to
- // *FuncType's. We only need the sorted list for generating
- // the type map key. It's detrimental for everything else.
- methods []IMethod
-}
-
-type IMethod struct {
- Name string
- Type *FuncType
-}
-
-var interfaceTypes = newTypeArrayMap()
-
-func NewInterfaceType(methods []IMethod, embeds []*InterfaceType) *InterfaceType {
- // Count methods of embedded interfaces
- nMethods := len(methods)
- for _, e := range embeds {
- nMethods += len(e.methods)
- }
-
- // Combine methods
- allMethods := make([]IMethod, nMethods)
- copy(allMethods, methods)
- n := len(methods)
- for _, e := range embeds {
- for _, m := range e.methods {
- allMethods[n] = m
- n++
- }
- }
-
- // Sort methods
- sort.Sort(iMethodSorter(allMethods))
-
- mts := make([]Type, len(allMethods))
- for i, m := range methods {
- mts[i] = m.Type
- }
- tMapI := interfaceTypes.Get(mts)
- if tMapI == nil {
- tMapI = interfaceTypes.Put(mts, make(map[string]*InterfaceType))
- }
- tMap := tMapI.(map[string]*InterfaceType)
-
- key := ""
- for _, m := range allMethods {
- key += m.Name + " "
- }
-
- t, ok := tMap[key]
- if !ok {
- t = &InterfaceType{commonType{}, allMethods}
- tMap[key] = t
- }
- return t
-}
-
-type iMethodSorter []IMethod
-
-func (s iMethodSorter) Less(a, b int) bool { return s[a].Name < s[b].Name }
-
-func (s iMethodSorter) Swap(a, b int) { s[a], s[b] = s[b], s[a] }
-
-func (s iMethodSorter) Len() int { return len(s) }
-
-func (t *InterfaceType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*InterfaceType)
- if !ok {
- return false
- }
- if len(t.methods) != len(t2.methods) {
- return false
- }
- for i, e := range t.methods {
- e2 := t2.methods[i]
- if e.Name != e2.Name || !e.Type.compat(e2.Type, conv) {
- return false
- }
- }
- return true
-}
-
-func (t *InterfaceType) lit() Type { return t }
-
-func (t *InterfaceType) String() string {
- // TODO(austin) Instead of showing embedded interfaces, this
- // shows their methods.
- s := "interface {"
- for i, m := range t.methods {
- if i > 0 {
- s += "; "
- }
- s += m.Name + funcTypeString(m.Type, nil, nil)
- }
- return s + "}"
-}
-
-// implementedBy tests if o implements t, returning nil, true if it does.
-// Otherwise, it returns a method of t that o is missing and false.
-func (t *InterfaceType) implementedBy(o Type) (*IMethod, bool) {
- if len(t.methods) == 0 {
- return nil, true
- }
-
- // The methods of a named interface types are those of the
- // underlying type.
- if it, ok := o.lit().(*InterfaceType); ok {
- o = it
- }
-
- // XXX(Spec) Interface types: "A type implements any interface
- // comprising any subset of its methods" It's unclear if
- // methods must have identical or compatible types. 6g
- // requires identical types.
-
- switch o := o.(type) {
- case *NamedType:
- for _, tm := range t.methods {
- sm, ok := o.methods[tm.Name]
- if !ok || sm.decl.Type != tm.Type {
- return &tm, false
- }
- }
- return nil, true
-
- case *InterfaceType:
- var ti, oi int
- for ti < len(t.methods) && oi < len(o.methods) {
- tm, om := &t.methods[ti], &o.methods[oi]
- switch {
- case tm.Name == om.Name:
- if tm.Type != om.Type {
- return tm, false
- }
- ti++
- oi++
- case tm.Name > om.Name:
- oi++
- default:
- return tm, false
- }
- }
- if ti < len(t.methods) {
- return &t.methods[ti], false
- }
- return nil, true
- }
-
- return &t.methods[0], false
-}
-
-func (t *InterfaceType) Zero() Value { return &interfaceV{} }
-
-/*
- * Slice
- */
-
-type SliceType struct {
- commonType
- Elem Type
-}
-
-var sliceTypes = make(map[Type]*SliceType)
-
-// Two slice types are identical if they have identical element types.
-
-func NewSliceType(elem Type) *SliceType {
- t, ok := sliceTypes[elem]
- if !ok {
- t = &SliceType{commonType{}, elem}
- sliceTypes[elem] = t
- }
- return t
-}
-
-func (t *SliceType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*SliceType)
- if !ok {
- return false
- }
- return t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *SliceType) lit() Type { return t }
-
-func (t *SliceType) String() string { return "[]" + t.Elem.String() }
-
-func (t *SliceType) Zero() Value {
- // The value of an uninitialized slice is nil. The length and
- // capacity of a nil slice are 0.
- return &sliceV{Slice{nil, 0, 0}}
-}
-
-/*
- * Map type
- */
-
-type MapType struct {
- commonType
- Key Type
- Elem Type
-}
-
-var mapTypes = make(map[Type]map[Type]*MapType)
-
-func NewMapType(key Type, elem Type) *MapType {
- ts, ok := mapTypes[key]
- if !ok {
- ts = make(map[Type]*MapType)
- mapTypes[key] = ts
- }
- t, ok := ts[elem]
- if !ok {
- t = &MapType{commonType{}, key, elem}
- ts[elem] = t
- }
- return t
-}
-
-func (t *MapType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*MapType)
- if !ok {
- return false
- }
- return t.Elem.compat(t2.Elem, conv) && t.Key.compat(t2.Key, conv)
-}
-
-func (t *MapType) lit() Type { return t }
-
-func (t *MapType) String() string { return "map[" + t.Key.String() + "] " + t.Elem.String() }
-
-func (t *MapType) Zero() Value {
- // The value of an uninitialized map is nil.
- return &mapV{nil}
-}
-
-/*
-type ChanType struct {
- // TODO(austin)
-}
-*/
-
-/*
- * Named types
- */
-
-type Method struct {
- decl *FuncDecl
- fn Func
-}
-
-type NamedType struct {
- NamePos token.Pos
- Name string
- // Underlying type. If incomplete is true, this will be nil.
- // If incomplete is false and this is still nil, then this is
- // a placeholder type representing an error.
- Def Type
- // True while this type is being defined.
- incomplete bool
- methods map[string]Method
-}
-
-// TODO(austin) This is temporarily needed by the debugger's remote
-// type parser. This should only be possible with block.DefineType.
-func NewNamedType(name string) *NamedType {
- return &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
-}
-
-func (t *NamedType) Pos() token.Pos {
- return t.NamePos
-}
-
-func (t *NamedType) Complete(def Type) {
- if !t.incomplete {
- log.Panicf("cannot complete already completed NamedType %+v", *t)
- }
- // We strip the name from def because multiple levels of
- // naming are useless.
- if ndef, ok := def.(*NamedType); ok {
- def = ndef.Def
- }
- t.Def = def
- t.incomplete = false
-}
-
-func (t *NamedType) compat(o Type, conv bool) bool {
- t2, ok := o.(*NamedType)
- if ok {
- if conv {
- // Two named types are conversion compatible
- // if their literals are conversion
- // compatible.
- return t.Def.compat(t2.Def, conv)
- } else {
- // Two named types are compatible if their
- // type names originate in the same type
- // declaration.
- return t == t2
- }
- }
- // A named and an unnamed type are compatible if the
- // respective type literals are compatible.
- return o.compat(t.Def, conv)
-}
-
-func (t *NamedType) lit() Type { return t.Def.lit() }
-
-func (t *NamedType) isBoolean() bool { return t.Def.isBoolean() }
-
-func (t *NamedType) isInteger() bool { return t.Def.isInteger() }
-
-func (t *NamedType) isFloat() bool { return t.Def.isFloat() }
-
-func (t *NamedType) isIdeal() bool { return false }
-
-func (t *NamedType) String() string { return t.Name }
-
-func (t *NamedType) Zero() Value { return t.Def.Zero() }
-
-/*
- * Multi-valued type
- */
-
-// MultiType is a special type used for multi-valued expressions, akin
-// to a tuple type. It's not generally accessible within the
-// language.
-type MultiType struct {
- commonType
- Elems []Type
-}
-
-var multiTypes = newTypeArrayMap()
-
-func NewMultiType(elems []Type) *MultiType {
- if t := multiTypes.Get(elems); t != nil {
- return t.(*MultiType)
- }
-
- t := &MultiType{commonType{}, elems}
- multiTypes.Put(elems, t)
- return t
-}
-
-func (t *MultiType) compat(o Type, conv bool) bool {
- t2, ok := o.lit().(*MultiType)
- if !ok {
- return false
- }
- if len(t.Elems) != len(t2.Elems) {
- return false
- }
- for i := range t.Elems {
- if !t.Elems[i].compat(t2.Elems[i], conv) {
- return false
- }
- }
- return true
-}
-
-var EmptyType Type = NewMultiType([]Type{})
-
-func (t *MultiType) lit() Type { return t }
-
-func (t *MultiType) String() string {
- if len(t.Elems) == 0 {
- return "<none>"
- }
- return typeListString(t.Elems, nil)
-}
-
-func (t *MultiType) Zero() Value {
- res := make([]Value, len(t.Elems))
- for i, t := range t.Elems {
- res[i] = t.Zero()
- }
- return multiV(res)
-}
-
-/*
- * Initialize the universe
- */
-
-func init() {
- numer := big.NewInt(0xffffff)
- numer.Lsh(numer, 127-23)
- maxFloat32Val = new(big.Rat).SetInt(numer)
- numer.SetInt64(0x1fffffffffffff)
- numer.Lsh(numer, 1023-52)
- maxFloat64Val = new(big.Rat).SetInt(numer)
- minFloat32Val = new(big.Rat).Neg(maxFloat32Val)
- minFloat64Val = new(big.Rat).Neg(maxFloat64Val)
-
- // To avoid portability issues all numeric types are distinct
- // except byte, which is an alias for uint8.
-
- // Make byte an alias for the named type uint8. Type aliases
- // are otherwise impossible in Go, so just hack it here.
- universe.defs["byte"] = universe.defs["uint8"]
-
- // Built-in functions
- universe.DefineConst("cap", universePos, capType, nil)
- universe.DefineConst("close", universePos, closeType, nil)
- universe.DefineConst("closed", universePos, closedType, nil)
- universe.DefineConst("copy", universePos, copyType, nil)
- universe.DefineConst("len", universePos, lenType, nil)
- universe.DefineConst("make", universePos, makeType, nil)
- universe.DefineConst("new", universePos, newType, nil)
- universe.DefineConst("panic", universePos, panicType, nil)
- universe.DefineConst("print", universePos, printType, nil)
- universe.DefineConst("println", universePos, printlnType, nil)
-}
« no previous file with comments | « src/pkg/exp/eval/test.bash ('k') | src/pkg/exp/eval/typec.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b