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,249 @@ 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 , boolean right ) {
1219+ return list ;
1220+ }
1221+
1222+ @ Specialization (guards = "isEmptyStorage(list)" )
1223+ PList doEmptyInt (PList list , 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+ }
1268+ }
1269+
1270+ @ Specialization (guards = "isIntStorage(list)" )
1271+ PList doIntLong (PList list , long right ) {
1272+ try {
1273+ return doIntInt (list , PInt .intValueExact (right ));
1274+ } catch (ArithmeticException e ) {
1275+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1276+ }
1277+ }
1278+
1279+ @ Specialization (guards = "isIntStorage(list)" )
1280+ PList doIntPInt (PList list , PInt right ) {
1281+ try {
1282+ return doIntInt (list , right .intValueExact ());
1283+ } catch (ArithmeticException e ) {
1284+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1285+ }
1286+ }
1287+
1288+ @ Specialization (guards = "isLongStorage(list)" )
1289+ PList doLongBoolean (PList list , boolean right ) {
1290+ return doLongInt (list , right ? 1 : 0 );
1291+ }
1292+
1293+ @ Specialization (guards = "isLongStorage(list)" )
1294+ PList doLongInt (PList list , int right ) {
1295+ LongSequenceStorage store = (LongSequenceStorage ) list .getSequenceStorage ();
1296+ if (right < 1 ) {
1297+ store .clear ();
1298+ return list ;
1299+ }
1300+ try {
1301+ LongSequenceStorage copy = (LongSequenceStorage ) store .copy ();
1302+ for (int i = 1 ; i < right ; i ++) {
1303+ store .extendWithLongStorage (copy );
1304+ }
1305+ return list ;
1306+ } catch (OutOfMemoryError e ) {
1307+ throw raise (MemoryError );
1308+ }
1309+ }
1310+
1311+ @ Specialization (guards = "isLongStorage(list)" )
1312+ PList doLongLong (PList list , long right ) {
1313+ try {
1314+ return doLongInt (list , PInt .intValueExact (right ));
1315+ } catch (ArithmeticException e ) {
1316+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1317+ }
1318+ }
1319+
1320+ @ Specialization (guards = "isLongStorage(list)" )
1321+ PList doLongPInt (PList list , PInt right ) {
1322+ try {
1323+ return doLongInt (list , right .intValueExact ());
1324+ } catch (ArithmeticException e ) {
1325+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1326+ }
1327+ }
1328+
1329+ @ Specialization (guards = "isDoubleStorage(list)" )
1330+ PList doDoubleBoolean (PList list , boolean right ) {
1331+ return doDoubleInt (list , right ? 1 : 0 );
1332+ }
1333+
1334+ @ Specialization (guards = "isDoubleStorage(list)" )
1335+ PList doDoubleInt (PList list , int right ) {
1336+ DoubleSequenceStorage store = (DoubleSequenceStorage ) list .getSequenceStorage ();
1337+ if (right < 1 ) {
1338+ store .clear ();
1339+ return list ;
1340+ }
1341+ try {
1342+ DoubleSequenceStorage copy = (DoubleSequenceStorage ) store .copy ();
1343+ for (int i = 1 ; i < right ; i ++) {
1344+ store .extendWithDoubleStorage (copy );
1345+ }
1346+ return list ;
1347+ } catch (OutOfMemoryError e ) {
1348+ throw raise (MemoryError );
1349+ }
1350+ }
1351+
1352+ @ Specialization (guards = "isDoubleStorage(list)" )
1353+ PList doDoubleLong (PList list , long right ) {
1354+ try {
1355+ return doDoubleInt (list , PInt .intValueExact (right ));
1356+ } catch (ArithmeticException e ) {
1357+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1358+ }
1359+ }
1360+
1361+ @ Specialization (guards = "isDoubleStorage(list)" )
1362+ PList doDoublePInt (PList list , PInt right ) {
1363+ try {
1364+ return doLongInt (list , right .intValueExact ());
1365+ } catch (ArithmeticException e ) {
1366+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1367+ }
1368+ }
1369+
1370+ @ Specialization (guards = "isObjectStorage(list)" )
1371+ PList doObjectBoolean (PList list , boolean right ) {
1372+ return doDoubleInt (list , right ? 1 : 0 );
1373+ }
1374+
1375+ @ Specialization (guards = "isObjectStorage(list)" )
1376+ PList doObjectInt (PList list , int right ) {
1377+ ObjectSequenceStorage store = (ObjectSequenceStorage ) list .getSequenceStorage ();
1378+ if (right < 1 ) {
1379+ store .clear ();
1380+ return list ;
1381+ }
1382+ try {
1383+ ObjectSequenceStorage copy = (ObjectSequenceStorage ) store .copy ();
1384+ for (int i = 1 ; i < right ; i ++) {
1385+ store .extend (copy );
1386+ }
1387+ return list ;
1388+ } catch (OutOfMemoryError e ) {
1389+ throw raise (MemoryError );
1390+ }
1391+ }
1392+
1393+ @ Specialization (guards = "isObjectStorage(list)" )
1394+ PList doObjectLong (PList list , long right ) {
1395+ try {
1396+ return doObjectInt (list , PInt .intValueExact (right ));
1397+ } catch (ArithmeticException e ) {
1398+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1399+ }
1400+ }
1401+
1402+ @ Specialization (guards = "isObjectStorage(list)" )
1403+ PList doObjectPInt (PList list , PInt right ) {
1404+ try {
1405+ return doObjectInt (list , right .intValueExact ());
1406+ } catch (ArithmeticException e ) {
1407+ throw raise (OverflowError , MulNode .CANNOT_FIT_MESSAGE );
1408+ }
1409+ }
1410+
1411+ @ Specialization (guards = {"!isInt(right)" })
1412+ Object doGeneric (PList list , Object right ,
1413+ @ Cached ("create(__INDEX__)" ) LookupAndCallUnaryNode dispatchIndex ,
1414+ @ Cached ("createIMulNode()" ) IMulNode imulNode ) {
1415+ Object index = dispatchIndex .executeObject (right );
1416+ if (index != PNone .NO_VALUE ) {
1417+ int iIndex ;
1418+ try {
1419+ iIndex = convertToInt (index );
1420+ } catch (ArithmeticException e ) {
1421+ throw raise (OverflowError , "cannot fit '%p' into an index-sized integer" , index );
1422+ }
1423+
1424+ return imulNode .execute (list , iIndex );
1425+ }
1426+ throw raise (TypeError , "can't multiply sequence by non-int of type '%p'" , right );
1427+ }
1428+
1429+ private int convertToInt (Object value ) throws ArithmeticException {
1430+ if (value instanceof Integer ) {
1431+ return (Integer ) value ;
1432+ }
1433+ if (value instanceof Boolean ) {
1434+ return (Boolean ) value ? 0 : 1 ;
1435+ }
1436+ if (value instanceof Long ) {
1437+ return PInt .intValueExact ((Long ) value );
1438+ }
1439+ if (value instanceof PInt ) {
1440+ return ((PInt ) value ).intValueExact ();
1441+ }
1442+ throw raise (TypeError , "can't multiply sequence by non-int of type '%p'" , value );
1443+ }
1444+
1445+ protected IMulNode createIMulNode () {
1446+ return ListBuiltinsFactory .IMulNodeFactory .create (new PNode [0 ]);
1447+ }
1448+
1449+ protected boolean isInt (Object value ) {
1450+ return value instanceof Boolean || value instanceof Integer || value instanceof Long || value instanceof PInt ;
1451+ }
1452+ }
1453+
12081454 @ Builtin (name = __RMUL__ , fixedNumOfArguments = 2 )
12091455 @ GenerateNodeFactory
12101456 abstract static class RMulNode extends MulNode {
0 commit comments