aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/go/go/types/operand.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/go/go/types/operand.go')
-rw-r--r--gcc-4.8.1/libgo/go/go/types/operand.go393
1 files changed, 0 insertions, 393 deletions
diff --git a/gcc-4.8.1/libgo/go/go/types/operand.go b/gcc-4.8.1/libgo/go/go/types/operand.go
deleted file mode 100644
index 6c2281027..000000000
--- a/gcc-4.8.1/libgo/go/go/types/operand.go
+++ /dev/null
@@ -1,393 +0,0 @@
-// Copyright 2012 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.
-
-// This file defines operands and associated operations.
-
-package types
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/token"
-)
-
-// An operandMode specifies the (addressing) mode of an operand.
-type operandMode int
-
-const (
- invalid operandMode = iota // operand is invalid (due to an earlier error) - ignore
- novalue // operand represents no value (result of a function call w/o result)
- typexpr // operand is a type
- constant // operand is a constant; the operand's typ is a Basic type
- variable // operand is an addressable variable
- value // operand is a computed value
- valueok // like mode == value, but operand may be used in a comma,ok expression
-)
-
-var operandModeString = [...]string{
- invalid: "invalid",
- novalue: "no value",
- typexpr: "type",
- constant: "constant",
- variable: "variable",
- value: "value",
- valueok: "value,ok",
-}
-
-// An operand represents an intermediate value during type checking.
-// Operands have an (addressing) mode, the expression evaluating to
-// the operand, the operand's type, and for constants a constant value.
-//
-type operand struct {
- mode operandMode
- expr ast.Expr
- typ Type
- val interface{}
-}
-
-// pos returns the position of the expression corresponding to x.
-// If x is invalid the position is token.NoPos.
-//
-func (x *operand) pos() token.Pos {
- // x.expr may not be set if x is invalid
- if x.expr == nil {
- return token.NoPos
- }
- return x.expr.Pos()
-}
-
-func (x *operand) String() string {
- if x.mode == invalid {
- return "invalid operand"
- }
- var buf bytes.Buffer
- if x.expr != nil {
- buf.WriteString(exprString(x.expr))
- buf.WriteString(" (")
- }
- buf.WriteString(operandModeString[x.mode])
- if x.mode == constant {
- format := " %v"
- if isString(x.typ) {
- format = " %q"
- }
- fmt.Fprintf(&buf, format, x.val)
- }
- if x.mode != novalue && (x.mode != constant || !isUntyped(x.typ)) {
- fmt.Fprintf(&buf, " of type %s", typeString(x.typ))
- }
- if x.expr != nil {
- buf.WriteByte(')')
- }
- return buf.String()
-}
-
-// setConst sets x to the untyped constant for literal lit.
-func (x *operand) setConst(tok token.Token, lit string) {
- x.mode = invalid
-
- var kind BasicKind
- var val interface{}
- switch tok {
- case token.INT:
- kind = UntypedInt
- val = makeIntConst(lit)
-
- case token.FLOAT:
- kind = UntypedFloat
- val = makeFloatConst(lit)
-
- case token.IMAG:
- kind = UntypedComplex
- val = makeComplexConst(lit)
-
- case token.CHAR:
- kind = UntypedRune
- val = makeRuneConst(lit)
-
- case token.STRING:
- kind = UntypedString
- val = makeStringConst(lit)
- }
-
- if val != nil {
- x.mode = constant
- x.typ = Typ[kind]
- x.val = val
- }
-}
-
-// isNil reports whether x is the predeclared nil constant.
-func (x *operand) isNil() bool {
- return x.mode == constant && x.val == nilConst
-}
-
-// TODO(gri) The functions operand.isAssignable, checker.convertUntyped,
-// checker.isRepresentable, and checker.assignOperand are
-// overlapping in functionality. Need to simplify and clean up.
-
-// isAssignable reports whether x is assignable to a variable of type T.
-func (x *operand) isAssignable(T Type) bool {
- if x.mode == invalid || T == Typ[Invalid] {
- return true // avoid spurious errors
- }
-
- V := x.typ
-
- // x's type is identical to T
- if IsIdentical(V, T) {
- return true
- }
-
- Vu := underlying(V)
- Tu := underlying(T)
-
- // x's type V and T have identical underlying types
- // and at least one of V or T is not a named type
- if IsIdentical(Vu, Tu) {
- return !isNamed(V) || !isNamed(T)
- }
-
- // T is an interface type and x implements T
- if Ti, ok := Tu.(*Interface); ok {
- if m, _ := missingMethod(x.typ, Ti); m == nil {
- return true
- }
- }
-
- // x is a bidirectional channel value, T is a channel
- // type, x's type V and T have identical element types,
- // and at least one of V or T is not a named type
- if Vc, ok := Vu.(*Chan); ok && Vc.Dir == ast.SEND|ast.RECV {
- if Tc, ok := Tu.(*Chan); ok && IsIdentical(Vc.Elt, Tc.Elt) {
- return !isNamed(V) || !isNamed(T)
- }
- }
-
- // x is the predeclared identifier nil and T is a pointer,
- // function, slice, map, channel, or interface type
- if x.isNil() {
- switch t := Tu.(type) {
- case *Basic:
- if t.Kind == UnsafePointer {
- return true
- }
- case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
- return true
- }
- return false
- }
-
- // x is an untyped constant representable by a value of type T
- // TODO(gri) This is borrowing from checker.convertUntyped and
- // checker.isRepresentable. Need to clean up.
- if isUntyped(Vu) {
- switch t := Tu.(type) {
- case *Basic:
- if x.mode == constant {
- return isRepresentableConst(x.val, t.Kind)
- }
- // The result of a comparison is an untyped boolean,
- // but may not be a constant.
- if Vb, _ := Vu.(*Basic); Vb != nil {
- return Vb.Kind == UntypedBool && isBoolean(Tu)
- }
- case *Interface:
- return x.isNil() || len(t.Methods) == 0
- case *Pointer, *Signature, *Slice, *Map, *Chan:
- return x.isNil()
- }
- }
-
- return false
-}
-
-// isInteger reports whether x is a (typed or untyped) integer value.
-func (x *operand) isInteger() bool {
- return x.mode == invalid ||
- isInteger(x.typ) ||
- x.mode == constant && isRepresentableConst(x.val, UntypedInt)
-}
-
-type lookupResult struct {
- mode operandMode
- typ Type
-}
-
-type embeddedType struct {
- typ *NamedType
- multiples bool // if set, typ is embedded multiple times at the same level
-}
-
-// lookupFieldBreadthFirst searches all types in list for a single entry (field
-// or method) of the given name from the given package. If such a field is found,
-// the result describes the field mode and type; otherwise the result mode is invalid.
-// (This function is similar in structure to FieldByNameFunc in reflect/type.go)
-//
-func lookupFieldBreadthFirst(list []embeddedType, name QualifiedName) (res lookupResult) {
- // visited records the types that have been searched already.
- visited := make(map[*NamedType]bool)
-
- // embedded types of the next lower level
- var next []embeddedType
-
- // potentialMatch is invoked every time a match is found.
- potentialMatch := func(multiples bool, mode operandMode, typ Type) bool {
- if multiples || res.mode != invalid {
- // name appeared already at this level - annihilate
- res.mode = invalid
- return false
- }
- // first appearance of name
- res.mode = mode
- res.typ = typ
- return true
- }
-
- // Search the current level if there is any work to do and collect
- // embedded types of the next lower level in the next list.
- for len(list) > 0 {
- // The res.mode indicates whether we have found a match already
- // on this level (mode != invalid), or not (mode == invalid).
- assert(res.mode == invalid)
-
- // start with empty next list (don't waste underlying array)
- next = next[:0]
-
- // look for name in all types at this level
- for _, e := range list {
- typ := e.typ
- if visited[typ] {
- continue
- }
- visited[typ] = true
-
- // look for a matching attached method
- for _, m := range typ.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- if !potentialMatch(e.multiples, value, m.Type) {
- return // name collision
- }
- }
- }
-
- switch t := typ.Underlying.(type) {
- case *Struct:
- // look for a matching field and collect embedded types
- for _, f := range t.Fields {
- if name.IsSame(f.QualifiedName) {
- assert(f.Type != nil)
- if !potentialMatch(e.multiples, variable, f.Type) {
- return // name collision
- }
- continue
- }
- // Collect embedded struct fields for searching the next
- // lower level, but only if we have not seen a match yet
- // (if we have a match it is either the desired field or
- // we have a name collision on the same level; in either
- // case we don't need to look further).
- // Embedded fields are always of the form T or *T where
- // T is a named type. If typ appeared multiple times at
- // this level, f.Type appears multiple times at the next
- // level.
- if f.IsAnonymous && res.mode == invalid {
- next = append(next, embeddedType{deref(f.Type).(*NamedType), e.multiples})
- }
- }
-
- case *Interface:
- // look for a matching method
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- if !potentialMatch(e.multiples, value, m.Type) {
- return // name collision
- }
- }
- }
- }
- }
-
- if res.mode != invalid {
- // we found a single match on this level
- return
- }
-
- // No match and no collision so far.
- // Compute the list to search for the next level.
- list = list[:0] // don't waste underlying array
- for _, e := range next {
- // Instead of adding the same type multiple times, look for
- // it in the list and mark it as multiple if it was added
- // before.
- // We use a sequential search (instead of a map for next)
- // because the lists tend to be small, can easily be reused,
- // and explicit search appears to be faster in this case.
- if alt := findType(list, e.typ); alt != nil {
- alt.multiples = true
- } else {
- list = append(list, e)
- }
- }
-
- }
-
- return
-}
-
-func findType(list []embeddedType, typ *NamedType) *embeddedType {
- for i := range list {
- if p := &list[i]; p.typ == typ {
- return p
- }
- }
- return nil
-}
-
-func lookupField(typ Type, name QualifiedName) (operandMode, Type) {
- typ = deref(typ)
-
- if t, ok := typ.(*NamedType); ok {
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- return value, m.Type
- }
- }
- typ = t.Underlying
- }
-
- switch t := typ.(type) {
- case *Struct:
- var next []embeddedType
- for _, f := range t.Fields {
- if name.IsSame(f.QualifiedName) {
- return variable, f.Type
- }
- if f.IsAnonymous {
- // Possible optimization: If the embedded type
- // is a pointer to the current type we could
- // ignore it.
- next = append(next, embeddedType{typ: deref(f.Type).(*NamedType)})
- }
- }
- if len(next) > 0 {
- res := lookupFieldBreadthFirst(next, name)
- return res.mode, res.typ
- }
-
- case *Interface:
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- return value, m.Type
- }
- }
- }
-
- // not found
- return invalid, nil
-}