LEFT | RIGHT |
(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 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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
LEFT | RIGHT |