py: Factor out impl of special methods for builtin types into opmethods.c
diff --git a/py/builtin.h b/py/builtin.h
index a298444..2159b71 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -35,6 +35,9 @@
 
 MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
 
+MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj);
+
 extern const mp_obj_module_t mp_module___main__;
 extern const mp_obj_module_t mp_module_array;
 extern const mp_obj_module_t mp_module_collections;
diff --git a/py/objdict.c b/py/objdict.c
index 8bdd002..2c56540 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -10,6 +10,7 @@
 #include "objtuple.h"
 #include "runtime0.h"
 #include "runtime.h"
+#include "builtin.h"
 
 STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
 STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
@@ -137,12 +138,6 @@
     return true;
 }
 
-STATIC mp_obj_t dict_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    return dict_binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(dict_getitem_obj, dict_getitem);
-
 /******************************************************************************/
 /* dict iterator                                                              */
 
@@ -501,7 +496,7 @@
     { MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj },
-    { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&dict_getitem_obj },
+    { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&mp_op_getitem_obj },
 };
 
 STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
diff --git a/py/objset.c b/py/objset.c
index 8ff12ba..bdc8d7f 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -9,6 +9,7 @@
 #include "obj.h"
 #include "runtime.h"
 #include "runtime0.h"
+#include "builtin.h"
 
 typedef struct _mp_obj_set_t {
     mp_obj_base_t base;
@@ -423,13 +424,6 @@
     }
 }
 
-// TODO: Move to common file
-STATIC mp_obj_t set_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    return set_binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_contains_obj, set_contains);
-
 /******************************************************************************/
 /* set constructors & public C API                                            */
 
@@ -452,7 +446,7 @@
     { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
-    { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&set_contains_obj },
+    { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&mp_op_contains_obj },
 };
 
 STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
diff --git a/py/opmethods.c b/py/opmethods.c
new file mode 100644
index 0000000..af2524c
--- /dev/null
+++ b/py/opmethods.c
@@ -0,0 +1,20 @@
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "runtime0.h"
+#include "builtin.h"
+
+STATIC mp_obj_t op_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+    mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+    return type->binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);
+
+STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+    mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+    return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains);
diff --git a/py/py.mk b/py/py.mk
index 23ba9eb..388e70a 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -69,6 +69,7 @@
 	objtuple.o \
 	objtype.o \
 	objzip.o \
+	opmethods.o \
 	sequence.o \
 	stream.o \
 	binary.o \