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 ratToFloat32(new(big.Rat).SetFrac(x.val, int1)) 262 case floatVal: 263 return ratToFloat32(x.val) 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 } 926