|
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