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