hslua
A Lua language interpreter embedding in Haskell
Version on this page: | 0.9.5.2 |
LTS Haskell 23.0: | 2.3.1 |
Stackage Nightly 2024-12-13: | 2.3.1 |
Latest on Hackage: | 2.3.1 |
hslua-0.9.5.2@sha256:dfe2e0e277a1790525fdb5fa0289e154208e63fe8818ee90c3769b8dbd45f87c,7963
Module documentation for 0.9.5.2
hslua – Lua interpreter interface for Haskell
Hslua provides bindings, wrappers, types, and helper functions to bridge haskell and lua.
Overview
Lua is a small, well-designed, embeddable scripting language. It has become the de-facto default to make programs extensible and is widely used everywhere from servers over games and desktop applications up to security software and embedded devices. This package provides Haskell bindings to Lua, enable coders to embed the language into their programs, making them scriptable.
HsLua ships with batteries included and includes the most recent Lua version. However, cabal flags make it easy to swap this out in favor of a Lua version already installed on the host system. It supports the versions 5.1, 5.2, 5.3, and LuaJIT.
Interacting with Lua
HsLua provides the Lua
type to define Lua operations. The operations are
executed by calling runLua
. A simple “Hello, World” program, using the Lua
print
function, is given below:
import Foreign.Lua
main :: IO ()
main = runLua prog
where
prog :: Lua ()
prog = do
openlibs -- load lua libraries so we can use 'print'
callFunc "print" "Hello, World!"
The Lua stack
Lua’s API is stack-centered: most operations involve pushing values to the stack
or receiving items from the stack. E.g., calling a function is performed by
pushing the function onto the stack, followed by the function arguments in the
order they should be passed to the function. The API function call
then
invokes the function with given numbers of arguments, pops the function and
parameters of the stack, and pushes the results.
,----------.
| arg 3 |
+----------+
| arg 2 |
+----------+
| arg 1 |
+----------+ ,----------.
| function | call 3 1 | result 1 |
+----------+ ===========> +----------+
| | | |
| stack | | stack |
| | | |
Manually pushing and pulling arguments can become tiresome, so HsLua makes
function calling simple by providing callFunc
. It uses type-magic to allow
different numbers of arguments. Think about it as having the signature
callFunc :: String -> a1 -> a2 -> … -> res
where the arguments a1, a2, …
must be of a type which can be pushed to the Lua
stack, and the result-type res
must be constructable from a value on the Lua
stack.
Getting values from and to the Lua stack
Conversion between Haskell and Lua values is governed by two type classes:
-- | A value that can be read from the Lua stack.
class FromLuaStack a where
-- | Check if at index @n@ there is a convertible Lua value and
-- if so return it. Throws a @'LuaException'@ otherwise.
peek :: StackIndex -> Lua a
and
-- | A value that can be pushed to the Lua stack.
class ToLuaStack a where
-- | Pushes a value onto Lua stack, casting it into meaningfully
-- nearest Lua type.
push :: a -> Lua ()
Many basic data types (except for numeric types, see the FAQ) have instances for
these type classes. New instances can be defined for custom types using the
functions in Foreign.Lua.Api
(also exported in Foreign.Lua
).
Build flags
The following cabal build flags are supported:
-
system-lua
: Use the locally installed Lua version instead of the version shipped as part of HsLua. -
use-pkgconfig
: Usepkg-config
to discover library and include paths. This is used only when thesystem-lua
flag is set or implied. -
lua501
: Build against Lua 5.1; this implies the flagsystem-lua
as well. -
lua502
: Build against Lua 5.2; this implies the flagsystem-lua
as well. -
luajit
: Build against LuaJIT; this implies the flagsystem-lua
as well. -
allow-unsafe-gc
: Allow optimizations which make Lua’s garbage collection potentially unsafe; haskell finalizers must be handled with extreme care. This is enabled per default, as this is rarely a problem in practice. -
apicheck
: Compile Lua with its API checks enabled. -
lua_32bits
: Compile Lua for a 32-bits system (e.g., i386, PowerPC G4).
Example: using a different lua version
To use a system-wide installed Lua/LuaJIT when linking hslua as a dependency,
build/install your package using --constraint="hslua +system-lua"
or for
LuaJIT: --constraint="hslua +luajit"
. For example, you can install Pandoc with
hslua that uses system-wide LuaJIT like this:
cabal install pandoc --constraint="hslua +system-lua +luajit"
or with stack:
stack install pandoc --flag=hslua:luajit
FAQ
Is anybody using this? Absolutely. E.g., Pandoc, the universal document converter, is written in Haskell and includes a Lua interpreter, enabling programmatic modifications of documents via Lua. Furthermore, custom output formats can be defined via Lua scripts. This has been used in pandoc-scholar (paper) to allow for semantically enriched scholarly articles.
Where are the coroutine related functions? Yielding from a coroutine works
via longjmp
, which plays very badly with Haskell’s RTS. Tests to get
coroutines working with HsLua were unsuccessful. No coroutine related functions
are exported from the default module for that reason. However, raw bindings to
the C API functions are still provided in Foreign.Lua.RawBindings
. If you get
coroutines to work, or just believe that there should be wrapper functions for
other reasons, we’d love to hear from you.
Why are there no predefined stack instances for default numerical types?
HsLua defines instances for the FromLuaStack
and ToLuaStack
type-classes
only if the following law holds: return x == push x *> peek x
. Lua can be
compiled with customized number types, making it impossible to verify the
correctness of the above equation. Furthermore, instances for numerical types
can be based on those of LuaInteger and LuaNumber and are easy to write.
Therefor hslua doesn’t provide any such instances.
Changes
Changelog
0.9.5.{1,2}
- Relax upper bound on exceptions
0.9.5
- Provide Optional as a replacement for OrNil. Exports of the latter have been fixed.
- Provide utility function
raiseError
: Its argument will be thrown as an error in Lua. - Add
modifyLuaError
: The function lives in Foreign.Lua.Error and allows to alter error messages. This is most useful for amending errors with additional information. - Fixed a bug in
toList
which left a element on the stack if deserializing that element lead to an error. This also affected the FromLuaStack instance for lists. - Fixed a bug in
pairsFromTable
which left a key-value pair on the stack if either of them could not be read into the expected type. This also affected the FromLuaStack instance for Map.
0.9.4
- Make Lua an instance of MonadMask: MonadMask from Control.Monad.Catch allows to mask asynchronous exceptions. This allows to define a finalizer for Lua operations.
- Add functions and constants to refer to stack indices: The functions
nthFromBottom
,nthFromTop
as well as the constantsstackTop
andstackBottom
have been introduced. Numeric constants are less clear, and named constants can aid readability. - Add type OrNil: This type can be used when dealing with optional arguments to Lua functions.
- Add function absindex: it converts the acceptable index
idx
into an equivalent absolute index (that is, one that does not depend on the stack top). The function callslua_absindex
when compiled with Lua 5.2 or later; for Lua 5.1, it is reimplemented in Haskell. - Functions in
tasty
which have been deprecated have been replaced with non-deprecated alternatives.
0.9.3
- Re-export more FunctionCalling helpers in
Foreign.Lua
: The typeclassToHaskellFunction
and the helper functiontoHaskellFunction
are useful when working with functions. Importing them separately fromForeign.Lua.FunctionCalling
was an unnecessary burden; they are therefor now re-exported by the main module. - Export registry-relatd constants
refnil
andnoref
: The constants are related to Lua’s registry functions (ref
andunref
). - Add helper to convert functions into CFunction: A new helper
wrapHaskellFunction
is provided. It expects a HaskellImportedFunction userdata (as produced bypushHaskellFunction
) on top of the stack and replaces it with a C function. The new function converts error values generated withlerror
into Lua errors, i.e. it callslua_error
. - Add utility function
setglobal'
: It works likesetglobal
, but works with packages and nested tables (dot-notation only).
0.9.2
- Add cabal flag ‘export-dynamic’: Default behavior is to include all symbols in the dynamic symbol table, as this enables users to load dynamic lua libraries. However, it is sometimes desirable to disable, e.g., when compiling a fully static binary. See jgm/pandoc#3986.
0.9.1
- Increase user-friendlyness of error messages: The error message returned by
toHaskellFunction
hinted at the fact that the failing function is a Haskell function. This is mostly unnecessary information and might have confused users.
0.9.0
- Added cabal flag to allow fully safe garbage collection: Lua garbage
collection can occur in most of the API functions, even in those usually not
calling back into haskell and hence marked as optimizable. The effect of this
is that finalizers which call Haskell functions will cause the program to
hang. A new flag
allow-unsafe-gc
is introduced and enabled by default. Disabling this flag will mark more C API functions as potentially calling back into Haskell. This has a serious performance impact. FromLuaStack
andToLuaStack
instances for lazy ByteStrings are added.- None-string error messages are handled properly: Lua allows error messages to be of any type, but the haskell error handlers expected string values. Tables, booleans, and other non-string values are now handled as well and converted to strings.
0.8.0
- Use newtype definitions instead of type aliases for LuaNumber and LuaInteger. This makes it easier to ensure the correct numeric instances in situations where Lua might have been compiled with 32-bit numbers.
- Instances of
FromLuaStack
andToLuaStack
forInt
are removed. The correctness of these instances cannot be guaranteed if Lua was compiled with a non-standard integer type.
0.7.1
- The flag
lua_32bits
was added to allow users to compile Lua for 32-bit systems. - When reading a list, throw an error if the lua value isn’t a table instead of silently returning an empty list.
0.7.0
- Tuples from pairs to octuples have been made instances of
FromLuaStack
andToLuaStack
. - New functions
dostring
anddofile
are provided to load and run strings and files in a single step. LuaStatus
was renamed toStatus
, the Lua prefix was removed from its type constructors.- The constructor
ErrFile
was added toStatus
. It is returned byloadfile
if the file cannot be read. - Remove unused FFI bindings and unused types, including all functions unsafe to use from within Haskell and the library functions added with 0.5.0. Users with special requirements should define their own wrappers and raw bindings.
- The module Foreign.Lua.Api.SafeBindings was merge into Foreign.Lua.Api.RawBindings.
- FFI bindings are changed to use newtypes where sensible, most notably
StackIndex
,NumArgs
, andNumResults
, but also the newly introduced newtypesStatusCode
,TypeCode
, andLuaBool
. - Add functions
tointegerx
andtonumberx
which can be used to get and check values from the stack in a single step. - The signature of
concat
was changed fromInt -> Lua ()
toNumArgs -> Lua ()
. - The signature of
loadfile
was changed fromString -> Lua Int
toString -> Lua Status
. - The type
LTYPE
was renamed toType
, its constructors were renamed to follow the patternType<Typename>
.LuaRelation
was renamed toRelationalOperator
, the Lua prefix was removed from its constructors. - Add function
tolist
to allow getting a generic list from the stack without having to worry about the overlapping instance with[Char]
.
0.6.0
- Supported Lua Versions now include Lua 5.2 and Lua 5.3. LuaJIT and Lua 5.1 remain supported as well.
- Flag
use-pkgconfig
was added to allow discovery of library and include paths via pkg-config. Setting a specific Lua version flag now impliessystem-lua
. (Sean Proctor) - The module was renamed from
Scripting.Lua
toForeign.Lua
. The code is now split over multiple sub-modules. Files processed with hsc2hs are restricted to Foreign.Lua.Api. - A
Lua
monad (reader monad over LuaState) is introduced. Functions which took a LuaState as their first argument are changed into monadic functions within that monad. - Error handling has been redesigned completely. A new LuaException was
introduced and is thrown in unexpected situations. Errors in lua which are
leading to a
longjmp
are now caught with the help of additional C wrapper functions. Those no longer lead to uncontrolled program termination but are converted into a LuaException. peek
no longer returnsMaybe a
but justa
. A LuaException is thrown if an error occurs (i.e. in situtations where Nothing would have been returned previously).- The
StackValue
typeclass has been split intoFromLuaStack
andToLuaStack
. Instances not satisfying the lawx == push x *> peek (-1)
have been dropped. - Documentation of API functions was improved. Most docstrings have been copied from the official Lua manual, enriched with proper markup and links, and changed to properly describe hslua specifics when necessary.
- Example programs have been moved to a separate repository.
- Unused files were removed. (Sean Proctor)
0.5.0
- New raw functions for
luaopen_base
,luaopen_package
,luaopen_string
,luaopen_table
,luaopen_math
,luaopen_io
,luaopen_os
,luaopen_debug
and their high-level wrappers (with namesopenbase
,opentable
etc.) implemented. - Remove custom versions of
loadfile
andloadstring
. - Drop support for GHC versions < 7.8, avoid compiler warnings.
- Ensure no symbols are stripped when linking the bundled lua interpreter.
- Simplify
tostring
function definition. (Sean Proctor) - Explicitly deprecate
strlen
. (Sean Proctor) - Add links to lua documentation for functions wrapping the official lua C API. (Sean Proctor).
0.4.1
- Bugfix(#30):
tolist
wasn’t popping elements of the list from stack.
0.4.0
pushstring
andtostring
now usesByteString
instead of[Char]
.StackValue [Char]
instance is removed,StackValue ByteString
is added.StackValue a => StackValue [a]
instance is added. It pushes a Lua array to the stack.pushlist
,islist
andtolist
functions are added.- Type errors in Haskell functions now propagated differently. See the
Scripting.Lua
documentation for detailed explanation. This should fix segfaults reported several times. lua_error
function is removed, it’s never safe to call in Haskell.
Related issues and pull requests: #12, #26, #24, #23, #18.
0.3.14
- Pkgconf-based setup removed. Cabal is now using
extra-libraries
to link with Lua. luajit
flag is added to link hslua with LuaJIT.
0.3.13
- Small bugfix related with GHCi running under Windows.
0.3.12
pushrawhsfunction
andregisterrawhsfunction
functions are added.apicheck
flag is added to Cabal package to enable Lua API checking. (useful for debugging)
0.3.11
luaL_ref
andluaL_unref
functions are added.