diff --git a/py/compile.c b/py/compile.c
index d622242b629464cfdfd2752d2105d420b1523dea..ede09058ffcb277dcc032aa005c167aee7459c7a 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -721,7 +721,7 @@ void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_
         for (int i = 0; i < this_scope->id_info_len; i++) {
             id_info_t *id_info = &this_scope->id_info[i];
             if (id_info->kind == ID_INFO_KIND_FREE) {
-                EMIT(load_closure, id_info->qstr);
+                EMIT(load_closure, id_info->qstr, id_info->local_num);
                 nfree += 1;
             }
         }
@@ -2624,7 +2624,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
         if (id->kind == ID_INFO_KIND_LOCAL) {
             EMIT(load_const_tok, PY_TOKEN_KW_NONE);
         } else {
-            EMIT(load_closure, comp->qstr___class__);
+            EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num
         }
         EMIT(return_value);
     }
@@ -2729,6 +2729,8 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
         }
     }
 
+    // TODO compute the index of free and cell vars (freevars[idx] in CPython)
+
     // compute flags
     //scope->flags = 0; since we set some things in parameters
     if (scope->kind != SCOPE_MODULE) {
diff --git a/py/emit.h b/py/emit.h
index a8bc1fca24acc5df564b6b1d5fe40a6ff168be9f..a04acf537db5aace4833a19bbb00ff9193dcd810 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -47,22 +47,22 @@ typedef struct _emit_method_table_t {
     void (*load_fast)(emit_t *emit, qstr qstr, int local_num);
     void (*load_name)(emit_t *emit, qstr qstr);
     void (*load_global)(emit_t *emit, qstr qstr);
-    void (*load_deref)(emit_t *emit, qstr qstr);
-    void (*load_closure)(emit_t *emit, qstr qstr);
+    void (*load_deref)(emit_t *emit, qstr qstr, int local_num);
+    void (*load_closure)(emit_t *emit, qstr qstr, int local_num);
     void (*load_attr)(emit_t *emit, qstr qstr);
     void (*load_method)(emit_t *emit, qstr qstr);
     void (*load_build_class)(emit_t *emit);
     void (*store_fast)(emit_t *emit, qstr qstr, int local_num);
     void (*store_name)(emit_t *emit, qstr qstr);
     void (*store_global)(emit_t *emit, qstr qstr);
-    void (*store_deref)(emit_t *emit, qstr qstr);
+    void (*store_deref)(emit_t *emit, qstr qstr, int local_num);
     void (*store_attr)(emit_t *emit, qstr qstr);
     void (*store_subscr)(emit_t *emit);
     void (*store_locals)(emit_t *emit);
     void (*delete_fast)(emit_t *emit, qstr qstr, int local_num);
     void (*delete_name)(emit_t *emit, qstr qstr);
     void (*delete_global)(emit_t *emit, qstr qstr);
-    void (*delete_deref)(emit_t *emit, qstr qstr);
+    void (*delete_deref)(emit_t *emit, qstr qstr, int local_num);
     void (*delete_attr)(emit_t *emit, qstr qstr);
     void (*delete_subscr)(emit_t *emit);
     void (*dup_top)(emit_t *emit);
diff --git a/py/emitbc.c b/py/emitbc.c
index dbd9c3bb93194d2138228aed4085bd92024884be..55a71cb463c8a74c26d55367c062a78a660e2367 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -291,12 +291,12 @@ static void emit_bc_load_global(emit_t *emit, qstr qstr) {
     emit_write_byte_1_qstr(emit, PYBC_LOAD_GLOBAL, qstr);
 }
 
-static void emit_bc_load_deref(emit_t *emit, qstr qstr) {
+static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 1);
     assert(0);
 }
 
-static void emit_bc_load_closure(emit_t *emit, qstr qstr) {
+static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 1);
     assert(0);
 }
@@ -337,7 +337,7 @@ static void emit_bc_store_global(emit_t *emit, qstr qstr) {
     emit_write_byte_1_qstr(emit, PYBC_STORE_GLOBAL, qstr);
 }
 
-static void emit_bc_store_deref(emit_t *emit, qstr qstr) {
+static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, -1);
     assert(0);
 }
@@ -374,9 +374,10 @@ static void emit_bc_delete_global(emit_t *emit, qstr qstr) {
     emit_write_byte_1_qstr(emit, PYBC_DELETE_GLOBAL, qstr);
 }
 
-static void emit_bc_delete_deref(emit_t *emit, qstr qstr) {
+static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 0);
-    emit_write_byte_1_qstr(emit, PYBC_DELETE_DEREF, qstr);
+    assert(0);
+    //emit_write_byte_1_qstr(emit, PYBC_DELETE_DEREF, qstr);
 }
 
 static void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
diff --git a/py/emitcommon.c b/py/emitcommon.c
index 07eb1812fd86198efc08a5bc61044db99108b176..0dfe96d891b068864e9bf7972aeed9e06a6033cc 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -28,7 +28,7 @@ void emit_common_load_id(emit_t *emit, const emit_method_table_t *emit_method_ta
     } else if (id->kind == ID_INFO_KIND_LOCAL) {
         EMIT(load_fast, qstr, id->local_num);
     } else if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
-        EMIT(load_deref, qstr);
+        EMIT(load_deref, qstr, id->local_num);
     } else {
         assert(0);
     }
@@ -48,7 +48,7 @@ void emit_common_store_id(emit_t *emit, const emit_method_table_t *emit_method_t
     } else if (id->kind == ID_INFO_KIND_LOCAL) {
         EMIT(store_fast, qstr, id->local_num);
     } else if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
-        EMIT(store_deref, qstr);
+        EMIT(store_deref, qstr, id->local_num);
     } else {
         assert(0);
     }
@@ -68,7 +68,7 @@ void emit_common_delete_id(emit_t *emit, const emit_method_table_t *emit_method_
     } else if (id->kind == ID_INFO_KIND_LOCAL) {
         EMIT(delete_fast, qstr, id->local_num);
     } else if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
-        EMIT(delete_deref, qstr);
+        EMIT(delete_deref, qstr, id->local_num);
     } else {
         assert(0);
     }
diff --git a/py/emitcpy.c b/py/emitcpy.c
index 089352c0fe804d9e80cd2e37005faaad904528cc..428e6fd00abef87968e3ef710c699fecc3831155 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -279,17 +279,17 @@ static void emit_cpy_load_global(emit_t *emit, qstr qstr) {
     }
 }
 
-static void emit_cpy_load_deref(emit_t *emit, qstr qstr) {
+static void emit_cpy_load_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 1, 3);
     if (emit->pass == PASS_3) {
-        printf("LOAD_DEREF %s\n", qstr_str(qstr));
+        printf("LOAD_DEREF %d %s\n", local_num, qstr_str(qstr));
     }
 }
 
-static void emit_cpy_load_closure(emit_t *emit, qstr qstr) {
+static void emit_cpy_load_closure(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 1, 3);
     if (emit->pass == PASS_3) {
-        printf("LOAD_CLOSURE %s\n", qstr_str(qstr));
+        printf("LOAD_CLOSURE %d %s\n", local_num, qstr_str(qstr));
     }
 }
 
@@ -332,10 +332,10 @@ static void emit_cpy_store_global(emit_t *emit, qstr qstr) {
     }
 }
 
-static void emit_cpy_store_deref(emit_t *emit, qstr qstr) {
+static void emit_cpy_store_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, -1, 3);
     if (emit->pass == PASS_3) {
-        printf("STORE_DEREF %s\n", qstr_str(qstr));
+        printf("STORE_DEREF %d %s\n", local_num, qstr_str(qstr));
     }
 }
 
@@ -381,10 +381,10 @@ static void emit_cpy_delete_global(emit_t *emit, qstr qstr) {
     }
 }
 
-static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) {
+static void emit_cpy_delete_deref(emit_t *emit, qstr qstr, int local_num) {
     emit_pre(emit, 0, 3);
     if (emit->pass == PASS_3) {
-        printf("DELETE_DEREF %s\n", qstr_str(qstr));
+        printf("DELETE_DEREF %d %s\n", local_num, qstr_str(qstr));
     }
 }
 
diff --git a/py/emitnative.c b/py/emitnative.c
index def1a66359375db783f5b7a3915f22583120d043..b535df74b6f99d6a10441231b5bcbc6e06daa169 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -675,13 +675,13 @@ static void emit_native_load_global(emit_t *emit, qstr qstr) {
     emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
 }
 
-static void emit_native_load_deref(emit_t *emit, qstr qstr) {
+static void emit_native_load_deref(emit_t *emit, qstr qstr, int local_num) {
     // not implemented
     // in principle could support this quite easily (ldr r0, [r0, #0]) and then get closed over variables!
     assert(0);
 }
 
-static void emit_native_load_closure(emit_t *emit, qstr qstr) {
+static void emit_native_load_closure(emit_t *emit, qstr qstr, int local_num) {
     // not implemented
     assert(0);
 }
@@ -760,7 +760,7 @@ static void emit_native_store_global(emit_t *emit, qstr qstr) {
     assert(0);
 }
 
-static void emit_native_store_deref(emit_t *emit, qstr qstr) {
+static void emit_native_store_deref(emit_t *emit, qstr qstr, int local_num) {
     // not implemented
     assert(0);
 }
@@ -812,7 +812,7 @@ static void emit_native_delete_global(emit_t *emit, qstr qstr) {
     assert(0);
 }
 
-static void emit_native_delete_deref(emit_t *emit, qstr qstr) {
+static void emit_native_delete_deref(emit_t *emit, qstr qstr, int local_num) {
     // not supported
     assert(0);
 }
diff --git a/py/scope.c b/py/scope.c
index c5816871c2eb65bac9cb55a6ae928afad97c53d7..7f844108e38abbccdb210e83edecb2af536e4d50 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -103,6 +103,7 @@ id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) {
     id_info->param = false;
     id_info->kind = 0;
     id_info->qstr = qstr;
+    id_info->local_num = 0;
     *added = true;
     return id_info;
 }
diff --git a/py/scope.h b/py/scope.h
index 1b626c8ec173b939e54a2d205a78d731a15e9fe1..9a04c56f6150d573b8d82acdbc584a2800f37483 100644
--- a/py/scope.h
+++ b/py/scope.h
@@ -7,6 +7,7 @@ enum {
 };
 
 typedef struct _id_info_t {
+    // TODO compress this info to make structure smaller in memory
     bool param;
     int kind;
     qstr qstr;