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