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