mp_compile(): Properly free module_scope and all nested scopes.
diff --git a/py/compile.c b/py/compile.c
index 0704cc4..7e77832 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -3156,6 +3156,12 @@
 
     bool had_error = comp->had_error;
     m_del_obj(compiler_t, comp);
+    uint unique_code_id = module_scope->unique_code_id;
+    for (scope_t *s = module_scope; s;) {
+        scope_t *next = s->next;
+        scope_free(s);
+        s = next;
+    }
 
     if (had_error) {
         // TODO return a proper error message
@@ -3163,11 +3169,11 @@
     } else {
 #if MICROPY_EMIT_CPYTHON
         // can't create code, so just return true
-        (void)module_scope; // to suppress warning that module_scope is unused
+        (void)unique_code_id; // to suppress warning that module_scope is unused
         return mp_const_true;
 #else
         // return function that executes the outer module
-        return rt_make_function_from_id(module_scope->unique_code_id);
+        return rt_make_function_from_id(unique_code_id);
 #endif
     }
 }
diff --git a/py/scope.c b/py/scope.c
index 1d240bb..1f602ac 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -60,6 +60,11 @@
     return scope;
 }
 
+void scope_free(scope_t *scope) {
+    m_del(id_info_t, scope->id_info, scope->id_info_alloc);
+    m_del(scope_t, scope, 1);
+}
+
 id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) {
     for (int i = 0; i < scope->id_info_len; i++) {
         if (scope->id_info[i].qstr == qstr) {
diff --git a/py/scope.h b/py/scope.h
index 718ce46..015a8ba 100644
--- a/py/scope.h
+++ b/py/scope.h
@@ -56,6 +56,7 @@
 } scope_t;
 
 scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options);
+void scope_free(scope_t *scope);
 id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added);
 id_info_t *scope_find(scope_t *scope, qstr qstr);
 id_info_t *scope_find_global(scope_t *scope, qstr qstr);