3737import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
3838import static com .oracle .graal .python .nodes .SpecialMethodNames .__LT__ ;
3939import static com .oracle .graal .python .nodes .SpecialMethodNames .__MUL__ ;
40+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__IMUL__ ;
4041import static com .oracle .graal .python .nodes .SpecialMethodNames .__NE__ ;
4142import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
4243import static com .oracle .graal .python .nodes .SpecialMethodNames .__RMUL__ ;
@@ -1162,6 +1163,8 @@ protected boolean isNotSameStorage(PList left, PList right) {
11621163 @ Builtin (name = __MUL__ , fixedNumOfArguments = 2 )
11631164 @ GenerateNodeFactory
11641165 abstract static class MulNode extends PythonBuiltinNode {
1166+ public static String CANNOT_FIT_MESSAGE = "cannot fit 'int' into an index-sized integer" ;
1167+
11651168 @ Specialization
11661169 PList doPListInt (PList left , boolean right ,
11671170 @ Cached ("createClassProfile()" ) ValueProfile profile ) {
@@ -1184,7 +1187,7 @@ PList doPListBigInt(PList left, long right,
11841187 try {
11851188 return doPListInt (left , PInt .intValueExact (right ), profile );
11861189 } catch (ArithmeticException e ) {
1187- throw raise (OverflowError , "cannot fit 'int' into an index-sized integer" );
1190+ throw raise (OverflowError , CANNOT_FIT_MESSAGE );
11881191 }
11891192 }
11901193
@@ -1194,7 +1197,7 @@ PList doPListBigInt(PList left, PInt right,
11941197 try {
11951198 return doPListInt (left , right .intValueExact (), profile );
11961199 } catch (ArithmeticException | OutOfMemoryError e ) {
1197- throw raise (OverflowError , "cannot fit 'int' into an index-sized integer" );
1200+ throw raise (OverflowError , CANNOT_FIT_MESSAGE );
11981201 }
11991202 }
12001203
@@ -1205,6 +1208,257 @@ Object doGeneric(Object left, Object right) {
12051208 }
12061209 }
12071210
1211+ @ Builtin (name = __IMUL__ , fixedNumOfArguments = 2 )
1212+ @ GenerateNodeFactory
1213+ abstract static class IMulNode extends PythonBuiltinNode {
1214+
1215+ public abstract PList execute (PList list , Object value );
1216+
1217+ @ Specialization (guards = "isEmptyStorage(list)" )
1218+ PList doEmptyBoolean (PList list , @ SuppressWarnings ("unused" ) boolean right ) {
1219+ return list ;
1220+ }
1221+
1222+ @ Specialization (guards = "isEmptyStorage(list)" )
1223+ PList doEmptyInt (PList list , @ SuppressWarnings ("unused" ) int right ) {
1224+ return list ;
1225+ }
1226+
1227+ @ Specialization (guards = "isEmptyStorage(list)" )
1228+ PList doEmptyLong (PList list , long right ) {
1229+ try {
1230+ PInt .intValueExact (right );
1231+ return list ;
1232+ } catch (ArithmeticException e ) {
1233+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1234+ }
1235+ }
1236+
1237+ @ Specialization (guards = "isEmptyStorage(list)" )
1238+ PList doEmptyPInt (PList list , PInt right ) {
1239+ try {
1240+ right .intValueExact ();
1241+ return list ;
1242+ } catch (ArithmeticException e ) {
1243+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1244+ }
1245+ }
1246+
1247+ @ Specialization (guards = "isIntStorage(list)" )
1248+ PList doIntBoolean (PList list , boolean right ) {
1249+ return doIntInt (list , right ? 1 : 0 );
1250+ }
1251+
1252+ @ Specialization (guards = "isIntStorage(list)" )
1253+ PList doIntInt (PList list , int right ) {
1254+ IntSequenceStorage store = (IntSequenceStorage ) list .getSequenceStorage ();
1255+ if (right < 1 ) {
1256+ store .clear ();
1257+ return list ;
1258+ }
1259+ try {
1260+ IntSequenceStorage copy = (IntSequenceStorage ) store .copy ();
1261+ for (int i = 1 ; i < right ; i ++) {
1262+ store .extendWithIntStorage (copy );
1263+ }
1264+ return list ;
1265+ } catch (OutOfMemoryError e ) {
1266+ throw raise (MemoryError );
1267+ } catch (ArithmeticException e ) {
1268+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1269+ }
1270+ }
1271+
1272+ @ Specialization (guards = "isIntStorage(list)" )
1273+ PList doIntLong (PList list , long right ) {
1274+ try {
1275+ return doIntInt (list , PInt .intValueExact (right ));
1276+ } catch (ArithmeticException e ) {
1277+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1278+ }
1279+ }
1280+
1281+ @ Specialization (guards = "isIntStorage(list)" )
1282+ PList doIntPInt (PList list , PInt right ) {
1283+ try {
1284+ return doIntInt (list , right .intValueExact ());
1285+ } catch (ArithmeticException e ) {
1286+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1287+ }
1288+ }
1289+
1290+ @ Specialization (guards = "isLongStorage(list)" )
1291+ PList doLongBoolean (PList list , boolean right ) {
1292+ return doLongInt (list , right ? 1 : 0 );
1293+ }
1294+
1295+ @ Specialization (guards = "isLongStorage(list)" )
1296+ PList doLongInt (PList list , int right ) {
1297+ LongSequenceStorage store = (LongSequenceStorage ) list .getSequenceStorage ();
1298+ if (right < 1 ) {
1299+ store .clear ();
1300+ return list ;
1301+ }
1302+ try {
1303+ LongSequenceStorage copy = (LongSequenceStorage ) store .copy ();
1304+ for (int i = 1 ; i < right ; i ++) {
1305+ store .extendWithLongStorage (copy );
1306+ }
1307+ return list ;
1308+ } catch (OutOfMemoryError e ) {
1309+ throw raise (MemoryError );
1310+ } catch (ArithmeticException e ) {
1311+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1312+ }
1313+ }
1314+
1315+ @ Specialization (guards = "isLongStorage(list)" )
1316+ PList doLongLong (PList list , long right ) {
1317+ try {
1318+ return doLongInt (list , PInt .intValueExact (right ));
1319+ } catch (ArithmeticException e ) {
1320+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1321+ }
1322+ }
1323+
1324+ @ Specialization (guards = "isLongStorage(list)" )
1325+ PList doLongPInt (PList list , PInt right ) {
1326+ try {
1327+ return doLongInt (list , right .intValueExact ());
1328+ } catch (ArithmeticException e ) {
1329+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1330+ }
1331+ }
1332+
1333+ @ Specialization (guards = "isDoubleStorage(list)" )
1334+ PList doDoubleBoolean (PList list , boolean right ) {
1335+ return doDoubleInt (list , right ? 1 : 0 );
1336+ }
1337+
1338+ @ Specialization (guards = "isDoubleStorage(list)" )
1339+ PList doDoubleInt (PList list , int right ) {
1340+ DoubleSequenceStorage store = (DoubleSequenceStorage ) list .getSequenceStorage ();
1341+ if (right < 1 ) {
1342+ store .clear ();
1343+ return list ;
1344+ }
1345+ try {
1346+ DoubleSequenceStorage copy = (DoubleSequenceStorage ) store .copy ();
1347+ for (int i = 1 ; i < right ; i ++) {
1348+ store .extendWithDoubleStorage (copy );
1349+ }
1350+ return list ;
1351+ } catch (OutOfMemoryError e ) {
1352+ throw raise (MemoryError );
1353+ } catch (ArithmeticException e ) {
1354+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1355+ }
1356+ }
1357+
1358+ @ Specialization (guards = "isDoubleStorage(list)" )
1359+ PList doDoubleLong (PList list , long right ) {
1360+ try {
1361+ return doDoubleInt (list , PInt .intValueExact (right ));
1362+ } catch (ArithmeticException e ) {
1363+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1364+ }
1365+ }
1366+
1367+ @ Specialization (guards = "isDoubleStorage(list)" )
1368+ PList doDoublePInt (PList list , PInt right ) {
1369+ try {
1370+ return doLongInt (list , right .intValueExact ());
1371+ } catch (ArithmeticException e ) {
1372+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1373+ }
1374+ }
1375+
1376+ @ Specialization (guards = "isObjectStorage(list)" )
1377+ PList doObjectBoolean (PList list , boolean right ) {
1378+ return doDoubleInt (list , right ? 1 : 0 );
1379+ }
1380+
1381+ @ Specialization (guards = "isObjectStorage(list)" )
1382+ PList doObjectInt (PList list , int right ) {
1383+ ObjectSequenceStorage store = (ObjectSequenceStorage ) list .getSequenceStorage ();
1384+ if (right < 1 ) {
1385+ store .clear ();
1386+ return list ;
1387+ }
1388+ try {
1389+ ObjectSequenceStorage copy = (ObjectSequenceStorage ) store .copy ();
1390+ for (int i = 1 ; i < right ; i ++) {
1391+ store .extend (copy );
1392+ }
1393+ return list ;
1394+ } catch (OutOfMemoryError e ) {
1395+ throw raise (MemoryError );
1396+ } catch (ArithmeticException e ) {
1397+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1398+ }
1399+ }
1400+
1401+ @ Specialization (guards = "isObjectStorage(list)" )
1402+ PList doObjectLong (PList list , long right ) {
1403+ try {
1404+ return doObjectInt (list , PInt .intValueExact (right ));
1405+ } catch (ArithmeticException e ) {
1406+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1407+ }
1408+ }
1409+
1410+ @ Specialization (guards = "isObjectStorage(list)" )
1411+ PList doObjectPInt (PList list , PInt right ) {
1412+ try {
1413+ return doObjectInt (list , right .intValueExact ());
1414+ } catch (ArithmeticException e ) {
1415+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1416+ }
1417+ }
1418+
1419+ @ Specialization (guards = {"!isInt(right)" })
1420+ Object doGeneric (PList list , Object right ,
1421+ @ Cached ("create(__INDEX__)" ) LookupAndCallUnaryNode dispatchIndex ,
1422+ @ Cached ("createIMulNode()" ) IMulNode imulNode ) {
1423+ Object index = dispatchIndex .executeObject (right );
1424+ if (index != PNone .NO_VALUE ) {
1425+ int iIndex ;
1426+ try {
1427+ iIndex = convertToInt (index );
1428+ } catch (ArithmeticException e ) {
1429+ throw raise (OverflowError , "cannot fit '%p' into an index-sized integer" , index );
1430+ }
1431+
1432+ return imulNode .execute (list , iIndex );
1433+ }
1434+ throw raise (TypeError , "can't multiply sequence by non-int of type '%p'" , right );
1435+ }
1436+
1437+ private int convertToInt (Object value ) throws ArithmeticException {
1438+ if (value instanceof Integer ) {
1439+ return (Integer ) value ;
1440+ }
1441+ if (value instanceof Boolean ) {
1442+ return (Boolean ) value ? 0 : 1 ;
1443+ }
1444+ if (value instanceof Long ) {
1445+ return PInt .intValueExact ((Long ) value );
1446+ }
1447+ if (value instanceof PInt ) {
1448+ return ((PInt ) value ).intValueExact ();
1449+ }
1450+ throw raise (TypeError , "can't multiply sequence by non-int of type '%p'" , value );
1451+ }
1452+
1453+ protected IMulNode createIMulNode () {
1454+ return ListBuiltinsFactory .IMulNodeFactory .create (new PNode [0 ]);
1455+ }
1456+
1457+ protected boolean isInt (Object value ) {
1458+ return value instanceof Boolean || value instanceof Integer || value instanceof Long || value instanceof PInt ;
1459+ }
1460+ }
1461+
12081462 @ Builtin (name = __RMUL__ , fixedNumOfArguments = 2 )
12091463 @ GenerateNodeFactory
12101464 abstract static class RMulNode extends MulNode {
0 commit comments