|
Packit |
f9207c |
# hslua – Lua interpreter interface for Haskell
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
[![Build Status]](https://travis-ci.org/hslua/hslua)
|
|
Packit |
f9207c |
[![AppVeyor Status]](https://ci.appveyor.com/project/tarleb/hslua-r2y18)
|
|
Packit |
f9207c |
[![Hackage]](https://hackage.haskell.org/package/hslua)
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Hslua provides bindings, wrappers, types, and helper functions to bridge haskell
|
|
Packit |
f9207c |
and lua.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
[Build Status]: https://travis-ci.org/hslua/hslua.svg?branch=master
|
|
Packit |
f9207c |
[AppVeyor Status]: https://ci.appveyor.com/api/projects/status/ldutrilgxhpcau94/branch/master?svg=true
|
|
Packit |
f9207c |
[Hackage]: http://img.shields.io/hackage/v/hslua.svg
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Overview
|
|
Packit |
f9207c |
--------
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
[Lua](https://lua.org) is a small, well-designed, embeddable scripting language.
|
|
Packit |
f9207c |
It has become the de-facto default to make programs extensible and is widely
|
|
Packit |
f9207c |
used everywhere from servers over games and desktop applications up to security
|
|
Packit |
f9207c |
software and embedded devices. This package provides Haskell bindings to Lua,
|
|
Packit |
f9207c |
enable coders to embed the language into their programs, making them scriptable.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
HsLua ships with batteries included and includes the most recent Lua version.
|
|
Packit |
f9207c |
However, cabal flags make it easy to swap this out in favor of a Lua version
|
|
Packit |
f9207c |
already installed on the host system. It supports the versions 5.1, 5.2, 5.3,
|
|
Packit |
f9207c |
and LuaJIT.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Interacting with Lua
|
|
Packit |
f9207c |
--------------------
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
HsLua provides the `Lua` type to define Lua operations. The operations are
|
|
Packit |
f9207c |
executed by calling `runLua`. A simple "Hello, World" program, using the Lua
|
|
Packit |
f9207c |
`print` function, is given below:
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
``` haskell
|
|
Packit |
f9207c |
import Foreign.Lua
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
main :: IO ()
|
|
Packit |
f9207c |
main = runLua prog
|
|
Packit |
f9207c |
where
|
|
Packit |
f9207c |
prog :: Lua ()
|
|
Packit |
f9207c |
prog = do
|
|
Packit |
f9207c |
openlibs -- load lua libraries so we can use 'print'
|
|
Packit |
f9207c |
callFunc "print" "Hello, World!"
|
|
Packit |
f9207c |
```
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
### The Lua stack
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Lua's API is stack-centered: most operations involve pushing values to the stack
|
|
Packit |
f9207c |
or receiving items from the stack. E.g., calling a function is performed by
|
|
Packit |
f9207c |
pushing the function onto the stack, followed by the function arguments in the
|
|
Packit |
f9207c |
order they should be passed to the function. The API function `call` then
|
|
Packit |
f9207c |
invokes the function with given numbers of arguments, pops the function and
|
|
Packit |
f9207c |
parameters of the stack, and pushes the results.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
,----------.
|
|
Packit |
f9207c |
| arg 3 |
|
|
Packit |
f9207c |
+----------+
|
|
Packit |
f9207c |
| arg 2 |
|
|
Packit |
f9207c |
+----------+
|
|
Packit |
f9207c |
| arg 1 |
|
|
Packit |
f9207c |
+----------+ ,----------.
|
|
Packit |
f9207c |
| function | call 3 1 | result 1 |
|
|
Packit |
f9207c |
+----------+ ===========> +----------+
|
|
Packit |
f9207c |
| | | |
|
|
Packit |
f9207c |
| stack | | stack |
|
|
Packit |
f9207c |
| | | |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Manually pushing and pulling arguments can become tiresome, so HsLua makes
|
|
Packit |
f9207c |
function calling simple by providing `callFunc`. It uses type-magic to allow
|
|
Packit |
f9207c |
different numbers of arguments. Think about it as having the signature
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
callFunc :: String -> a1 -> a2 -> … -> res
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
where the arguments `a1, a2, …` must be of a type which can be pushed to the Lua
|
|
Packit |
f9207c |
stack, and the result-type `res` must be constructable from a value on the Lua
|
|
Packit |
f9207c |
stack.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
### Getting values from and to the Lua stack
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Conversion between Haskell and Lua values is governed by two type classes:
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
``` haskell
|
|
Packit |
f9207c |
-- | A value that can be read from the Lua stack.
|
|
Packit |
f9207c |
class FromLuaStack a where
|
|
Packit |
f9207c |
-- | Check if at index @n@ there is a convertible Lua value and
|
|
Packit |
f9207c |
-- if so return it. Throws a @'LuaException'@ otherwise.
|
|
Packit |
f9207c |
peek :: StackIndex -> Lua a
|
|
Packit |
f9207c |
```
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
and
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
``` haskell
|
|
Packit |
f9207c |
-- | A value that can be pushed to the Lua stack.
|
|
Packit |
f9207c |
class ToLuaStack a where
|
|
Packit |
f9207c |
-- | Pushes a value onto Lua stack, casting it into meaningfully
|
|
Packit |
f9207c |
-- nearest Lua type.
|
|
Packit |
f9207c |
push :: a -> Lua ()
|
|
Packit |
f9207c |
```
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Many basic data types (except for numeric types, see the FAQ) have instances for
|
|
Packit |
f9207c |
these type classes. New instances can be defined for custom types using the
|
|
Packit |
f9207c |
functions in `Foreign.Lua.Api` (also exported in `Foreign.Lua`).
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
Build flags
|
|
Packit |
f9207c |
-----------
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
The following cabal build flags are supported:
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `system-lua`: Use the locally installed Lua version instead of the version
|
|
Packit |
f9207c |
shipped as part of HsLua.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `use-pkgconfig`: Use `pkg-config` to discover library and include paths. This
|
|
Packit |
f9207c |
is used only when the `system-lua` flag is set or implied.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `lua501`: Build against Lua 5.1; this implies the flag `system-lua` as well.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `lua502`: Build against Lua 5.2; this implies the flag `system-lua` as well.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `luajit`: Build against LuaJIT; this implies the flag `system-lua` as well.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `allow-unsafe-gc`: Allow optimizations which make Lua's garbage collection
|
|
Packit |
f9207c |
potentially unsafe; haskell finalizers must be handled with extreme care. This
|
|
Packit |
f9207c |
is *enabled* per default, as this is rarely a problem in practice.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `apicheck`: Compile Lua with its API checks enabled.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
- `lua_32bits`: Compile Lua for a 32-bits system (e.g., i386, PowerPC G4).
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
### Example: using a different lua version
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
To use a system-wide installed Lua/LuaJIT when linking hslua as a dependency,
|
|
Packit |
f9207c |
build/install your package using `--constraint="hslua +system-lua"` or for
|
|
Packit |
f9207c |
LuaJIT: `--constraint="hslua +luajit"`. For example, you can install Pandoc with
|
|
Packit |
f9207c |
hslua that uses system-wide LuaJIT like this:
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
``` sh
|
|
Packit |
f9207c |
cabal install pandoc --constraint="hslua +system-lua +luajit"
|
|
Packit |
f9207c |
```
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
or with stack:
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
``` sh
|
|
Packit |
f9207c |
stack install pandoc --flag=hslua:luajit
|
|
Packit |
f9207c |
```
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
FAQ
|
|
Packit |
f9207c |
---
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
**Is anybody using this?** Absolutely. E.g., [Pandoc](https://pandoc.org), the
|
|
Packit |
f9207c |
universal document converter, is written in Haskell and includes a Lua
|
|
Packit |
f9207c |
interpreter, enabling programmatic modifications of documents via Lua.
|
|
Packit |
f9207c |
Furthermore, custom output formats can be defined via Lua scripts. This has been
|
|
Packit |
f9207c |
used in [pandoc-scholar](https://github.com/pandoc-scholar/pandoc-scholar)
|
|
Packit |
f9207c |
([paper](https://peerj.com/articles/cs-112/)) to allow for semantically enriched
|
|
Packit |
f9207c |
scholarly articles.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
**Where are the coroutine related functions?** Yielding from a coroutine works
|
|
Packit |
f9207c |
via `longjmp`, which plays very badly with Haskell's RTS. Tests to get
|
|
Packit |
f9207c |
coroutines working with HsLua were unsuccessful. No coroutine related functions
|
|
Packit |
f9207c |
are exported from the default module for that reason. However, raw bindings to
|
|
Packit |
f9207c |
the C API functions are still provided in `Foreign.Lua.RawBindings`. If you get
|
|
Packit |
f9207c |
coroutines to work, or just believe that there should be wrapper functions for
|
|
Packit |
f9207c |
other reasons, we'd love to hear from you.
|
|
Packit |
f9207c |
|
|
Packit |
f9207c |
**Why are there no predefined stack instances for default numerical types?**
|
|
Packit |
f9207c |
HsLua defines instances for the `FromLuaStack` and `ToLuaStack` type-classes
|
|
Packit |
f9207c |
only if the following law holds: `return x == push x *> peek x`. Lua can be
|
|
Packit |
f9207c |
compiled with customized number types, making it impossible to verify the
|
|
Packit |
f9207c |
correctness of the above equation. Furthermore, instances for numerical types
|
|
Packit |
f9207c |
can be based on those of LuaInteger and LuaNumber and are easy to write.
|
|
Packit |
f9207c |
Therefor hslua doesn't provide any such instances.
|