github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/const14.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !go1.5 6 7 package ssa 8 9 // This file defines the Const SSA value type. 10 11 import ( 12 "fmt" 13 "go/token" 14 "strconv" 15 16 "golang.org/x/tools/go/exact" 17 "golang.org/x/tools/go/types" 18 ) 19 20 // NewConst returns a new constant of the specified value and type. 21 // val must be valid according to the specification of Const.Value. 22 // 23 func NewConst(val exact.Value, typ types.Type) *Const { 24 return &Const{typ, val} 25 } 26 27 // intConst returns an 'int' constant that evaluates to i. 28 // (i is an int64 in case the host is narrower than the target.) 29 func intConst(i int64) *Const { 30 return NewConst(exact.MakeInt64(i), tInt) 31 } 32 33 // nilConst returns a nil constant of the specified type, which may 34 // be any reference type, including interfaces. 35 // 36 func nilConst(typ types.Type) *Const { 37 return NewConst(nil, typ) 38 } 39 40 // stringConst returns a 'string' constant that evaluates to s. 41 func stringConst(s string) *Const { 42 return NewConst(exact.MakeString(s), tString) 43 } 44 45 // zeroConst returns a new "zero" constant of the specified type, 46 // which must not be an array or struct type: the zero values of 47 // aggregates are well-defined but cannot be represented by Const. 48 // 49 func zeroConst(t types.Type) *Const { 50 switch t := t.(type) { 51 case *types.Basic: 52 switch { 53 case t.Info()&types.IsBoolean != 0: 54 return NewConst(exact.MakeBool(false), t) 55 case t.Info()&types.IsNumeric != 0: 56 return NewConst(exact.MakeInt64(0), t) 57 case t.Info()&types.IsString != 0: 58 return NewConst(exact.MakeString(""), t) 59 case t.Kind() == types.UnsafePointer: 60 fallthrough 61 case t.Kind() == types.UntypedNil: 62 return nilConst(t) 63 default: 64 panic(fmt.Sprint("zeroConst for unexpected type:", t)) 65 } 66 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: 67 return nilConst(t) 68 case *types.Named: 69 return NewConst(zeroConst(t.Underlying()).Value, t) 70 case *types.Array, *types.Struct, *types.Tuple: 71 panic(fmt.Sprint("zeroConst applied to aggregate:", t)) 72 } 73 panic(fmt.Sprint("zeroConst: unexpected ", t)) 74 } 75 76 func (c *Const) RelString(from *types.Package) string { 77 var s string 78 if c.Value == nil { 79 s = "nil" 80 } else if c.Value.Kind() == exact.String { 81 s = exact.StringVal(c.Value) 82 const max = 20 83 // TODO(adonovan): don't cut a rune in half. 84 if len(s) > max { 85 s = s[:max-3] + "..." // abbreviate 86 } 87 s = strconv.Quote(s) 88 } else { 89 s = c.Value.String() 90 } 91 return s + ":" + relType(c.Type(), from) 92 } 93 94 func (c *Const) Name() string { 95 return c.RelString(nil) 96 } 97 98 func (c *Const) String() string { 99 return c.Name() 100 } 101 102 func (c *Const) Type() types.Type { 103 return c.typ 104 } 105 106 func (c *Const) Referrers() *[]Instruction { 107 return nil 108 } 109 110 func (c *Const) Parent() *Function { return nil } 111 112 func (c *Const) Pos() token.Pos { 113 return token.NoPos 114 } 115 116 // IsNil returns true if this constant represents a typed or untyped nil value. 117 func (c *Const) IsNil() bool { 118 return c.Value == nil 119 } 120 121 // Int64 returns the numeric value of this constant truncated to fit 122 // a signed 64-bit integer. 123 // 124 func (c *Const) Int64() int64 { 125 switch x := c.Value; x.Kind() { 126 case exact.Int: 127 if i, ok := exact.Int64Val(x); ok { 128 return i 129 } 130 return 0 131 case exact.Float: 132 f, _ := exact.Float64Val(x) 133 return int64(f) 134 } 135 panic(fmt.Sprintf("unexpected constant value: %T", c.Value)) 136 } 137 138 // Uint64 returns the numeric value of this constant truncated to fit 139 // an unsigned 64-bit integer. 140 // 141 func (c *Const) Uint64() uint64 { 142 switch x := c.Value; x.Kind() { 143 case exact.Int: 144 if u, ok := exact.Uint64Val(x); ok { 145 return u 146 } 147 return 0 148 case exact.Float: 149 f, _ := exact.Float64Val(x) 150 return uint64(f) 151 } 152 panic(fmt.Sprintf("unexpected constant value: %T", c.Value)) 153 } 154 155 // Float64 returns the numeric value of this constant truncated to fit 156 // a float64. 157 // 158 func (c *Const) Float64() float64 { 159 f, _ := exact.Float64Val(c.Value) 160 return f 161 } 162 163 // Complex128 returns the complex value of this constant truncated to 164 // fit a complex128. 165 // 166 func (c *Const) Complex128() complex128 { 167 re, _ := exact.Float64Val(exact.Real(c.Value)) 168 im, _ := exact.Float64Val(exact.Imag(c.Value)) 169 return complex(re, im) 170 }