|
46 | 46 | import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
|
47 | 47 | import static com.oracle.graal.python.nodes.SpecialAttributeNames.__PACKAGE__;
|
48 | 48 | import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SPEC__;
|
| 49 | +import static com.oracle.graal.python.nodes.SpecialMethodNames.__DIR__; |
49 | 50 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
|
50 | 51 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTR__;
|
51 | 52 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT__;
|
52 | 53 | import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError;
|
53 | 54 |
|
| 55 | +import java.util.ArrayList; |
| 56 | +import java.util.Iterator; |
54 | 57 | import java.util.List;
|
55 | 58 |
|
56 | 59 | import com.oracle.graal.python.builtins.Builtin;
|
|
59 | 62 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
60 | 63 | import com.oracle.graal.python.builtins.objects.PNone;
|
61 | 64 | import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
|
| 65 | +import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; |
| 66 | +import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
| 67 | +import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary; |
62 | 68 | import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
|
63 | 69 | import com.oracle.graal.python.builtins.objects.dict.PDict;
|
64 | 70 | import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
|
|
71 | 77 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
72 | 78 | import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
|
73 | 79 | import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
|
| 80 | +import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; |
74 | 81 | import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
|
75 | 82 | import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
|
76 | 83 | import com.oracle.graal.python.nodes.util.CannotCastException;
|
@@ -132,6 +139,59 @@ public PNone module(PythonModule self, String name, Object doc,
|
132 | 139 | }
|
133 | 140 | }
|
134 | 141 |
|
| 142 | + @Builtin(name = __DIR__, minNumOfPositionalArgs = 1, declaresExplicitSelf = true) |
| 143 | + @GenerateNodeFactory |
| 144 | + public abstract static class ModuleDirNode extends PythonUnaryBuiltinNode { |
| 145 | + @Specialization |
| 146 | + Object dir(PythonModule self, |
| 147 | + @Cached CastToJavaStringNode castToJavaStringNode, |
| 148 | + @Cached IsBuiltinClassProfile isDictProfile, |
| 149 | + @Cached HashingCollectionNodes.GetDictStorageNode getDictStorageNode, |
| 150 | + @Cached CallNode callNode, |
| 151 | + @CachedLibrary(limit = "1") HashingStorageLibrary hashLib, |
| 152 | + @CachedLibrary(limit = "1") PythonObjectLibrary pol) { |
| 153 | + Object dict = pol.lookupAttribute(self, __DICT__); |
| 154 | + if (isDict(dict, isDictProfile)) { |
| 155 | + HashingStorage dictStorage = getDictStorageNode.execute((PHashingCollection) dict); |
| 156 | + Object dirFunc = hashLib.getItem(dictStorage, __DIR__); |
| 157 | + if (dirFunc != null) { |
| 158 | + return callNode.execute(dirFunc); |
| 159 | + } else { |
| 160 | + return factory().createList(exhaustIterator(hashLib.keys(dictStorage))); |
| 161 | + } |
| 162 | + } else { |
| 163 | + String name = getName(self, pol, hashLib, castToJavaStringNode); |
| 164 | + throw this.raise(PythonBuiltinClassType.TypeError, "%s.__dict__ is not a dictionary", name); |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | + private static <T> Object[] exhaustIterator(Iterable<T> iterable) { |
| 169 | + return exhaustIterator(iterable.iterator()); |
| 170 | + } |
| 171 | + |
| 172 | + @CompilerDirectives.TruffleBoundary |
| 173 | + private static <T> Object[] exhaustIterator(Iterator<T> iterator) { |
| 174 | + ArrayList<T> values = new ArrayList<>(); |
| 175 | + iterator.forEachRemaining(values::add); |
| 176 | + return values.toArray(); |
| 177 | + } |
| 178 | + |
| 179 | + private String getName(PythonModule self, PythonObjectLibrary pol, HashingStorageLibrary hashLib, CastToJavaStringNode castToJavaStringNode) { |
| 180 | + PHashingCollection dict = pol.getDict(self); |
| 181 | + if (dict != null) { |
| 182 | + Object name = hashLib.getItem(dict.getDictStorage(), __NAME__); |
| 183 | + if (name != null) { |
| 184 | + return castToJavaStringNode.execute(name); |
| 185 | + } |
| 186 | + } |
| 187 | + throw raise(PythonBuiltinClassType.SystemError, "nameless module"); |
| 188 | + } |
| 189 | + |
| 190 | + protected static boolean isDict(Object object, IsBuiltinClassProfile profile) { |
| 191 | + return profile.profileObject(object, PythonBuiltinClassType.PDict); |
| 192 | + } |
| 193 | + } |
| 194 | + |
135 | 195 | @Builtin(name = __DICT__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
|
136 | 196 | @GenerateNodeFactory
|
137 | 197 | public abstract static class ModuleDictNode extends PythonBinaryBuiltinNode {
|
|
0 commit comments