Left: | ||
Right: |
OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |