27
27
package com .oracle .graal .python .builtins .objects .type ;
28
28
29
29
import static com .oracle .graal .python .builtins .objects .PNone .NO_VALUE ;
30
+ import static com .oracle .graal .python .builtins .objects .cext .structs .CFields .PyHeapTypeObject__ht_name ;
30
31
import static com .oracle .graal .python .builtins .objects .cext .structs .CFields .PyHeapTypeObject__ht_qualname ;
31
32
import static com .oracle .graal .python .builtins .objects .cext .structs .CFields .PyTypeObject__tp_name ;
32
33
import static com .oracle .graal .python .nodes .BuiltinNames .T_BUILTINS ;
54
55
import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___DOC__ ;
55
56
import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___MODULE__ ;
56
57
import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___NAME__ ;
58
+ import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___QUALNAME__ ;
57
59
import static com .oracle .graal .python .nodes .SpecialMethodNames .J_MRO ;
58
60
import static com .oracle .graal .python .nodes .SpecialMethodNames .J___CALL__ ;
59
61
import static com .oracle .graal .python .nodes .SpecialMethodNames .J___DIR__ ;
87
89
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
88
90
import com .oracle .graal .python .builtins .PythonBuiltins ;
89
91
import com .oracle .graal .python .builtins .modules .BuiltinConstructorsFactory ;
92
+ import com .oracle .graal .python .builtins .modules .SysModuleBuiltins ;
90
93
import com .oracle .graal .python .builtins .objects .PNone ;
91
94
import com .oracle .graal .python .builtins .objects .PNotImplemented ;
95
+ import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
92
96
import com .oracle .graal .python .builtins .objects .cext .PythonAbstractNativeObject ;
93
97
import com .oracle .graal .python .builtins .objects .cext .PythonNativeClass ;
98
+ import com .oracle .graal .python .builtins .objects .cext .capi .PySequenceArrayWrapper ;
94
99
import com .oracle .graal .python .builtins .objects .cext .structs .CFields ;
95
100
import com .oracle .graal .python .builtins .objects .cext .structs .CStructAccess ;
96
101
import com .oracle .graal .python .builtins .objects .common .DynamicObjectStorage ;
111
116
import com .oracle .graal .python .builtins .objects .object .ObjectNodes ;
112
117
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
113
118
import com .oracle .graal .python .builtins .objects .set .PSet ;
119
+ import com .oracle .graal .python .builtins .objects .str .PString ;
114
120
import com .oracle .graal .python .builtins .objects .str .StringUtils .SimpleTruffleStringFormatNode ;
115
121
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
116
122
import com .oracle .graal .python .builtins .objects .type .TpSlots .GetObjectSlotsNode ;
@@ -1045,7 +1051,29 @@ static PList getSubclasses(Object cls,
1045
1051
abstract static class AbstractSlotNode extends PythonBinaryBuiltinNode {
1046
1052
}
1047
1053
1048
- @ Builtin (name = J___NAME__ , minNumOfPositionalArgs = 1 , maxNumOfPositionalArgs = 2 , isGetter = true , isSetter = true )
1054
+ @ GenerateInline
1055
+ @ GenerateCached (false )
1056
+ static abstract class CheckSetSpecialTypeAttrNode extends Node {
1057
+ abstract void execute (Node inliningTarget , Object type , Object value , TruffleString name );
1058
+
1059
+ @ Specialization
1060
+ static void check (Node inliningTarget , Object type , Object value , TruffleString name ,
1061
+ @ Cached PRaiseNode .Lazy raiseNode ,
1062
+ @ Cached (inline = false ) GetTypeFlagsNode getTypeFlagsNode ,
1063
+ @ Cached SysModuleBuiltins .AuditNode auditNode ) {
1064
+ if (PGuards .isKindOfBuiltinClass (type ) || (getTypeFlagsNode .execute (type ) & TypeFlags .IMMUTABLETYPE ) != 0 ) {
1065
+ throw raiseNode .get (inliningTarget ).raise (TypeError , ErrorMessages .CANT_SET_ATTRIBUTE_S_OF_IMMUTABLE_TYPE_N , name , type );
1066
+ }
1067
+ if (value == DescriptorDeleteMarker .INSTANCE ) {
1068
+ // Sic, it's not immutable, but CPython has this message
1069
+ throw raiseNode .get (inliningTarget ).raise (TypeError , ErrorMessages .CANT_DELETE_ATTRIBUTE_S_OF_IMMUTABLE_TYPE_N , name , type );
1070
+ }
1071
+ auditNode .audit (inliningTarget , "object.__setattr__" , type , name , value );
1072
+ }
1073
+ }
1074
+
1075
+ @ Builtin (name = J___NAME__ , minNumOfPositionalArgs = 1 , maxNumOfPositionalArgs = 2 , isGetter = true , isSetter = true , //
1076
+ allowsDelete = true /* Delete handled by CheckSetSpecialTypeAttrNode */ )
1049
1077
abstract static class NameNode extends AbstractSlotNode {
1050
1078
@ Specialization (guards = "isNoValue(value)" )
1051
1079
static TruffleString getNameType (PythonBuiltinClassType cls , @ SuppressWarnings ("unused" ) PNone value ) {
@@ -1057,42 +1085,6 @@ static TruffleString getNameBuiltin(PythonManagedClass cls, @SuppressWarnings("u
1057
1085
return cls .getName ();
1058
1086
}
1059
1087
1060
- @ Specialization (guards = "!isNoValue(value)" )
1061
- static Object setName (@ SuppressWarnings ("unused" ) PythonBuiltinClassType cls , @ SuppressWarnings ("unused" ) Object value ,
1062
- @ Shared @ Cached PRaiseNode raiseNode ) {
1063
- throw raiseNode .raise (PythonErrorType .TypeError , ErrorMessages .CANT_SET_ATTRIBUTES_OF_TYPE , "built-in/extension 'type'" );
1064
- }
1065
-
1066
- @ Specialization (guards = "!isNoValue(value)" )
1067
- static Object setName (@ SuppressWarnings ("unused" ) PythonBuiltinClass cls , @ SuppressWarnings ("unused" ) Object value ,
1068
- @ Shared @ Cached PRaiseNode raiseNode ) {
1069
- throw raiseNode .raise (PythonErrorType .TypeError , ErrorMessages .CANT_SET_ATTRIBUTES_OF_TYPE , "built-in/extension 'type'" );
1070
- }
1071
-
1072
- @ Specialization (guards = {"!isNoValue(value)" , "!isPythonBuiltinClass(cls)" })
1073
- static Object setName (VirtualFrame frame , PythonClass cls , Object value ,
1074
- @ Bind ("this" ) Node inliningTarget ,
1075
- @ Exclusive @ Cached CastToTruffleStringNode castToTruffleStringNode ,
1076
- @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ,
1077
- @ Cached TruffleString .IsValidNode isValidNode ,
1078
- @ Shared ("cpLen" ) @ Cached TruffleString .CodePointLengthNode codePointLengthNode ,
1079
- @ Cached TruffleString .IndexOfCodePointNode indexOfCodePointNode ,
1080
- @ Cached PRaiseNode .Lazy raiseNode ) {
1081
- try {
1082
- TruffleString string = castToTruffleStringNode .execute (inliningTarget , value );
1083
- if (indexOfCodePointNode .execute (string , 0 , 0 , codePointLengthNode .execute (string , TS_ENCODING ), TS_ENCODING ) >= 0 ) {
1084
- throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .ValueError , ErrorMessages .TYPE_NAME_NO_NULL_CHARS );
1085
- }
1086
- if (!isValidNode .execute (string , TS_ENCODING )) {
1087
- throw constructAndRaiseNode .get (inliningTarget ).raiseUnicodeEncodeError (frame , "utf-8" , string , 0 , string .codePointLengthUncached (TS_ENCODING ), "can't encode classname" );
1088
- }
1089
- cls .setName (string );
1090
- return PNone .NONE ;
1091
- } catch (CannotCastException e ) {
1092
- throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .TypeError , ErrorMessages .CAN_ONLY_ASSIGN_S_TO_P_S_NOT_P , "string" , cls , T___NAME__ , value );
1093
- }
1094
- }
1095
-
1096
1088
@ Specialization (guards = "isNoValue(value)" )
1097
1089
static Object getName (PythonAbstractNativeObject cls , @ SuppressWarnings ("unused" ) PNone value ,
1098
1090
@ Cached CStructAccess .ReadCharPtrNode getTpNameNode ,
@@ -1109,10 +1101,59 @@ static Object getName(PythonAbstractNativeObject cls, @SuppressWarnings("unused"
1109
1101
return substringNode .execute (tpName , lastDot + 1 , nameLen - lastDot - 1 , TS_ENCODING , true );
1110
1102
}
1111
1103
1104
+ @ GenerateInline
1105
+ @ GenerateCached (false )
1106
+ abstract static class SetNameInnerNode extends Node {
1107
+ abstract void execute (Node inliningTarget , Object type , TruffleString value );
1108
+
1109
+ @ Specialization
1110
+ static void set (PythonClass type , TruffleString value ) {
1111
+ type .setName (value );
1112
+ }
1113
+
1114
+ @ Specialization
1115
+ static void set (PythonAbstractNativeObject type , TruffleString value ,
1116
+ @ Cached (inline = false ) CStructAccess .WritePointerNode writePointerNode ,
1117
+ @ Cached (inline = false ) CStructAccess .WriteObjectNewRefNode writeObject ,
1118
+ @ Cached (inline = false ) TruffleString .SwitchEncodingNode switchEncodingNode ,
1119
+ @ Cached (inline = false ) TruffleString .CopyToByteArrayNode copyToByteArrayNode ,
1120
+ @ Cached (inline = false ) PythonObjectFactory factory ) {
1121
+ value = switchEncodingNode .execute (value , TruffleString .Encoding .UTF_8 );
1122
+ byte [] bytes = copyToByteArrayNode .execute (value , TruffleString .Encoding .UTF_8 );
1123
+ PBytes bytesObject = factory .createBytes (bytes );
1124
+ writePointerNode .writeToObj (type , PyTypeObject__tp_name , PySequenceArrayWrapper .ensureNativeSequence (bytesObject ));
1125
+ PString pString = factory .createString (value );
1126
+ pString .setUtf8Bytes (bytesObject );
1127
+ writeObject .writeToObject (type , PyHeapTypeObject__ht_name , pString );
1128
+ }
1129
+ }
1130
+
1112
1131
@ Specialization (guards = "!isNoValue(value)" )
1113
- static Object getModule (@ SuppressWarnings ("unused" ) PythonAbstractNativeObject cls , @ SuppressWarnings ("unused" ) Object value ,
1114
- @ Shared @ Cached PRaiseNode raiseNode ) {
1115
- throw raiseNode .raise (PythonErrorType .RuntimeError , ErrorMessages .CANT_SET_ATTRIBUTES_OF_TYPE , "native type" );
1132
+ static Object setName (VirtualFrame frame , Object cls , Object value ,
1133
+ @ Bind ("this" ) Node inliningTarget ,
1134
+ @ Cached CheckSetSpecialTypeAttrNode check ,
1135
+ @ Exclusive @ Cached CastToTruffleStringNode castToTruffleStringNode ,
1136
+ @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ,
1137
+ @ Cached TruffleString .IsValidNode isValidNode ,
1138
+ @ Shared ("cpLen" ) @ Cached TruffleString .CodePointLengthNode codePointLengthNode ,
1139
+ @ Cached TruffleString .IndexOfCodePointNode indexOfCodePointNode ,
1140
+ @ Cached SetNameInnerNode innerNode ,
1141
+ @ Cached PRaiseNode .Lazy raiseNode ) {
1142
+ check .execute (inliningTarget , cls , value , T___NAME__ );
1143
+ TruffleString string ;
1144
+ try {
1145
+ string = castToTruffleStringNode .execute (inliningTarget , value );
1146
+ } catch (CannotCastException e ) {
1147
+ throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .TypeError , ErrorMessages .CAN_ONLY_ASSIGN_S_TO_P_S_NOT_P , "string" , cls , T___NAME__ , value );
1148
+ }
1149
+ if (indexOfCodePointNode .execute (string , 0 , 0 , codePointLengthNode .execute (string , TS_ENCODING ), TS_ENCODING ) >= 0 ) {
1150
+ throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .ValueError , ErrorMessages .TYPE_NAME_NO_NULL_CHARS );
1151
+ }
1152
+ if (!isValidNode .execute (string , TS_ENCODING )) {
1153
+ throw constructAndRaiseNode .get (inliningTarget ).raiseUnicodeEncodeError (frame , "utf-8" , string , 0 , string .codePointLengthUncached (TS_ENCODING ), "can't encode classname" );
1154
+ }
1155
+ innerNode .execute (inliningTarget , cls , string );
1156
+ return PNone .NONE ;
1116
1157
}
1117
1158
}
1118
1159
@@ -1205,7 +1246,8 @@ static Object setModuleBuiltin(@SuppressWarnings("unused") PythonBuiltinClass cl
1205
1246
}
1206
1247
}
1207
1248
1208
- @ Builtin (name = J___QUALNAME__ , minNumOfPositionalArgs = 1 , maxNumOfPositionalArgs = 2 , isGetter = true , isSetter = true )
1249
+ @ Builtin (name = J___QUALNAME__ , minNumOfPositionalArgs = 1 , maxNumOfPositionalArgs = 2 , isGetter = true , isSetter = true , //
1250
+ allowsDelete = true /* Delete handled by CheckSetSpecialTypeAttrNode */ )
1209
1251
abstract static class QualNameNode extends AbstractSlotNode {
1210
1252
@ Specialization (guards = "isNoValue(value)" )
1211
1253
static TruffleString getName (PythonBuiltinClassType cls , @ SuppressWarnings ("unused" ) PNone value ) {
@@ -1217,25 +1259,6 @@ static TruffleString getName(PythonManagedClass cls, @SuppressWarnings("unused")
1217
1259
return cls .getQualName ();
1218
1260
}
1219
1261
1220
- @ Specialization (guards = "!isNoValue(value)" )
1221
- static Object setName (@ SuppressWarnings ("unused" ) PythonBuiltinClass cls , @ SuppressWarnings ("unused" ) Object value ,
1222
- @ Shared @ Cached PRaiseNode raiseNode ) {
1223
- throw raiseNode .raise (PythonErrorType .TypeError , ErrorMessages .CANT_SET_ATTRIBUTES_OF_TYPE , "built-in/extension 'type'" );
1224
- }
1225
-
1226
- @ Specialization (guards = {"!isNoValue(value)" , "!isPythonBuiltinClass(cls)" })
1227
- static Object setName (PythonClass cls , Object value ,
1228
- @ Bind ("this" ) Node inliningTarget ,
1229
- @ Cached CastToTruffleStringNode castToStringNode ,
1230
- @ Cached PRaiseNode .Lazy raiseNode ) {
1231
- try {
1232
- cls .setQualName (castToStringNode .execute (inliningTarget , value ));
1233
- return PNone .NONE ;
1234
- } catch (CannotCastException e ) {
1235
- throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .TypeError , ErrorMessages .CAN_ONLY_ASSIGN_STR_TO_QUALNAME , cls , value );
1236
- }
1237
- }
1238
-
1239
1262
@ Specialization (guards = "isNoValue(value)" )
1240
1263
static Object getNative (PythonNativeClass cls , @ SuppressWarnings ("unused" ) PNone value ,
1241
1264
@ Cached GetTypeFlagsNode getTypeFlagsNode ,
@@ -1258,10 +1281,39 @@ static Object getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone
1258
1281
}
1259
1282
}
1260
1283
1284
+ @ GenerateInline
1285
+ @ GenerateCached (false )
1286
+ abstract static class SetQualNameInnerNode extends Node {
1287
+ abstract void execute (Node inliningTarget , Object type , TruffleString value );
1288
+
1289
+ @ Specialization
1290
+ static void set (PythonClass type , TruffleString value ) {
1291
+ type .setQualName (value );
1292
+ }
1293
+
1294
+ @ Specialization
1295
+ static void set (PythonAbstractNativeObject type , TruffleString value ,
1296
+ @ Cached (inline = false ) CStructAccess .WriteObjectNewRefNode writeObject ) {
1297
+ writeObject .writeToObject (type , PyHeapTypeObject__ht_qualname , value );
1298
+ }
1299
+ }
1300
+
1261
1301
@ Specialization (guards = "!isNoValue(value)" )
1262
- static Object setNative (@ SuppressWarnings ("unused" ) PythonNativeClass cls , @ SuppressWarnings ("unused" ) Object value ,
1263
- @ Shared @ Cached PRaiseNode raiseNode ) {
1264
- throw raiseNode .raise (PythonErrorType .RuntimeError , ErrorMessages .CANT_SET_ATTRIBUTES_OF_TYPE , "native type" );
1302
+ static Object setName (Object cls , Object value ,
1303
+ @ Bind ("this" ) Node inliningTarget ,
1304
+ @ Cached CheckSetSpecialTypeAttrNode check ,
1305
+ @ Cached CastToTruffleStringNode castToStringNode ,
1306
+ @ Cached SetQualNameInnerNode innerNode ,
1307
+ @ Cached PRaiseNode .Lazy raiseNode ) {
1308
+ check .execute (inliningTarget , cls , value , T___QUALNAME__ );
1309
+ TruffleString stringValue ;
1310
+ try {
1311
+ stringValue = castToStringNode .execute (inliningTarget , value );
1312
+ } catch (CannotCastException e ) {
1313
+ throw raiseNode .get (inliningTarget ).raise (PythonBuiltinClassType .TypeError , ErrorMessages .CAN_ONLY_ASSIGN_STR_TO_QUALNAME , cls , value );
1314
+ }
1315
+ innerNode .execute (inliningTarget , cls , stringValue );
1316
+ return PNone .NONE ;
1265
1317
}
1266
1318
}
1267
1319
0 commit comments