|
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