|
1 | 1 | /* |
2 | | - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. |
| 2 | + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. |
3 | 3 | * Copyright (c) 2013, Regents of the University of California |
4 | 4 | * |
5 | 5 | * All rights reserved. |
|
164 | 164 | import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; |
165 | 165 | import com.oracle.graal.python.nodes.subscript.GetItemNode; |
166 | 166 | import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; |
167 | | -import com.oracle.graal.python.nodes.util.CastToIntegerFromIndexNode; |
168 | 167 | import com.oracle.graal.python.nodes.util.CastToJavaStringNode; |
169 | 168 | import com.oracle.graal.python.nodes.util.CoerceToStringNode; |
170 | 169 | import com.oracle.graal.python.nodes.util.CoerceToStringNodeGen; |
@@ -260,160 +259,124 @@ public Object absObject(VirtualFrame frame, Object object, |
260 | 259 | @TypeSystemReference(PythonArithmeticTypes.class) |
261 | 260 | @GenerateNodeFactory |
262 | 261 | public abstract static class BinNode extends PythonUnaryBuiltinNode { |
263 | | - |
264 | | - public abstract String executeObject(VirtualFrame frame, Object x); |
265 | | - |
266 | 262 | @TruffleBoundary |
267 | | - private static String buildString(boolean isNegative, String number) { |
| 263 | + protected String buildString(boolean isNegative, String number) { |
268 | 264 | StringBuilder sb = new StringBuilder(); |
269 | 265 | if (isNegative) { |
270 | 266 | sb.append('-'); |
271 | 267 | } |
272 | | - sb.append("0b"); |
| 268 | + sb.append(prefix()); |
273 | 269 | sb.append(number); |
274 | 270 | return sb.toString(); |
275 | 271 | } |
276 | 272 |
|
277 | | - @Specialization |
278 | | - String doL(long x) { |
279 | | - return buildString(x < 0, longToBinaryString(x)); |
| 273 | + protected String prefix() { |
| 274 | + return "0b"; |
280 | 275 | } |
281 | 276 |
|
282 | 277 | @TruffleBoundary |
283 | | - private static String longToBinaryString(long x) { |
| 278 | + protected String longToString(long x) { |
284 | 279 | return Long.toBinaryString(Math.abs(x)); |
285 | 280 | } |
286 | 281 |
|
| 282 | + @TruffleBoundary |
| 283 | + protected String bigToString(BigInteger x) { |
| 284 | + return x.toString(2); |
| 285 | + } |
| 286 | + |
287 | 287 | @Specialization |
288 | | - String doD(double x) { |
289 | | - throw raise(TypeError, "'%p' object cannot be interpreted as an integer", x); |
| 288 | + String doL(long x) { |
| 289 | + return buildString(x < 0, longToString(x)); |
| 290 | + } |
| 291 | + |
| 292 | + @Specialization |
| 293 | + String doD(double x, |
| 294 | + @Cached PRaiseNode raise) { |
| 295 | + throw raise.raiseIntegerInterpretationError(x); |
290 | 296 | } |
291 | 297 |
|
292 | 298 | @Specialization |
293 | 299 | @TruffleBoundary |
294 | 300 | String doPI(PInt x) { |
295 | 301 | BigInteger value = x.getValue(); |
296 | | - return buildString(value.compareTo(BigInteger.ZERO) < 0, value.abs().toString(2)); |
| 302 | + return buildString(value.compareTo(BigInteger.ZERO) < 0, bigToString(value.abs())); |
297 | 303 | } |
298 | 304 |
|
299 | | - @Specialization |
| 305 | + @Specialization(replaces = {"doL", "doD", "doPI"}) |
300 | 306 | String doO(VirtualFrame frame, Object x, |
301 | | - @Cached("create()") CastToIntegerFromIndexNode toIntNode, |
302 | | - @Cached("create()") BinNode recursiveNode) { |
303 | | - Object value = toIntNode.execute(frame, x); |
304 | | - return recursiveNode.executeObject(frame, value); |
305 | | - } |
306 | | - |
307 | | - protected static BinNode create() { |
308 | | - return BuiltinFunctionsFactory.BinNodeFactory.create(); |
| 307 | + @Cached IsSubtypeNode isSubtype, |
| 308 | + @CachedLibrary(limit = "getCallSiteInlineCacheMaxDepth()") PythonObjectLibrary lib, |
| 309 | + @Cached BranchProfile isInt, |
| 310 | + @Cached BranchProfile isLong, |
| 311 | + @Cached BranchProfile isPInt) { |
| 312 | + Object index = lib.asIndexWithState(x, PArguments.getThreadState(frame)); |
| 313 | + if (isSubtype.execute(lib.getLazyPythonClass(index), PythonBuiltinClassType.PInt)) { |
| 314 | + if (index instanceof Boolean || index instanceof Integer) { |
| 315 | + isInt.enter(); |
| 316 | + return doL(lib.asSize(index)); |
| 317 | + } else if (index instanceof Long) { |
| 318 | + isLong.enter(); |
| 319 | + return doL((long) index); |
| 320 | + } else if (index instanceof PInt) { |
| 321 | + isPInt.enter(); |
| 322 | + return doPI((PInt) index); |
| 323 | + } else { |
| 324 | + CompilerDirectives.transferToInterpreter(); |
| 325 | + throw raise(PythonBuiltinClassType.NotImplementedError, "bin/oct/hex with native integer subclasses"); |
| 326 | + } |
| 327 | + } |
| 328 | + CompilerDirectives.transferToInterpreter(); |
| 329 | + /* |
| 330 | + * It should not be possible to get here, as PyNumber_Index already has a check for the |
| 331 | + * same condition |
| 332 | + */ |
| 333 | + throw raise(PythonBuiltinClassType.ValueError, "PyNumber_ToBase: index not int"); |
309 | 334 | } |
310 | 335 | } |
311 | 336 |
|
312 | 337 | // oct(object) |
313 | 338 | @Builtin(name = OCT, minNumOfPositionalArgs = 1) |
314 | 339 | @TypeSystemReference(PythonArithmeticTypes.class) |
315 | 340 | @GenerateNodeFactory |
316 | | - public abstract static class OctNode extends PythonUnaryBuiltinNode { |
317 | | - |
318 | | - public abstract String executeObject(VirtualFrame frame, Object x); |
319 | | - |
320 | | - @TruffleBoundary |
321 | | - private static String buildString(boolean isNegative, String number) { |
322 | | - StringBuilder sb = new StringBuilder(); |
323 | | - if (isNegative) { |
324 | | - sb.append('-'); |
325 | | - } |
326 | | - sb.append("0o"); |
327 | | - sb.append(number); |
328 | | - return sb.toString(); |
329 | | - } |
330 | | - |
331 | | - @Specialization |
332 | | - public String doL(long x) { |
333 | | - return buildString(x < 0, longToOctString(x)); |
334 | | - } |
335 | | - |
| 341 | + public abstract static class OctNode extends BinNode { |
| 342 | + @Override |
336 | 343 | @TruffleBoundary |
337 | | - private static String longToOctString(long x) { |
338 | | - return Long.toOctalString(Math.abs(x)); |
339 | | - } |
340 | | - |
341 | | - @Specialization |
342 | | - public String doD(double x) { |
343 | | - throw raise(TypeError, "'%p' object cannot be interpreted as an integer", x); |
| 344 | + protected String bigToString(BigInteger x) { |
| 345 | + return x.toString(8); |
344 | 346 | } |
345 | 347 |
|
346 | | - @Specialization |
| 348 | + @Override |
347 | 349 | @TruffleBoundary |
348 | | - public String doPI(PInt x) { |
349 | | - BigInteger value = x.getValue(); |
350 | | - return buildString(value.compareTo(BigInteger.ZERO) < 0, value.abs().toString(8)); |
351 | | - } |
352 | | - |
353 | | - @Specialization |
354 | | - String doO(VirtualFrame frame, Object x, |
355 | | - @Cached("create()") CastToIntegerFromIndexNode toIntNode, |
356 | | - @Cached("create()") OctNode recursiveNode) { |
357 | | - Object value = toIntNode.execute(frame, x); |
358 | | - return recursiveNode.executeObject(frame, value); |
| 350 | + protected String longToString(long x) { |
| 351 | + return Long.toOctalString(x); |
359 | 352 | } |
360 | 353 |
|
361 | | - protected static OctNode create() { |
362 | | - return BuiltinFunctionsFactory.OctNodeFactory.create(); |
| 354 | + @Override |
| 355 | + protected String prefix() { |
| 356 | + return "0o"; |
363 | 357 | } |
364 | 358 | } |
365 | 359 |
|
366 | 360 | // hex(object) |
367 | 361 | @Builtin(name = HEX, minNumOfPositionalArgs = 1) |
368 | 362 | @TypeSystemReference(PythonArithmeticTypes.class) |
369 | 363 | @GenerateNodeFactory |
370 | | - public abstract static class HexNode extends PythonUnaryBuiltinNode { |
371 | | - |
372 | | - public abstract String executeObject(VirtualFrame frame, Object x); |
373 | | - |
374 | | - @TruffleBoundary |
375 | | - private static String buildString(boolean isNegative, String number) { |
376 | | - StringBuilder sb = new StringBuilder(); |
377 | | - if (isNegative) { |
378 | | - sb.append('-'); |
379 | | - } |
380 | | - sb.append("0x"); |
381 | | - sb.append(number); |
382 | | - return sb.toString(); |
383 | | - } |
384 | | - |
385 | | - @Specialization |
386 | | - String doL(long x) { |
387 | | - return buildString(x < 0, longToHexString(x)); |
388 | | - } |
389 | | - |
| 364 | + public abstract static class HexNode extends BinNode { |
| 365 | + @Override |
390 | 366 | @TruffleBoundary |
391 | | - private static String longToHexString(long x) { |
392 | | - return Long.toHexString(Math.abs(x)); |
393 | | - } |
394 | | - |
395 | | - @Specialization |
396 | | - String doD(double x) { |
397 | | - throw raise(TypeError, "'%p' object cannot be interpreted as an integer", x); |
| 367 | + protected String bigToString(BigInteger x) { |
| 368 | + return x.toString(16); |
398 | 369 | } |
399 | 370 |
|
400 | | - @Specialization |
| 371 | + @Override |
401 | 372 | @TruffleBoundary |
402 | | - String doPI(PInt x) { |
403 | | - BigInteger value = x.getValue(); |
404 | | - return buildString(value.compareTo(BigInteger.ZERO) < 0, value.abs().toString(8)); |
| 373 | + protected String longToString(long x) { |
| 374 | + return Long.toHexString(x); |
405 | 375 | } |
406 | 376 |
|
407 | | - @Specialization |
408 | | - String doO(VirtualFrame frame, Object x, |
409 | | - @Cached("create()") CastToIntegerFromIndexNode toIntNode, |
410 | | - @Cached("create()") HexNode recursiveNode) { |
411 | | - Object value = toIntNode.execute(frame, x); |
412 | | - return recursiveNode.executeObject(frame, value); |
413 | | - } |
414 | | - |
415 | | - protected static HexNode create() { |
416 | | - return BuiltinFunctionsFactory.HexNodeFactory.create(); |
| 377 | + @Override |
| 378 | + protected String prefix() { |
| 379 | + return "0x"; |
417 | 380 | } |
418 | 381 | } |
419 | 382 |
|
|
0 commit comments