...
1
2
3
4
5 package ssa
6
7
8
9 import (
10 "fmt"
11 "go/constant"
12 "go/token"
13 "go/types"
14 "strconv"
15 "strings"
16
17 "golang.org/x/tools/internal/typeparams"
18 )
19
20
21
22 func NewConst(val constant.Value, typ types.Type) *Const {
23 if val == nil {
24 switch soleTypeKind(typ) {
25 case types.IsBoolean:
26 val = constant.MakeBool(false)
27 case types.IsInteger:
28 val = constant.MakeInt64(0)
29 case types.IsString:
30 val = constant.MakeString("")
31 }
32 }
33 return &Const{typ, val}
34 }
35
36
37
38
39
40
41
42
43 func soleTypeKind(typ types.Type) types.BasicInfo {
44
45
46
47 state := types.IsBoolean | types.IsInteger | types.IsString
48 underIs(typeSetOf(typ), func(t types.Type) bool {
49 var c types.BasicInfo
50 if t, ok := t.(*types.Basic); ok {
51 c = t.Info()
52 }
53 if c&types.IsNumeric != 0 {
54 c = types.IsInteger
55 }
56 state = state & c
57 return state != 0
58 })
59 return state
60 }
61
62
63
64 func intConst(i int64) *Const {
65 return NewConst(constant.MakeInt64(i), tInt)
66 }
67
68
69 func stringConst(s string) *Const {
70 return NewConst(constant.MakeString(s), tString)
71 }
72
73
74 func zeroConst(t types.Type) *Const {
75 return NewConst(nil, t)
76 }
77
78 func (c *Const) RelString(from *types.Package) string {
79 var s string
80 if c.Value == nil {
81 s = zeroString(c.typ, from)
82 } else if c.Value.Kind() == constant.String {
83 s = constant.StringVal(c.Value)
84 const max = 20
85
86 if len(s) > max {
87 s = s[:max-3] + "..."
88 }
89 s = strconv.Quote(s)
90 } else {
91 s = c.Value.String()
92 }
93 return s + ":" + relType(c.Type(), from)
94 }
95
96
97 func zeroString(t types.Type, from *types.Package) string {
98 switch t := t.(type) {
99 case *types.Basic:
100 switch {
101 case t.Info()&types.IsBoolean != 0:
102 return "false"
103 case t.Info()&types.IsNumeric != 0:
104 return "0"
105 case t.Info()&types.IsString != 0:
106 return `""`
107 case t.Kind() == types.UnsafePointer:
108 fallthrough
109 case t.Kind() == types.UntypedNil:
110 return "nil"
111 default:
112 panic(fmt.Sprint("zeroString for unexpected type:", t))
113 }
114 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
115 return "nil"
116 case *types.Named:
117 return zeroString(t.Underlying(), from)
118 case *types.Array, *types.Struct:
119 return relType(t, from) + "{}"
120 case *types.Tuple:
121
122
123 components := make([]string, t.Len())
124 for i := 0; i < t.Len(); i++ {
125 components[i] = zeroString(t.At(i).Type(), from)
126 }
127 return "(" + strings.Join(components, ", ") + ")"
128 case *typeparams.TypeParam:
129 return "*new(" + relType(t, from) + ")"
130 }
131 panic(fmt.Sprint("zeroString: unexpected ", t))
132 }
133
134 func (c *Const) Name() string {
135 return c.RelString(nil)
136 }
137
138 func (c *Const) String() string {
139 return c.Name()
140 }
141
142 func (c *Const) Type() types.Type {
143 return c.typ
144 }
145
146 func (c *Const) Referrers() *[]Instruction {
147 return nil
148 }
149
150 func (c *Const) Parent() *Function { return nil }
151
152 func (c *Const) Pos() token.Pos {
153 return token.NoPos
154 }
155
156
157
158
159
160
161
162 func (c *Const) IsNil() bool {
163 return c.Value == nil && nillable(c.typ)
164 }
165
166
167 func nillable(t types.Type) bool {
168 switch t := t.Underlying().(type) {
169 case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
170 return true
171 case *types.Interface:
172 return typeSetOf(t).Len() == 0
173 default:
174 return false
175 }
176 }
177
178
179
180
181
182 func (c *Const) Int64() int64 {
183 switch x := constant.ToInt(c.Value); x.Kind() {
184 case constant.Int:
185 if i, ok := constant.Int64Val(x); ok {
186 return i
187 }
188 return 0
189 case constant.Float:
190 f, _ := constant.Float64Val(x)
191 return int64(f)
192 }
193 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
194 }
195
196
197
198 func (c *Const) Uint64() uint64 {
199 switch x := constant.ToInt(c.Value); x.Kind() {
200 case constant.Int:
201 if u, ok := constant.Uint64Val(x); ok {
202 return u
203 }
204 return 0
205 case constant.Float:
206 f, _ := constant.Float64Val(x)
207 return uint64(f)
208 }
209 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
210 }
211
212
213
214 func (c *Const) Float64() float64 {
215 x := constant.ToFloat(c.Value)
216 f, _ := constant.Float64Val(x)
217 return f
218 }
219
220
221
222 func (c *Const) Complex128() complex128 {
223 x := constant.ToComplex(c.Value)
224 re, _ := constant.Float64Val(constant.Real(x))
225 im, _ := constant.Float64Val(constant.Imag(x))
226 return complex(re, im)
227 }
228
View as plain text