Skip to content

Commit 7699831

Browse files
committed
ModuleBuiltins: add __dir__ builtin
1 parent 289ec81 commit 7699831

File tree

1 file changed

+60
-0
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module

1 file changed

+60
-0
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/ModuleBuiltins.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@
4646
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
4747
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__PACKAGE__;
4848
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SPEC__;
49+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DIR__;
4950
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
5051
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTR__;
5152
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT__;
5253
import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError;
5354

55+
import java.util.ArrayList;
56+
import java.util.Iterator;
5457
import java.util.List;
5558

5659
import com.oracle.graal.python.builtins.Builtin;
@@ -59,6 +62,9 @@
5962
import com.oracle.graal.python.builtins.PythonBuiltins;
6063
import com.oracle.graal.python.builtins.objects.PNone;
6164
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;
6268
import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
6369
import com.oracle.graal.python.builtins.objects.dict.PDict;
6470
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
@@ -71,6 +77,7 @@
7177
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7278
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
7379
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
80+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
7481
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
7582
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
7683
import com.oracle.graal.python.nodes.util.CannotCastException;
@@ -132,6 +139,59 @@ public PNone module(PythonModule self, String name, Object doc,
132139
}
133140
}
134141

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+
135195
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
136196
@GenerateNodeFactory
137197
public abstract static class ModuleDictNode extends PythonBinaryBuiltinNode {

0 commit comments

Comments
 (0)