From 660aef67c4e7b598d98b7048784065922c7ab393 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Wed, 2 Apr 2014 12:22:07 +0100
Subject: [PATCH] py: Allow multiple of str/list/tuple on left by an integer.

---
 py/objint.c          | 19 +++++++++++++------
 py/objint_longlong.c |  8 ++++++++
 py/objint_mpz.c      |  9 ++++++++-
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/py/objint.c b/py/objint.c
index 27834b81f..3a853eab8 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <stdint.h>
 #include <assert.h>
 
@@ -9,6 +10,8 @@
 #include "parsenum.h"
 #include "mpz.h"
 #include "objint.h"
+#include "runtime0.h"
+#include "runtime.h"
 
 #if MICROPY_ENABLE_FLOAT
 #include <math.h>
@@ -59,16 +62,20 @@ void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
     }
 }
 
-// This is called only for non-SMALL_INT
+// This is called for operations on SMALL_INT that are not handled by mp_unary_op
 mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
-    assert(0);
-    return mp_const_none;
+    return MP_OBJ_NULL;
 }
 
-// This is called only for non-SMALL_INT
+// This is called for operations on SMALL_INT that are not handled by mp_binary_op
 mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    assert(0);
-    return mp_const_none;
+    if (op == MP_BINARY_OP_MULTIPLY) {
+        if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
+            // multiply is commutative for these types, so delegate to them
+            return mp_binary_op(op, rhs_in, lhs_in);
+        }
+    }
+    return MP_OBJ_NULL;
 }
 
 // This is called only with strings whose value doesn't fit in SMALL_INT
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index e64cc6734..acbd477a9 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -9,6 +9,7 @@
 #include "mpz.h"
 #include "objint.h"
 #include "runtime0.h"
+#include "runtime.h"
 
 #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
 
@@ -57,6 +58,13 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {
         rhs_val = ((mp_obj_int_t*)rhs_in)->val;
     } else {
+        if (op == MP_BINARY_OP_MULTIPLY) {
+            if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
+                // multiply is commutative for these types, so delegate to them
+                return mp_binary_op(op, rhs_in, lhs_in);
+            }
+        }
+        // unsupported operation/type
         return MP_OBJ_NULL;
     }
 
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 7f12fbcd0..27f77d14b 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -11,6 +11,7 @@
 #include "mpz.h"
 #include "objint.h"
 #include "runtime0.h"
+#include "runtime.h"
 
 #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
 
@@ -74,7 +75,13 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
         return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
 #endif
     } else {
-        // unsupported type
+        if (op == MP_BINARY_OP_MULTIPLY) {
+            if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
+                // multiply is commutative for these types, so delegate to them
+                return mp_binary_op(op, rhs_in, lhs_in);
+            }
+        }
+        // unsupported operation/type
         return MP_OBJ_NULL;
     }
 
-- 
GitLab