|
71 | 71 | import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
|
72 | 72 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
|
73 | 73 | import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
|
74 |
| -import com.oracle.graal.python.nodes.util.CastToJavaStringNodeGen; |
75 | 74 | import com.oracle.graal.python.runtime.PythonCore;
|
76 | 75 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
77 | 76 | import com.oracle.truffle.api.CompilerDirectives;
|
@@ -504,82 +503,77 @@ public PDictView values(PDict self) {
|
504 | 503 | @GenerateNodeFactory
|
505 | 504 | public abstract static class ReprNode extends PythonUnaryBuiltinNode {
|
506 | 505 | @ValueType
|
507 |
| - private static final class ReprState { |
508 |
| - private final PDict self; |
| 506 | + protected static final class ReprState { |
509 | 507 | private final HashingStorage dictStorage;
|
510 | 508 | private final StringBuilder result;
|
511 | 509 |
|
512 |
| - ReprState(PDict self, HashingStorage dictStorage, StringBuilder result) { |
513 |
| - this.self = self; |
| 510 | + ReprState(HashingStorage dictStorage, StringBuilder result) { |
514 | 511 | this.dictStorage = dictStorage;
|
515 | 512 | this.result = result;
|
516 | 513 | }
|
517 | 514 | }
|
518 | 515 |
|
519 |
| - static final class EachRepr extends HashingStorageLibrary.ForEachNode<ReprState> { |
520 |
| - @Child LookupAndCallUnaryDynamicNode reprKeyNode; |
521 |
| - @Child LookupAndCallUnaryDynamicNode reprValueNode; |
522 |
| - @Child CastToJavaStringNode castStr; |
523 |
| - @Child PRaiseNode raiseNode; |
524 |
| - @Child HashingStorageLibrary lib; |
| 516 | + abstract static class EachRepr extends HashingStorageLibrary.ForEachNode<ReprState> { |
525 | 517 | private final int limit;
|
526 | 518 |
|
527 | 519 | EachRepr(int limit) {
|
528 | 520 | this.limit = limit;
|
529 | 521 | }
|
530 | 522 |
|
531 |
| - static final EachRepr create(int limit) { |
532 |
| - return new EachRepr(limit); |
| 523 | + protected final int getLimit() { |
| 524 | + return limit; |
533 | 525 | }
|
534 | 526 |
|
| 527 | + public abstract ReprState executeReprState(Object key, ReprState arg); |
| 528 | + |
535 | 529 | @Override
|
536 |
| - public ReprState execute(Object key, ReprState s) { |
537 |
| - if (lib == null) { |
538 |
| - lib = insert(HashingStorageLibrary.getFactory().createDispatched(limit)); |
539 |
| - } |
540 |
| - Object value = lib.getItem(s.dictStorage, key); |
541 |
| - if (reprKeyNode == null) { |
542 |
| - reprKeyNode = insert(LookupAndCallUnaryDynamicNode.create()); |
543 |
| - } |
| 530 | + public final ReprState execute(Object key, ReprState arg) { |
| 531 | + return executeReprState(key, arg); |
| 532 | + } |
| 533 | + |
| 534 | + @Specialization |
| 535 | + public ReprState dict(Object key, ReprState s, |
| 536 | + @Cached LookupAndCallUnaryDynamicNode reprKeyNode, |
| 537 | + @Cached LookupAndCallUnaryDynamicNode reprValueNode, |
| 538 | + @Cached CastToJavaStringNode castStr, |
| 539 | + @Cached PRaiseNode raiseNode, |
| 540 | + @Cached("createBinaryProfile()") ConditionProfile lengthCheck, |
| 541 | + @Cached("createBinaryProfile()") ConditionProfile nullKeyCheck, |
| 542 | + @Cached("createBinaryProfile()") ConditionProfile nullValueCheck, |
| 543 | + @CachedLibrary(limit = "getLimit()") HashingStorageLibrary lib) { |
544 | 544 | Object keyRepr = reprKeyNode.executeObject(key, __REPR__);
|
545 |
| - if (reprValueNode == null) { |
546 |
| - reprValueNode = insert(LookupAndCallUnaryDynamicNode.create()); |
547 |
| - } |
548 |
| - Object valueRepr = value != s.self ? reprValueNode.executeObject(value, __REPR__) : "{...}"; |
549 |
| - if (castStr == null) { |
550 |
| - castStr = insert(CastToJavaStringNodeGen.create()); |
551 |
| - } |
552 | 545 | String keyReprString = castStr.execute(keyRepr);
|
553 |
| - checkString(keyReprString); |
| 546 | + if (nullKeyCheck.profile(keyReprString == null)) { |
| 547 | + throw raiseNode.raise(PythonErrorType.TypeError, "__repr__ returned non-string (type %s)", keyRepr); |
| 548 | + } |
| 549 | + |
| 550 | + Object value = lib.getItem(s.dictStorage, key); |
| 551 | + Object valueRepr = value != s.dictStorage ? reprValueNode.executeObject(value, __REPR__) : "{...}"; |
554 | 552 | String valueReprString = castStr.execute(valueRepr);
|
555 |
| - checkString(valueReprString); |
| 553 | + if (nullValueCheck.profile(valueReprString == null)) { |
| 554 | + throw raiseNode.raise(PythonErrorType.TypeError, "__repr__ returned non-string (type %s)", valueRepr); |
| 555 | + } |
556 | 556 |
|
557 |
| - if (s.result.length() > 0) { |
| 557 | + // assuming '{' is inserted already |
| 558 | + if (lengthCheck.profile(s.result.length() > 1)) { |
558 | 559 | sbAppend(s.result, ", ");
|
559 | 560 | }
|
560 |
| - s.result.append(keyReprString).append(": ").append(valueReprString); |
| 561 | + sbAppend(s.result, keyReprString); |
| 562 | + sbAppend(s.result, ": "); |
| 563 | + sbAppend(s.result, valueReprString); |
561 | 564 | return s;
|
562 | 565 | }
|
563 | 566 |
|
564 |
| - private void checkString(Object strObj) { |
565 |
| - if (!(strObj instanceof String)) { |
566 |
| - if (raiseNode == null) { |
567 |
| - raiseNode = insert(PRaiseNode.create()); |
568 |
| - } |
569 |
| - throw raiseNode.raise(PythonErrorType.TypeError, "__repr__ returned non-string (type %s)", strObj); |
570 |
| - } |
571 |
| - } |
572 | 567 | }
|
573 | 568 |
|
574 | 569 | @Specialization(limit = "3") // use same limit as for EachRepr nodes library
|
575 | 570 | public Object repr(PDict self,
|
576 | 571 | @Cached("create(3)") EachRepr consumerNode,
|
577 | 572 | @CachedLibrary("self.getDictStorage()") HashingStorageLibrary lib) {
|
578 |
| - StringBuilder result = new StringBuilder(); |
579 |
| - sbAppend(result, "{"); |
| 573 | + StringBuilder keyValue = new StringBuilder("{"); |
580 | 574 | HashingStorage dictStorage = self.getDictStorage();
|
581 |
| - lib.forEach(dictStorage, consumerNode, new ReprState(self, dictStorage, result)); |
582 |
| - return sbAppend(result, "}").toString(); |
| 575 | + lib.forEach(dictStorage, consumerNode, new ReprState(dictStorage, keyValue)); |
| 576 | + return sbAppend(keyValue, "}").toString(); |
583 | 577 | }
|
584 | 578 |
|
585 | 579 | @TruffleBoundary
|
|
0 commit comments