[ANN] Halfway-usable Lua-ML

Lua-ML is a pure OCaml, heavily functorized implementation of Lua 2.5. It’s possible to extend it with your own libraries or replace its own libraries.

Originally it was a part of the now defunct C-- project, then Christian Lindig rescued it from it and packaged as a standalone library, but he didn’t have much time to work on it. Recently he passed the project to me, so I’m now its maintainer, for better or worse.

Thanks to a patch by @Drup it can now be installed as an OPAM package, and I’ve made an effort to remove the dependency on lipsum and eliminate the fork of an old Hashtbl from its source tree.

From my quick tests it appears to work as expected, but since it never had real users, it needs as much testing as it can get. And a test suite. And features of Lua newer than the bronze age 2.5. And code clean-up. But the first steps towards reviving it have been made at least.

6 Likes

Are there any neat things you can do with it? Like can Lua code call into OCaml code?

@perry I should have given more information in the announce indeed.

Yes, you can expose any OCaml values as Lua userdata and any functions as fallbacks. Here is my quick test of exposing lambdasoup to Lua:

utop # let st = I.mk () ;;
val st : I.state =
  {I.Value.globals = <abstr>; fallbacks = <abstr>; callstack = [];
   currentloc = None; startup = <abstr>}

utop # I.register_globals ["soup", lua_of_soup (Html.SoupNode (Soup.parse "<p>foo</p> <p>bar</p>"))] st;;
- : unit = ()

utop # I.dostring st "x = HTML.select(\"p\", soup); k, v = next(x); while k do print(v); k, v = next(x, k) end";;
<p>foo</p>
<p>bar</p>
2
- : I.value list = [I.Value.LuaValueBase.String "executed without errors"]

The module for that took quite a bit of yak shaving to get right, and there may be a better way around the phantom types than that artificial sum type, but here it is: https://gitlab.com/snippets/1883747

1 Like

I don’t know if it’s still accurate but this paper specifically talks about this.

2 Likes

It is cool to see more Lua implementations, though I am a bit surprised that the version is 2.5 and not 5.1, the version that the community has seemingly decided to ossify on. How hard or easy would it be to update it to a newer version?

I would expect this to be a lot of work. The motivation for providing Lua as an extension language is spelled out in the README: to make your OCaml application more flexible. The motivation was not to consume all the existing Lua code - which indeed would require a Lua 5.x implementation. I believe Lua 2.5 still serves the original purpose well enough.

If one wanted Lua 5.x integration, it would be easier to embed a Lua 5.x C implementation into OCaml at the cost of a more complicated interface.

Lack of for loops is quite annoying to modern Lua users, so I’m planning to add it. Other than that, I also think for the intended use case, compatibility with Lua libraries isn’t much of a concern.

What makes it worse is that after Hashtbl fork removal, the next() function is O(n), so any iteration is quadratic, and I see no straightforward way to memoize it. Probably not that much of an issue for small data on modern machines, but it’s far from nice. A built-in for that calls Hashtbl.iter directly would alleviate that problem.

One thing @dmbaturin didn’t mention, is that lua-ml is highly functorized to accommodate for very deep integration between the embedded lua language and its host.

I strongly encourage OCamlers curious about functors to read the paper linked by @dbuenzli. It’s a great demonstration about the kind of ridiculous and amazing things you can do with weird functor architectures.

5 Likes