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

Delta Between Two Patch Sets: go/exact/exact.go

Issue 41170043: code review 41170043: go.tools/go/exact: serialization support and better unk... (Closed)
Left Patch Set: Created 10 years, 3 months ago
Right Patch Set: diff -r a5b52e9abb06 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:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | go/exact/exact_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
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
185 189 //
186 // BoolVal returns the Go boolean value of x, which must be a Bool. 190 // For unknown arguments the result is the zero value for the respective
187 // The result is false for unknown values. 191 // accessor type, except for Sign, where the result is 1.
192
193 // BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown .
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("%v not a Bool", 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("%v not a String", 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("%v not an Int", 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("%v not an Int", 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("%v not a Float", 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("%v not an Int", 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("%v not numeric", x))
303 }
304
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("%v not an Int", x))
326 » }
327
328 » words := val.Bits()
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 }
346
347 // MakeFromBytes returns the Int value given the bytes of its little-endian
348 // binary representation. An empty byte slice argument represents 0.
349 func MakeFromBytes(bytes []byte) Value {
350 » words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
351
352 » i := 0
353 » var w big.Word
354 » var s uint
355 » for _, b := range bytes {
356 » » w |= big.Word(b) << s
357 » » if s += 8; s == wordSize*8 {
358 » » » words[i] = w
359 » » » i++
360 » » » w = 0
361 » » » s = 0
362 » » }
363 » }
364 » // store last word
365 » if i < len(words) {
366 » » words[i] = w
367 » » i++
368 » }
369 » // remove leading 0's
370 » for i > 0 && words[i-1] == 0 {
371 » » i--
372 » }
373
374 » return normInt(new(big.Int).SetBits(words[:i]))
375 }
376
377 // ----------------------------------------------------------------------------
378 // Support for disassembling fractions
379
380 // Num returns the numerator of x; x must be Int, Float, or Unknown.
381 // If x is Unknown, the result is Unknown, otherwise it is an Int.
382 func Num(x Value) Value {
383 » switch x := x.(type) {
384 » case unknownVal, int64Val, intVal:
385 » » return x
386 » case floatVal:
387 » » return normInt(x.val.Num())
388 » }
389 » panic(fmt.Sprintf("%v not Int or Float", x))
390 }
391
392 // Denom returns the denominator of x; x must be Int, Float, or Unknown.
393 // If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
394 func Denom(x Value) Value {
395 » switch x := x.(type) {
396 » case unknownVal:
397 » » return x
398 » case int64Val, intVal:
399 » » return int64Val(1)
400 » case floatVal:
401 » » return normInt(x.val.Denom())
402 » }
403 » panic(fmt.Sprintf("%v not Int or Float", x))
296 } 404 }
297 405
298 // ---------------------------------------------------------------------------- 406 // ----------------------------------------------------------------------------
299 // Support for assembling/disassembling complex numbers 407 // Support for assembling/disassembling complex numbers
300 408
301 // MakeImag returns the numeric value x*i (possibly 0); 409 // MakeImag returns the numeric value x*i (possibly 0);
302 // x must be numeric but not Complex. 410 // x must be Int, Float, or Unknown.
303 // The result is unknown for unknown values. 411 // If x is Unknown, the result is Unknown.
304 func MakeImag(x Value) Value { 412 func MakeImag(x Value) Value {
305 var im *big.Rat 413 var im *big.Rat
306 switch x := x.(type) { 414 switch x := x.(type) {
415 case unknownVal:
416 return x
307 case int64Val: 417 case int64Val:
308 im = big.NewRat(int64(x), 1) 418 im = big.NewRat(int64(x), 1)
309 case intVal: 419 case intVal:
310 im = new(big.Rat).SetFrac(x.val, int1) 420 im = new(big.Rat).SetFrac(x.val, int1)
311 case floatVal: 421 case floatVal:
312 im = x.val 422 im = x.val
423 default:
424 panic(fmt.Sprintf("%v not Int or Float", x))
425 }
426 return normComplex(rat0, im)
427 }
428
429 // Real returns the real part of x, which must be a numeric or unknown value.
430 // If x is Unknown, the result is Unknown.
431 func Real(x Value) Value {
432 switch x := x.(type) {
313 case unknownVal: 433 case unknownVal:
314 return x 434 return x
315 » default: 435 » case int64Val, intVal, floatVal:
316 » » panic(fmt.Sprintf("invalid MakeImag(%v)", x)) 436 » » return int64Val(0)
317 » } 437 » case complexVal:
318 » return normComplex(rat0, im) 438 » » return normFloat(x.re)
319 } 439 » }
320 440 » panic(fmt.Sprintf("%v not numeric", x))
321 // Real returns the real part of x, which must be a numeric value. 441 }
322 // The result is unknown for unknown values. 442
323 func Real(x Value) Value { 443 // Imag returns the imaginary part of x, which must be a numeric or unknown valu e.
324 » if z, ok := x.(complexVal); ok { 444 // If x is Unknown, the result is Unknown.
325 » » return normFloat(z.re)
326 » }
327 » // TODO(gri) should we check explicit for unknownVal and disallow all ot hers?
328 » return x
329 }
330
331 // Imag returns the imaginary part of x, which must be a numeric value.
332 // The result is 0 for unknown values.
333 func Imag(x Value) Value { 445 func Imag(x Value) Value {
334 » if z, ok := x.(complexVal); ok { 446 » switch x := x.(type) {
335 » » return normFloat(z.im) 447 » case unknownVal:
336 » } 448 » » return x
337 » // TODO(gri) should we check explicit for unknownVal and disallow all ot hers? 449 » case int64Val, intVal, floatVal:
338 » return int64Val(0) 450 » » return int64Val(0)
451 » case complexVal:
452 » » return normFloat(x.im)
453 » }
454 » panic(fmt.Sprintf("%v not numeric", x))
339 } 455 }
340 456
341 // ---------------------------------------------------------------------------- 457 // ----------------------------------------------------------------------------
342 // Operations 458 // Operations
343 459
344 // is32bit reports whether x can be represented using 32 bits. 460 // is32bit reports whether x can be represented using 32 bits.
345 func is32bit(x int64) bool { 461 func is32bit(x int64) bool {
346 const s = 32 462 const s = 32
347 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 463 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
348 } 464 }
349 465
350 // is63bit reports whether x can be represented using 63 bits. 466 // is63bit reports whether x can be represented using 63 bits.
351 func is63bit(x int64) bool { 467 func is63bit(x int64) bool {
352 const s = 63 468 const s = 63
353 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 469 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
354 } 470 }
355 471
356 // UnaryOp returns the result of the unary expression op y. 472 // UnaryOp returns the result of the unary expression op y.
357 // The operation must be defined for the operand. 473 // The operation must be defined for the operand.
358 // If size >= 0 it specifies the ^ (xor) result size in bytes. 474 // If size >= 0 it specifies the ^ (xor) result size in bytes.
475 // If y is Unknown, the result is Unknown.
359 // 476 //
360 func UnaryOp(op token.Token, y Value, size int) Value { 477 func UnaryOp(op token.Token, y Value, size int) Value {
361 switch op { 478 switch op {
362 case token.ADD: 479 case token.ADD:
363 switch y.(type) { 480 switch y.(type) {
364 case unknownVal, int64Val, intVal, floatVal, complexVal: 481 case unknownVal, int64Val, intVal, floatVal, complexVal:
365 return y 482 return y
366 } 483 }
367 484
368 case token.SUB: 485 case token.SUB:
369 switch y := y.(type) { 486 switch y := y.(type) {
487 case unknownVal:
488 return y
370 case int64Val: 489 case int64Val:
371 if z := -y; z != y { 490 if z := -y; z != y {
372 return z // no overflow 491 return z // no overflow
373 } 492 }
374 return normInt(new(big.Int).Neg(big.NewInt(int64(y)))) 493 return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
375 case intVal: 494 case intVal:
376 return normInt(new(big.Int).Neg(y.val)) 495 return normInt(new(big.Int).Neg(y.val))
377 case floatVal: 496 case floatVal:
378 return normFloat(new(big.Rat).Neg(y.val)) 497 return normFloat(new(big.Rat).Neg(y.val))
379 case complexVal: 498 case complexVal:
380 return normComplex(new(big.Rat).Neg(y.re), new(big.Rat). Neg(y.im)) 499 return normComplex(new(big.Rat).Neg(y.re), new(big.Rat). Neg(y.im))
381 } 500 }
382 501
383 case token.XOR: 502 case token.XOR:
384 var z big.Int 503 var z big.Int
385 switch y := y.(type) { 504 switch y := y.(type) {
505 case unknownVal:
506 return y
386 case int64Val: 507 case int64Val:
387 z.Not(big.NewInt(int64(y))) 508 z.Not(big.NewInt(int64(y)))
388 case intVal: 509 case intVal:
389 z.Not(y.val) 510 z.Not(y.val)
390 default: 511 default:
391 goto Error 512 goto Error
392 } 513 }
393 // For unsigned types, the result will be negative and 514 // For unsigned types, the result will be negative and
394 // thus "too large": We must limit the result size to 515 // thus "too large": We must limit the result size to
395 // the type's size. 516 // the type's size.
396 if size >= 0 { 517 if size >= 0 {
397 s := uint(size) * 8 518 s := uint(size) * 8
398 z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z & ^= (-1)<<s 519 z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z & ^= (-1)<<s
399 } 520 }
400 return normInt(&z) 521 return normInt(&z)
401 522
402 case token.NOT: 523 case token.NOT:
403 » » return !y.(boolVal) 524 » » switch y := y.(type) {
525 » » case unknownVal:
526 » » » return y
527 » » case boolVal:
528 » » » return !y
529 » » }
404 } 530 }
405 531
406 Error: 532 Error:
407 panic(fmt.Sprintf("invalid unary operation %s%v", op, y)) 533 panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
408 } 534 }
409 535
410 var ( 536 var (
411 int1 = big.NewInt(1) 537 int1 = big.NewInt(1)
412 rat0 = big.NewRat(0, 1) 538 rat0 = big.NewRat(0, 1)
413 ) 539 )
414 540
415 func ord(x Value) int { 541 func ord(x Value) int {
416 switch x.(type) { 542 switch x.(type) {
417 default: 543 default:
418 return 0 544 return 0
419 case int64Val: 545 case int64Val:
420 return 1 546 return 1
421 case intVal: 547 case intVal:
422 return 2 548 return 2
423 case floatVal: 549 case floatVal:
424 return 3 550 return 3
425 case complexVal: 551 case complexVal:
426 return 4 552 return 4
427 } 553 }
428 } 554 }
429 555
430 // match returns the matching representation (same type) with the 556 // match returns the matching representation (same type) with the
431 // smallest complexity for two values x and y. If one of them is 557 // smallest complexity for two values x and y. If one of them is
432 // numeric, both of them must be numeric. 558 // numeric, both of them must be numeric. If one of them is Unknown,
559 // both results are Unknown.
433 // 560 //
434 func match(x, y Value) (_, _ Value) { 561 func match(x, y Value) (_, _ Value) {
435 if ord(x) > ord(y) { 562 if ord(x) > ord(y) {
436 y, x = match(y, x) 563 y, x = match(y, x)
437 return x, y 564 return x, y
438 } 565 }
439 // ord(x) <= ord(y) 566 // ord(x) <= ord(y)
440 567
441 switch x := x.(type) { 568 switch x := x.(type) {
442 » case unknownVal, boolVal, stringVal, complexVal: 569 » case unknownVal:
570 » » return x, x
571
572 » case boolVal, stringVal, complexVal:
443 return x, y 573 return x, y
444 574
445 case int64Val: 575 case int64Val:
446 switch y := y.(type) { 576 switch y := y.(type) {
447 case int64Val: 577 case int64Val:
448 return x, y 578 return x, y
449 case intVal: 579 case intVal:
450 return intVal{big.NewInt(int64(x))}, y 580 return intVal{big.NewInt(int64(x))}, y
451 case floatVal: 581 case floatVal:
452 return floatVal{big.NewRat(int64(x), 1)}, y 582 return floatVal{big.NewRat(int64(x), 1)}, y
(...skipping 17 matching lines...) Expand all
470 return x, y 600 return x, y
471 case complexVal: 601 case complexVal:
472 return complexVal{x.val, rat0}, y 602 return complexVal{x.val, rat0}, y
473 } 603 }
474 } 604 }
475 605
476 panic("unreachable") 606 panic("unreachable")
477 } 607 }
478 608
479 // BinaryOp returns the result of the binary expression x op y. 609 // BinaryOp returns the result of the binary expression x op y.
480 // The operation must be defined for the operands. 610 // The operation must be defined for the operands. If one of the
611 // operands is Unknown, the result is Unknown.
481 // To force integer division of Int operands, use op == token.QUO_ASSIGN 612 // 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. 613 // instead of token.QUO; the result is guaranteed to be Int in this case.
483 // Division by zero leads to a run-time panic. 614 // Division by zero leads to a run-time panic.
484 // 615 //
485 func BinaryOp(x Value, op token.Token, y Value) Value { 616 func BinaryOp(x Value, op token.Token, y Value) Value {
486 x, y = match(x, y) 617 x, y = match(x, y)
487 618
488 switch x := x.(type) { 619 switch x := x.(type) {
489 case unknownVal: 620 case unknownVal:
490 return x 621 return x
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 return x + y.(stringVal) 763 return x + y.(stringVal)
633 } 764 }
634 } 765 }
635 766
636 Error: 767 Error:
637 panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y)) 768 panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
638 } 769 }
639 770
640 // Shift returns the result of the shift expression x op s 771 // Shift returns the result of the shift expression x op s
641 // with op == token.SHL or token.SHR (<< or >>). x must be 772 // with op == token.SHL or token.SHR (<< or >>). x must be
642 // an Int. 773 // an Int or an Unknown. If x is Unknown, the result is x.
643 // 774 //
644 func Shift(x Value, op token.Token, s uint) Value { 775 func Shift(x Value, op token.Token, s uint) Value {
645 switch x := x.(type) { 776 switch x := x.(type) {
646 case unknownVal: 777 case unknownVal:
647 return x 778 return x
648 779
649 case int64Val: 780 case int64Val:
650 if s == 0 { 781 if s == 0 {
651 return x 782 return x
652 } 783 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 case token.GTR: 818 case token.GTR:
688 return x > 0 819 return x > 0
689 case token.GEQ: 820 case token.GEQ:
690 return x >= 0 821 return x >= 0
691 } 822 }
692 panic("unreachable") 823 panic("unreachable")
693 } 824 }
694 825
695 // Compare returns the result of the comparison x op y. 826 // Compare returns the result of the comparison x op y.
696 // The comparison must be defined for the operands. 827 // The comparison must be defined for the operands.
828 // If one of the operands is Unknown, the result is
829 // false.
697 // 830 //
698 func Compare(x Value, op token.Token, y Value) bool { 831 func Compare(x Value, op token.Token, y Value) bool {
699 x, y = match(x, y) 832 x, y = match(x, y)
700 833
701 switch x := x.(type) { 834 switch x := x.(type) {
702 case unknownVal: 835 case unknownVal:
703 » » return true 836 » » return false
704 837
705 case boolVal: 838 case boolVal:
706 y := y.(boolVal) 839 y := y.(boolVal)
707 switch op { 840 switch op {
708 case token.EQL: 841 case token.EQL:
709 return x == y 842 return x == y
710 case token.NEQ: 843 case token.NEQ:
711 return x != y 844 return x != y
712 } 845 }
713 846
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 return x <= y 891 return x <= y
759 case token.GTR: 892 case token.GTR:
760 return x > y 893 return x > y
761 case token.GEQ: 894 case token.GEQ:
762 return x >= y 895 return x >= y
763 } 896 }
764 } 897 }
765 898
766 panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y)) 899 panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
767 } 900 }
LEFTRIGHT

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