Skip to content

Commit 44a114d

Browse files
committed
add length message
1 parent 3d5558e commit 44a114d

File tree

5 files changed

+87
-1
lines changed

5 files changed

+87
-1
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,36 @@ public boolean isSequence(@Shared("thisObject") @Cached GetLazyClassNode getClas
590590
return pythonTypeLibrary.isSequenceType(getClassNode.execute(this));
591591
}
592592

593+
@ExportMessage
594+
public int lengthWithState(ThreadState state,
595+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile gotState,
596+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile hasLen,
597+
@Exclusive @Cached("createBinaryProfile()") ConditionProfile ltZero,
598+
@Exclusive @Cached LookupInheritedAttributeNode.Dynamic getLenNode,
599+
@Exclusive @Cached CallNode callNode,
600+
@Exclusive @Cached PRaiseNode raiseNode,
601+
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
602+
Object lenFunc = getLenNode.execute(this, SpecialMethodNames.__LEN__);
603+
if (hasLen.profile(lenFunc != PNone.NO_VALUE)) {
604+
Object lenResult;
605+
int len;
606+
if (gotState.profile(state == null)) {
607+
lenResult = callNode.execute(lenFunc, this);
608+
len = lib.asSize(lenResult);
609+
} else {
610+
lenResult = callNode.execute(PArguments.frameForCall(state), lenFunc, this);
611+
len = lib.asSizeWithState(lenResult, state);
612+
}
613+
if (ltZero.profile(len < 0)) {
614+
throw raiseNode.raise(PythonBuiltinClassType.ValueError, "__len__() should return >= 0");
615+
} else {
616+
return len;
617+
}
618+
} else {
619+
throw raiseNode.raiseHasNoLength(this);
620+
}
621+
}
622+
593623
@ExportMessage
594624
public boolean isMapping(@Shared("thisObject") @Cached GetLazyClassNode getClassNode,
595625
@CachedLibrary(limit = "1") PythonObjectLibrary pythonTypeLibrary) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonObjectExports.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static Object asIndex(Object receiver,
9292
@ExportMessage
9393
static int asSize(Object receiver, LazyPythonClass type,
9494
@Shared("raiseNode") @Cached PRaiseNode raise,
95-
@CachedLibrary("receiver") InteropLibrary interopLib) {
95+
@CachedLibrary(limit = "2") InteropLibrary interopLib) {
9696
Object index = asIndex(receiver, raise, interopLib);
9797
if (interopLib.fitsInInt(index)) {
9898
try {
@@ -116,4 +116,26 @@ static LazyPythonClass getLazyPythonClass(@SuppressWarnings("unused") Object val
116116
static long hash(Object receiver) {
117117
return receiver.hashCode();
118118
}
119+
120+
@ExportMessage
121+
static int length(Object receiver,
122+
@Shared("raiseNode") @Cached PRaiseNode raise,
123+
@CachedLibrary("receiver") InteropLibrary interopLib) {
124+
if (interopLib.hasArrayElements(receiver)) {
125+
long sz;
126+
try {
127+
sz = interopLib.getArraySize(receiver);
128+
} catch (UnsupportedMessageException e) {
129+
CompilerDirectives.transferToInterpreter();
130+
throw new IllegalStateException(e);
131+
}
132+
if (sz == (int) sz) {
133+
return (int) sz;
134+
} else {
135+
throw raise.raiseNumberTooLarge(PythonBuiltinClassType.OverflowError, sz);
136+
}
137+
} else {
138+
throw raise.raiseHasNoLength(receiver);
139+
}
140+
}
119141
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonStringExports.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,9 @@ static byte[] getBufferBytes(String str) {
8484
static long hash(String self) {
8585
return self.hashCode();
8686
}
87+
88+
@ExportMessage
89+
static int length(String self) {
90+
return self.length();
91+
}
8792
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObjectLibrary.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,31 @@ public boolean isSequence(Object receiver) {
315315
return false;
316316
}
317317

318+
319+
/**
320+
* Implements the logic from {@code PyObject_Size} (to which {@code
321+
* PySequence_Length} is an alias). The logic which is to try a) {@code
322+
* sq_length} and b) {@code mp_length}. Each of these can also be reached
323+
* via {@code PySequence_Length} or {@code PyMapping_Length}, respectively.
324+
*
325+
* The implementation for {@code slot_sq_length} is to call {@code __len__}
326+
* and then to convert it to an index and a size, making sure it's
327+
* >=0. {@code slot_mp_length} is just an alias for that slot.
328+
*/
329+
public int lengthWithState(Object receiver, ThreadState state) {
330+
if (state == null) {
331+
throw PRaiseNode.getUncached().raiseHasNoLength(receiver);
332+
}
333+
return length(receiver);
334+
}
335+
336+
/**
337+
* @see #lengthWithState
338+
*/
339+
public int length(Object receiver) {
340+
return lengthWithState(receiver, null);
341+
}
342+
318343
/**
319344
* Checks whether the receiver is a Python mapping. As described in the
320345
* <a href="https://docs.python.org/3/reference/datamodel.html">Python Data Model</a> and

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PRaiseNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ public final PException raiseNumberTooLarge(LazyPythonClass type, Object result)
8484
return execute(type, PNone.NO_VALUE, "cannot fit '%p' into an index-sized integer", new Object[]{result});
8585
}
8686

87+
public final PException raiseHasNoLength(Object result) {
88+
return raise(PythonBuiltinClassType.TypeError, "object of type '%p' has no len()", result);
89+
}
90+
8791
public final PException raiseIntegerInterpretationError(Object result) {
8892
return raise(PythonBuiltinClassType.TypeError, "'%p' object cannot be interpreted as an integer", result);
8993
}

0 commit comments

Comments
 (0)