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  }