|
46 | 46 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
47 | 47 | import com.oracle.graal.python.builtins.objects.PNone;
|
48 | 48 | import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
|
| 49 | +import com.oracle.graal.python.builtins.objects.list.ListBuiltins; |
| 50 | +import com.oracle.graal.python.builtins.objects.list.PList; |
49 | 51 | import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
|
50 | 52 | import com.oracle.graal.python.builtins.objects.object.ObjectNodes;
|
| 53 | +import com.oracle.graal.python.builtins.objects.set.PSet; |
| 54 | +import com.oracle.graal.python.builtins.objects.set.SetNodes; |
51 | 55 | import com.oracle.graal.python.builtins.objects.type.TpSlots;
|
| 56 | +import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; |
52 | 57 | import com.oracle.graal.python.builtins.objects.type.slots.TpSlotGetAttr.GetAttrBuiltinNode;
|
53 | 58 | import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSetAttr.SetAttrBuiltinNode;
|
54 | 59 | import com.oracle.graal.python.nodes.ErrorMessages;
|
55 | 60 | import com.oracle.graal.python.nodes.PGuards;
|
56 | 61 | import com.oracle.graal.python.nodes.PRaiseNode;
|
57 | 62 | import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
|
| 63 | +import com.oracle.graal.python.nodes.builtins.ListNodes; |
58 | 64 | import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
|
59 | 65 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
60 | 66 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
|
|
68 | 74 | import com.oracle.graal.python.runtime.PythonOptions;
|
69 | 75 | import com.oracle.graal.python.runtime.exception.PException;
|
70 | 76 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
71 |
| -import com.oracle.graal.python.runtime.object.PFactory; |
72 | 77 | import com.oracle.truffle.api.CompilerDirectives;
|
73 | 78 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
74 | 79 | import com.oracle.truffle.api.dsl.Bind;
|
|
83 | 88 | import com.oracle.truffle.api.frame.VirtualFrame;
|
84 | 89 | import com.oracle.truffle.api.interop.ArityException;
|
85 | 90 | import com.oracle.truffle.api.interop.InteropLibrary;
|
| 91 | +import com.oracle.truffle.api.interop.InvalidArrayIndexException; |
86 | 92 | import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
87 | 93 | import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
88 | 94 | import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
@@ -268,29 +274,54 @@ static void doDelete(Object object, Object key, @SuppressWarnings("unused") PNon
|
268 | 274 | }
|
269 | 275 | }
|
270 | 276 |
|
271 |
| - // TODO dir(foreign) should list both foreign object members and attributes from class |
272 | 277 | @Builtin(name = J___DIR__, minNumOfPositionalArgs = 1)
|
273 | 278 | @GenerateNodeFactory
|
274 | 279 | abstract static class DirNode extends PythonUnaryBuiltinNode {
|
275 | 280 | @Specialization
|
276 |
| - protected Object doIt(Object object, |
| 281 | + protected Object doIt(VirtualFrame frame, Object object, |
277 | 282 | @Bind("this") Node inliningTarget,
|
278 | 283 | @CachedLibrary(limit = "3") InteropLibrary lib,
|
| 284 | + @CachedLibrary(limit = "3") InteropLibrary arrayInterop, |
| 285 | + @CachedLibrary(limit = "3") InteropLibrary stringInterop, |
| 286 | + @Cached TruffleString.SwitchEncodingNode switchEncodingNode, |
279 | 287 | @Cached GilNode gil,
|
280 |
| - @Cached InlinedConditionProfile profile) { |
| 288 | + @Cached InlinedConditionProfile profile, |
| 289 | + @Cached GetClassNode getClassNode, |
| 290 | + @Cached TypeBuiltins.DirNode typeDirNode, |
| 291 | + @Cached SetNodes.AddNode addNode, |
| 292 | + @Cached(inline = false) ListBuiltins.ListSortNode sortNode, |
| 293 | + @Cached(inline = false) ListNodes.ConstructListNode constructListNode) { |
| 294 | + // Inspired by ObjectBuiltins.DirNode |
| 295 | + var pythonClass = getClassNode.execute(inliningTarget, object); |
| 296 | + PSet attributes = typeDirNode.execute(frame, pythonClass); |
| 297 | + |
281 | 298 | if (profile.profile(inliningTarget, lib.hasMembers(object))) {
|
| 299 | + final Object members; |
282 | 300 | gil.release(true);
|
283 | 301 | try {
|
284 |
| - return lib.getMembers(object); |
| 302 | + members = lib.getMembers(object); |
285 | 303 | } catch (UnsupportedMessageException e) {
|
286 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
287 |
| - throw new IllegalStateException("foreign object claims to have members, but does not return them"); |
| 304 | + throw CompilerDirectives.shouldNotReachHere("foreign object claims to have members, but does not return them"); |
288 | 305 | } finally {
|
289 | 306 | gil.acquire();
|
290 | 307 | }
|
291 |
| - } else { |
292 |
| - return PFactory.createList(PythonLanguage.get(inliningTarget)); |
| 308 | + |
| 309 | + try { |
| 310 | + long size = arrayInterop.getArraySize(members); |
| 311 | + for (int i = 0; i < size; i++) { |
| 312 | + TruffleString memberString = stringInterop.asTruffleString(arrayInterop.readArrayElement(members, i)); |
| 313 | + memberString = switchEncodingNode.execute(memberString, TS_ENCODING); |
| 314 | + addNode.execute(frame, attributes, memberString); |
| 315 | + } |
| 316 | + } catch (UnsupportedMessageException | InvalidArrayIndexException e) { |
| 317 | + throw CompilerDirectives.shouldNotReachHere(e); |
| 318 | + } |
293 | 319 | }
|
| 320 | + |
| 321 | + // set to sorted list, like in PyObjectDir |
| 322 | + PList list = constructListNode.execute(frame, attributes); |
| 323 | + sortNode.execute(frame, list); |
| 324 | + return list; |
294 | 325 | }
|
295 | 326 | }
|
296 | 327 |
|
|
0 commit comments