diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+## Changelog
+
+
+### 0.3.12
+
+* `pushrawhsfunction` and `registerrawhsfunction` functions are added.
+* `apicheck` flag is added to Cabal package to enable Lua API checking. (useful for debugging)
+
+### 0.3.11
+
+* `luaL_ref` and `luaL_unref` functions are added.
diff --git a/hslua.cabal b/hslua.cabal
--- a/hslua.cabal
+++ b/hslua.cabal
@@ -1,5 +1,5 @@
 Name:                   hslua
-Version:                0.3.11
+Version:                0.3.12
 Stability:              beta
 Cabal-version:          >= 1.8
 License:                MIT
@@ -16,6 +16,8 @@
                         If you want to link it with system-wide Lua installation, use system-lua flag.
 Category:               Scripting
 Extra-source-files:     src/*.h
+                        CHANGELOG.md
+                        COPYRIGHT
 
 source-repository head
   type:                 git
@@ -25,6 +27,10 @@
   description:          Use the system-wide lua instead of the bundled copy
   default:              False
 
+flag apicheck
+  description:          Compile Lua with -DLUA_USE_APICHECK.
+  default:              False
+
 Library
   Build-depends:        base==4.*, mtl >= 2.1
   Exposed-modules:      Scripting.Lua, Scripting.Lua.ConfigFile
@@ -51,6 +57,9 @@
 
   if os(freebsd)
     CC-Options:         "-DLUA_USE_POSIX"
+
+  if flag(apicheck)
+    CC-Options:         "-DLUA_USE_APICHECK"
 
 Test-Suite simple-test
   type:                 exitcode-stdio-1.0
diff --git a/src/Scripting/Lua.hs b/src/Scripting/Lua.hs
deleted file mode 100644
--- a/src/Scripting/Lua.hs
+++ /dev/null
@@ -1,1091 +0,0 @@
-
-{-# LANGUAGE ForeignFunctionInterface, TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-}
-{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind -fno-warn-unused-binds #-}
--- |
--- Module      : Scripting.Lua
--- Copyright   : (c) Gracjan Polak 2007
---
--- License     : MIT
---
--- Maintainer  : omeragacan@gmail.com
--- Stability   : alpha
--- Portability : portable, ffi
---
--- A Haskell wrapper library for a scripting language Lua.
--- See @http:\/\/www.lua.org\/@ for more details.
---
--- This module is intended to be imported @qualified@, eg.
---
--- > import qualified Scripting.Lua as Lua
---
--- This way we use Haskell module hierarchy to make Lua names shorter.
--- Haskell functions are named after Lua functions, but the @lua_@ or
--- @luaL_@ prefix.
---
--- Lua types are mapped to Haskell types as in the following table:
---
--- > int (stack index)        Int
--- > lua_Integer              LuaInteger
--- > lua_Number               LuaNumber
--- > int (bool result)        Bool
--- > const char * (string)    String
--- > void *                   Ptr ()
--- > lua_State *              LuaState
---
--- Most functions are one-to-one mappings.
--- Rare special cases are clearly marked in this document.
---
--- Minmal sample embedding:
---
--- > import qualified Scripting.Lua as Lua
---
--- > main = do
--- >     l <- Lua.newstate
--- >     Lua.openlibs l
--- >     Lua.callproc l "print" "Hello from Lua"
--- >     Lua.close l
-
-module Scripting.Lua
-(
-    -- * Basic Lua types
-    LuaState(..),
-    LuaCFunction,
-    LuaInteger,
-    LuaNumber,
-    LuaImport(..),
-
-    -- * Constants and enumerations
-    GCCONTROL(..),
-    LTYPE(..),
-    multret,
-    registryindex,
-    environindex,
-    globalsindex,
-
-    -- * lua_* functions
-    atpanic,
-    call,
-    checkstack,
-    close,
-    concat,
-    cpcall,
-    createtable,
-    dump,
-    equal,
-    --error,    -- cannot import this one, as this uses setjmp/longjmp
-    gc,
-    --getallocf,
-    getfenv,
-    getfield,
-    getglobal,
-    --gethook,
-    --gethookcount,
-    --gethookmask,
-    --getinfo,
-    --getlocal,
-    getmetatable,
-    --getstack,
-    gettable,
-    gettop,
-    getupvalue,
-    insert,
-    isboolean,
-    iscfunction,
-    isfunction,
-    islightuserdata,
-    isnil,
-    isnumber,
-    isstring,
-    istable,
-    isthread,
-    isuserdata,
-    lessthan,
-    --load,
-    newstate,
-    newtable,
-    newthread,
-    newuserdata,
-    next,
-    objlen,
-    pcall,
-    pop,
-    pushboolean,
-    pushcclosure,
-    pushcfunction,
-    --pushfstring,
-    pushinteger,
-    pushlightuserdata,
-    --pushlstring,
-    pushnil,
-    pushnumber,
-    pushstring,
-    pushthread,
-    pushvalue,
-    --pushvfstring,
-    rawequal,
-    rawget,
-    rawgeti,
-    rawset,
-    rawseti,
-    register,
-    remove,
-    replace,
-    resume,
-    --setallocf,
-    setfenv,
-    setfield,
-    setglobal,
-    --sethook,
-    --setlocal,
-    setmetatable,
-    settable,
-    settop,
-    setupvalue,
-    status,
-    toboolean,
-    tocfunction,
-    tointeger,
-    --tolstring,
-    tonumber,
-    topointer,
-    tostring,
-    tothread,
-    touserdata,
-    ltype,
-    typename,
-    upvalueindex,
-    xmove,
-    yield,
-
-    -- * luaL_* functions
-    openlibs,
-    loadfile,
-    loadstring,
-    newmetatable,
-    argerror,
-    ref,
-    unref,
-
-    -- * Haskell extensions
-    StackValue(..),
-    callproc,
-    callfunc,
-    getglobal2,
-    newcfunction,
-    freecfunction,
-    luaimport,
-    pushhsfunction,
-    registerhsfunction
-)
-where
-import Prelude hiding (concat, catch)
-import Foreign.C
-import Foreign.Ptr
-import Foreign.StablePtr
-import Control.Monad
-import Control.Exception
-import Foreign.Marshal.Alloc
-import Data.IORef
-import qualified Foreign.Storable as F
-import qualified Data.List as L
-import Data.Maybe
-
--- | Wrapper for @lua_State *@. See @lua_State@ in Lua Reference Manual.
-newtype LuaState = LuaState (Ptr ())
--- | Wrapper for @lua_Alloc@. See @lua_Alloc@ in Lua Reference Manual.
-type LuaAlloc = Ptr () -> Ptr () -> CSize -> CSize -> IO (Ptr ())
--- | Wrapper for @lua_Reader@. See @lua_Reader@ in Lua Reference Manual.
-type LuaReader = Ptr () -> Ptr () -> Ptr CSize -> IO (Ptr CChar)
-
--- | Wrapper for @lua_Writer@. See @lua_Writer@ in Lua Reference Manual.
-type LuaWriter = LuaState -> Ptr CChar -> CSize -> Ptr () -> IO CInt
--- | Wrapper for @lua_CFunction@. See @lua_CFunction@ in Lua Reference Manual.
-type LuaCFunction = LuaState -> IO CInt
--- | Wrapper for @lua_Integer@. See @lua_Integer@ in Lua Reference Manual.
--- HsLua uses C @ptrdiff_t@ as @lua_Integer@.
-type LuaInteger = CPtrdiff
--- | Wrapper for @lua_Number@. See @lua_Number@ in Lua Reference Manual.
--- HsLua uses C @double@ as @lua_Integer@.
-type LuaNumber = CDouble
-
-
--- | Enumeration used as type tag. See @lua_type@ in Lua Reference Manual.
-data LTYPE = TNONE
-           | TNIL
-           | TBOOLEAN
-           | TLIGHTUSERDATA
-           | TNUMBER
-           | TSTRING
-           | TTABLE
-           | TFUNCTION
-           | TUSERDATA
-           | TTHREAD
-           deriving (Eq,Show,Ord)
-
-instance Enum LTYPE where
-    fromEnum TNONE          = -1
-    fromEnum TNIL           = 0
-    fromEnum TBOOLEAN       = 1
-    fromEnum TLIGHTUSERDATA = 2
-    fromEnum TNUMBER        = 3
-    fromEnum TSTRING        = 4
-    fromEnum TTABLE         = 5
-    fromEnum TFUNCTION      = 6
-    fromEnum TUSERDATA      = 7
-    fromEnum TTHREAD        = 8
-    toEnum (-1)             = TNONE
-    toEnum 0                = TNIL
-    toEnum 1                = TBOOLEAN
-    toEnum 2                = TLIGHTUSERDATA
-    toEnum 3                = TNUMBER
-    toEnum 4                = TSTRING
-    toEnum 5                = TTABLE
-    toEnum 6                = TFUNCTION
-    toEnum 7                = TUSERDATA
-    toEnum 8                = TTHREAD
-    toEnum n                = error $ "Cannot convert (" ++ show n ++ ") to LTYPE"
-
--- | Enumeration used by @gc@ function.
-data GCCONTROL  = GCSTOP
-                | GCRESTART
-                | GCCOLLECT
-                | GCCOUNT
-                | GCCOUNTB
-                | GCSTEP
-                | GCSETPAUSE
-                | GCSETSTEPMUL
-                deriving (Eq,Ord,Show,Enum)
-
--- | See @LUA_MULTRET@ in Lua Reference Manual.
-multret :: Int
-multret = -1
-
-{-
-
-It is unknown which of the imported function may trigger garbage collector.
-GC may in turn call some finalizars that will require come back to
-the Haskell world.
-
-This means we must declare almost all functions as 'safe'. This is slow, so
-some functions known not to call gc are marked with faster 'unsafe' modifier.
-
--}
-foreign import ccall "lua.h lua_close" c_lua_close :: LuaState -> IO ()
-foreign import ccall "lua.h lua_newstate" c_lua_newstate :: FunPtr LuaAlloc -> Ptr () -> IO LuaState
-foreign import ccall "lua.h lua_newthread" c_lua_newthread :: LuaState -> IO LuaState
-foreign import ccall "lua.h lua_atpanic" c_lua_atpanic :: LuaState -> FunPtr LuaCFunction -> IO (FunPtr LuaCFunction)
-
-
-foreign import ccall "lua.h lua_gettop" c_lua_gettop :: LuaState -> IO CInt
-foreign import ccall "lua.h lua_settop" c_lua_settop :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_pushvalue" c_lua_pushvalue :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_remove" c_lua_remove :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_insert" c_lua_insert :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_replace" c_lua_replace :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_checkstack" c_lua_checkstack :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_xmove" c_lua_xmove :: LuaState -> LuaState -> CInt -> IO ()
-
-
-foreign import ccall "lua.h lua_isnumber" c_lua_isnumber :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_isstring" c_lua_isstring :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_iscfunction" c_lua_iscfunction :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_isuserdata" c_lua_isuserdata :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_type" c_lua_type :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_typename" c_lua_typename :: LuaState -> CInt -> IO (Ptr CChar)
-
-foreign import ccall "lua.h lua_equal" c_lua_equal :: LuaState -> CInt -> CInt -> IO CInt
-foreign import ccall "lua.h lua_rawequal" c_lua_rawequal :: LuaState -> CInt -> CInt -> IO CInt
-foreign import ccall "lua.h lua_lessthan" c_lua_lessthan :: LuaState -> CInt -> CInt -> IO CInt
-
-foreign import ccall "lua.h lua_tonumber" c_lua_tonumber :: LuaState -> CInt -> IO LuaNumber
-foreign import ccall "lua.h lua_tointeger" c_lua_tointeger :: LuaState -> CInt -> IO LuaInteger
-foreign import ccall "lua.h lua_toboolean" c_lua_toboolean :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_tolstring" c_lua_tolstring :: LuaState -> CInt -> Ptr CInt -> IO (Ptr CChar)
-foreign import ccall "lua.h lua_objlen" c_lua_objlen :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_tocfunction" c_lua_tocfunction :: LuaState -> CInt -> IO (FunPtr LuaCFunction)
-foreign import ccall "lua.h lua_touserdata" c_lua_touserdata :: LuaState -> CInt -> IO (Ptr a)
-foreign import ccall "lua.h lua_tothread" c_lua_tothread :: LuaState -> CInt -> IO LuaState
-foreign import ccall "lua.h lua_topointer" c_lua_topointer :: LuaState -> CInt -> IO (Ptr ())
-
-
-foreign import ccall "lua.h lua_pushnil" c_lua_pushnil :: LuaState -> IO ()
-foreign import ccall "lua.h lua_pushnumber" c_lua_pushnumber :: LuaState -> LuaNumber -> IO ()
-foreign import ccall "lua.h lua_pushinteger" c_lua_pushinteger :: LuaState -> LuaInteger -> IO ()
-foreign import ccall "lua.h lua_pushlstring" c_lua_pushlstring :: LuaState -> Ptr CChar -> CInt -> IO ()
-foreign import ccall "lua.h lua_pushstring" c_lua_pushstring :: LuaState -> Ptr CChar -> IO ()
-{-
-LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
-                                                      va_list argp);
-LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
--}
-foreign import ccall "lua.h lua_pushcclosure" c_lua_pushcclosure :: LuaState -> FunPtr LuaCFunction -> CInt -> IO ()
-foreign import ccall "lua.h lua_pushboolean" c_lua_pushboolean :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_pushlightuserdata" c_lua_pushlightuserdata :: LuaState -> Ptr a -> IO ()
-foreign import ccall "lua.h lua_pushthread" c_lua_pushthread :: LuaState -> IO CInt
-
-
-foreign import ccall "lua.h lua_gettable" c_lua_gettable :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_getfield" c_lua_getfield :: LuaState -> CInt -> Ptr CChar -> IO ()
-foreign import ccall "lua.h lua_rawget" c_lua_rawget :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_rawgeti" c_lua_rawgeti :: LuaState -> CInt -> CInt -> IO ()
-foreign import ccall "lua.h lua_createtable" c_lua_createtable :: LuaState -> CInt -> CInt -> IO ()
-foreign import ccall "lua.h lua_newuserdata" c_lua_newuserdata :: LuaState -> CInt -> IO (Ptr ())
-foreign import ccall "lua.h lua_getmetatable" c_lua_getmetatable :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_getfenv" c_lua_getfenv :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_getupvalue" c_lua_getupvalue :: LuaState -> CInt -> CInt -> IO (Ptr CChar)
-foreign import ccall "lua.h lua_setupvalue" c_lua_setupvalue :: LuaState -> CInt -> CInt -> IO (Ptr CChar)
-
-
-foreign import ccall "lua.h lua_settable" c_lua_settable :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_setfield" c_lua_setfield :: LuaState -> CInt -> Ptr CChar -> IO ()
-foreign import ccall "lua.h lua_rawset" c_lua_rawset :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_rawseti" c_lua_rawseti :: LuaState -> CInt -> CInt -> IO ()
-foreign import ccall "lua.h lua_setmetatable" c_lua_setmetatable :: LuaState -> CInt -> IO ()
-foreign import ccall "lua.h lua_setfenv" c_lua_setfenv :: LuaState -> CInt -> IO CInt
-
-
-foreign import ccall "lua.h lua_call" c_lua_call :: LuaState -> CInt -> CInt -> IO ()
-foreign import ccall "lua.h lua_pcall" c_lua_pcall :: LuaState -> CInt -> CInt -> CInt -> IO CInt
-foreign import ccall "lua.h lua_cpcall" c_lua_cpcall :: LuaState -> FunPtr LuaCFunction -> Ptr a -> IO CInt
-
-foreign import ccall "lua.h lua_load" c_lua_load :: LuaState -> FunPtr LuaReader -> Ptr () -> Ptr CChar -> IO CInt
-
-foreign import ccall "lua.h lua_dump" c_lua_dump :: LuaState -> FunPtr LuaWriter -> Ptr () -> IO ()
-
-foreign import ccall "lua.h lua_yield" c_lua_yield :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_resume" c_lua_resume :: LuaState -> CInt -> IO CInt
-foreign import ccall "lua.h lua_status" c_lua_status :: LuaState -> IO CInt
-
-foreign import ccall "lua.h lua_gc" c_lua_gc :: LuaState -> CInt -> CInt -> IO CInt
-
-foreign import ccall "lua.h lua_error" c_lua_error :: LuaState -> IO CInt
-
-foreign import ccall "lua.h lua_next" c_lua_next :: LuaState -> CInt -> IO CInt
-
-foreign import ccall "lua.h lua_concat" c_lua_concat :: LuaState -> CInt -> IO ()
-
-foreign import ccall "lualib.h luaL_openlibs" c_luaL_openlibs :: LuaState -> IO ()
-foreign import ccall "lauxlib.h luaL_newstate" c_luaL_newstate :: IO LuaState
-foreign import ccall "lauxlib.h luaL_newmetatable" c_luaL_newmetatable :: LuaState -> Ptr CChar -> IO CInt
-foreign import ccall "lauxlib.h luaL_argerror" c_luaL_argerror :: LuaState -> CInt -> Ptr CChar -> IO CInt
-foreign import ccall "lauxlib.h luaL_ref" c_luaL_ref :: LuaState -> CInt -> IO CInt
-foreign import ccall "lauxlib.h luaL_unref" c_luaL_unref :: LuaState -> CInt -> CInt -> IO ()
-
-foreign import ccall "ntrljmp.h lua_neutralize_longjmp" c_lua_neutralize_longjmp :: LuaState -> IO CInt
-foreign import ccall "ntrljmp.h &lua_neutralize_longjmp" c_lua_neutralize_longjmp_addr :: FunPtr (LuaState -> IO CInt)
-
-
--- | See @lua_settop@ in Lua Reference Manual.
-settop :: LuaState -> Int -> IO ()
-settop l n = c_lua_settop l (fromIntegral n)
-
--- | See @lua_createtable@ in Lua Reference Manual.
-createtable :: LuaState -> Int -> Int -> IO ()
-createtable l s z = c_lua_createtable l (fromIntegral s) (fromIntegral z)
-
--- | See @lua_objlen@ in Lua Reference Manual.
-objlen :: LuaState -> Int -> IO Int
-objlen l n = liftM fromIntegral (c_lua_objlen l (fromIntegral n))
-
--- | See @lua_pop@ in Lua Reference Manual.
-pop :: LuaState -> Int -> IO ()
-pop l n = settop l (-n-1)
-
-
--- | See @lua_newtable@ in Lua Reference Manual.
-newtable :: LuaState -> IO ()
-newtable l = createtable l 0 0
-
--- | See @lua_pushcclosure@ in Lua Reference Manual.
-pushcclosure :: LuaState -> FunPtr LuaCFunction -> Int -> IO ()
-pushcclosure l f n = c_lua_pushcclosure l f (fromIntegral n)
-
--- | See @lua_pushcfunction@ in Lua Reference Manual.
-pushcfunction :: LuaState -> FunPtr LuaCFunction -> IO ()
-pushcfunction l f = pushcclosure l f 0
-
-
--- | See @lua_strlen@ in Lua Reference Manual.
-strlen :: LuaState -> Int -> IO Int
-strlen l i =  objlen l i
-
--- | See @lua_type@ in Lua Reference Manual.
-ltype :: LuaState -> Int -> IO LTYPE
-ltype l n = liftM (toEnum . fromIntegral) (c_lua_type l (fromIntegral n))
-
--- | See @lua_isfunction@ in Lua Reference Manual.
-isfunction :: LuaState -> Int -> IO Bool
-isfunction l n = liftM (==TFUNCTION) (ltype l n)
-
--- | See @lua_istable@ in Lua Reference Manual.
-istable :: LuaState -> Int -> IO Bool
-istable l n = liftM (==TTABLE) (ltype l n)
-
--- | See @lua_islightuserdata@ in Lua Reference Manual.
-islightuserdata :: LuaState -> Int -> IO Bool
-islightuserdata l n = liftM (==TLIGHTUSERDATA) (ltype l n)
-
--- | See @lua_isnil@ in Lua Reference Manual.
-isnil :: LuaState -> Int -> IO Bool
-isnil l n = liftM (==TNIL) (ltype l n)
-
--- | See @lua_isboolean@ in Lua Reference Manual.
-isboolean :: LuaState -> Int -> IO Bool
-isboolean l n = liftM (==TBOOLEAN) (ltype l n)
-
--- | See @lua_isthread@ in Lua Reference Manual.
-isthread :: LuaState -> Int -> IO Bool
-isthread l n = liftM (==TTHREAD) (ltype l n)
-
--- | See @lua_none@ in Lua Reference Manual.
-isnone :: LuaState -> Int -> IO Bool
-isnone l n = liftM (==TNONE) (ltype l n)
-
--- | See @lua_noneornil@ in Lua Reference Manual.
-isnoneornil :: LuaState -> Int -> IO Bool
-isnoneornil l n = liftM (<=TNIL) (ltype l n)
-
--- | See @LUA_REGISTRYINDEX@ in Lua Reference Manual.
-registryindex :: Int
-registryindex = (-10000)
-
--- | See @LUA_ENVIRONINDEX@ in Lua Reference Manual.
-environindex :: Int
-environindex = (-10001)
-
--- | See @LUA_GLOBALSINDEX@ in Lua Reference Manual.
-globalsindex :: Int
-globalsindex = (-10002)
-
--- | See @lua_upvalueindex@ in Lua Reference Manual.
-upvalueindex :: Int -> Int
-upvalueindex i = (globalsindex-(i))
-
-{-
-The following seem to be really bad idea, as calls from C
-back to Haskell land are costly.
-
-Use standard Lua malloc based allocator.
-
-foreign export ccall "hslua_alloc" hslua_alloc :: Ptr () -> Ptr () -> CInt -> CInt -> IO (Ptr ())
-foreign import ccall "&hslua_alloc" hslua_alloc_addr :: FunPtr LuaAlloc
-
-hslua_alloc :: Ptr () -> Ptr () -> CInt -> CInt -> IO (Ptr ())
-hslua_alloc ud ptr osize nsize = reallocBytes ptr (fromIntegral nsize)
-
-static void *l_alloc (void *ud, void *ptr, size_t osize,
-                                                size_t nsize) {
-       (void)ud;  (void)osize;  /* not used */
-       if (nsize == 0) {
-         free(ptr);
-         return NULL;
-       }
-       else
-         return realloc(ptr, nsize);
-     }
--}
-
--- | See @lua_atpanic@ in Lua Reference Manual.
-atpanic :: LuaState -> FunPtr LuaCFunction -> IO (FunPtr LuaCFunction)
-atpanic = c_lua_atpanic
-
--- | See @lua_tostring@ in Lua Reference Manual.
-tostring :: LuaState -> Int -> IO String
-tostring l n = alloca $ \lenPtr -> do
-    cstr <- c_lua_tolstring l (fromIntegral n) lenPtr
-    len <- F.peek lenPtr
-    peekCStringLen (cstr, fromIntegral len)
-
--- | See @lua_tothread@ in Lua Reference Manual.
-tothread :: LuaState -> Int -> IO LuaState
-tothread l n = c_lua_tothread l (fromIntegral n)
-
--- | See @lua_touserdata@ in Lua Reference Manual.
-touserdata :: LuaState -> Int -> IO (Ptr a)
-touserdata l n = c_lua_touserdata l (fromIntegral n)
-
--- | See @lua_typename@ in Lua Reference Manual.
-typename :: LuaState -> LTYPE -> IO String
-typename l n = c_lua_typename l (fromIntegral (fromEnum n)) >>= peekCString
-
--- | See @lua_xmove@ in Lua Reference Manual.
-xmove :: LuaState -> LuaState -> Int -> IO ()
-xmove l1 l2 n = c_lua_xmove l1 l2 (fromIntegral n)
-
--- | See @lua_yield@ in Lua Reference Manual.
-yield :: LuaState -> Int -> IO Int
-yield l n = liftM fromIntegral (c_lua_yield l (fromIntegral n))
-
--- | See @lua_checkstack@ in Lua Reference Manual.
-checkstack :: LuaState -> Int -> IO Bool
-checkstack l n = liftM (/=0) (c_lua_checkstack l (fromIntegral n))
-
--- | See @lua_newstate@ and @luaL_newstate@ in Lua Reference Manual.
-newstate :: IO LuaState
-newstate = c_luaL_newstate
-
--- | See @lua_close@ in Lua Reference Manual.
-close :: LuaState -> IO ()
-close = c_lua_close
-
--- | See @lua_concat@ in Lua Reference Manual.
-concat :: LuaState -> Int -> IO ()
-concat l n = c_lua_concat l (fromIntegral n)
-
-
-
--- | See @lua_call@ and @lua_call@ in Lua Reference Manual. This is
--- a wrapper over @lua_pcall@, as @lua_call@ is unsafe in controlled environment
--- like Haskell VM.
-call :: LuaState -> Int -> Int -> IO ()
-call l a b = c_lua_call l (fromIntegral a) (fromIntegral b)
-
--- | See @lua_pcall@ in Lua Reference Manual.
-pcall :: LuaState -> Int -> Int -> Int -> IO Int
-pcall l a b c = liftM fromIntegral (c_lua_pcall l (fromIntegral a) (fromIntegral b) (fromIntegral c))
-
--- | See @lua_cpcall@ in Lua Reference Manual.
-cpcall :: LuaState -> FunPtr LuaCFunction -> Ptr a -> IO Int
-cpcall l a c = liftM fromIntegral (c_lua_cpcall l a c)
-
--- | See @lua_getfield@ in Lua Reference Manual.
-getfield :: LuaState -> Int -> String -> IO ()
-getfield l i n = withCString n $ \n -> c_lua_getfield l (fromIntegral i) n
-
--- | See @lua_setfield@ in Lua Reference Manual.
-setfield :: LuaState -> Int -> String -> IO ()
-setfield l i n = withCString n $ \n -> c_lua_setfield l (fromIntegral i) n
-
--- | See @lua_getglobal@ in Lua Reference Manual.
-getglobal :: LuaState -> String -> IO ()
-getglobal l n = getfield l globalsindex n
-
--- | See @lua_setglobal@ in Lua Reference Manual.
-setglobal :: LuaState -> String -> IO ()
-setglobal l n = setfield l globalsindex n
-
--- | See @luaL_openlibs@ in Lua Reference Manual.
-openlibs :: LuaState -> IO ()
-openlibs = c_luaL_openlibs
-
-foreign import ccall "wrapper" mkStringWriter :: LuaWriter -> IO (FunPtr LuaWriter)
-
-dump :: LuaState -> IO String
-dump l = do
-    r <- newIORef ""
-    let wr :: LuaWriter
-        wr _l p s _d = do
-               k <- peekCStringLen (p,fromIntegral s)
-               modifyIORef r (++k)
-               return 0
-    writer <- mkStringWriter wr
-    c_lua_dump l writer nullPtr
-    freeHaskellFunPtr writer
-    readIORef r
-
--- | See @lua_equal@ in Lua Reference Manual.
-equal :: LuaState -> Int -> Int -> IO Bool
-equal l i j = liftM (/=0) (c_lua_equal l (fromIntegral i) (fromIntegral j))
-
--- | See @lua_error@ in Lua Reference Manual.
---error :: LuaState -> IO Int
---error l = liftM fromIntegral (c_lua_error l)
-
--- | See @lua_gc@ in Lua Reference Manual.
-gc :: LuaState -> GCCONTROL -> Int -> IO Int
-gc l i j= liftM fromIntegral (c_lua_gc l (fromIntegral (fromEnum i)) (fromIntegral j))
-
--- | See @lua_getfenv@ in Lua Reference Manual.
-getfenv :: LuaState -> Int -> IO ()
-getfenv l n = c_lua_getfenv l (fromIntegral n)
-
--- | See @lua_getmetatable@ in Lua Reference Manual.
-getmetatable :: LuaState -> Int -> IO Bool
-getmetatable l n = liftM (/=0) (c_lua_getmetatable l (fromIntegral n))
-
--- | See @lua_gettable@ in Lua Reference Manual.
-gettable :: LuaState -> Int -> IO ()
-gettable l n = c_lua_gettable l (fromIntegral n)
-
--- | See @lua_gettop@ in Lua Reference Manual.
-gettop :: LuaState -> IO Int
-gettop l = liftM fromIntegral (c_lua_gettop l)
-
--- | See @lua_getupvalue@ in Lua Reference Manual.
-getupvalue :: LuaState -> Int -> Int -> IO String
-getupvalue l funcindex n = c_lua_getupvalue l (fromIntegral funcindex) (fromIntegral n) >>= peekCString
-
--- | See @lua_insert@ in Lua Reference Manual.
-insert :: LuaState -> Int -> IO ()
-insert l n  = c_lua_insert l (fromIntegral n)
-
--- | See @lua_iscfunction@ in Lua Reference Manual.
-iscfunction :: LuaState -> Int -> IO Bool
-iscfunction l n = liftM (/=0) (c_lua_iscfunction l (fromIntegral n))
-
--- | See @lua_isnumber@ in Lua Reference Manual.
-isnumber :: LuaState -> Int -> IO Bool
-isnumber l n = liftM (/=0) (c_lua_isnumber l (fromIntegral n))
-
--- | See @lua_isstring@ in Lua Reference Manual.
-isstring :: LuaState -> Int -> IO Bool
-isstring l n = liftM (/=0) (c_lua_isstring l (fromIntegral n))
-
--- | See @lua_isuserdata@ in Lua Reference Manual.
-isuserdata :: LuaState -> Int -> IO Bool
-isuserdata l n = liftM (/=0) (c_lua_isuserdata l (fromIntegral n))
-
--- | See @lua_lessthan@ in Lua Reference Manual.
-lessthan :: LuaState -> Int -> Int -> IO Bool
-lessthan l i j = liftM (/=0) (c_lua_lessthan l (fromIntegral i) (fromIntegral j))
-
-
--- | See @luaL_loadfile@ in Lua Reference Manual.
-loadfile :: LuaState -> String -> IO Int
-loadfile l f = readFile f >>= \c -> loadstring l c f
-
-
-foreign import ccall "wrapper" mkStringReader :: LuaReader -> IO (FunPtr LuaReader)
-
--- | See @luaL_loadstring@ in Lua Reference Manual.
-loadstring :: LuaState -> String -> String -> IO Int
-loadstring l script cn = do
-    w <- newIORef nullPtr
-    let rd :: LuaReader
-        rd _l _d ps = do
-               k <- readIORef w
-               if k==nullPtr
-                   then do
-                       (k,l) <- newCStringLen script
-                       writeIORef w k
-                       F.poke ps (fromIntegral l)
-                       return k
-                   else do
-                       return nullPtr
-    writer <- mkStringReader rd
-    res <- withCString cn $ \cn -> c_lua_load l writer nullPtr cn
-    freeHaskellFunPtr writer
-    k <- readIORef w
-    free k
-    return (fromIntegral res)
-
--- | See @lua_newthread@ in Lua Reference Manual.
-newthread :: LuaState -> IO LuaState
-newthread l = c_lua_newthread l
-
--- | See @lua_newuserdata@ in Lua Reference Manual.
-newuserdata :: LuaState -> Int -> IO (Ptr ())
-newuserdata l s = c_lua_newuserdata l (fromIntegral s)
-
--- | See @lua_next@ in Lua Reference Manual.
-next :: LuaState -> Int -> IO Bool
-next l i = liftM (/=0) (c_lua_next l (fromIntegral i))
-
--- | See @lua_pushboolean@ in Lua Reference Manual.
-pushboolean :: LuaState -> Bool -> IO ()
-pushboolean l v = c_lua_pushboolean l (fromIntegral (fromEnum v))
-
--- | See @lua_pushinteger@ in Lua Reference Manual.
-pushinteger :: LuaState -> LuaInteger -> IO ()
-pushinteger = c_lua_pushinteger
-
--- | See @lua_pushlightuserdata@ in Lua Reference Manual.
-pushlightuserdata :: LuaState -> Ptr a -> IO ()
-pushlightuserdata = c_lua_pushlightuserdata
-
--- | See @lua_pushnil@ in Lua Reference Manual.
-pushnil :: LuaState -> IO ()
-pushnil = c_lua_pushnil
-
--- | See @lua_pushnumber@ in Lua Reference Manual.
-pushnumber :: LuaState -> LuaNumber -> IO ()
-pushnumber = c_lua_pushnumber
-
--- | See @lua_pushstring@ in Lua Reference Manual.
-pushstring :: LuaState -> String -> IO ()
-pushstring l s = withCStringLen s $ \(s,z) -> c_lua_pushlstring l s (fromIntegral z)
-
--- | See @lua_pushthread@ in Lua Reference Manual.
-pushthread :: LuaState -> IO Bool
-pushthread l = liftM (/=0) (c_lua_pushthread l)
-
--- | See @lua_pushvalue@ in Lua Reference Manual.
-pushvalue :: LuaState -> Int -> IO ()
-pushvalue l n = c_lua_pushvalue l (fromIntegral n)
-
--- | See @lua_rawequal@ in Lua Reference Manual.
-rawequal :: LuaState -> Int -> Int -> IO Bool
-rawequal l n m = liftM (/=0) (c_lua_rawequal l (fromIntegral n) (fromIntegral m))
-
--- | See @lua_rawget@ in Lua Reference Manual.
-rawget :: LuaState -> Int -> IO ()
-rawget l n = c_lua_rawget l (fromIntegral n)
-
--- | See @lua_rawgeti@ in Lua Reference Manual.
-rawgeti :: LuaState -> Int -> Int -> IO ()
-rawgeti l k m = c_lua_rawgeti l (fromIntegral k) (fromIntegral m)
-
--- | See @lua_rawset@ in Lua Reference Manual.
-rawset :: LuaState -> Int -> IO ()
-rawset l n = c_lua_rawset l (fromIntegral n)
-
--- | See @lua_rawseti@ in Lua Reference Manual.
-rawseti :: LuaState -> Int -> Int -> IO ()
-rawseti l k m = c_lua_rawseti l (fromIntegral k) (fromIntegral m)
-
--- | See @lua_remove@ in Lua Reference Manual.
-remove :: LuaState -> Int -> IO ()
-remove l n = c_lua_remove l (fromIntegral n)
-
--- | See @lua_replace@ in Lua Reference Manual.
-replace :: LuaState -> Int -> IO ()
-replace l n = c_lua_replace l (fromIntegral n)
-
--- | See @lua_resume@ in Lua Reference Manual.
-resume :: LuaState -> Int -> IO Int
-resume l n = liftM fromIntegral (c_lua_resume l (fromIntegral n))
-
--- | See @lua_setfenv@ in Lua Reference Manual.
-setfenv :: LuaState -> Int -> IO Int
-setfenv l n = liftM fromIntegral (c_lua_setfenv l (fromIntegral n))
-
--- | See @lua_setmetatable@ in Lua Reference Manual.
-setmetatable :: LuaState -> Int -> IO ()
-setmetatable l n = c_lua_setmetatable l (fromIntegral n)
-
--- | See @lua_settable@ in Lua Reference Manual.
-settable :: LuaState -> Int -> IO ()
-settable l index = c_lua_settable l (fromIntegral index)
-
-
--- | See @lua_setupvalue@ in Lua Reference Manual.
-setupvalue :: LuaState -> Int -> Int -> IO String
-setupvalue l funcindex n = c_lua_setupvalue l (fromIntegral funcindex) (fromIntegral n) >>= peekCString
-
--- | See @lua_status@ in Lua Reference Manual.
-status :: LuaState -> IO Int
-status l = liftM fromIntegral (c_lua_status l)
-
--- | See @lua_toboolean@ in Lua Reference Manual.
-toboolean :: LuaState -> Int -> IO Bool
-toboolean l n = liftM (/=0) (c_lua_toboolean l (fromIntegral n))
-
--- | See @lua_tocfunction@ in Lua Reference Manual.
-tocfunction :: LuaState -> Int -> IO (FunPtr LuaCFunction)
-tocfunction l n = c_lua_tocfunction l (fromIntegral n)
-
--- | See @lua_tointeger@ in Lua Reference Manual.
-tointeger :: LuaState -> Int -> IO LuaInteger
-tointeger l n = c_lua_tointeger l (fromIntegral n)
-
--- | See @lua_tonumber@ in Lua Reference Manual.
-tonumber :: LuaState -> Int -> IO CDouble
-tonumber l n = c_lua_tonumber l (fromIntegral n)
-
--- | See @lua_topointer@ in Lua Reference Manual.
-topointer :: LuaState -> Int -> IO (Ptr ())
-topointer l n = c_lua_topointer l (fromIntegral n)
-
--- | See @lua_register@ in Lua Reference Manual.
-register :: LuaState -> String -> FunPtr LuaCFunction -> IO ()
-register l n f = do
-    pushcclosure l f 0
-    setglobal l n
-
--- | See @luaL_newmetatable@ in Lua Reference Manual.
-newmetatable :: LuaState -> String -> IO Int
-newmetatable l s = withCString s $ \s -> liftM fromIntegral (c_luaL_newmetatable l s)
-
--- | See @luaL_argerror@ in Lua Reference Manual. Contrary to the
--- manual, Haskell function does return with value less than zero.
-argerror :: LuaState -> Int -> String -> IO CInt
-argerror l n msg = withCString msg $ \msg -> do
-    let doit l = c_luaL_argerror l (fromIntegral n) msg
-    f <- mkWrapper doit
-    c_lua_cpcall l f nullPtr
-    freeHaskellFunPtr f
-    -- here we should have error message string on top of the stack
-    return (-1)
-
--- | See @luaL_ref@ in Lua Reference Manual.
-ref :: LuaState -> Int -> IO Int
-ref l n = fmap fromIntegral $ c_luaL_ref l (fromIntegral n)
-
--- | See @luaL_unref@ in Lua Reference Manual.
-unref :: LuaState -> Int -> Int -> IO ()
-unref l t ref = c_luaL_unref l (fromIntegral t) (fromIntegral ref)
-
--- | A value that can be pushed and poped from the Lua stack.
--- All instances are natural, except following:
---
---  * @LuaState@ push ignores its argument, pushes current state
---
---  * @()@ push ignores its argument, just pushes nil
---
---  * @Ptr ()@ pushes light user data, peek checks for lightuserdata or userdata
-class StackValue a where
-    -- | Pushes a value onto Lua stack, casting it into meaningfully nearest Lua type.
-    push :: LuaState -> a -> IO ()
-    -- | Check if at index @n@ there is a convertible Lua value and if so return it
-    -- wrapped in @Just@. Return @Nothing@ otherwise.
-    peek :: LuaState -> Int -> IO (Maybe a)
-    -- | Lua type id code of the vaule expected. Parameter is unused.
-    valuetype :: a -> LTYPE
-
-maybepeek :: l -> n -> (l -> n -> IO Bool) -> (l -> n -> IO r) -> IO (Maybe r)
-maybepeek l n test peek = do
-    v <- test l n
-    if v
-        then liftM Just (peek l n)
-        else return Nothing
-
-instance StackValue LuaInteger where
-    push l x = pushinteger l x
-    peek l n = maybepeek l n isnumber tointeger
-    valuetype _ = TNUMBER
-
-instance StackValue LuaNumber where
-    push l x = pushnumber l x
-    peek l n = maybepeek l n isnumber tonumber
-    valuetype _ = TNUMBER
-
-instance StackValue Int where
-    push l x = pushinteger l (fromIntegral x)
-    peek l n = maybepeek l n isnumber (\l n -> liftM fromIntegral (tointeger l n))
-    valuetype _ = TNUMBER
-
-instance StackValue Double where
-    push l x = pushnumber l (realToFrac x)
-    peek l n = maybepeek l n isnumber (\l n -> liftM realToFrac (tonumber l n))
-    valuetype _ = TNUMBER
-
-instance StackValue String where
-    push l x = pushstring l x
-    peek l n = maybepeek l n isstring tostring
-    valuetype _ = TSTRING
-
-instance StackValue Bool where
-    push l x = pushboolean l x
-    peek l n = maybepeek l n isboolean toboolean
-    valuetype _ = TBOOLEAN
-
-instance StackValue (FunPtr LuaCFunction) where
-    push l x = pushcfunction l x
-    peek l n = maybepeek l n iscfunction tocfunction
-    valuetype _ = TFUNCTION
-
--- watch out for the asymetry here
-instance StackValue (Ptr a) where
-    push l x = pushlightuserdata l x
-    peek l n = maybepeek l n isuserdata touserdata
-    valuetype _ = TUSERDATA
-
--- watch out for push here
-instance StackValue LuaState where
-    push l _ = pushthread l >> return ()
-    peek l n = maybepeek l n isthread tothread
-    valuetype _ = TTHREAD
-
-instance StackValue () where
-    push l _ = pushnil l
-    peek l n = maybepeek l n isnil (\_l _n -> return ())
-    valuetype _ = TNIL
-
-
-{-
--- | Argument wrapper, to be used in connection with @callproc@ and @callfunc@.
-arg :: StackValue a => a -> LuaState -> IO ()
-arg a l = push l a
-
--- | Call a Lua procedure. Use as:
--- > callproc l "proc" [arg "abc", arg 1, arg 5]
-callproc :: LuaState -> String -> [LuaState -> IO ()] -> IO ()
-callproc l f as = do
-    getglobal2 l f
-    mapM_ ($ l) as
-    call l (length as) 0
-
--- | Call a Lua function. Use as:
--- > v <- callfunc l "proc" [arg "abc", arg 1, arg 5]
-callfunc :: StackValue a => LuaState -> String -> [LuaState -> IO ()] -> IO (Maybe a)
-callfunc l f as = do
-    getglobal2 l f
-    mapM_ ($ l) as
-    call l (length as) 1
-    z <- peek l (-1)
-    pop l 1
-    return z
--}
-
--- | Like @getglobal@, but knows about packages. e. g.
---
--- > getglobal l "math.sin"
---
--- returns correct result
-getglobal2 :: LuaState -> String -> IO ()
-getglobal2 l n = do
-    getglobal l x
-    mapM_ dotable xs
-    where (x:xs) = splitdot n
-          splitdot = filter (/=".") . L.groupBy (\a b -> a/='.' && b/='.')
-          dotable x = getfield l (-1) x >> gettop l >>= \n -> remove l (n-1)
-
-
-typenameindex :: LuaState -> Int -> IO String
-typenameindex l n = ltype l n >>= typename l
-
-class LuaImport a where
-    luaimport' :: Int -> a -> LuaCFunction
-    luaimportargerror :: Int -> String -> a -> LuaCFunction
-
-instance (StackValue a) => LuaImport (IO a) where
-    luaimportargerror n msg _x l = argerror l n msg
-    luaimport' _narg x l = x >>= push l >> return 1
-
-instance (StackValue a,LuaImport b) => LuaImport (a -> b) where
-    luaimportargerror n msg x l = luaimportargerror n msg (x undefined) l
-    {-
-     - FIXME: Cannot catch this exception here, because we are called from C,
-     - and error propagation, stack unwinding, etc does not work.
-     - Cannot call lua_error, because it uses longjmp and would skip two layers of abstraction.
-     -}
-    luaimport' narg x l = do
-        arg <- peek l narg
-        case arg of
-            Just v -> luaimport' (narg+1) (x v) l
-            Nothing -> do
-                t <- ltype l narg
-                exp <- typename l (valuetype (fromJust arg))
-                got <- typename l t
-                luaimportargerror narg (exp ++ " expected, got " ++ got) (x undefined) l
-
-foreign import ccall "wrapper" mkWrapper :: LuaCFunction -> IO (FunPtr LuaCFunction)
-
--- | Create new foreign Lua function. Function created can be called
--- by Lua engine. Remeber to free the pointer with @freecfunction@.
-newcfunction :: LuaImport a => a -> IO (FunPtr LuaCFunction)
-newcfunction = mkWrapper . luaimport
-
--- | Convert a Haskell function to Lua function. Any Haskell function
--- can be converted provided that:
---
---   * all arguments are instances of StackValue
---   * return type is IO t, where t is an instance of StackValue
---
--- Any Haskell exception will be converted to a string and returned
--- as Lua error.
-luaimport :: LuaImport a => a -> LuaCFunction
-luaimport a l = luaimport' 1 a l `catch` (\(e :: IOError) -> push l (show e) >> return (-1))
-
--- | Free function pointer created with @newcfunction@.
-freecfunction :: FunPtr LuaCFunction -> IO ()
-freecfunction = freeHaskellFunPtr
-
-class LuaCallProc a where
-    callproc' :: LuaState -> String -> IO () -> Int -> a
-
--- | Call a Lua procedure. Use as:
---
--- > callproc l "proc" "abc" (1::Int) (5.0::Double)
---
-callproc :: (LuaCallProc a) => LuaState -> String -> a
-callproc l f = callproc' l f (return ()) 0
-
-class LuaCallFunc a where
-    callfunc' :: LuaState -> String -> IO () -> Int -> a
-
--- | Call a Lua function. Use as:
---
--- > Just v <- callfunc l "proc" "abc" (1::Int) (5.0::Double)
-callfunc :: (LuaCallFunc a) => LuaState -> String -> a
-callfunc l f = callfunc' l f (return ()) 0
-
-instance LuaCallProc (IO t) where
-    callproc' l f a k = do
-        getglobal2 l f
-        a
-        z <- pcall l k 0 0
-        if z/=0
-            then do
-                Just msg <- peek l (-1)
-                pop l 1
-                Prelude.fail msg
-            else do
-                return undefined
-
-instance (StackValue t) => LuaCallFunc (IO t) where
-    callfunc' l f a k = do
-        getglobal2 l f
-        a
-        z <- pcall l k 1 0
-        if z/=0
-            then do
-                Just msg <- peek l (-1)
-                pop l 1
-                Prelude.fail msg
-            else do
-                r <- peek l (-1)
-                pop l 1
-                case r of
-                    Just x -> return x
-                    Nothing -> do
-                        exp <- typename l (valuetype (fromJust r))
-                        t <- ltype l (-1)
-                        got <- typename l t
-                        Prelude.fail ("Incorrect result type (" ++ exp ++ " expected, got " ++ got ++ ")")
-
-instance (StackValue t,LuaCallProc b) => LuaCallProc (t -> b) where
-    callproc' l f a k x = callproc' l f (a >> push l x) (k+1)
-
-instance (StackValue t,LuaCallFunc b) => LuaCallFunc (t -> b) where
-    callfunc' l f a k x = callfunc' l f (a >> push l x) (k+1)
-
-
-foreign export ccall hsmethod__gc :: LuaState -> IO CInt
-foreign import ccall "&hsmethod__gc" hsmethod__gc_addr :: FunPtr LuaCFunction
-
-foreign export ccall hsmethod__call :: LuaState -> IO CInt
-foreign import ccall "&hsmethod__call" hsmethod__call_addr :: FunPtr LuaCFunction
-
-hsmethod__gc :: LuaState -> IO CInt
-hsmethod__gc l = do
-    Just ptr <- peek l (-1)
-    stableptr <- F.peek (castPtr ptr)
-    freeStablePtr stableptr
-    return 0
-
-hsmethod__call :: LuaState -> IO CInt
-hsmethod__call l = do
-    Just ptr <- peek l (1)
-    remove l 1
-    stableptr <- F.peek (castPtr ptr)
-    f <- deRefStablePtr stableptr
-    f l
-
--- | Pushes Haskell function converted to a Lua function.
--- All values created will be garbage collected. Use as:
---
--- > Lua.pushhsfunction l myfun
--- > Lua.setglobal l "myfun"
---
--- You are not allowed to use @lua_error@ anywhere, but
--- use an error code of (-1) to the same effect. Push
--- error message as the sole return value.
-pushhsfunction :: LuaImport a => LuaState -> a -> IO ()
-pushhsfunction l f = do
-    stableptr <- newStablePtr (luaimport f)
-    p <- newuserdata l (F.sizeOf stableptr);
-    F.poke (castPtr p) stableptr
-    v <- newmetatable l "HaskellImportedFunction"
-    when (v/=0) $ do
-        -- create new metatable, fill it with two entries __gc and __call
-        push l hsmethod__gc_addr
-        setfield l (-2) "__gc"
-        push l c_lua_neutralize_longjmp_addr
-        setfield l (-2) "__call"
-    setmetatable l (-2)
-    return ()
-
--- | Imports a Haskell function and registers it at global name.
-registerhsfunction :: LuaImport a => LuaState -> String -> a -> IO ()
-registerhsfunction l n f = pushhsfunction l f >> setglobal l n
diff --git a/src/Scripting/Lua.hsc b/src/Scripting/Lua.hsc
new file mode 100644
--- /dev/null
+++ b/src/Scripting/Lua.hsc
@@ -0,0 +1,1120 @@
+
+{-# LANGUAGE ForeignFunctionInterface, TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind -fno-warn-unused-binds #-}
+-- |
+-- Module      : Scripting.Lua
+-- Copyright   : (c) Gracjan Polak 2007
+--
+-- License     : MIT
+--
+-- Maintainer  : omeragacan@gmail.com
+-- Stability   : alpha
+-- Portability : portable, ffi
+--
+-- A Haskell wrapper library for a scripting language Lua.
+-- See @http:\/\/www.lua.org\/@ for more details.
+--
+-- This module is intended to be imported @qualified@, eg.
+--
+-- > import qualified Scripting.Lua as Lua
+--
+-- This way we use Haskell module hierarchy to make Lua names shorter.
+-- Haskell functions are named after Lua functions, but the @lua_@ or
+-- @luaL_@ prefix.
+--
+-- Lua types are mapped to Haskell types as in the following table:
+--
+-- > int (stack index)        Int
+-- > lua_Integer              LuaInteger
+-- > lua_Number               LuaNumber
+-- > int (bool result)        Bool
+-- > const char * (string)    String
+-- > void *                   Ptr ()
+-- > lua_State *              LuaState
+--
+-- Most functions are one-to-one mappings.
+-- Rare special cases are clearly marked in this document.
+--
+-- Minmal sample embedding:
+--
+-- > import qualified Scripting.Lua as Lua
+--
+-- > main = do
+-- >     l <- Lua.newstate
+-- >     Lua.openlibs l
+-- >     Lua.callproc l "print" "Hello from Lua"
+-- >     Lua.close l
+
+module Scripting.Lua
+(
+    -- * Basic Lua types
+    LuaState(..),
+    LuaCFunction,
+    LuaInteger,
+    LuaNumber,
+    LuaImport(..),
+
+    -- * Constants and enumerations
+    GCCONTROL(..),
+    LTYPE(..),
+    multret,
+    registryindex,
+    environindex,
+    globalsindex,
+
+    -- * lua_* functions
+    atpanic,
+    call,
+    checkstack,
+    close,
+    concat,
+    cpcall,
+    createtable,
+    dump,
+    equal,
+    --error,    -- cannot import this one, as this uses setjmp/longjmp
+    gc,
+    --getallocf,
+    getfenv,
+    getfield,
+    getglobal,
+    --gethook,
+    --gethookcount,
+    --gethookmask,
+    --getinfo,
+    --getlocal,
+    getmetatable,
+    --getstack,
+    gettable,
+    gettop,
+    getupvalue,
+    insert,
+    isboolean,
+    iscfunction,
+    isfunction,
+    islightuserdata,
+    isnil,
+    isnumber,
+    isstring,
+    istable,
+    isthread,
+    isuserdata,
+    lessthan,
+    --load,
+    newstate,
+    newtable,
+    newthread,
+    newuserdata,
+    next,
+    objlen,
+    pcall,
+    pop,
+    pushboolean,
+    pushcclosure,
+    pushcfunction,
+    --pushfstring,
+    pushinteger,
+    pushlightuserdata,
+    --pushlstring,
+    pushnil,
+    pushnumber,
+    pushstring,
+    pushthread,
+    pushvalue,
+    --pushvfstring,
+    rawequal,
+    rawget,
+    rawgeti,
+    rawset,
+    rawseti,
+    register,
+    remove,
+    replace,
+    resume,
+    --setallocf,
+    setfenv,
+    setfield,
+    setglobal,
+    --sethook,
+    --setlocal,
+    setmetatable,
+    settable,
+    settop,
+    setupvalue,
+    status,
+    toboolean,
+    tocfunction,
+    tointeger,
+    --tolstring,
+    tonumber,
+    topointer,
+    tostring,
+    tothread,
+    touserdata,
+    ltype,
+    typename,
+    upvalueindex,
+    xmove,
+    yield,
+
+    -- * luaL_* functions
+    openlibs,
+    loadfile,
+    loadstring,
+    newmetatable,
+    argerror,
+    ref,
+    unref,
+
+    -- * Haskell extensions
+    StackValue(..),
+    callproc,
+    callfunc,
+    getglobal2,
+    newcfunction,
+    freecfunction,
+    luaimport,
+    pushhsfunction,
+    pushrawhsfunction,
+    registerhsfunction,
+    registerrawhsfunction
+)
+where
+import Prelude hiding (concat, catch)
+import Foreign.C
+import Foreign.Ptr
+import Foreign.StablePtr
+import Control.Monad
+import Control.Exception
+import Foreign.Marshal.Alloc
+import Data.IORef
+import qualified Foreign.Storable as F
+import qualified Data.List as L
+import Data.Maybe
+
+#include "lua.h"
+
+-- | Wrapper for @lua_State *@. See @lua_State@ in Lua Reference Manual.
+newtype LuaState = LuaState (Ptr ())
+-- | Wrapper for @lua_Alloc@. See @lua_Alloc@ in Lua Reference Manual.
+type LuaAlloc = Ptr () -> Ptr () -> CSize -> CSize -> IO (Ptr ())
+-- | Wrapper for @lua_Reader@. See @lua_Reader@ in Lua Reference Manual.
+type LuaReader = Ptr () -> Ptr () -> Ptr CSize -> IO (Ptr CChar)
+
+-- | Wrapper for @lua_Writer@. See @lua_Writer@ in Lua Reference Manual.
+type LuaWriter = LuaState -> Ptr CChar -> CSize -> Ptr () -> IO CInt
+-- | Wrapper for @lua_CFunction@. See @lua_CFunction@ in Lua Reference Manual.
+type LuaCFunction = LuaState -> IO CInt
+-- | Wrapper for @lua_Integer@. See @lua_Integer@ in Lua Reference Manual.
+-- HsLua uses C @ptrdiff_t@ as @lua_Integer@.
+type LuaInteger = CPtrdiff
+-- | Wrapper for @lua_Number@. See @lua_Number@ in Lua Reference Manual.
+-- HsLua uses C @double@ as @lua_Integer@.
+type LuaNumber = CDouble
+
+
+-- | Enumeration used as type tag. See @lua_type@ in Lua Reference Manual.
+data LTYPE = TNONE
+           | TNIL
+           | TBOOLEAN
+           | TLIGHTUSERDATA
+           | TNUMBER
+           | TSTRING
+           | TTABLE
+           | TFUNCTION
+           | TUSERDATA
+           | TTHREAD
+           deriving (Eq,Show,Ord)
+
+instance Enum LTYPE where
+    fromEnum TNONE          = #{const LUA_TNONE}
+    fromEnum TNIL           = #{const LUA_TNIL}
+    fromEnum TBOOLEAN       = #{const LUA_TBOOLEAN}
+    fromEnum TLIGHTUSERDATA = #{const LUA_TLIGHTUSERDATA}
+    fromEnum TNUMBER        = #{const LUA_TNUMBER}
+    fromEnum TSTRING        = #{const LUA_TSTRING}
+    fromEnum TTABLE         = #{const LUA_TTABLE}
+    fromEnum TFUNCTION      = #{const LUA_TFUNCTION}
+    fromEnum TUSERDATA      = #{const LUA_TUSERDATA}
+    fromEnum TTHREAD        = #{const LUA_TTHREAD}
+
+    toEnum (#{const LUA_TNONE})          = TNONE
+    toEnum (#{const LUA_TNIL})           = TNIL
+    toEnum (#{const LUA_TBOOLEAN})       = TBOOLEAN
+    toEnum (#{const LUA_TLIGHTUSERDATA}) = TLIGHTUSERDATA
+    toEnum (#{const LUA_TNUMBER})        = TNUMBER
+    toEnum (#{const LUA_TSTRING})        = TSTRING
+    toEnum (#{const LUA_TTABLE})         = TTABLE
+    toEnum (#{const LUA_TFUNCTION})      = TFUNCTION
+    toEnum (#{const LUA_TUSERDATA})      = TUSERDATA
+    toEnum (#{const LUA_TTHREAD})        = TTHREAD
+    toEnum n                             = error $ "Cannot convert (" ++ show n ++ ") to LTYPE"
+
+-- | Enumeration used by @gc@ function.
+data GCCONTROL  = GCSTOP
+                | GCRESTART
+                | GCCOLLECT
+                | GCCOUNT
+                | GCCOUNTB
+                | GCSTEP
+                | GCSETPAUSE
+                | GCSETSTEPMUL
+                deriving (Eq,Ord,Show,Enum)
+
+-- | See @LUA_MULTRET@ in Lua Reference Manual.
+multret :: Int
+multret = #{const LUA_MULTRET}
+
+{-
+
+It is unknown which of the imported function may trigger garbage collector.
+GC may in turn call some finalizars that will require come back to
+the Haskell world.
+
+This means we must declare almost all functions as 'safe'. This is slow, so
+some functions known not to call gc are marked with faster 'unsafe' modifier.
+
+-}
+foreign import ccall "lua.h lua_close" c_lua_close :: LuaState -> IO ()
+foreign import ccall "lua.h lua_newstate" c_lua_newstate :: FunPtr LuaAlloc -> Ptr () -> IO LuaState
+foreign import ccall "lua.h lua_newthread" c_lua_newthread :: LuaState -> IO LuaState
+foreign import ccall "lua.h lua_atpanic" c_lua_atpanic :: LuaState -> FunPtr LuaCFunction -> IO (FunPtr LuaCFunction)
+
+
+foreign import ccall "lua.h lua_gettop" c_lua_gettop :: LuaState -> IO CInt
+foreign import ccall "lua.h lua_settop" c_lua_settop :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_pushvalue" c_lua_pushvalue :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_remove" c_lua_remove :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_insert" c_lua_insert :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_replace" c_lua_replace :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_checkstack" c_lua_checkstack :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_xmove" c_lua_xmove :: LuaState -> LuaState -> CInt -> IO ()
+
+
+foreign import ccall "lua.h lua_isnumber" c_lua_isnumber :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_isstring" c_lua_isstring :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_iscfunction" c_lua_iscfunction :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_isuserdata" c_lua_isuserdata :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_type" c_lua_type :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_typename" c_lua_typename :: LuaState -> CInt -> IO (Ptr CChar)
+
+foreign import ccall "lua.h lua_equal" c_lua_equal :: LuaState -> CInt -> CInt -> IO CInt
+foreign import ccall "lua.h lua_rawequal" c_lua_rawequal :: LuaState -> CInt -> CInt -> IO CInt
+foreign import ccall "lua.h lua_lessthan" c_lua_lessthan :: LuaState -> CInt -> CInt -> IO CInt
+
+foreign import ccall "lua.h lua_tonumber" c_lua_tonumber :: LuaState -> CInt -> IO LuaNumber
+foreign import ccall "lua.h lua_tointeger" c_lua_tointeger :: LuaState -> CInt -> IO LuaInteger
+foreign import ccall "lua.h lua_toboolean" c_lua_toboolean :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_tolstring" c_lua_tolstring :: LuaState -> CInt -> Ptr CInt -> IO (Ptr CChar)
+foreign import ccall "lua.h lua_objlen" c_lua_objlen :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_tocfunction" c_lua_tocfunction :: LuaState -> CInt -> IO (FunPtr LuaCFunction)
+foreign import ccall "lua.h lua_touserdata" c_lua_touserdata :: LuaState -> CInt -> IO (Ptr a)
+foreign import ccall "lua.h lua_tothread" c_lua_tothread :: LuaState -> CInt -> IO LuaState
+foreign import ccall "lua.h lua_topointer" c_lua_topointer :: LuaState -> CInt -> IO (Ptr ())
+
+
+foreign import ccall "lua.h lua_pushnil" c_lua_pushnil :: LuaState -> IO ()
+foreign import ccall "lua.h lua_pushnumber" c_lua_pushnumber :: LuaState -> LuaNumber -> IO ()
+foreign import ccall "lua.h lua_pushinteger" c_lua_pushinteger :: LuaState -> LuaInteger -> IO ()
+foreign import ccall "lua.h lua_pushlstring" c_lua_pushlstring :: LuaState -> Ptr CChar -> CInt -> IO ()
+foreign import ccall "lua.h lua_pushstring" c_lua_pushstring :: LuaState -> Ptr CChar -> IO ()
+{-
+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
+                                                      va_list argp);
+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
+-}
+foreign import ccall "lua.h lua_pushcclosure" c_lua_pushcclosure :: LuaState -> FunPtr LuaCFunction -> CInt -> IO ()
+foreign import ccall "lua.h lua_pushboolean" c_lua_pushboolean :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_pushlightuserdata" c_lua_pushlightuserdata :: LuaState -> Ptr a -> IO ()
+foreign import ccall "lua.h lua_pushthread" c_lua_pushthread :: LuaState -> IO CInt
+
+
+foreign import ccall "lua.h lua_gettable" c_lua_gettable :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_getfield" c_lua_getfield :: LuaState -> CInt -> Ptr CChar -> IO ()
+foreign import ccall "lua.h lua_rawget" c_lua_rawget :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_rawgeti" c_lua_rawgeti :: LuaState -> CInt -> CInt -> IO ()
+foreign import ccall "lua.h lua_createtable" c_lua_createtable :: LuaState -> CInt -> CInt -> IO ()
+foreign import ccall "lua.h lua_newuserdata" c_lua_newuserdata :: LuaState -> CInt -> IO (Ptr ())
+foreign import ccall "lua.h lua_getmetatable" c_lua_getmetatable :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_getfenv" c_lua_getfenv :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_getupvalue" c_lua_getupvalue :: LuaState -> CInt -> CInt -> IO (Ptr CChar)
+foreign import ccall "lua.h lua_setupvalue" c_lua_setupvalue :: LuaState -> CInt -> CInt -> IO (Ptr CChar)
+
+
+foreign import ccall "lua.h lua_settable" c_lua_settable :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_setfield" c_lua_setfield :: LuaState -> CInt -> Ptr CChar -> IO ()
+foreign import ccall "lua.h lua_rawset" c_lua_rawset :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_rawseti" c_lua_rawseti :: LuaState -> CInt -> CInt -> IO ()
+foreign import ccall "lua.h lua_setmetatable" c_lua_setmetatable :: LuaState -> CInt -> IO ()
+foreign import ccall "lua.h lua_setfenv" c_lua_setfenv :: LuaState -> CInt -> IO CInt
+
+
+foreign import ccall "lua.h lua_call" c_lua_call :: LuaState -> CInt -> CInt -> IO ()
+foreign import ccall "lua.h lua_pcall" c_lua_pcall :: LuaState -> CInt -> CInt -> CInt -> IO CInt
+foreign import ccall "lua.h lua_cpcall" c_lua_cpcall :: LuaState -> FunPtr LuaCFunction -> Ptr a -> IO CInt
+
+foreign import ccall "lua.h lua_load" c_lua_load :: LuaState -> FunPtr LuaReader -> Ptr () -> Ptr CChar -> IO CInt
+
+foreign import ccall "lua.h lua_dump" c_lua_dump :: LuaState -> FunPtr LuaWriter -> Ptr () -> IO ()
+
+foreign import ccall "lua.h lua_yield" c_lua_yield :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_resume" c_lua_resume :: LuaState -> CInt -> IO CInt
+foreign import ccall "lua.h lua_status" c_lua_status :: LuaState -> IO CInt
+
+foreign import ccall "lua.h lua_gc" c_lua_gc :: LuaState -> CInt -> CInt -> IO CInt
+
+foreign import ccall "lua.h lua_error" c_lua_error :: LuaState -> IO CInt
+
+foreign import ccall "lua.h lua_next" c_lua_next :: LuaState -> CInt -> IO CInt
+
+foreign import ccall "lua.h lua_concat" c_lua_concat :: LuaState -> CInt -> IO ()
+
+foreign import ccall "lualib.h luaL_openlibs" c_luaL_openlibs :: LuaState -> IO ()
+foreign import ccall "lauxlib.h luaL_newstate" c_luaL_newstate :: IO LuaState
+foreign import ccall "lauxlib.h luaL_newmetatable" c_luaL_newmetatable :: LuaState -> Ptr CChar -> IO CInt
+foreign import ccall "lauxlib.h luaL_argerror" c_luaL_argerror :: LuaState -> CInt -> Ptr CChar -> IO CInt
+foreign import ccall "lauxlib.h luaL_ref" c_luaL_ref :: LuaState -> CInt -> IO CInt
+foreign import ccall "lauxlib.h luaL_unref" c_luaL_unref :: LuaState -> CInt -> CInt -> IO ()
+
+foreign import ccall "ntrljmp.h lua_neutralize_longjmp" c_lua_neutralize_longjmp :: LuaState -> IO CInt
+foreign import ccall "ntrljmp.h &lua_neutralize_longjmp" c_lua_neutralize_longjmp_addr :: FunPtr (LuaState -> IO CInt)
+
+
+-- | See @lua_settop@ in Lua Reference Manual.
+settop :: LuaState -> Int -> IO ()
+settop l n = c_lua_settop l (fromIntegral n)
+
+-- | See @lua_createtable@ in Lua Reference Manual.
+createtable :: LuaState -> Int -> Int -> IO ()
+createtable l s z = c_lua_createtable l (fromIntegral s) (fromIntegral z)
+
+-- | See @lua_objlen@ in Lua Reference Manual.
+objlen :: LuaState -> Int -> IO Int
+objlen l n = liftM fromIntegral (c_lua_objlen l (fromIntegral n))
+
+-- | See @lua_pop@ in Lua Reference Manual.
+pop :: LuaState -> Int -> IO ()
+pop l n = settop l (-n-1)
+
+
+-- | See @lua_newtable@ in Lua Reference Manual.
+newtable :: LuaState -> IO ()
+newtable l = createtable l 0 0
+
+-- | See @lua_pushcclosure@ in Lua Reference Manual.
+pushcclosure :: LuaState -> FunPtr LuaCFunction -> Int -> IO ()
+pushcclosure l f n = c_lua_pushcclosure l f (fromIntegral n)
+
+-- | See @lua_pushcfunction@ in Lua Reference Manual.
+pushcfunction :: LuaState -> FunPtr LuaCFunction -> IO ()
+pushcfunction l f = pushcclosure l f 0
+
+
+-- | See @lua_strlen@ in Lua Reference Manual.
+strlen :: LuaState -> Int -> IO Int
+strlen l i =  objlen l i
+
+-- | See @lua_type@ in Lua Reference Manual.
+ltype :: LuaState -> Int -> IO LTYPE
+ltype l n = liftM (toEnum . fromIntegral) (c_lua_type l (fromIntegral n))
+
+-- | See @lua_isfunction@ in Lua Reference Manual.
+isfunction :: LuaState -> Int -> IO Bool
+isfunction l n = liftM (==TFUNCTION) (ltype l n)
+
+-- | See @lua_istable@ in Lua Reference Manual.
+istable :: LuaState -> Int -> IO Bool
+istable l n = liftM (==TTABLE) (ltype l n)
+
+-- | See @lua_islightuserdata@ in Lua Reference Manual.
+islightuserdata :: LuaState -> Int -> IO Bool
+islightuserdata l n = liftM (==TLIGHTUSERDATA) (ltype l n)
+
+-- | See @lua_isnil@ in Lua Reference Manual.
+isnil :: LuaState -> Int -> IO Bool
+isnil l n = liftM (==TNIL) (ltype l n)
+
+-- | See @lua_isboolean@ in Lua Reference Manual.
+isboolean :: LuaState -> Int -> IO Bool
+isboolean l n = liftM (==TBOOLEAN) (ltype l n)
+
+-- | See @lua_isthread@ in Lua Reference Manual.
+isthread :: LuaState -> Int -> IO Bool
+isthread l n = liftM (==TTHREAD) (ltype l n)
+
+-- | See @lua_none@ in Lua Reference Manual.
+isnone :: LuaState -> Int -> IO Bool
+isnone l n = liftM (==TNONE) (ltype l n)
+
+-- | See @lua_noneornil@ in Lua Reference Manual.
+isnoneornil :: LuaState -> Int -> IO Bool
+isnoneornil l n = liftM (<=TNIL) (ltype l n)
+
+-- | See @LUA_REGISTRYINDEX@ in Lua Reference Manual.
+registryindex :: Int
+registryindex = #{const LUA_REGISTRYINDEX}
+
+-- | See @LUA_ENVIRONINDEX@ in Lua Reference Manual.
+environindex :: Int
+environindex = #{const LUA_ENVIRONINDEX}
+
+-- | See @LUA_GLOBALSINDEX@ in Lua Reference Manual.
+globalsindex :: Int
+globalsindex = #{const LUA_GLOBALSINDEX}
+
+-- | See @lua_upvalueindex@ in Lua Reference Manual.
+upvalueindex :: Int -> Int
+upvalueindex i = globalsindex - i
+
+{-
+The following seem to be really bad idea, as calls from C
+back to Haskell land are costly.
+
+Use standard Lua malloc based allocator.
+
+foreign export ccall "hslua_alloc" hslua_alloc :: Ptr () -> Ptr () -> CInt -> CInt -> IO (Ptr ())
+foreign import ccall "&hslua_alloc" hslua_alloc_addr :: FunPtr LuaAlloc
+
+hslua_alloc :: Ptr () -> Ptr () -> CInt -> CInt -> IO (Ptr ())
+hslua_alloc ud ptr osize nsize = reallocBytes ptr (fromIntegral nsize)
+
+static void *l_alloc (void *ud, void *ptr, size_t osize,
+                                                size_t nsize) {
+       (void)ud;  (void)osize;  /* not used */
+       if (nsize == 0) {
+         free(ptr);
+         return NULL;
+       }
+       else
+         return realloc(ptr, nsize);
+     }
+-}
+
+-- | See @lua_atpanic@ in Lua Reference Manual.
+atpanic :: LuaState -> FunPtr LuaCFunction -> IO (FunPtr LuaCFunction)
+atpanic = c_lua_atpanic
+
+-- | See @lua_tostring@ in Lua Reference Manual.
+tostring :: LuaState -> Int -> IO String
+tostring l n = alloca $ \lenPtr -> do
+    cstr <- c_lua_tolstring l (fromIntegral n) lenPtr
+    len <- F.peek lenPtr
+    peekCStringLen (cstr, fromIntegral len)
+
+-- | See @lua_tothread@ in Lua Reference Manual.
+tothread :: LuaState -> Int -> IO LuaState
+tothread l n = c_lua_tothread l (fromIntegral n)
+
+-- | See @lua_touserdata@ in Lua Reference Manual.
+touserdata :: LuaState -> Int -> IO (Ptr a)
+touserdata l n = c_lua_touserdata l (fromIntegral n)
+
+-- | See @lua_typename@ in Lua Reference Manual.
+typename :: LuaState -> LTYPE -> IO String
+typename l n = c_lua_typename l (fromIntegral (fromEnum n)) >>= peekCString
+
+-- | See @lua_xmove@ in Lua Reference Manual.
+xmove :: LuaState -> LuaState -> Int -> IO ()
+xmove l1 l2 n = c_lua_xmove l1 l2 (fromIntegral n)
+
+-- | See @lua_yield@ in Lua Reference Manual.
+yield :: LuaState -> Int -> IO Int
+yield l n = liftM fromIntegral (c_lua_yield l (fromIntegral n))
+
+-- | See @lua_checkstack@ in Lua Reference Manual.
+checkstack :: LuaState -> Int -> IO Bool
+checkstack l n = liftM (/=0) (c_lua_checkstack l (fromIntegral n))
+
+-- | See @lua_newstate@ and @luaL_newstate@ in Lua Reference Manual.
+newstate :: IO LuaState
+newstate = c_luaL_newstate
+
+-- | See @lua_close@ in Lua Reference Manual.
+close :: LuaState -> IO ()
+close = c_lua_close
+
+-- | See @lua_concat@ in Lua Reference Manual.
+concat :: LuaState -> Int -> IO ()
+concat l n = c_lua_concat l (fromIntegral n)
+
+
+
+-- | See @lua_call@ and @lua_call@ in Lua Reference Manual. This is
+-- a wrapper over @lua_pcall@, as @lua_call@ is unsafe in controlled environment
+-- like Haskell VM.
+call :: LuaState -> Int -> Int -> IO ()
+call l a b = c_lua_call l (fromIntegral a) (fromIntegral b)
+
+-- | See @lua_pcall@ in Lua Reference Manual.
+pcall :: LuaState -> Int -> Int -> Int -> IO Int
+pcall l a b c = liftM fromIntegral (c_lua_pcall l (fromIntegral a) (fromIntegral b) (fromIntegral c))
+
+-- | See @lua_cpcall@ in Lua Reference Manual.
+cpcall :: LuaState -> FunPtr LuaCFunction -> Ptr a -> IO Int
+cpcall l a c = liftM fromIntegral (c_lua_cpcall l a c)
+
+-- | See @lua_getfield@ in Lua Reference Manual.
+getfield :: LuaState -> Int -> String -> IO ()
+getfield l i n = withCString n $ \n -> c_lua_getfield l (fromIntegral i) n
+
+-- | See @lua_setfield@ in Lua Reference Manual.
+setfield :: LuaState -> Int -> String -> IO ()
+setfield l i n = withCString n $ \n -> c_lua_setfield l (fromIntegral i) n
+
+-- | See @lua_getglobal@ in Lua Reference Manual.
+getglobal :: LuaState -> String -> IO ()
+getglobal l n = getfield l globalsindex n
+
+-- | See @lua_setglobal@ in Lua Reference Manual.
+setglobal :: LuaState -> String -> IO ()
+setglobal l n = setfield l globalsindex n
+
+-- | See @luaL_openlibs@ in Lua Reference Manual.
+openlibs :: LuaState -> IO ()
+openlibs = c_luaL_openlibs
+
+foreign import ccall "wrapper" mkStringWriter :: LuaWriter -> IO (FunPtr LuaWriter)
+
+dump :: LuaState -> IO String
+dump l = do
+    r <- newIORef ""
+    let wr :: LuaWriter
+        wr _l p s _d = do
+               k <- peekCStringLen (p,fromIntegral s)
+               modifyIORef r (++k)
+               return 0
+    writer <- mkStringWriter wr
+    c_lua_dump l writer nullPtr
+    freeHaskellFunPtr writer
+    readIORef r
+
+-- | See @lua_equal@ in Lua Reference Manual.
+equal :: LuaState -> Int -> Int -> IO Bool
+equal l i j = liftM (/=0) (c_lua_equal l (fromIntegral i) (fromIntegral j))
+
+-- | See @lua_error@ in Lua Reference Manual.
+--error :: LuaState -> IO Int
+--error l = liftM fromIntegral (c_lua_error l)
+
+-- | See @lua_gc@ in Lua Reference Manual.
+gc :: LuaState -> GCCONTROL -> Int -> IO Int
+gc l i j= liftM fromIntegral (c_lua_gc l (fromIntegral (fromEnum i)) (fromIntegral j))
+
+-- | See @lua_getfenv@ in Lua Reference Manual.
+getfenv :: LuaState -> Int -> IO ()
+getfenv l n = c_lua_getfenv l (fromIntegral n)
+
+-- | See @lua_getmetatable@ in Lua Reference Manual.
+getmetatable :: LuaState -> Int -> IO Bool
+getmetatable l n = liftM (/=0) (c_lua_getmetatable l (fromIntegral n))
+
+-- | See @lua_gettable@ in Lua Reference Manual.
+gettable :: LuaState -> Int -> IO ()
+gettable l n = c_lua_gettable l (fromIntegral n)
+
+-- | See @lua_gettop@ in Lua Reference Manual.
+gettop :: LuaState -> IO Int
+gettop l = liftM fromIntegral (c_lua_gettop l)
+
+-- | See @lua_getupvalue@ in Lua Reference Manual.
+getupvalue :: LuaState -> Int -> Int -> IO String
+getupvalue l funcindex n = c_lua_getupvalue l (fromIntegral funcindex) (fromIntegral n) >>= peekCString
+
+-- | See @lua_insert@ in Lua Reference Manual.
+insert :: LuaState -> Int -> IO ()
+insert l n  = c_lua_insert l (fromIntegral n)
+
+-- | See @lua_iscfunction@ in Lua Reference Manual.
+iscfunction :: LuaState -> Int -> IO Bool
+iscfunction l n = liftM (/=0) (c_lua_iscfunction l (fromIntegral n))
+
+-- | See @lua_isnumber@ in Lua Reference Manual.
+isnumber :: LuaState -> Int -> IO Bool
+isnumber l n = liftM (/=0) (c_lua_isnumber l (fromIntegral n))
+
+-- | See @lua_isstring@ in Lua Reference Manual.
+isstring :: LuaState -> Int -> IO Bool
+isstring l n = liftM (/=0) (c_lua_isstring l (fromIntegral n))
+
+-- | See @lua_isuserdata@ in Lua Reference Manual.
+isuserdata :: LuaState -> Int -> IO Bool
+isuserdata l n = liftM (/=0) (c_lua_isuserdata l (fromIntegral n))
+
+-- | See @lua_lessthan@ in Lua Reference Manual.
+lessthan :: LuaState -> Int -> Int -> IO Bool
+lessthan l i j = liftM (/=0) (c_lua_lessthan l (fromIntegral i) (fromIntegral j))
+
+
+-- | See @luaL_loadfile@ in Lua Reference Manual.
+loadfile :: LuaState -> String -> IO Int
+loadfile l f = readFile f >>= \c -> loadstring l c f
+
+
+foreign import ccall "wrapper" mkStringReader :: LuaReader -> IO (FunPtr LuaReader)
+
+-- | See @luaL_loadstring@ in Lua Reference Manual.
+loadstring :: LuaState -> String -> String -> IO Int
+loadstring l script cn = do
+    w <- newIORef nullPtr
+    let rd :: LuaReader
+        rd _l _d ps = do
+               k <- readIORef w
+               if k==nullPtr
+                   then do
+                       (k,l) <- newCStringLen script
+                       writeIORef w k
+                       F.poke ps (fromIntegral l)
+                       return k
+                   else do
+                       return nullPtr
+    writer <- mkStringReader rd
+    res <- withCString cn $ \cn -> c_lua_load l writer nullPtr cn
+    freeHaskellFunPtr writer
+    k <- readIORef w
+    free k
+    return (fromIntegral res)
+
+-- | See @lua_newthread@ in Lua Reference Manual.
+newthread :: LuaState -> IO LuaState
+newthread l = c_lua_newthread l
+
+-- | See @lua_newuserdata@ in Lua Reference Manual.
+newuserdata :: LuaState -> Int -> IO (Ptr ())
+newuserdata l s = c_lua_newuserdata l (fromIntegral s)
+
+-- | See @lua_next@ in Lua Reference Manual.
+next :: LuaState -> Int -> IO Bool
+next l i = liftM (/=0) (c_lua_next l (fromIntegral i))
+
+-- | See @lua_pushboolean@ in Lua Reference Manual.
+pushboolean :: LuaState -> Bool -> IO ()
+pushboolean l v = c_lua_pushboolean l (fromIntegral (fromEnum v))
+
+-- | See @lua_pushinteger@ in Lua Reference Manual.
+pushinteger :: LuaState -> LuaInteger -> IO ()
+pushinteger = c_lua_pushinteger
+
+-- | See @lua_pushlightuserdata@ in Lua Reference Manual.
+pushlightuserdata :: LuaState -> Ptr a -> IO ()
+pushlightuserdata = c_lua_pushlightuserdata
+
+-- | See @lua_pushnil@ in Lua Reference Manual.
+pushnil :: LuaState -> IO ()
+pushnil = c_lua_pushnil
+
+-- | See @lua_pushnumber@ in Lua Reference Manual.
+pushnumber :: LuaState -> LuaNumber -> IO ()
+pushnumber = c_lua_pushnumber
+
+-- | See @lua_pushstring@ in Lua Reference Manual.
+pushstring :: LuaState -> String -> IO ()
+pushstring l s = withCStringLen s $ \(s,z) -> c_lua_pushlstring l s (fromIntegral z)
+
+-- | See @lua_pushthread@ in Lua Reference Manual.
+pushthread :: LuaState -> IO Bool
+pushthread l = liftM (/=0) (c_lua_pushthread l)
+
+-- | See @lua_pushvalue@ in Lua Reference Manual.
+pushvalue :: LuaState -> Int -> IO ()
+pushvalue l n = c_lua_pushvalue l (fromIntegral n)
+
+-- | See @lua_rawequal@ in Lua Reference Manual.
+rawequal :: LuaState -> Int -> Int -> IO Bool
+rawequal l n m = liftM (/=0) (c_lua_rawequal l (fromIntegral n) (fromIntegral m))
+
+-- | See @lua_rawget@ in Lua Reference Manual.
+rawget :: LuaState -> Int -> IO ()
+rawget l n = c_lua_rawget l (fromIntegral n)
+
+-- | See @lua_rawgeti@ in Lua Reference Manual.
+rawgeti :: LuaState -> Int -> Int -> IO ()
+rawgeti l k m = c_lua_rawgeti l (fromIntegral k) (fromIntegral m)
+
+-- | See @lua_rawset@ in Lua Reference Manual.
+rawset :: LuaState -> Int -> IO ()
+rawset l n = c_lua_rawset l (fromIntegral n)
+
+-- | See @lua_rawseti@ in Lua Reference Manual.
+rawseti :: LuaState -> Int -> Int -> IO ()
+rawseti l k m = c_lua_rawseti l (fromIntegral k) (fromIntegral m)
+
+-- | See @lua_remove@ in Lua Reference Manual.
+remove :: LuaState -> Int -> IO ()
+remove l n = c_lua_remove l (fromIntegral n)
+
+-- | See @lua_replace@ in Lua Reference Manual.
+replace :: LuaState -> Int -> IO ()
+replace l n = c_lua_replace l (fromIntegral n)
+
+-- | See @lua_resume@ in Lua Reference Manual.
+resume :: LuaState -> Int -> IO Int
+resume l n = liftM fromIntegral (c_lua_resume l (fromIntegral n))
+
+-- | See @lua_setfenv@ in Lua Reference Manual.
+setfenv :: LuaState -> Int -> IO Int
+setfenv l n = liftM fromIntegral (c_lua_setfenv l (fromIntegral n))
+
+-- | See @lua_setmetatable@ in Lua Reference Manual.
+setmetatable :: LuaState -> Int -> IO ()
+setmetatable l n = c_lua_setmetatable l (fromIntegral n)
+
+-- | See @lua_settable@ in Lua Reference Manual.
+settable :: LuaState -> Int -> IO ()
+settable l index = c_lua_settable l (fromIntegral index)
+
+
+-- | See @lua_setupvalue@ in Lua Reference Manual.
+setupvalue :: LuaState -> Int -> Int -> IO String
+setupvalue l funcindex n = c_lua_setupvalue l (fromIntegral funcindex) (fromIntegral n) >>= peekCString
+
+-- | See @lua_status@ in Lua Reference Manual.
+status :: LuaState -> IO Int
+status l = liftM fromIntegral (c_lua_status l)
+
+-- | See @lua_toboolean@ in Lua Reference Manual.
+toboolean :: LuaState -> Int -> IO Bool
+toboolean l n = liftM (/=0) (c_lua_toboolean l (fromIntegral n))
+
+-- | See @lua_tocfunction@ in Lua Reference Manual.
+tocfunction :: LuaState -> Int -> IO (FunPtr LuaCFunction)
+tocfunction l n = c_lua_tocfunction l (fromIntegral n)
+
+-- | See @lua_tointeger@ in Lua Reference Manual.
+tointeger :: LuaState -> Int -> IO LuaInteger
+tointeger l n = c_lua_tointeger l (fromIntegral n)
+
+-- | See @lua_tonumber@ in Lua Reference Manual.
+tonumber :: LuaState -> Int -> IO CDouble
+tonumber l n = c_lua_tonumber l (fromIntegral n)
+
+-- | See @lua_topointer@ in Lua Reference Manual.
+topointer :: LuaState -> Int -> IO (Ptr ())
+topointer l n = c_lua_topointer l (fromIntegral n)
+
+-- | See @lua_register@ in Lua Reference Manual.
+register :: LuaState -> String -> FunPtr LuaCFunction -> IO ()
+register l n f = do
+    pushcclosure l f 0
+    setglobal l n
+
+-- | See @luaL_newmetatable@ in Lua Reference Manual.
+newmetatable :: LuaState -> String -> IO Int
+newmetatable l s = withCString s $ \s -> liftM fromIntegral (c_luaL_newmetatable l s)
+
+-- | See @luaL_argerror@ in Lua Reference Manual. Contrary to the
+-- manual, Haskell function does return with value less than zero.
+argerror :: LuaState -> Int -> String -> IO CInt
+argerror l n msg = withCString msg $ \msg -> do
+    let doit l = c_luaL_argerror l (fromIntegral n) msg
+    f <- mkWrapper doit
+    c_lua_cpcall l f nullPtr
+    freeHaskellFunPtr f
+    -- here we should have error message string on top of the stack
+    return (-1)
+
+-- | See @luaL_ref@ in Lua Reference Manual.
+ref :: LuaState -> Int -> IO Int
+ref l n = fmap fromIntegral $ c_luaL_ref l (fromIntegral n)
+
+-- | See @luaL_unref@ in Lua Reference Manual.
+unref :: LuaState -> Int -> Int -> IO ()
+unref l t ref = c_luaL_unref l (fromIntegral t) (fromIntegral ref)
+
+-- | A value that can be pushed and poped from the Lua stack.
+-- All instances are natural, except following:
+--
+--  * @LuaState@ push ignores its argument, pushes current state
+--
+--  * @()@ push ignores its argument, just pushes nil
+--
+--  * @Ptr ()@ pushes light user data, peek checks for lightuserdata or userdata
+class StackValue a where
+    -- | Pushes a value onto Lua stack, casting it into meaningfully nearest Lua type.
+    push :: LuaState -> a -> IO ()
+    -- | Check if at index @n@ there is a convertible Lua value and if so return it
+    -- wrapped in @Just@. Return @Nothing@ otherwise.
+    peek :: LuaState -> Int -> IO (Maybe a)
+    -- | Lua type id code of the vaule expected. Parameter is unused.
+    valuetype :: a -> LTYPE
+
+maybepeek :: l -> n -> (l -> n -> IO Bool) -> (l -> n -> IO r) -> IO (Maybe r)
+maybepeek l n test peek = do
+    v <- test l n
+    if v
+        then liftM Just (peek l n)
+        else return Nothing
+
+instance StackValue LuaInteger where
+    push l x = pushinteger l x
+    peek l n = maybepeek l n isnumber tointeger
+    valuetype _ = TNUMBER
+
+instance StackValue LuaNumber where
+    push l x = pushnumber l x
+    peek l n = maybepeek l n isnumber tonumber
+    valuetype _ = TNUMBER
+
+instance StackValue Int where
+    push l x = pushinteger l (fromIntegral x)
+    peek l n = maybepeek l n isnumber (\l n -> liftM fromIntegral (tointeger l n))
+    valuetype _ = TNUMBER
+
+instance StackValue Double where
+    push l x = pushnumber l (realToFrac x)
+    peek l n = maybepeek l n isnumber (\l n -> liftM realToFrac (tonumber l n))
+    valuetype _ = TNUMBER
+
+instance StackValue String where
+    push l x = pushstring l x
+    peek l n = maybepeek l n isstring tostring
+    valuetype _ = TSTRING
+
+instance StackValue Bool where
+    push l x = pushboolean l x
+    peek l n = maybepeek l n isboolean toboolean
+    valuetype _ = TBOOLEAN
+
+instance StackValue (FunPtr LuaCFunction) where
+    push l x = pushcfunction l x
+    peek l n = maybepeek l n iscfunction tocfunction
+    valuetype _ = TFUNCTION
+
+-- watch out for the asymetry here
+instance StackValue (Ptr a) where
+    push l x = pushlightuserdata l x
+    peek l n = maybepeek l n isuserdata touserdata
+    valuetype _ = TUSERDATA
+
+-- watch out for push here
+instance StackValue LuaState where
+    push l _ = pushthread l >> return ()
+    peek l n = maybepeek l n isthread tothread
+    valuetype _ = TTHREAD
+
+instance StackValue () where
+    push l _ = pushnil l
+    peek l n = maybepeek l n isnil (\_l _n -> return ())
+    valuetype _ = TNIL
+
+
+{-
+-- | Argument wrapper, to be used in connection with @callproc@ and @callfunc@.
+arg :: StackValue a => a -> LuaState -> IO ()
+arg a l = push l a
+
+-- | Call a Lua procedure. Use as:
+-- > callproc l "proc" [arg "abc", arg 1, arg 5]
+callproc :: LuaState -> String -> [LuaState -> IO ()] -> IO ()
+callproc l f as = do
+    getglobal2 l f
+    mapM_ ($ l) as
+    call l (length as) 0
+
+-- | Call a Lua function. Use as:
+-- > v <- callfunc l "proc" [arg "abc", arg 1, arg 5]
+callfunc :: StackValue a => LuaState -> String -> [LuaState -> IO ()] -> IO (Maybe a)
+callfunc l f as = do
+    getglobal2 l f
+    mapM_ ($ l) as
+    call l (length as) 1
+    z <- peek l (-1)
+    pop l 1
+    return z
+-}
+
+-- | Like @getglobal@, but knows about packages. e. g.
+--
+-- > getglobal l "math.sin"
+--
+-- returns correct result
+getglobal2 :: LuaState -> String -> IO ()
+getglobal2 l n = do
+    getglobal l x
+    mapM_ dotable xs
+    where (x:xs) = splitdot n
+          splitdot = filter (/=".") . L.groupBy (\a b -> a/='.' && b/='.')
+          dotable x = getfield l (-1) x >> gettop l >>= \n -> remove l (n-1)
+
+
+typenameindex :: LuaState -> Int -> IO String
+typenameindex l n = ltype l n >>= typename l
+
+class LuaImport a where
+    luaimport' :: Int -> a -> LuaCFunction
+    luaimportargerror :: Int -> String -> a -> LuaCFunction
+
+instance (StackValue a) => LuaImport (IO a) where
+    luaimportargerror n msg _x l = argerror l n msg
+    luaimport' _narg x l = x >>= push l >> return 1
+
+instance (StackValue a,LuaImport b) => LuaImport (a -> b) where
+    luaimportargerror n msg x l = luaimportargerror n msg (x undefined) l
+    {-
+     - FIXME: Cannot catch this exception here, because we are called from C,
+     - and error propagation, stack unwinding, etc does not work.
+     - Cannot call lua_error, because it uses longjmp and would skip two layers of abstraction.
+     -}
+    luaimport' narg x l = do
+        arg <- peek l narg
+        case arg of
+            Just v -> luaimport' (narg+1) (x v) l
+            Nothing -> do
+                t <- ltype l narg
+                exp <- typename l (valuetype (fromJust arg))
+                got <- typename l t
+                luaimportargerror narg (exp ++ " expected, got " ++ got) (x undefined) l
+
+foreign import ccall "wrapper" mkWrapper :: LuaCFunction -> IO (FunPtr LuaCFunction)
+
+-- | Create new foreign Lua function. Function created can be called
+-- by Lua engine. Remeber to free the pointer with @freecfunction@.
+newcfunction :: LuaImport a => a -> IO (FunPtr LuaCFunction)
+newcfunction = mkWrapper . luaimport
+
+-- | Convert a Haskell function to Lua function. Any Haskell function
+-- can be converted provided that:
+--
+--   * all arguments are instances of StackValue
+--   * return type is IO t, where t is an instance of StackValue
+--
+-- Any Haskell exception will be converted to a string and returned
+-- as Lua error.
+luaimport :: LuaImport a => a -> LuaCFunction
+luaimport a l = luaimport' 1 a l `catch` (\(e :: IOError) -> push l (show e) >> return (-1))
+
+-- | Free function pointer created with @newcfunction@.
+freecfunction :: FunPtr LuaCFunction -> IO ()
+freecfunction = freeHaskellFunPtr
+
+class LuaCallProc a where
+    callproc' :: LuaState -> String -> IO () -> Int -> a
+
+-- | Call a Lua procedure. Use as:
+--
+-- > callproc l "proc" "abc" (1::Int) (5.0::Double)
+--
+callproc :: (LuaCallProc a) => LuaState -> String -> a
+callproc l f = callproc' l f (return ()) 0
+
+class LuaCallFunc a where
+    callfunc' :: LuaState -> String -> IO () -> Int -> a
+
+-- | Call a Lua function. Use as:
+--
+-- > Just v <- callfunc l "proc" "abc" (1::Int) (5.0::Double)
+callfunc :: (LuaCallFunc a) => LuaState -> String -> a
+callfunc l f = callfunc' l f (return ()) 0
+
+instance LuaCallProc (IO t) where
+    callproc' l f a k = do
+        getglobal2 l f
+        a
+        z <- pcall l k 0 0
+        if z/=0
+            then do
+                Just msg <- peek l (-1)
+                pop l 1
+                fail msg
+            else do
+                return undefined
+
+instance (StackValue t) => LuaCallFunc (IO t) where
+    callfunc' l f a k = do
+        getglobal2 l f
+        a
+        z <- pcall l k 1 0
+        if z/=0
+            then do
+                Just msg <- peek l (-1)
+                pop l 1
+                fail msg
+            else do
+                r <- peek l (-1)
+                pop l 1
+                case r of
+                    Just x -> return x
+                    Nothing -> do
+                        exp <- typename l (valuetype (fromJust r))
+                        t <- ltype l (-1)
+                        got <- typename l t
+                        fail ("Incorrect result type (" ++ exp ++ " expected, got " ++ got ++ ")")
+
+instance (StackValue t,LuaCallProc b) => LuaCallProc (t -> b) where
+    callproc' l f a k x = callproc' l f (a >> push l x) (k+1)
+
+instance (StackValue t,LuaCallFunc b) => LuaCallFunc (t -> b) where
+    callfunc' l f a k x = callfunc' l f (a >> push l x) (k+1)
+
+
+foreign export ccall hsmethod__gc :: LuaState -> IO CInt
+foreign import ccall "&hsmethod__gc" hsmethod__gc_addr :: FunPtr LuaCFunction
+
+foreign export ccall hsmethod__call :: LuaState -> IO CInt
+foreign import ccall "&hsmethod__call" hsmethod__call_addr :: FunPtr LuaCFunction
+
+hsmethod__gc :: LuaState -> IO CInt
+hsmethod__gc l = do
+    Just ptr <- peek l (-1)
+    stableptr <- F.peek (castPtr ptr)
+    freeStablePtr stableptr
+    return 0
+
+hsmethod__call :: LuaState -> IO CInt
+hsmethod__call l = do
+    Just ptr <- peek l 1
+    remove l 1
+    stableptr <- F.peek (castPtr ptr)
+    f <- deRefStablePtr stableptr
+    f l
+
+
+-- | Pushes Haskell function converted to a Lua function.
+-- All values created will be garbage collected. Use as:
+--
+-- > Lua.pushhsfunction l myfun
+-- > Lua.setglobal l "myfun"
+--
+-- You are not allowed to use @lua_error@ anywhere, but
+-- use an error code of (-1) to the same effect. Push
+-- error message as the sole return value.
+pushhsfunction :: LuaImport a => LuaState -> a -> IO ()
+pushhsfunction l f = do
+    stableptr <- newStablePtr (luaimport f)
+    p <- newuserdata l (F.sizeOf stableptr);
+    F.poke (castPtr p) stableptr
+    v <- newmetatable l "HaskellImportedFunction"
+    when (v/=0) $ do
+        -- create new metatable, fill it with two entries __gc and __call
+        push l hsmethod__gc_addr
+        setfield l (-2) "__gc"
+        push l c_lua_neutralize_longjmp_addr
+        setfield l (-2) "__call"
+    setmetatable l (-2)
+    return ()
+
+-- | Pushes _raw_ Haskell function converted to a Lua function.
+-- Raw Haskell functions collect parameters from the stack and return
+-- a `CInt` that represents number of return values left in the stack.
+pushrawhsfunction :: LuaState -> (LuaState -> IO CInt) -> IO ()
+pushrawhsfunction l f = do
+    stableptr <- newStablePtr f
+    p <- newuserdata l (F.sizeOf stableptr);
+    F.poke (castPtr p) stableptr
+    v <- newmetatable l "HaskellImportedFunction"
+    when (v/=0) $ do
+        -- create new metatable, fill it with two entries __gc and __call
+        push l hsmethod__gc_addr
+        setfield l (-2) "__gc"
+        push l c_lua_neutralize_longjmp_addr
+        setfield l (-2) "__call"
+    setmetatable l (-2)
+    return ()
+
+-- | Imports a Haskell function and registers it at global name.
+registerhsfunction :: LuaImport a => LuaState -> String -> a -> IO ()
+registerhsfunction l n f = pushhsfunction l f >> setglobal l n
+
+-- | Imports a raw Haskell function and registers it at global name.
+registerrawhsfunction :: LuaState -> String -> (LuaState -> IO CInt) -> IO ()
+registerrawhsfunction l n f = pushrawhsfunction l f >> setglobal l n
+
diff --git a/src/Scripting/Lua/ConfigFile.hs b/src/Scripting/Lua/ConfigFile.hs
--- a/src/Scripting/Lua/ConfigFile.hs
+++ b/src/Scripting/Lua/ConfigFile.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveDataTypeable #-} 
+{-# LANGUAGE DeriveDataTypeable #-}
 
 -- |
 -- Module      : Scripting.Lua.ConfigFile
@@ -70,7 +70,7 @@
 
 -- | Returns a boolean value from a configuration file.  Returns @False@
 -- if the value is not defined in the file.  Example:
--- 
+--
 -- > someVal = true
 getBool :: Config -> String -> IO Bool
 getBool (Config l) name = do
@@ -83,7 +83,7 @@
 
 -- | Returns a string value from a configuration file.  Returns the
 -- empty string if the value is not defined in the file.  Example:
--- 
+--
 -- > someVal = "foo"
 getString :: Config -> String -> IO String
 getString (Config l) name = do
@@ -95,7 +95,7 @@
               "expected string value: " ++ name
 
 -- | Returns an integer value from a configuration file.  Example:
--- 
+--
 -- > someVal = 2
 getInt :: Config -> String -> IO (Maybe Int)
 getInt (Config l) name = do
@@ -107,7 +107,7 @@
               "expected numeric value: " ++ name
 
 -- | Returns a double value from a configuration file.  Example:
--- 
+--
 -- > someVal = 3.1415926
 getDouble :: Config -> String -> IO (Maybe Double)
 getDouble (Config l) name = do
@@ -121,7 +121,7 @@
 -- | Returns a list of strings (i.e. a Lua table in which the keys
 -- are integers and the values are strings) from a configuration file.
 -- Example:
--- 
+--
 -- > someVal = { "foo", "bar", "baz" }
 getList :: Config -> String -> IO [String]
 getList (Config l) name =
@@ -130,7 +130,7 @@
 -- | Returns a list of lists, i.e. a Lua table of tables.  In the outer
 -- table, the keys are integers and the values are tables, and in the inner
 -- tables, the keys are integers and the values are strings.  Example:
--- 
+--
 -- > someVal = {
 -- >    { "foo one", "foo two", "foo three" },
 -- >    { "bar one", "bar two", "bar three" }
@@ -141,7 +141,7 @@
 
 -- | Returns an association list, i.e. a Lua table in which the keys
 -- and values are strings.  Example:
--- 
+--
 -- > someVal = {
 -- >    one = "foo",
 -- >    two = "bar",
@@ -154,7 +154,7 @@
 -- | Returns a list of association lists, i.e. a Lua table of tables.
 -- In the outer table, the keys are integers and the values are tables,
 -- and in the inner tables, the keys and values are strings.  Example:
--- 
+--
 -- > someVal = {
 -- >    {
 -- >       foo = "aaa",
@@ -175,7 +175,7 @@
 -- of tables.  In the outer table, the keys are strings and the values
 -- are tables, and in the inner tables, the keys and values are strings.
 -- Example:
--- 
+--
 -- > someVal = {
 -- >    something = {
 -- >       foo = "aaa",
@@ -199,13 +199,13 @@
 Gets a Lua global and pops it off the Lua stack.
 
 -}
-getGlobalVal l name = do  
+getGlobalVal l name = do
   Lua.getglobal l name
   val <- Lua.peek l (-1)
   valType <- Lua.ltype l (-1)
   Lua.pop l 1
   return (val, valType)
-  
+
 {-
 
 Checks whether a value can be converted to a string.
@@ -233,11 +233,11 @@
                      return items
     Lua.TNIL -> return []
     _ -> liftIO $ throwIO $ ConfigFileException $ "expected table: " ++ name
-  
 
+
 {-
 
-Iterates over the elements of a Lua table whose keys are integers,  
+Iterates over the elements of a Lua table whose keys are integers,
 performs some action on each element, and returns the results as a
 list.
 
@@ -377,8 +377,8 @@
       else liftIO $ throwIO $ ConfigFileException $
            "expected string keys and string values: " ++ name
     else return []
-  
-{- 
+
+{-
 
 These are liftIO wrappers for the Lua functions we use, to reduce
 clutter in the monadic code above.
