43
43
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .AttributeError ;
44
44
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
45
45
import static com .oracle .graal .python .nodes .SpecialMethodNames .FILENO ;
46
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .ITEMS ;
47
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .KEYS ;
48
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .VALUES ;
46
49
import static com .oracle .graal .python .nodes .SpecialMethodNames .__BOOL__ ;
47
50
import static com .oracle .graal .python .nodes .SpecialMethodNames .__CALL__ ;
48
51
import static com .oracle .graal .python .nodes .SpecialMethodNames .__DELETE__ ;
136
139
import com .oracle .graal .python .runtime .exception .PException ;
137
140
import com .oracle .graal .python .util .OverflowException ;
138
141
import com .oracle .truffle .api .CompilerDirectives ;
139
- import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
140
142
import com .oracle .truffle .api .TruffleLanguage ;
143
+ import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
141
144
import com .oracle .truffle .api .dsl .Cached ;
142
- import com .oracle .truffle .api .dsl .Cached .Exclusive ;
143
- import com .oracle .truffle .api .dsl .Cached .Shared ;
144
145
import com .oracle .truffle .api .dsl .CachedContext ;
145
146
import com .oracle .truffle .api .dsl .GenerateUncached ;
146
147
import com .oracle .truffle .api .dsl .ImportStatic ;
147
148
import com .oracle .truffle .api .dsl .ReportPolymorphism ;
148
149
import com .oracle .truffle .api .dsl .Specialization ;
150
+ import com .oracle .truffle .api .dsl .Cached .Exclusive ;
151
+ import com .oracle .truffle .api .dsl .Cached .Shared ;
149
152
import com .oracle .truffle .api .interop .ArityException ;
150
153
import com .oracle .truffle .api .interop .InteropLibrary ;
151
154
import com .oracle .truffle .api .interop .InvalidArrayIndexException ;
@@ -192,6 +195,21 @@ public final void clearNativeWrapper(ConditionProfile hasHandleValidAssumptionPr
192
195
nativeWrapper = null ;
193
196
}
194
197
198
+ /**
199
+ * Checks if the object is a Mapping as described in the
200
+ * <a href="https://docs.python.org/3/reference/datamodel.html">Python Data Model</a>. Mappings
201
+ * are treated differently to other containers in some interop messages.
202
+ */
203
+ private static boolean isAbstractMapping (Object receiver , PythonObjectLibrary lib ) {
204
+ return lib .isSequence (receiver ) && lib .lookupAttribute (receiver , KEYS , true ) != PNone .NO_VALUE && //
205
+ lib .lookupAttribute (receiver , ITEMS , true ) != PNone .NO_VALUE && //
206
+ lib .lookupAttribute (receiver , VALUES , true ) != PNone .NO_VALUE ;
207
+ }
208
+
209
+ private boolean isAbstractMapping (PythonObjectLibrary thisLib ) {
210
+ return isAbstractMapping (this , thisLib );
211
+ }
212
+
195
213
@ ExportMessage
196
214
public void writeMember (String key , Object value ,
197
215
@ Exclusive @ Cached PInteropSubscriptAssignNode setItemNode ,
@@ -219,7 +237,7 @@ public void writeMember(String key, Object value,
219
237
return ;
220
238
}
221
239
}
222
- if (dataModelLibrary . isMapping ( this )) {
240
+ if (isAbstractMapping ( dataModelLibrary )) {
223
241
setItemNode .execute (this , key , value );
224
242
} else {
225
243
writeNode .execute (this , key , value );
@@ -278,7 +296,7 @@ public Object readMember(String key,
278
296
@ ExportMessage
279
297
public boolean hasArrayElements (
280
298
@ CachedLibrary ("this" ) PythonObjectLibrary dataModelLibrary ) {
281
- return dataModelLibrary .isSequence (this ) && !dataModelLibrary . isMapping ( this );
299
+ return dataModelLibrary .isSequence (this ) && !isAbstractMapping ( dataModelLibrary );
282
300
}
283
301
284
302
@ ExportMessage
@@ -290,7 +308,7 @@ public Object readArrayElement(long key,
290
308
try {
291
309
return toForeign .executeConvert (getItemNode .execute (this , key ));
292
310
} catch (PException e ) {
293
- if (dataModelLibrary . isMapping ( this )) {
311
+ if (isAbstractMapping ( dataModelLibrary )) {
294
312
throw UnsupportedMessageException .create ();
295
313
} else {
296
314
// TODO(fa) refine exception handling
@@ -505,8 +523,8 @@ public Object getMembers(boolean includeInternal,
505
523
}
506
524
if (includeInternal ) {
507
525
// we use the internal flag to also return dictionary keys for mappings
508
- if (dataModelLibrary . isMapping ( this )) {
509
- PList mapKeys = castToList .executeWithGlobalState (keysNode .executeObject (this , SpecialMethodNames . KEYS ));
526
+ if (isAbstractMapping ( dataModelLibrary )) {
527
+ PList mapKeys = castToList .executeWithGlobalState (keysNode .executeObject (this , KEYS ));
510
528
int len = lenNode .execute (mapKeys );
511
529
for (int i = 0 ; i < len ; i ++) {
512
530
Object key = getItemNode .execute (mapKeys , i );
@@ -550,7 +568,7 @@ public void removeMember(String member,
550
568
return ;
551
569
}
552
570
}
553
- if (dataModelLibrary . isMapping ( this ) && getDelItemNode .execute (this , __DELITEM__ ) != PNone .NO_VALUE ) {
571
+ if (isAbstractMapping ( dataModelLibrary ) && getDelItemNode .execute (this , __DELITEM__ ) != PNone .NO_VALUE ) {
554
572
delItemNode .execute (this , member );
555
573
} else {
556
574
deleteAttributeNode .execute (this , member );
@@ -645,9 +663,9 @@ public boolean isMapping(@CachedLibrary("this") PythonObjectLibrary plib,
645
663
public boolean isSequenceType (
646
664
@ CachedLibrary ("this" ) PythonObjectLibrary lib ,
647
665
@ Shared ("hasGetItemNode" ) @ Cached LookupAttributeInMRONode .Dynamic hasGetItemNode ,
648
- @ Shared ( "hasLenNode" ) @ Cached LookupAttributeInMRONode .Dynamic hasLenNode ,
666
+ @ Exclusive @ Cached LookupAttributeInMRONode .Dynamic hasLenNode ,
649
667
@ Shared ("isLazyClass" ) @ Cached ("createBinaryProfile()" ) ConditionProfile isLazyClass ,
650
- @ Shared ( "lenProfile" ) @ Cached ("createBinaryProfile()" ) ConditionProfile lenProfile ,
668
+ @ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile lenProfile ,
651
669
@ Shared ("getItemProfile" ) @ Cached ("createBinaryProfile()" ) ConditionProfile getItemProfile ) {
652
670
if (isLazyClass .profile (lib .isLazyPythonClass (this ))) {
653
671
if (lenProfile .profile (hasLenNode .execute (this , __LEN__ ) != PNone .NO_VALUE )) {
@@ -661,18 +679,10 @@ public boolean isSequenceType(
661
679
public boolean isMappingType (
662
680
@ CachedLibrary ("this" ) PythonObjectLibrary lib ,
663
681
@ Shared ("hasGetItemNode" ) @ Cached LookupAttributeInMRONode .Dynamic hasGetItemNode ,
664
- @ Shared ("hasLenNode" ) @ Cached LookupAttributeInMRONode .Dynamic hasLenNode ,
665
682
@ Shared ("isLazyClass" ) @ Cached ("createBinaryProfile()" ) ConditionProfile isLazyClass ,
666
- @ Shared ("lenProfile" ) @ Cached ("createBinaryProfile()" ) ConditionProfile lenProfile ,
667
- @ Shared ("getItemProfile" ) @ Cached ("createBinaryProfile()" ) ConditionProfile getItemProfile ,
668
- @ Exclusive @ Cached LookupAttributeInMRONode .Dynamic hasKeysNode ,
669
- @ Exclusive @ Cached LookupAttributeInMRONode .Dynamic hasItemsNode ,
670
- @ Exclusive @ Cached LookupAttributeInMRONode .Dynamic hasValuesNode ,
671
- @ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile profile ) {
672
- if (isSequenceType (lib , hasGetItemNode , hasLenNode , isLazyClass , lenProfile , getItemProfile )) {
673
- return profile .profile (hasKeysNode .execute (this , SpecialMethodNames .KEYS ) != PNone .NO_VALUE &&
674
- hasItemsNode .execute (this , SpecialMethodNames .ITEMS ) != PNone .NO_VALUE &&
675
- hasValuesNode .execute (this , SpecialMethodNames .VALUES ) != PNone .NO_VALUE );
683
+ @ Shared ("getItemProfile" ) @ Cached ("createBinaryProfile()" ) ConditionProfile getItemProfile ) {
684
+ if (isLazyClass .profile (lib .isLazyPythonClass (this ))) {
685
+ return getItemProfile .profile (hasGetItemNode .execute (this , __GETITEM__ ) != PNone .NO_VALUE );
676
686
}
677
687
return false ;
678
688
}
@@ -1505,7 +1515,7 @@ int access(Object object, String fieldName,
1505
1515
info |= REMOVABLE ;
1506
1516
info |= MODIFIABLE ;
1507
1517
}
1508
- } else if (!isImmutable .execute (object ) || dataModelLibrary . isMapping (object )) {
1518
+ } else if (!isImmutable .execute (object ) || isAbstractMapping (object , dataModelLibrary )) {
1509
1519
// If the member does not exist yet, it is insertable if this object is mutable,
1510
1520
// i.e., it's not a builtin object or it is a mapping.
1511
1521
info |= INSERTABLE ;
0 commit comments