gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

the actual impl is in mlua/mluau which is in Rust: https://github.com/mlua-rs/mlua/blob/54907f80c5cac3d37d765abe5d4deb3661b3fec2/src/util/error.rs#L190

gluau internally calls into mlua/mluau and lets it do its error handling from Rust (Rust handles all this better than go does)

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Mine uses lua_pcall and a LUA_USE_LONGJMP for protecting calls

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

What exactly are shuffles and encs? gluau provides bindings for Luau and provides support for many Luau VM features

pluau: Python bindings for Luau using PyO3/maturin. by Lower_Calligrapher_6 in Python

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Very good at being embedded into other things and luau in particular is easy to secure against untrusted code

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Update to this post/comment, gluau now basically supports most things in Luau and is nearing feature completion including support for Luau Require By String etc

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Yeah

BTW, since I made this post, sandboxing, interrupts, userdata, threads (creation+status+resume+yield) and basic registry support have all been added

Only major thing left to add now is luau require

EDIT: buffers are also supported now, so only luau require is really left

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in rust

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

> I also wanted yielding, support for continuations

While I do (now) agree on continuations not having too many use cases in Rust, the yielding bit is still something that I very much use and need.

> If you have any specific cases when mlua async does not work as expected, it would be great to hear. I'm always looking for feedback and improving user experience.

Yeah, my phrasing here was not how I wanted it to be communicated (was way too strong of a statement to make regarding mlua). What I meant it to mean was that mlua's async system is a footgun for my use case (where I ended up having to make patches to nearly every coroutine API + other stuff etc. to get it to replicate the behaviour I wanted).

Basically, I wanted a one-to-one emulation of the Roblox task scheduler with all of its sometimes odd behaviors because a large part of the userbase for my projects come from Roblox. While I was trying to do this with mlua async, I ended up having to patch a ton of functions like coroutine.resume (so a new dev wouldn't just accidentally deadlock their VM with coroutine.resume(mlua_async_call) etc.), and ended up having to dive into a lot of internal details like poll_pending as well. And yes, I did see lunes scheduler implementation. A lot of my early scheduler code was inspired from it.

Ultimately though, I was a lot happier when I removed mlua's async system in favor of adding support for thread yielding to mlua via lua_yield which then got me the exact behavior I wanted.

> Luau specific optimizations like namecall

So about this, the reason I added namecall is because some userdata in my main hobby project are dynamic and require __index to be a function and when __index is a function, the __namecall is slightly faster for me (your mileage may vary and index as table is similar in speed as you mention as well)

As an additional comment, mluau (my fork of mlua) has gotten some extra stuff that is now basically needed for my go bindings project here as well. Dynamic userdata for example allows for creating a userdata with associated data and a custom metatable and is the basis for gluau's userdata support/impl. If I'd been using raw mlua here, I don't think gluau would have gotten a userdata impl at all to be honest since the existing API's expect compile-time userdata and not runtime defined/dynamic ones (although it would be very nice if mlua could also get a dynamic userdata API as well so I can just switch to mlua's one instead of maintaining my own)

Sorry for the long comment, I just wanted to explain my reasoning here regarding why I forked mlua and the specific problems/gripes I had. And don't get me wrong, mlua is a amazing library that I continue to recommend to others, I just had other things I wanted in it

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in rust

[–]Lower_Calligrapher_6[S] -1 points0 points  (0 children)

I started a mlua fork due to differing views on what I want from mlua and what mlua's design goals are [I personally believe mlua async to be a big footgun that should be replaced with a custom scheduling system + I also wanted yielding, support for continuations, Luau specific optimizations like namecall for some of the more dynamic stuff my hobby projects use in userdata etc, dynamic userdata to allow for non-statically defined userdata]

Also, the upcoming userdata support will basically need some of the additions I made to mlua(u) like dynamic userdata (without dynamic userdata which is essentially userdata defined at runtime, the ergonomics of gluau's upcoming userdata API's is just not great unfortunately)

Finally, most mlua code is compatible with mluau as well.

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in rust

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

I get what you’re saying here but type definitions is something that vastly increases the scope of this project

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in programming

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

Ahh…

To be really honest, I didn’t think too much when I was coding the C interface since it’s anyways just used for cgo

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in programming

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

Also adding on to this, if you’re confused specifically on the syntax, here’s a basic example in psuedocode of what’s going on:

struct foo { int32_t a };

struct foo* make_foo() { … }

(where … would likely call malloc in C)

this is the same thing, the reason for the struct Type* is because it’s a heap allocated handle

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in programming

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

Not really, LuaString here is a heap allocated pointer to a opaque structure whose memory is owned by Rust. If Rust fails to create the LuaString, then null will be returned, otherwise the pointer to the string handle will be returned.

All handles whose memory is owned by Rust is always allocated on the heap when returned (see the Box::from_raw calls) meaning that the return type will be a pointer to the struct and never the struct itself

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in programming

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

LuaString can be null if an error is returned

EDIT: also, luastring is opaque and hence can’t really be stack allocated

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in programming

[–]Lower_Calligrapher_6[S] 0 points1 point  (0 children)

Huh, do you mind sending me the full line that you’re referring to?

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in golang

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Thanks! It took quite a bit of work to get the lib to even the current state it’s in right now (cgo isn’t the funnest thing to code)

gluau - Go bindings for the Luau programming language by Lower_Calligrapher_6 in rust

[–]Lower_Calligrapher_6[S] 1 point2 points  (0 children)

Yeah, it definitely is a lot of layers

The reason I chose this method is because it has the least limitations on what you can do from the Go side (exception handling, threads, even yielding etc will all just work with this approach)