|
40 | 40 | */
|
41 | 41 | package com.oracle.graal.python.lib;
|
42 | 42 |
|
43 |
| -import com.oracle.graal.python.builtins.objects.function.PArguments; |
44 |
| -import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary; |
| 43 | +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError; |
| 44 | +import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__; |
| 45 | + |
| 46 | +import com.oracle.graal.python.builtins.PythonBuiltinClassType; |
| 47 | +import com.oracle.graal.python.builtins.objects.PNone; |
45 | 48 | import com.oracle.graal.python.builtins.objects.str.PString;
|
| 49 | +import com.oracle.graal.python.nodes.ErrorMessages; |
46 | 50 | import com.oracle.graal.python.nodes.PNodeWithContext;
|
| 51 | +import com.oracle.graal.python.nodes.PRaiseNode; |
| 52 | +import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode; |
| 53 | +import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodNode; |
| 54 | +import com.oracle.graal.python.nodes.classes.IsSubtypeNode; |
| 55 | +import com.oracle.graal.python.nodes.object.GetClassNode; |
47 | 56 | import com.oracle.truffle.api.dsl.Cached;
|
48 | 57 | import com.oracle.truffle.api.dsl.GenerateUncached;
|
49 | 58 | import com.oracle.truffle.api.dsl.Specialization;
|
50 | 59 | import com.oracle.truffle.api.frame.Frame;
|
51 | 60 | import com.oracle.truffle.api.frame.VirtualFrame;
|
52 |
| -import com.oracle.truffle.api.library.CachedLibrary; |
53 |
| -import com.oracle.truffle.api.profiles.ConditionProfile; |
54 | 61 |
|
55 | 62 | /**
|
56 | 63 | * Equivalent of CPython's {@code PyObject_Str}. Converts object to a string using its
|
57 |
| - * {@code __str__} special method. Falls back to calling {@link PyObjectReprAsObjectNode} on the |
58 |
| - * value. |
| 64 | + * {@code __str__} special method. |
59 | 65 | * <p>
|
60 | 66 | * The output can be either a {@link String} or a {@link PString}.
|
61 | 67 | *
|
|
65 | 71 | public abstract class PyObjectStrAsObjectNode extends PNodeWithContext {
|
66 | 72 | public abstract Object execute(Frame frame, Object object);
|
67 | 73 |
|
68 |
| - @Specialization(limit = "3") |
| 74 | + @Specialization |
| 75 | + static Object str(String obj) { |
| 76 | + return obj; |
| 77 | + } |
| 78 | + |
| 79 | + @Specialization(guards = "!isJavaString(obj)") |
69 | 80 | static Object str(VirtualFrame frame, Object obj,
|
70 |
| - @Cached ConditionProfile gotState, |
71 |
| - @CachedLibrary("obj") PythonObjectLibrary objLib) { |
72 |
| - if (gotState.profile(frame != null)) { |
73 |
| - return objLib.asPStringWithState(obj, PArguments.getThreadState(frame)); |
| 81 | + @Cached GetClassNode getClassNode, |
| 82 | + @Cached LookupSpecialMethodNode.Dynamic lookupStr, |
| 83 | + @Cached CallUnaryMethodNode callStr, |
| 84 | + @Cached GetClassNode getResultClassNode, |
| 85 | + @Cached IsSubtypeNode isSubtypeNode, |
| 86 | + @Cached PRaiseNode raiseNode) { |
| 87 | + Object type = getClassNode.execute(obj); |
| 88 | + Object strDescr = lookupStr.execute(frame, type, __STR__, obj, false); |
| 89 | + // All our objects should have __str__ |
| 90 | + assert strDescr != PNone.NONE; |
| 91 | + Object result = callStr.executeObject(frame, strDescr, obj); |
| 92 | + if (result instanceof String || isSubtypeNode.execute(getResultClassNode.execute(result), PythonBuiltinClassType.PString)) { |
| 93 | + return result; |
74 | 94 | } else {
|
75 |
| - return objLib.asPString(obj); |
| 95 | + throw raiseNode.raise(TypeError, ErrorMessages.RETURNED_NON_STRING, __STR__, result); |
76 | 96 | }
|
77 | 97 | }
|
78 | 98 |
|
|
0 commit comments