github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/go/constant/value.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  // Package constant implements Values representing untyped
     6  // Go constants and the corresponding operations. Values
     7  // and operations may have arbitrary or unlimited precision.
     8  //
     9  // A special Unknown value may be used when a value
    10  // is unknown due to an error. Operations on unknown
    11  // values produce unknown values unless specified
    12  // otherwise.
    13  //
    14  package constant // import "go/constant"
    15  
    16  import (
    17  	"fmt"
    18  	"go/token"
    19  	"math/big"
    20  	"strconv"
    21  )
    22  
    23  // Kind specifies the kind of value represented by a Value.
    24  type Kind int
    25  
    26  // Implementation note: Kinds must be enumerated in
    27  // order of increasing "complexity" (used by match).
    28  
    29  const (
    30  	// unknown values
    31  	Unknown Kind = iota
    32  
    33  	// non-numeric values
    34  	Bool
    35  	String
    36  
    37  	// numeric values
    38  	Int
    39  	Float
    40  	Complex
    41  )
    42  
    43  // A Value represents a mathematically exact value of a given Kind.
    44  type Value interface {
    45  	// Kind returns the value kind; it is always the smallest
    46  	// kind in which the value can be represented exactly.
    47  	Kind() Kind
    48  
    49  	// String returns a human-readable form of the value.
    50  	String() string
    51  
    52  	// Prevent external implementations.
    53  	implementsValue()
    54  }
    55  
    56  // ----------------------------------------------------------------------------
    57  // Implementations
    58  
    59  type (
    60  	unknownVal struct{}
    61  	boolVal    bool
    62  	stringVal  string
    63  	int64Val   int64
    64  	intVal     struct{ val *big.Int }
    65  	floatVal   struct{ val *big.Rat }
    66  	complexVal struct{ re, im *big.Rat }
    67  )
    68  
    69  func (unknownVal) Kind() Kind { return Unknown }
    70  func (boolVal) Kind() Kind    { return Bool }
    71  func (stringVal) Kind() Kind  { return String }
    72  func (int64Val) Kind() Kind   { return Int }
    73  func (intVal) Kind() Kind     { return Int }
    74  func (floatVal) Kind() Kind   { return Float }
    75  func (complexVal) Kind() Kind { return Complex }
    76  
    77  func (unknownVal) String() string   { return "unknown" }
    78  func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
    79  func (x stringVal) String() string  { return strconv.Quote(string(x)) }
    80  func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
    81  func (x intVal) String() string     { return x.val.String() }
    82  func (x floatVal) String() string   { return x.val.String() }
    83  func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
    84  
    85  func (unknownVal) implementsValue() {}
    86  func (boolVal) implementsValue()    {}
    87  func (stringVal) implementsValue()  {}
    88  func (int64Val) implementsValue()   {}
    89  func (intVal) implementsValue()     {}
    90  func (floatVal) implementsValue()   {}
    91  func (complexVal) implementsValue() {}
    92  
    93  // int64 bounds
    94  var (
    95  	minInt64 = big.NewInt(-1 << 63)
    96  	maxInt64 = big.NewInt(1<<63 - 1)
    97  )
    98  
    99  func normInt(x *big.Int) Value {
   100  	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
   101  		return int64Val(x.Int64())
   102  	}
   103  	return intVal{x}
   104  }
   105  
   106  func normFloat(x *big.Rat) Value {
   107  	if x.IsInt() {
   108  		return normInt(x.Num())
   109  	}
   110  	return floatVal{x}
   111  }
   112  
   113  func normComplex(re, im *big.Rat) Value {
   114  	if im.Sign() == 0 {
   115  		return normFloat(re)
   116  	}
   117  	return complexVal{re, im}
   118  }
   119  
   120  // ----------------------------------------------------------------------------
   121  // Factories
   122  
   123  // MakeUnknown returns the Unknown value.
   124  func MakeUnknown() Value { return unknownVal{} }
   125  
   126  // MakeBool returns the Bool value for x.
   127  func MakeBool(b bool) Value { return boolVal(b) }
   128  
   129  // MakeString returns the String value for x.
   130  func MakeString(s string) Value { return stringVal(s) }
   131  
   132  // MakeInt64 returns the Int value for x.
   133  func MakeInt64(x int64) Value { return int64Val(x) }
   134  
   135  // MakeUint64 returns the Int value for x.
   136  func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
   137  
   138  // MakeFloat64 returns the numeric value for x.
   139  // If x is not finite, the result is unknown.
   140  func MakeFloat64(x float64) Value {
   141  	if f := new(big.Rat).SetFloat64(x); f != nil {
   142  		return normFloat(f)
   143  	}
   144  	return unknownVal{}
   145  }
   146  
   147  // MakeFromLiteral returns the corresponding integer, floating-point,
   148  // imaginary, character, or string value for a Go literal string.
   149  // If prec > 0, prec specifies an upper limit for the precision of
   150  // a numeric value. If the literal string is invalid, the result is
   151  // nil.
   152  // BUG(gri) Only prec == 0 is supported at the moment.
   153  func MakeFromLiteral(lit string, tok token.Token, prec uint) Value {
   154  	if prec != 0 {
   155  		panic("limited precision not supported")
   156  	}
   157  	switch tok {
   158  	case token.INT:
   159  		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
   160  			return int64Val(x)
   161  		}
   162  		if x, ok := new(big.Int).SetString(lit, 0); ok {
   163  			return intVal{x}
   164  		}
   165  
   166  	case token.FLOAT:
   167  		if x, ok := new(big.Rat).SetString(lit); ok {
   168  			return normFloat(x)
   169  		}
   170  
   171  	case token.IMAG:
   172  		if n := len(lit); n > 0 && lit[n-1] == 'i' {
   173  			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
   174  				return normComplex(big.NewRat(0, 1), im)
   175  			}
   176  		}
   177  
   178  	case token.CHAR:
   179  		if n := len(lit); n >= 2 {
   180  			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
   181  				return int64Val(code)
   182  			}
   183  		}
   184  
   185  	case token.STRING:
   186  		if s, err := strconv.Unquote(lit); err == nil {
   187  			return stringVal(s)
   188  		}
   189  	}
   190  
   191  	return nil
   192  }
   193  
   194  // ----------------------------------------------------------------------------
   195  // Accessors
   196  //
   197  // For unknown arguments the result is the zero value for the respective
   198  // accessor type, except for Sign, where the result is 1.
   199  
   200  // BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown.
   201  // If x is Unknown, the result is false.
   202  func BoolVal(x Value) bool {
   203  	switch x := x.(type) {
   204  	case boolVal:
   205  		return bool(x)
   206  	case unknownVal:
   207  		return false
   208  	}
   209  	panic(fmt.Sprintf("%v not a Bool", x))
   210  }
   211  
   212  // StringVal returns the Go string value of x, which must be a String or an Unknown.
   213  // If x is Unknown, the result is "".
   214  func StringVal(x Value) string {
   215  	switch x := x.(type) {
   216  	case stringVal:
   217  		return string(x)
   218  	case unknownVal:
   219  		return ""
   220  	}
   221  	panic(fmt.Sprintf("%v not a String", x))
   222  }
   223  
   224  // Int64Val returns the Go int64 value of x and whether the result is exact;
   225  // x must be an Int or an Unknown. If the result is not exact, its value is undefined.
   226  // If x is Unknown, the result is (0, false).
   227  func Int64Val(x Value) (int64, bool) {
   228  	switch x := x.(type) {
   229  	case int64Val:
   230  		return int64(x), true
   231  	case intVal:
   232  		return x.val.Int64(), x.val.BitLen() <= 63
   233  	case unknownVal:
   234  		return 0, false
   235  	}
   236  	panic(fmt.Sprintf("%v not an Int", x))
   237  }
   238  
   239  // Uint64Val returns the Go uint64 value of x and whether the result is exact;
   240  // x must be an Int or an Unknown. If the result is not exact, its value is undefined.
   241  // If x is Unknown, the result is (0, false).
   242  func Uint64Val(x Value) (uint64, bool) {
   243  	switch x := x.(type) {
   244  	case int64Val:
   245  		return uint64(x), x >= 0
   246  	case intVal:
   247  		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
   248  	case unknownVal:
   249  		return 0, false
   250  	}
   251  	panic(fmt.Sprintf("%v not an Int", x))
   252  }
   253  
   254  // Float32Val is like Float64Val but for float32 instead of float64.
   255  func Float32Val(x Value) (float32, bool) {
   256  	switch x := x.(type) {
   257  	case int64Val:
   258  		f := float32(x)
   259  		return f, int64Val(f) == x
   260  	case intVal:
   261  		return new(big.Rat).SetFrac(x.val, int1).Float32()
   262  	case floatVal:
   263  		return x.val.Float32()
   264  	case unknownVal:
   265  		return 0, false
   266  	}
   267  	panic(fmt.Sprintf("%v not a Float", x))
   268  }
   269  
   270  // Float64Val returns the nearest Go float64 value of x and whether the result is exact;
   271  // x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
   272  // to represent as float64, Float64Val silently underflows to 0. The result sign always
   273  // matches the sign of x, even for 0.
   274  // If x is Unknown, the result is (0, false).
   275  func Float64Val(x Value) (float64, bool) {
   276  	switch x := x.(type) {
   277  	case int64Val:
   278  		f := float64(int64(x))
   279  		return f, int64Val(f) == x
   280  	case intVal:
   281  		return new(big.Rat).SetFrac(x.val, int1).Float64()
   282  	case floatVal:
   283  		return x.val.Float64()
   284  	case unknownVal:
   285  		return 0, false
   286  	}
   287  	panic(fmt.Sprintf("%v not a Float", x))
   288  }
   289  
   290  // BitLen returns the number of bits required to represent
   291  // the absolute value x in binary representation; x must be an Int or an Unknown.
   292  // If x is Unknown, the result is 0.
   293  func BitLen(x Value) int {
   294  	switch x := x.(type) {
   295  	case int64Val:
   296  		return new(big.Int).SetInt64(int64(x)).BitLen()
   297  	case intVal:
   298  		return x.val.BitLen()
   299  	case unknownVal:
   300  		return 0
   301  	}
   302  	panic(fmt.Sprintf("%v not an Int", x))
   303  }
   304  
   305  // Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
   306  // x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
   307  // otherwise it is != 0. If x is Unknown, the result is 1.
   308  func Sign(x Value) int {
   309  	switch x := x.(type) {
   310  	case int64Val:
   311  		switch {
   312  		case x < 0:
   313  			return -1
   314  		case x > 0:
   315  			return 1
   316  		}
   317  		return 0
   318  	case intVal:
   319  		return x.val.Sign()
   320  	case floatVal:
   321  		return x.val.Sign()
   322  	case complexVal:
   323  		return x.re.Sign() | x.im.Sign()
   324  	case unknownVal:
   325  		return 1 // avoid spurious division by zero errors
   326  	}
   327  	panic(fmt.Sprintf("%v not numeric", x))
   328  }
   329  
   330  // ----------------------------------------------------------------------------
   331  // Support for serializing/deserializing integers
   332  
   333  const (
   334  	// Compute the size of a Word in bytes.
   335  	_m       = ^big.Word(0)
   336  	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
   337  	wordSize = 1 << _log
   338  )
   339  
   340  // Bytes returns the bytes for the absolute value of x in little-
   341  // endian binary representation; x must be an Int.
   342  func Bytes(x Value) []byte {
   343  	var val *big.Int
   344  	switch x := x.(type) {
   345  	case int64Val:
   346  		val = new(big.Int).SetInt64(int64(x))
   347  	case intVal:
   348  		val = x.val
   349  	default:
   350  		panic(fmt.Sprintf("%v not an Int", x))
   351  	}
   352  
   353  	words := val.Bits()
   354  	bytes := make([]byte, len(words)*wordSize)
   355  
   356  	i := 0
   357  	for _, w := range words {
   358  		for j := 0; j < wordSize; j++ {
   359  			bytes[i] = byte(w)
   360  			w >>= 8
   361  			i++
   362  		}
   363  	}
   364  	// remove leading 0's
   365  	for i > 0 && bytes[i-1] == 0 {
   366  		i--
   367  	}
   368  
   369  	return bytes[:i]
   370  }
   371  
   372  // MakeFromBytes returns the Int value given the bytes of its little-endian
   373  // binary representation. An empty byte slice argument represents 0.
   374  func MakeFromBytes(bytes []byte) Value {
   375  	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
   376  
   377  	i := 0
   378  	var w big.Word
   379  	var s uint
   380  	for _, b := range bytes {
   381  		w |= big.Word(b) << s
   382  		if s += 8; s == wordSize*8 {
   383  			words[i] = w
   384  			i++
   385  			w = 0
   386  			s = 0
   387  		}
   388  	}
   389  	// store last word
   390  	if i < len(words) {
   391  		words[i] = w
   392  		i++
   393  	}
   394  	// remove leading 0's
   395  	for i > 0 && words[i-1] == 0 {
   396  		i--
   397  	}
   398  
   399  	return normInt(new(big.Int).SetBits(words[:i]))
   400  }
   401  
   402  // ----------------------------------------------------------------------------
   403  // Support for disassembling fractions
   404  
   405  // Num returns the numerator of x; x must be Int, Float, or Unknown.
   406  // If x is Unknown, the result is Unknown, otherwise it is an Int
   407  // with the same sign as x.
   408  func Num(x Value) Value {
   409  	switch x := x.(type) {
   410  	case unknownVal, int64Val, intVal:
   411  		return x
   412  	case floatVal:
   413  		return normInt(x.val.Num())
   414  	}
   415  	panic(fmt.Sprintf("%v not Int or Float", x))
   416  }
   417  
   418  // Denom returns the denominator of x; x must be Int, Float, or Unknown.
   419  // If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
   420  func Denom(x Value) Value {
   421  	switch x := x.(type) {
   422  	case unknownVal:
   423  		return x
   424  	case int64Val, intVal:
   425  		return int64Val(1)
   426  	case floatVal:
   427  		return normInt(x.val.Denom())
   428  	}
   429  	panic(fmt.Sprintf("%v not Int or Float", x))
   430  }
   431  
   432  // ----------------------------------------------------------------------------
   433  // Support for assembling/disassembling complex numbers
   434  
   435  // MakeImag returns the numeric value x*i (possibly 0);
   436  // x must be Int, Float, or Unknown.
   437  // If x is Unknown, the result is Unknown.
   438  func MakeImag(x Value) Value {
   439  	var im *big.Rat
   440  	switch x := x.(type) {
   441  	case unknownVal:
   442  		return x
   443  	case int64Val:
   444  		im = big.NewRat(int64(x), 1)
   445  	case intVal:
   446  		im = new(big.Rat).SetFrac(x.val, int1)
   447  	case floatVal:
   448  		im = x.val
   449  	default:
   450  		panic(fmt.Sprintf("%v not Int or Float", x))
   451  	}
   452  	return normComplex(rat0, im)
   453  }
   454  
   455  // Real returns the real part of x, which must be a numeric or unknown value.
   456  // If x is Unknown, the result is Unknown.
   457  func Real(x Value) Value {
   458  	switch x := x.(type) {
   459  	case unknownVal, int64Val, intVal, floatVal:
   460  		return x
   461  	case complexVal:
   462  		return normFloat(x.re)
   463  	}
   464  	panic(fmt.Sprintf("%v not numeric", x))
   465  }
   466  
   467  // Imag returns the imaginary part of x, which must be a numeric or unknown value.
   468  // If x is Unknown, the result is Unknown.
   469  func Imag(x Value) Value {
   470  	switch x := x.(type) {
   471  	case unknownVal:
   472  		return x
   473  	case int64Val, intVal, floatVal:
   474  		return int64Val(0)
   475  	case complexVal:
   476  		return normFloat(x.im)
   477  	}
   478  	panic(fmt.Sprintf("%v not numeric", x))
   479  }
   480  
   481  // ----------------------------------------------------------------------------
   482  // Operations
   483  
   484  // is32bit reports whether x can be represented using 32 bits.
   485  func is32bit(x int64) bool {
   486  	const s = 32
   487  	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
   488  }
   489  
   490  // is63bit reports whether x can be represented using 63 bits.
   491  func is63bit(x int64) bool {
   492  	const s = 63
   493  	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
   494  }
   495  
   496  // UnaryOp returns the result of the unary expression op y.
   497  // The operation must be defined for the operand.
   498  // If prec > 0 it specifies the ^ (xor) result size in bits.
   499  // If y is Unknown, the result is Unknown.
   500  //
   501  func UnaryOp(op token.Token, y Value, prec uint) Value {
   502  	switch op {
   503  	case token.ADD:
   504  		switch y.(type) {
   505  		case unknownVal, int64Val, intVal, floatVal, complexVal:
   506  			return y
   507  		}
   508  
   509  	case token.SUB:
   510  		switch y := y.(type) {
   511  		case unknownVal:
   512  			return y
   513  		case int64Val:
   514  			if z := -y; z != y {
   515  				return z // no overflow
   516  			}
   517  			return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
   518  		case intVal:
   519  			return normInt(new(big.Int).Neg(y.val))
   520  		case floatVal:
   521  			return normFloat(new(big.Rat).Neg(y.val))
   522  		case complexVal:
   523  			return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
   524  		}
   525  
   526  	case token.XOR:
   527  		var z big.Int
   528  		switch y := y.(type) {
   529  		case unknownVal:
   530  			return y
   531  		case int64Val:
   532  			z.Not(big.NewInt(int64(y)))
   533  		case intVal:
   534  			z.Not(y.val)
   535  		default:
   536  			goto Error
   537  		}
   538  		// For unsigned types, the result will be negative and
   539  		// thus "too large": We must limit the result precision
   540  		// to the type's precision.
   541  		if prec > 0 {
   542  			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), prec)) // z &^= (-1)<<prec
   543  		}
   544  		return normInt(&z)
   545  
   546  	case token.NOT:
   547  		switch y := y.(type) {
   548  		case unknownVal:
   549  			return y
   550  		case boolVal:
   551  			return !y
   552  		}
   553  	}
   554  
   555  Error:
   556  	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
   557  }
   558  
   559  var (
   560  	int1 = big.NewInt(1)
   561  	rat0 = big.NewRat(0, 1)
   562  )
   563  
   564  func ord(x Value) int {
   565  	switch x.(type) {
   566  	default:
   567  		return 0
   568  	case boolVal, stringVal:
   569  		return 1
   570  	case int64Val:
   571  		return 2
   572  	case intVal:
   573  		return 3
   574  	case floatVal:
   575  		return 4
   576  	case complexVal:
   577  		return 5
   578  	}
   579  }
   580  
   581  // match returns the matching representation (same type) with the
   582  // smallest complexity for two values x and y. If one of them is
   583  // numeric, both of them must be numeric. If one of them is Unknown,
   584  // both results are Unknown.
   585  //
   586  func match(x, y Value) (_, _ Value) {
   587  	if ord(x) > ord(y) {
   588  		y, x = match(y, x)
   589  		return x, y
   590  	}
   591  	// ord(x) <= ord(y)
   592  
   593  	switch x := x.(type) {
   594  	case unknownVal:
   595  		return x, x
   596  
   597  	case boolVal, stringVal, complexVal:
   598  		return x, y
   599  
   600  	case int64Val:
   601  		switch y := y.(type) {
   602  		case int64Val:
   603  			return x, y
   604  		case intVal:
   605  			return intVal{big.NewInt(int64(x))}, y
   606  		case floatVal:
   607  			return floatVal{big.NewRat(int64(x), 1)}, y
   608  		case complexVal:
   609  			return complexVal{big.NewRat(int64(x), 1), rat0}, y
   610  		}
   611  
   612  	case intVal:
   613  		switch y := y.(type) {
   614  		case intVal:
   615  			return x, y
   616  		case floatVal:
   617  			return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
   618  		case complexVal:
   619  			return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
   620  		}
   621  
   622  	case floatVal:
   623  		switch y := y.(type) {
   624  		case floatVal:
   625  			return x, y
   626  		case complexVal:
   627  			return complexVal{x.val, rat0}, y
   628  		}
   629  	}
   630  
   631  	panic("unreachable")
   632  }
   633  
   634  // BinaryOp returns the result of the binary expression x op y.
   635  // The operation must be defined for the operands. If one of the
   636  // operands is Unknown, the result is Unknown.
   637  // To force integer division of Int operands, use op == token.QUO_ASSIGN
   638  // instead of token.QUO; the result is guaranteed to be Int in this case.
   639  // Division by zero leads to a run-time panic.
   640  //
   641  func BinaryOp(x Value, op token.Token, y Value) Value {
   642  	x, y = match(x, y)
   643  
   644  	switch x := x.(type) {
   645  	case unknownVal:
   646  		return x
   647  
   648  	case boolVal:
   649  		y := y.(boolVal)
   650  		switch op {
   651  		case token.LAND:
   652  			return x && y
   653  		case token.LOR:
   654  			return x || y
   655  		}
   656  
   657  	case int64Val:
   658  		a := int64(x)
   659  		b := int64(y.(int64Val))
   660  		var c int64
   661  		switch op {
   662  		case token.ADD:
   663  			if !is63bit(a) || !is63bit(b) {
   664  				return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
   665  			}
   666  			c = a + b
   667  		case token.SUB:
   668  			if !is63bit(a) || !is63bit(b) {
   669  				return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
   670  			}
   671  			c = a - b
   672  		case token.MUL:
   673  			if !is32bit(a) || !is32bit(b) {
   674  				return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
   675  			}
   676  			c = a * b
   677  		case token.QUO:
   678  			return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
   679  		case token.QUO_ASSIGN: // force integer division
   680  			c = a / b
   681  		case token.REM:
   682  			c = a % b
   683  		case token.AND:
   684  			c = a & b
   685  		case token.OR:
   686  			c = a | b
   687  		case token.XOR:
   688  			c = a ^ b
   689  		case token.AND_NOT:
   690  			c = a &^ b
   691  		default:
   692  			goto Error
   693  		}
   694  		return int64Val(c)
   695  
   696  	case intVal:
   697  		a := x.val
   698  		b := y.(intVal).val
   699  		var c big.Int
   700  		switch op {
   701  		case token.ADD:
   702  			c.Add(a, b)
   703  		case token.SUB:
   704  			c.Sub(a, b)
   705  		case token.MUL:
   706  			c.Mul(a, b)
   707  		case token.QUO:
   708  			return normFloat(new(big.Rat).SetFrac(a, b))
   709  		case token.QUO_ASSIGN: // force integer division
   710  			c.Quo(a, b)
   711  		case token.REM:
   712  			c.Rem(a, b)
   713  		case token.AND:
   714  			c.And(a, b)
   715  		case token.OR:
   716  			c.Or(a, b)
   717  		case token.XOR:
   718  			c.Xor(a, b)
   719  		case token.AND_NOT:
   720  			c.AndNot(a, b)
   721  		default:
   722  			goto Error
   723  		}
   724  		return normInt(&c)
   725  
   726  	case floatVal:
   727  		a := x.val
   728  		b := y.(floatVal).val
   729  		var c big.Rat
   730  		switch op {
   731  		case token.ADD:
   732  			c.Add(a, b)
   733  		case token.SUB:
   734  			c.Sub(a, b)
   735  		case token.MUL:
   736  			c.Mul(a, b)
   737  		case token.QUO:
   738  			c.Quo(a, b)
   739  		default:
   740  			goto Error
   741  		}
   742  		return normFloat(&c)
   743  
   744  	case complexVal:
   745  		y := y.(complexVal)
   746  		a, b := x.re, x.im
   747  		c, d := y.re, y.im
   748  		var re, im big.Rat
   749  		switch op {
   750  		case token.ADD:
   751  			// (a+c) + i(b+d)
   752  			re.Add(a, c)
   753  			im.Add(b, d)
   754  		case token.SUB:
   755  			// (a-c) + i(b-d)
   756  			re.Sub(a, c)
   757  			im.Sub(b, d)
   758  		case token.MUL:
   759  			// (ac-bd) + i(bc+ad)
   760  			var ac, bd, bc, ad big.Rat
   761  			ac.Mul(a, c)
   762  			bd.Mul(b, d)
   763  			bc.Mul(b, c)
   764  			ad.Mul(a, d)
   765  			re.Sub(&ac, &bd)
   766  			im.Add(&bc, &ad)
   767  		case token.QUO:
   768  			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
   769  			var ac, bd, bc, ad, s, cc, dd big.Rat
   770  			ac.Mul(a, c)
   771  			bd.Mul(b, d)
   772  			bc.Mul(b, c)
   773  			ad.Mul(a, d)
   774  			cc.Mul(c, c)
   775  			dd.Mul(d, d)
   776  			s.Add(&cc, &dd)
   777  			re.Add(&ac, &bd)
   778  			re.Quo(&re, &s)
   779  			im.Sub(&bc, &ad)
   780  			im.Quo(&im, &s)
   781  		default:
   782  			goto Error
   783  		}
   784  		return normComplex(&re, &im)
   785  
   786  	case stringVal:
   787  		if op == token.ADD {
   788  			return x + y.(stringVal)
   789  		}
   790  	}
   791  
   792  Error:
   793  	panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
   794  }
   795  
   796  // Shift returns the result of the shift expression x op s
   797  // with op == token.SHL or token.SHR (<< or >>). x must be
   798  // an Int or an Unknown. If x is Unknown, the result is x.
   799  //
   800  func Shift(x Value, op token.Token, s uint) Value {
   801  	switch x := x.(type) {
   802  	case unknownVal:
   803  		return x
   804  
   805  	case int64Val:
   806  		if s == 0 {
   807  			return x
   808  		}
   809  		switch op {
   810  		case token.SHL:
   811  			z := big.NewInt(int64(x))
   812  			return normInt(z.Lsh(z, s))
   813  		case token.SHR:
   814  			return x >> s
   815  		}
   816  
   817  	case intVal:
   818  		if s == 0 {
   819  			return x
   820  		}
   821  		var z big.Int
   822  		switch op {
   823  		case token.SHL:
   824  			return normInt(z.Lsh(x.val, s))
   825  		case token.SHR:
   826  			return normInt(z.Rsh(x.val, s))
   827  		}
   828  	}
   829  
   830  	panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
   831  }
   832  
   833  func cmpZero(x int, op token.Token) bool {
   834  	switch op {
   835  	case token.EQL:
   836  		return x == 0
   837  	case token.NEQ:
   838  		return x != 0
   839  	case token.LSS:
   840  		return x < 0
   841  	case token.LEQ:
   842  		return x <= 0
   843  	case token.GTR:
   844  		return x > 0
   845  	case token.GEQ:
   846  		return x >= 0
   847  	}
   848  	panic("unreachable")
   849  }
   850  
   851  // Compare returns the result of the comparison x op y.
   852  // The comparison must be defined for the operands.
   853  // If one of the operands is Unknown, the result is
   854  // false.
   855  //
   856  func Compare(x Value, op token.Token, y Value) bool {
   857  	x, y = match(x, y)
   858  
   859  	switch x := x.(type) {
   860  	case unknownVal:
   861  		return false
   862  
   863  	case boolVal:
   864  		y := y.(boolVal)
   865  		switch op {
   866  		case token.EQL:
   867  			return x == y
   868  		case token.NEQ:
   869  			return x != y
   870  		}
   871  
   872  	case int64Val:
   873  		y := y.(int64Val)
   874  		switch op {
   875  		case token.EQL:
   876  			return x == y
   877  		case token.NEQ:
   878  			return x != y
   879  		case token.LSS:
   880  			return x < y
   881  		case token.LEQ:
   882  			return x <= y
   883  		case token.GTR:
   884  			return x > y
   885  		case token.GEQ:
   886  			return x >= y
   887  		}
   888  
   889  	case intVal:
   890  		return cmpZero(x.val.Cmp(y.(intVal).val), op)
   891  
   892  	case floatVal:
   893  		return cmpZero(x.val.Cmp(y.(floatVal).val), op)
   894  
   895  	case complexVal:
   896  		y := y.(complexVal)
   897  		re := x.re.Cmp(y.re)
   898  		im := x.im.Cmp(y.im)
   899  		switch op {
   900  		case token.EQL:
   901  			return re == 0 && im == 0
   902  		case token.NEQ:
   903  			return re != 0 || im != 0
   904  		}
   905  
   906  	case stringVal:
   907  		y := y.(stringVal)
   908  		switch op {
   909  		case token.EQL:
   910  			return x == y
   911  		case token.NEQ:
   912  			return x != y
   913  		case token.LSS:
   914  			return x < y
   915  		case token.LEQ:
   916  			return x <= y
   917  		case token.GTR:
   918  			return x > y
   919  		case token.GEQ:
   920  			return x >= y
   921  		}
   922  	}
   923  
   924  	panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
   925  }