Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(48)

Side by Side Diff: go/exact/exact.go

Issue 41170043: code review 41170043: go.tools/go/exact: serialization support and better unk... (Closed)
Patch Set: diff -r af8717213853 https://code.google.com/p/go.tools Created 10 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | go/exact/exact_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package exact implements mathematically exact values 5 // Package exact implements mathematically exact values
6 // and operations for all Go basic types. 6 // and operations for untyped Go constant values.
7 //
8 // A special Unknown value may be used when a constant
9 // value is unknown due to an error; operations on unknown
10 // values produce unknown values.
7 // 11 //
8 package exact 12 package exact
9 13
10 import ( 14 import (
11 "fmt" 15 "fmt"
12 "go/token" 16 "go/token"
13 "math/big" 17 "math/big"
14 "strconv" 18 "strconv"
15 ) 19 )
16 20
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 129
126 // MakeInt64 returns the Int value for x. 130 // MakeInt64 returns the Int value for x.
127 func MakeInt64(x int64) Value { return int64Val(x) } 131 func MakeInt64(x int64) Value { return int64Val(x) }
128 132
129 // MakeUint64 returns the Int value for x. 133 // MakeUint64 returns the Int value for x.
130 func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) } 134 func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
131 135
132 // MakeFloat64 returns the numeric value for x. 136 // MakeFloat64 returns the numeric value for x.
133 // If x is not finite, the result is unknown. 137 // If x is not finite, the result is unknown.
134 func MakeFloat64(x float64) Value { 138 func MakeFloat64(x float64) Value {
135 » f := new(big.Rat).SetFloat64(x) 139 » if f := new(big.Rat).SetFloat64(x); f != nil {
136 » if f != nil {
137 return normFloat(f) 140 return normFloat(f)
138 } 141 }
139 return unknownVal{} 142 return unknownVal{}
140 } 143 }
141 144
142 // MakeFromLiteral returns the corresponding literal value. 145 // MakeFromLiteral returns the corresponding integer, floating-point,
143 // If the literal has illegal format, the result is nil. 146 // imaginary, character, or string value for a Go literal string. The
147 // result is nil if the literal string is invalid.
144 func MakeFromLiteral(lit string, tok token.Token) Value { 148 func MakeFromLiteral(lit string, tok token.Token) Value {
145 switch tok { 149 switch tok {
146 case token.INT: 150 case token.INT:
147 if x, err := strconv.ParseInt(lit, 0, 64); err == nil { 151 if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
148 return int64Val(x) 152 return int64Val(x)
149 } 153 }
150 if x, ok := new(big.Int).SetString(lit, 0); ok { 154 if x, ok := new(big.Int).SetString(lit, 0); ok {
151 return intVal{x} 155 return intVal{x}
152 } 156 }
153 157
(...skipping 15 matching lines...) Expand all
169 return int64Val(code) 173 return int64Val(code)
170 } 174 }
171 } 175 }
172 176
173 case token.STRING: 177 case token.STRING:
174 if s, err := strconv.Unquote(lit); err == nil { 178 if s, err := strconv.Unquote(lit); err == nil {
175 return stringVal(s) 179 return stringVal(s)
176 } 180 }
177 } 181 }
178 182
179 » // TODO(gri) should we instead a) return unknown, or b) an error? 183 » // TODO(gri) should we return an Unknown instead?
180 return nil 184 return nil
181 } 185 }
182 186
183 // ---------------------------------------------------------------------------- 187 // ----------------------------------------------------------------------------
184 // Accessors 188 // Accessors
189 //
190 // For unknown arguments the result is the zero value for the respective
191 // accessor type, except for Sign, where the result is 1.
185 192
186 // BoolVal returns the Go boolean value of x, which must be a Bool. 193 // BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown .
187 // The result is false for unknown values. 194 // If x is Unknown, the result is false.
188 func BoolVal(x Value) bool { 195 func BoolVal(x Value) bool {
189 switch x := x.(type) { 196 switch x := x.(type) {
190 case boolVal: 197 case boolVal:
191 return bool(x) 198 return bool(x)
192 case unknownVal: 199 case unknownVal:
193 return false 200 return false
194 } 201 }
195 panic(fmt.Sprintf("invalid BoolVal(%v)", x)) 202 panic(fmt.Sprintf("invalid BoolVal(%v)", x))
196 } 203 }
197 204
198 // StringVal returns the Go string value of x, which must be a String. 205 // StringVal returns the Go string value of x, which must be a String or an Unkn own.
199 // The result is "" for unknown values. 206 // If x is Unknown, the result is "".
200 func StringVal(x Value) string { 207 func StringVal(x Value) string {
201 switch x := x.(type) { 208 switch x := x.(type) {
202 case stringVal: 209 case stringVal:
203 return string(x) 210 return string(x)
204 case unknownVal: 211 case unknownVal:
205 return "" 212 return ""
206 } 213 }
207 panic(fmt.Sprintf("invalidStringVal(%v)", x)) 214 panic(fmt.Sprintf("invalidStringVal(%v)", x))
208 } 215 }
209 216
210 // Int64Val returns the Go int64 value of x and whether the result is exact; 217 // Int64Val returns the Go int64 value of x and whether the result is exact;
211 // x must be an Int. If the result is not exact, its value is undefined. 218 // x must be an Int or an Unknown. If the result is not exact, its value is unde fined.
212 // The result is (0, false) for unknown values. 219 // If x is Unknown, the result is (0, false).
213 func Int64Val(x Value) (int64, bool) { 220 func Int64Val(x Value) (int64, bool) {
214 switch x := x.(type) { 221 switch x := x.(type) {
215 case int64Val: 222 case int64Val:
216 return int64(x), true 223 return int64(x), true
217 case intVal: 224 case intVal:
218 return x.val.Int64(), x.val.BitLen() <= 63 225 return x.val.Int64(), x.val.BitLen() <= 63
219 case unknownVal: 226 case unknownVal:
220 return 0, false 227 return 0, false
221 } 228 }
222 panic(fmt.Sprintf("invalid Int64Val(%v)", x)) 229 panic(fmt.Sprintf("invalid Int64Val(%v)", x))
223 } 230 }
224 231
225 // Uint64Val returns the Go uint64 value of x and whether the result is exact; 232 // Uint64Val returns the Go uint64 value of x and whether the result is exact;
226 // x must be an Int. If the result is not exact, its value is undefined. 233 // x must be an Int or an Unknown. If the result is not exact, its value is unde fined.
227 // The result is (0, false) for unknown values. 234 // If x is Unknown, the result is (0, false).
228 func Uint64Val(x Value) (uint64, bool) { 235 func Uint64Val(x Value) (uint64, bool) {
229 switch x := x.(type) { 236 switch x := x.(type) {
230 case int64Val: 237 case int64Val:
231 return uint64(x), x >= 0 238 return uint64(x), x >= 0
232 case intVal: 239 case intVal:
233 return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64 240 return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
234 case unknownVal: 241 case unknownVal:
235 return 0, false 242 return 0, false
236 } 243 }
237 panic(fmt.Sprintf("invalid Uint64Val(%v)", x)) 244 panic(fmt.Sprintf("invalid Uint64Val(%v)", x))
238 } 245 }
239 246
240 // Float64Val returns the nearest Go float64 value of x and whether the result i s exact; 247 // Float64Val returns the nearest Go float64 value of x and whether the result i s exact;
241 // x must be numeric but not Complex. The result is (0, false) for unknown value s. 248 // x must be numeric but not Complex, or Unknown.
249 // If x is Unknown, the result is (0, false).
242 func Float64Val(x Value) (float64, bool) { 250 func Float64Val(x Value) (float64, bool) {
243 switch x := x.(type) { 251 switch x := x.(type) {
244 case int64Val: 252 case int64Val:
245 f := float64(int64(x)) 253 f := float64(int64(x))
246 return f, int64Val(f) == x 254 return f, int64Val(f) == x
247 case intVal: 255 case intVal:
248 return new(big.Rat).SetFrac(x.val, int1).Float64() 256 return new(big.Rat).SetFrac(x.val, int1).Float64()
249 case floatVal: 257 case floatVal:
250 return x.val.Float64() 258 return x.val.Float64()
251 case unknownVal: 259 case unknownVal:
252 return 0, false 260 return 0, false
253 } 261 }
254 panic(fmt.Sprintf("invalid Float64Val(%v)", x)) 262 panic(fmt.Sprintf("invalid Float64Val(%v)", x))
255 } 263 }
256 264
257 // BitLen() returns the number of bits required to represent 265 // BitLen returns the number of bits required to represent
258 // the absolute value x in binary representation; x must be an Int. 266 // the absolute value x in binary representation; x must be an Int or an Unknown .
259 // The result is 0 for unknown values. 267 // If x is Unknown, the result is 0.
260 func BitLen(x Value) int { 268 func BitLen(x Value) int {
261 switch x := x.(type) { 269 switch x := x.(type) {
262 case int64Val: 270 case int64Val:
263 return new(big.Int).SetInt64(int64(x)).BitLen() 271 return new(big.Int).SetInt64(int64(x)).BitLen()
264 case intVal: 272 case intVal:
265 return x.val.BitLen() 273 return x.val.BitLen()
266 case unknownVal: 274 case unknownVal:
267 return 0 275 return 0
268 } 276 }
269 panic(fmt.Sprintf("invalid BitLen(%v)", x)) 277 panic(fmt.Sprintf("invalid BitLen(%v)", x))
270 } 278 }
271 279
272 // Sign returns -1, 0, or 1 depending on whether 280 // Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
273 // x < 0, x == 0, or x > 0. For complex values z, 281 // x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
274 // the sign is 0 if z == 0, otherwise it is != 0. 282 // otherwise it is != 0. If x is Unknown, the result is 1.
275 // The result is 1 for unknown values.
276 func Sign(x Value) int { 283 func Sign(x Value) int {
277 switch x := x.(type) { 284 switch x := x.(type) {
278 case int64Val: 285 case int64Val:
279 switch { 286 switch {
280 case x < 0: 287 case x < 0:
281 return -1 288 return -1
282 case x > 0: 289 case x > 0:
283 return 1 290 return 1
284 } 291 }
285 return 0 292 return 0
286 case intVal: 293 case intVal:
287 return x.val.Sign() 294 return x.val.Sign()
288 case floatVal: 295 case floatVal:
289 return x.val.Sign() 296 return x.val.Sign()
290 case complexVal: 297 case complexVal:
291 return x.re.Sign() | x.im.Sign() 298 return x.re.Sign() | x.im.Sign()
292 case unknownVal: 299 case unknownVal:
293 return 1 // avoid spurious division by zero errors 300 return 1 // avoid spurious division by zero errors
294 } 301 }
295 panic(fmt.Sprintf("invalid Sign(%v)", x)) 302 panic(fmt.Sprintf("invalid Sign(%v)", x))
296 } 303 }
297 304
298 // ---------------------------------------------------------------------------- 305 // ----------------------------------------------------------------------------
306 // Support for serializing/deserializing integers
307
308 const (
309 // Compute the size of a Word in bytes.
310 _m = ^big.Word(0)
311 _log = _m>>8&1 + _m>>16&1 + _m>>32&1
312 wordSize = 1 << _log
313 )
314
315 // Bytes returns the bytes for the absolute value of x in little-
316 // endian binary representation; x must be an Int.
317 func Bytes(x Value) []byte {
318 var val *big.Int
319 switch x := x.(type) {
320 case int64Val:
321 val = new(big.Int).SetInt64(int64(x))
322 case intVal:
323 val = x.val
324 default:
325 panic(fmt.Sprintf("invalid Bits(%v)", x))
adonovan 2013/12/12 21:29:12 "Bits"? How about: "Bytes(%v): not an Int"?
gri 2013/12/12 21:42:58 Done. Adjusted everywhere.
326 }
327
328 words := val.Bits()
adonovan 2013/12/12 21:29:12 Consider splitting the rest into: func bigIntByt
gri 2013/12/12 21:42:58 It's only used here - no need.
329 bytes := make([]byte, len(words)*wordSize)
330
331 i := 0
332 for _, w := range words {
333 for j := 0; j < wordSize; j++ {
334 bytes[i] = byte(w)
335 w >>= 8
336 i++
337 }
338 }
339 // remove leading 0's
340 for i > 0 && bytes[i-1] == 0 {
341 i--
342 }
343
344 return bytes[:i]
345
adonovan 2013/12/12 21:29:12 Remove blank.
gri 2013/12/12 21:42:58 Done.
346 }
347
348 // MakeFromBytes returns the Int value given the bytes of its little-endian
349 // binary representation. An empty byte slice argument represents 0.
adonovan 2013/12/12 21:29:12 Does the empty case need describing? It seems obv
gri 2013/12/12 21:42:58 I think it does - it could be []byte{0} (which wou
350 func MakeFromBytes(bytes []byte) Value {
351 words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
adonovan 2013/12/12 21:29:12 Consider putting most of this into a bigIntFromByt
gri 2013/12/12 21:42:58 leaving alone for now (see above)
352
353 i := 0
354 var w big.Word
355 var s uint
356 for _, b := range bytes {
357 w |= big.Word(b) << s
358 if s += 8; s == wordSize*8 {
359 words[i] = w
360 i++
361 w = 0
362 s = 0
363 }
364 }
365 // store last word
366 if i < len(words) {
367 words[i] = w
368 i++
369 }
370 // remove leading 0's
371 for i > 0 && words[i-1] == 0 {
372 i--
373 }
374
375 return normInt(new(big.Int).SetBits(words[:i]))
376 }
377
378 // ----------------------------------------------------------------------------
379 // Support for disassembling fractions
380
381 // Num returns the numerator of x; x must be numeric but not Complex, or Unknown .
382 // If x is Unknown, the result is Unknown, otherwise it is an Int.
383 func Num(x Value) Value {
384 switch x := x.(type) {
385 case unknownVal, int64Val, intVal:
386 return x
387 case floatVal:
388 return normInt(x.val.Num())
389 }
390 panic(fmt.Sprintf("invalid Num(%v)", x))
391 }
392
393 // Denom returns the denominator of x; x must be numeric but not Complex, or Unk nown.
394 // If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
adonovan 2013/12/12 21:29:12 "a positive Int"?
395 func Denom(x Value) Value {
396 switch x := x.(type) {
397 case unknownVal:
398 return x
399 case int64Val, intVal:
400 return int64Val(1)
401 case floatVal:
402 return normInt(x.val.Denom())
403 }
404 panic(fmt.Sprintf("invalid Denom(%v)", x))
405 }
406
407 // ----------------------------------------------------------------------------
299 // Support for assembling/disassembling complex numbers 408 // Support for assembling/disassembling complex numbers
300 409
301 // MakeImag returns the numeric value x*i (possibly 0); 410 // MakeImag returns the numeric value x*i (possibly 0);
302 // x must be numeric but not Complex. 411 // x must be numeric but not Complex, or Unknown.
303 // The result is unknown for unknown values. 412 // If x is Unknown, the result is Unknown.
304 func MakeImag(x Value) Value { 413 func MakeImag(x Value) Value {
305 var im *big.Rat 414 var im *big.Rat
306 switch x := x.(type) { 415 switch x := x.(type) {
416 case unknownVal:
417 return x
307 case int64Val: 418 case int64Val:
308 im = big.NewRat(int64(x), 1) 419 im = big.NewRat(int64(x), 1)
309 case intVal: 420 case intVal:
310 im = new(big.Rat).SetFrac(x.val, int1) 421 im = new(big.Rat).SetFrac(x.val, int1)
311 case floatVal: 422 case floatVal:
312 im = x.val 423 im = x.val
313 case unknownVal:
314 return x
315 default: 424 default:
316 panic(fmt.Sprintf("invalid MakeImag(%v)", x)) 425 panic(fmt.Sprintf("invalid MakeImag(%v)", x))
317 } 426 }
318 return normComplex(rat0, im) 427 return normComplex(rat0, im)
319 } 428 }
320 429
321 // Real returns the real part of x, which must be a numeric value. 430 // Real returns the real part of x, which must be a numeric or unknown value.
322 // The result is unknown for unknown values. 431 // If x is Unknown, the result is Unknown.
323 func Real(x Value) Value { 432 func Real(x Value) Value {
324 » if z, ok := x.(complexVal); ok { 433 » switch x := x.(type) {
325 » » return normFloat(z.re) 434 » case unknownVal:
435 » » return x
436 » case int64Val, intVal, floatVal:
437 » » return int64Val(0)
adonovan 2013/12/12 21:29:12 Isn't the real part of an integer... all of it?
adonovan 2013/12/12 21:58:31 Sorry, I should have been more explicit: this is a
gri 2013/12/12 22:17:45 https://codereview.appspot.com/37820052
438 » case complexVal:
439 » » return normFloat(x.re)
326 } 440 }
327 » // TODO(gri) should we check explicit for unknownVal and disallow all ot hers? 441 » panic(fmt.Sprintf("invalid Real(%v)", x))
328 » return x
329 } 442 }
330 443
331 // Imag returns the imaginary part of x, which must be a numeric value. 444 // Imag returns the imaginary part of x, which must be a numeric or unknown valu e.
332 // The result is 0 for unknown values. 445 // If x is Unknown, the result is Unknown.
333 func Imag(x Value) Value { 446 func Imag(x Value) Value {
334 » if z, ok := x.(complexVal); ok { 447 » switch x := x.(type) {
335 » » return normFloat(z.im) 448 » case unknownVal:
449 » » return x
450 » case int64Val, intVal, floatVal:
451 » » return int64Val(0)
452 » case complexVal:
453 » » return normFloat(x.im)
336 } 454 }
337 » // TODO(gri) should we check explicit for unknownVal and disallow all ot hers? 455 » panic(fmt.Sprintf("invalid Imag(%v)", x))
338 » return int64Val(0)
339 } 456 }
340 457
341 // ---------------------------------------------------------------------------- 458 // ----------------------------------------------------------------------------
342 // Operations 459 // Operations
343 460
344 // is32bit reports whether x can be represented using 32 bits. 461 // is32bit reports whether x can be represented using 32 bits.
345 func is32bit(x int64) bool { 462 func is32bit(x int64) bool {
346 const s = 32 463 const s = 32
347 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 464 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
348 } 465 }
349 466
350 // is63bit reports whether x can be represented using 63 bits. 467 // is63bit reports whether x can be represented using 63 bits.
351 func is63bit(x int64) bool { 468 func is63bit(x int64) bool {
352 const s = 63 469 const s = 63
353 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 470 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
354 } 471 }
355 472
356 // UnaryOp returns the result of the unary expression op y. 473 // UnaryOp returns the result of the unary expression op y.
357 // The operation must be defined for the operand. 474 // The operation must be defined for the operand.
358 // If size >= 0 it specifies the ^ (xor) result size in bytes. 475 // If size >= 0 it specifies the ^ (xor) result size in bytes.
476 // If y is Unknown, the result is Unknown.
359 // 477 //
360 func UnaryOp(op token.Token, y Value, size int) Value { 478 func UnaryOp(op token.Token, y Value, size int) Value {
361 switch op { 479 switch op {
362 case token.ADD: 480 case token.ADD:
363 switch y.(type) { 481 switch y.(type) {
364 case unknownVal, int64Val, intVal, floatVal, complexVal: 482 case unknownVal, int64Val, intVal, floatVal, complexVal:
365 return y 483 return y
366 } 484 }
367 485
368 case token.SUB: 486 case token.SUB:
369 switch y := y.(type) { 487 switch y := y.(type) {
488 case unknownVal:
489 return y
370 case int64Val: 490 case int64Val:
371 if z := -y; z != y { 491 if z := -y; z != y {
372 return z // no overflow 492 return z // no overflow
373 } 493 }
374 return normInt(new(big.Int).Neg(big.NewInt(int64(y)))) 494 return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
375 case intVal: 495 case intVal:
376 return normInt(new(big.Int).Neg(y.val)) 496 return normInt(new(big.Int).Neg(y.val))
377 case floatVal: 497 case floatVal:
378 return normFloat(new(big.Rat).Neg(y.val)) 498 return normFloat(new(big.Rat).Neg(y.val))
379 case complexVal: 499 case complexVal:
380 return normComplex(new(big.Rat).Neg(y.re), new(big.Rat). Neg(y.im)) 500 return normComplex(new(big.Rat).Neg(y.re), new(big.Rat). Neg(y.im))
381 } 501 }
382 502
383 case token.XOR: 503 case token.XOR:
384 var z big.Int 504 var z big.Int
385 switch y := y.(type) { 505 switch y := y.(type) {
506 case unknownVal:
507 return y
386 case int64Val: 508 case int64Val:
387 z.Not(big.NewInt(int64(y))) 509 z.Not(big.NewInt(int64(y)))
388 case intVal: 510 case intVal:
389 z.Not(y.val) 511 z.Not(y.val)
390 default: 512 default:
391 goto Error 513 goto Error
392 } 514 }
393 // For unsigned types, the result will be negative and 515 // For unsigned types, the result will be negative and
394 // thus "too large": We must limit the result size to 516 // thus "too large": We must limit the result size to
395 // the type's size. 517 // the type's size.
396 if size >= 0 { 518 if size >= 0 {
397 s := uint(size) * 8 519 s := uint(size) * 8
398 z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z & ^= (-1)<<s 520 z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z & ^= (-1)<<s
399 } 521 }
400 return normInt(&z) 522 return normInt(&z)
401 523
402 case token.NOT: 524 case token.NOT:
403 » » return !y.(boolVal) 525 » » switch y := y.(type) {
526 » » case unknownVal:
527 » » » return y
528 » » case boolVal:
529 » » » return !y
530 » » }
404 } 531 }
405 532
406 Error: 533 Error:
407 panic(fmt.Sprintf("invalid unary operation %s%v", op, y)) 534 panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
408 } 535 }
409 536
410 var ( 537 var (
411 int1 = big.NewInt(1) 538 int1 = big.NewInt(1)
412 rat0 = big.NewRat(0, 1) 539 rat0 = big.NewRat(0, 1)
413 ) 540 )
414 541
415 func ord(x Value) int { 542 func ord(x Value) int {
416 switch x.(type) { 543 switch x.(type) {
417 default: 544 default:
418 return 0 545 return 0
419 case int64Val: 546 case int64Val:
420 return 1 547 return 1
421 case intVal: 548 case intVal:
422 return 2 549 return 2
423 case floatVal: 550 case floatVal:
424 return 3 551 return 3
425 case complexVal: 552 case complexVal:
426 return 4 553 return 4
427 } 554 }
428 } 555 }
429 556
430 // match returns the matching representation (same type) with the 557 // match returns the matching representation (same type) with the
431 // smallest complexity for two values x and y. If one of them is 558 // smallest complexity for two values x and y. If one of them is
432 // numeric, both of them must be numeric. 559 // numeric, both of them must be numeric. If one of them is Unknown,
560 // both results are Unknown.
433 // 561 //
434 func match(x, y Value) (_, _ Value) { 562 func match(x, y Value) (_, _ Value) {
435 if ord(x) > ord(y) { 563 if ord(x) > ord(y) {
436 y, x = match(y, x) 564 y, x = match(y, x)
437 return x, y 565 return x, y
438 } 566 }
439 // ord(x) <= ord(y) 567 // ord(x) <= ord(y)
440 568
441 switch x := x.(type) { 569 switch x := x.(type) {
442 » case unknownVal, boolVal, stringVal, complexVal: 570 » case unknownVal:
571 » » return x, x
572
573 » case boolVal, stringVal, complexVal:
443 return x, y 574 return x, y
444 575
445 case int64Val: 576 case int64Val:
446 switch y := y.(type) { 577 switch y := y.(type) {
447 case int64Val: 578 case int64Val:
448 return x, y 579 return x, y
449 case intVal: 580 case intVal:
450 return intVal{big.NewInt(int64(x))}, y 581 return intVal{big.NewInt(int64(x))}, y
451 case floatVal: 582 case floatVal:
452 return floatVal{big.NewRat(int64(x), 1)}, y 583 return floatVal{big.NewRat(int64(x), 1)}, y
(...skipping 17 matching lines...) Expand all
470 return x, y 601 return x, y
471 case complexVal: 602 case complexVal:
472 return complexVal{x.val, rat0}, y 603 return complexVal{x.val, rat0}, y
473 } 604 }
474 } 605 }
475 606
476 panic("unreachable") 607 panic("unreachable")
477 } 608 }
478 609
479 // BinaryOp returns the result of the binary expression x op y. 610 // BinaryOp returns the result of the binary expression x op y.
480 // The operation must be defined for the operands. 611 // The operation must be defined for the operands. If one of the
612 // operands is Unknown, the result is Unknown.
481 // To force integer division of Int operands, use op == token.QUO_ASSIGN 613 // To force integer division of Int operands, use op == token.QUO_ASSIGN
482 // instead of token.QUO; the result is guaranteed to be Int in this case. 614 // instead of token.QUO; the result is guaranteed to be Int in this case.
483 // Division by zero leads to a run-time panic. 615 // Division by zero leads to a run-time panic.
484 // 616 //
485 func BinaryOp(x Value, op token.Token, y Value) Value { 617 func BinaryOp(x Value, op token.Token, y Value) Value {
486 x, y = match(x, y) 618 x, y = match(x, y)
487 619
488 switch x := x.(type) { 620 switch x := x.(type) {
489 case unknownVal: 621 case unknownVal:
490 return x 622 return x
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 return x + y.(stringVal) 764 return x + y.(stringVal)
633 } 765 }
634 } 766 }
635 767
636 Error: 768 Error:
637 panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y)) 769 panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
638 } 770 }
639 771
640 // Shift returns the result of the shift expression x op s 772 // Shift returns the result of the shift expression x op s
641 // with op == token.SHL or token.SHR (<< or >>). x must be 773 // with op == token.SHL or token.SHR (<< or >>). x must be
642 // an Int. 774 // an Int or an Unknown. If x is Unknown, the result is x.
643 // 775 //
644 func Shift(x Value, op token.Token, s uint) Value { 776 func Shift(x Value, op token.Token, s uint) Value {
645 switch x := x.(type) { 777 switch x := x.(type) {
646 case unknownVal: 778 case unknownVal:
647 return x 779 return x
648 780
649 case int64Val: 781 case int64Val:
650 if s == 0 { 782 if s == 0 {
651 return x 783 return x
652 } 784 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 case token.GTR: 819 case token.GTR:
688 return x > 0 820 return x > 0
689 case token.GEQ: 821 case token.GEQ:
690 return x >= 0 822 return x >= 0
691 } 823 }
692 panic("unreachable") 824 panic("unreachable")
693 } 825 }
694 826
695 // Compare returns the result of the comparison x op y. 827 // Compare returns the result of the comparison x op y.
696 // The comparison must be defined for the operands. 828 // The comparison must be defined for the operands.
829 // If one of the operands is Unknown, the result is
830 // false.
697 // 831 //
698 func Compare(x Value, op token.Token, y Value) bool { 832 func Compare(x Value, op token.Token, y Value) bool {
699 x, y = match(x, y) 833 x, y = match(x, y)
700 834
701 switch x := x.(type) { 835 switch x := x.(type) {
702 case unknownVal: 836 case unknownVal:
703 » » return true 837 » » return false
704 838
705 case boolVal: 839 case boolVal:
706 y := y.(boolVal) 840 y := y.(boolVal)
707 switch op { 841 switch op {
708 case token.EQL: 842 case token.EQL:
709 return x == y 843 return x == y
710 case token.NEQ: 844 case token.NEQ:
711 return x != y 845 return x != y
712 } 846 }
713 847
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 return x <= y 892 return x <= y
759 case token.GTR: 893 case token.GTR:
760 return x > y 894 return x > y
761 case token.GEQ: 895 case token.GEQ:
762 return x >= y 896 return x >= y
763 } 897 }
764 } 898 }
765 899
766 panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y)) 900 panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
767 } 901 }
OLDNEW
« no previous file with comments | « no previous file | go/exact/exact_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b