diff --git a/src/bindings/lua/leanlua_state.cpp b/src/bindings/lua/leanlua_state.cpp
index 46ab84a5c..f004210cc 100644
--- a/src/bindings/lua/leanlua_state.cpp
+++ b/src/bindings/lua/leanlua_state.cpp
@@ -31,54 +31,133 @@ Author: Leonardo de Moura
 extern "C" void * lua_realloc(void *, void * q, size_t, size_t new_size) { return lean::realloc(q, new_size); }
 
 namespace lean {
-void _check_result(lua_State * L, int result) {
-    if (result) {
-        if (is_justification(L, -1))
-            throw elaborator_exception(to_justification(L, -1));
-        else
-            throw lua_exception(lua_tostring(L, -1));
+void open_extra(lua_State * L);
+
+static char g_weak_ptr_key; // key for Lua registry (used at get_weak_ptr and save_weak_ptr)
+
+struct leanlua_state::imp {
+    lua_State *           m_state;
+    std::recursive_mutex  m_mutex;
+
+    static std::weak_ptr<imp> * get_weak_ptr(lua_State * L) {
+        lua_pushlightuserdata(L, static_cast<void *>(&g_weak_ptr_key));
+        lua_gettable(L, LUA_REGISTRYINDEX);
+        std::weak_ptr<imp> * ptr = static_cast<std::weak_ptr<imp>*>(lua_touserdata(L, -1));
+        lua_pop(L, 1);
+        return ptr;
     }
-}
 
-static set_check_result set_check(_check_result);
-
-static int _safe_function_wrapper(lua_State * L, lua_CFunction f) {
-    try {
-        return f(L);
-    } catch (kernel_exception & e) {
-        std::ostringstream out;
-        options o = get_global_options(L);
-        out << mk_pair(e.pp(get_global_formatter(L), o), o);
-        lua_pushstring(L, out.str().c_str());
-    } catch (elaborator_exception & e) {
-        push_justification(L, e.get_justification());
-    } catch (exception & e) {
-        lua_pushstring(L, e.what());
-    } catch (std::bad_alloc &) {
-        lua_pushstring(L, "out of memory");
-    } catch (std::exception & e) {
-        lua_pushstring(L, e.what());
-    } catch(...) {
-        lua_pushstring(L, "unknown error");
+    void save_weak_ptr(std::shared_ptr<imp> & ptr) {
+        lua_pushlightuserdata(m_state, static_cast<void *>(&g_weak_ptr_key));
+        void * mem = lua_newuserdata(m_state, sizeof(std::weak_ptr<imp>));
+        new (mem) std::weak_ptr<imp>(ptr);
+        lua_settable(m_state, LUA_REGISTRYINDEX);
     }
-    return lua_error(L);
+
+    imp() {
+        // TODO(Leo) investigate why TCMALLOC + lua_realloc do not work together
+        // #ifdef LEAN_USE_LUA_NEWSTATE
+        #if 0
+        m_state = lua_newstate(lua_realloc, nullptr);
+        #else
+        m_state = luaL_newstate();
+        #endif
+        if (m_state == nullptr)
+            throw exception("fail to create Lua interpreter");
+        luaL_openlibs(m_state);
+        open_util_module(m_state);
+        open_numerics_module(m_state);
+        open_sexpr_module(m_state);
+        open_kernel_module(m_state);
+        open_arith_module(m_state);
+        open_tactic_module(m_state);
+        open_extra(m_state);
+
+        dostring(g_leanlua_extra);
+    }
+
+    ~imp() {
+        typedef std::weak_ptr<imp> wptr;
+        wptr * ptr = get_weak_ptr(m_state);
+        ptr->~wptr(); // destruct weak pointer
+        lua_close(m_state);
+    }
+
+    void dofile(char const * fname) {
+        std::lock_guard<std::recursive_mutex> lock(m_mutex);
+        ::lean::dofile(m_state, fname);
+    }
+
+    void dostring(char const * str) {
+        std::lock_guard<std::recursive_mutex> lock(m_mutex);
+        ::lean::dostring(m_state, str);
+    }
+
+    void dostring(char const * str, environment & env, io_state & st) {
+        set_io_state    set1(m_state, st);
+        set_environment set2(m_state, env);
+        dostring(str);
+    }
+};
+
+leanlua_state to_leanlua_state(lua_State * L) {
+    return leanlua_state(*leanlua_state::imp::get_weak_ptr(L));
 }
 
-static int mk_environment(lua_State * L) {
-    frontend f;
-    return push_environment(L, f.get_environment());
+leanlua_state::leanlua_state():
+    m_ptr(new imp()) {
+    m_ptr->save_weak_ptr(m_ptr);
 }
 
-static void decl_environment(lua_State * L) {
-    SET_GLOBAL_FUN(mk_environment,  "environment");
+leanlua_state::leanlua_state(std::weak_ptr<imp> const & ptr):m_ptr(ptr.lock()) {
+    lean_assert(m_ptr);
 }
 
-static set_safe_function_wrapper set_wrapper(_safe_function_wrapper);
+leanlua_state::~leanlua_state() {
+}
+
+void leanlua_state::dofile(char const * fname) {
+    m_ptr->dofile(fname);
+}
+
+void leanlua_state::dostring(char const * str) {
+    m_ptr->dostring(str);
+}
+
+void leanlua_state::dostring(char const * str, environment & env, io_state & st) {
+    m_ptr->dostring(str, env, st);
+}
+
+constexpr char const * state_mt = "luastate.mt";
+
+bool is_state(lua_State * L, int idx) {
+    return testudata(L, idx, state_mt);
+}
+
+leanlua_state & to_state(lua_State * L, int idx) {
+    return *static_cast<leanlua_state*>(luaL_checkudata(L, idx, state_mt));
+}
+
+int push_state(lua_State * L, leanlua_state const & s) {
+    void * mem = lua_newuserdata(L, sizeof(leanlua_state));
+    new (mem) leanlua_state(s);
+    luaL_getmetatable(L, state_mt);
+    lua_setmetatable(L, -2);
+    return 1;
+}
+
+static int mk_state(lua_State * L) {
+    leanlua_state r;
+    return push_state(L, r);
+}
+
+static int state_gc(lua_State * L) {
+    to_state(L, 1).~leanlua_state();
+    return 0;
+}
 
-static void open_state(lua_State * L);
-static void open_thread(lua_State * L);
-static void open_interrupt(lua_State * L);
 environment & to_environment(lua_State * L, int idx);
+
 static int writer(lua_State *, void const * p, size_t sz, void * buf) {
     buffer<char> & _buf = *static_cast<buffer<char>*>(buf);
     char const * in = static_cast<char const *>(p);
@@ -167,137 +246,6 @@ static void copy_values(lua_State * src, int first, int last, lua_State * tgt) {
     }
 }
 
-void open_splay_map(lua_State * L);
-
-static char g_weak_ptr_key; // key for Lua registry (used at get_weak_ptr and save_weak_ptr)
-
-struct leanlua_state::imp {
-    lua_State *           m_state;
-    std::recursive_mutex  m_mutex;
-
-    static std::weak_ptr<imp> * get_weak_ptr(lua_State * L) {
-        lua_pushlightuserdata(L, static_cast<void *>(&g_weak_ptr_key));
-        lua_gettable(L, LUA_REGISTRYINDEX);
-        std::weak_ptr<imp> * ptr = static_cast<std::weak_ptr<imp>*>(lua_touserdata(L, -1));
-        lua_pop(L, 1);
-        return ptr;
-    }
-
-    void save_weak_ptr(std::shared_ptr<imp> & ptr) {
-        lua_pushlightuserdata(m_state, static_cast<void *>(&g_weak_ptr_key));
-        void * mem = lua_newuserdata(m_state, sizeof(std::weak_ptr<imp>));
-        new (mem) std::weak_ptr<imp>(ptr);
-        lua_settable(m_state, LUA_REGISTRYINDEX);
-    }
-
-    imp() {
-        // TODO(Leo) investigate why TCMALLOC + lua_realloc do not work together
-        // #ifdef LEAN_USE_LUA_NEWSTATE
-        #if 0
-        m_state = lua_newstate(lua_realloc, nullptr);
-        #else
-        m_state = luaL_newstate();
-        #endif
-        if (m_state == nullptr)
-            throw exception("fail to create Lua interpreter");
-        luaL_openlibs(m_state);
-        open_util_module(m_state);
-        open_numerics_module(m_state);
-        open_sexpr_module(m_state);
-        open_kernel_module(m_state);
-        open_arith_module(m_state);
-        open_tactic_module(m_state);
-
-        open_state(m_state);
-        open_frontend_lean(m_state);
-        open_thread(m_state);
-        open_interrupt(m_state);
-
-        decl_environment(m_state);
-
-        dostring(g_leanlua_extra);
-    }
-
-    ~imp() {
-        typedef std::weak_ptr<imp> wptr;
-        wptr * ptr = get_weak_ptr(m_state);
-        ptr->~wptr(); // destruct weak pointer
-        lua_close(m_state);
-    }
-
-    void dofile(char const * fname) {
-        std::lock_guard<std::recursive_mutex> lock(m_mutex);
-        ::lean::dofile(m_state, fname);
-    }
-
-    void dostring(char const * str) {
-        std::lock_guard<std::recursive_mutex> lock(m_mutex);
-        ::lean::dostring(m_state, str);
-    }
-
-    void dostring(char const * str, environment & env, io_state & st) {
-        set_io_state    set1(m_state, st);
-        set_environment set2(m_state, env);
-        dostring(str);
-    }
-};
-
-leanlua_state to_leanlua_state(lua_State * L) {
-    return leanlua_state(*leanlua_state::imp::get_weak_ptr(L));
-}
-
-leanlua_state::leanlua_state():
-    m_ptr(new imp()) {
-    m_ptr->save_weak_ptr(m_ptr);
-}
-
-leanlua_state::leanlua_state(std::weak_ptr<imp> const & ptr):m_ptr(ptr.lock()) {
-    lean_assert(m_ptr);
-}
-
-leanlua_state::~leanlua_state() {
-}
-
-void leanlua_state::dofile(char const * fname) {
-    m_ptr->dofile(fname);
-}
-
-void leanlua_state::dostring(char const * str) {
-    m_ptr->dostring(str);
-}
-
-void leanlua_state::dostring(char const * str, environment & env, io_state & st) {
-    m_ptr->dostring(str, env, st);
-}
-
-constexpr char const * state_mt = "luastate.mt";
-
-bool is_state(lua_State * L, int idx) {
-    return testudata(L, idx, state_mt);
-}
-
-leanlua_state & to_state(lua_State * L, int idx) {
-    return *static_cast<leanlua_state*>(luaL_checkudata(L, idx, state_mt));
-}
-
-int push_state(lua_State * L, leanlua_state const & s) {
-    void * mem = lua_newuserdata(L, sizeof(leanlua_state));
-    new (mem) leanlua_state(s);
-    luaL_getmetatable(L, state_mt);
-    lua_setmetatable(L, -2);
-    return 1;
-}
-
-static int mk_state(lua_State * L) {
-    leanlua_state r;
-    return push_state(L, r);
-}
-
-static int state_gc(lua_State * L) {
-    to_state(L, 1).~leanlua_state();
-    return 0;
-}
-
 int state_dostring(lua_State * L) {
     auto S = to_state(L, 1).m_ptr;
     char const * script = luaL_checkstring(L, 2);
@@ -591,7 +539,6 @@ static int thread_interrupt(lua_State * L) {
     return 0;
 }
 
-
 int thread_wait(lua_State * L) {
     return to_thread(L, 1).wait(L);
 }
@@ -632,4 +579,51 @@ static void open_interrupt(lua_State * L) {
     SET_GLOBAL_FUN(channel_read,      "read");
     SET_GLOBAL_FUN(channel_write,     "write");
 }
+
+void _check_result(lua_State * L, int result) {
+    if (result) {
+        if (is_justification(L, -1))
+            throw elaborator_exception(to_justification(L, -1));
+        else
+            throw lua_exception(lua_tostring(L, -1));
+    }
+}
+
+static set_check_result set_check(_check_result);
+
+static int _safe_function_wrapper(lua_State * L, lua_CFunction f) {
+    try {
+        return f(L);
+    } catch (kernel_exception & e) {
+        std::ostringstream out;
+        options o = get_global_options(L);
+        out << mk_pair(e.pp(get_global_formatter(L), o), o);
+        lua_pushstring(L, out.str().c_str());
+    } catch (elaborator_exception & e) {
+        push_justification(L, e.get_justification());
+    } catch (exception & e) {
+        lua_pushstring(L, e.what());
+    } catch (std::bad_alloc &) {
+        lua_pushstring(L, "out of memory");
+    } catch (std::exception & e) {
+        lua_pushstring(L, e.what());
+    } catch(...) {
+        lua_pushstring(L, "unknown error");
+    }
+    return lua_error(L);
+}
+
+static int mk_environment(lua_State * L) {
+    frontend f;
+    return push_environment(L, f.get_environment());
+}
+
+static set_safe_function_wrapper set_wrapper(_safe_function_wrapper);
+
+void open_extra(lua_State * L) {
+    open_state(L);
+    open_thread(L);
+    open_interrupt(L);
+    SET_GLOBAL_FUN(mk_environment,  "environment");
+}
 }