• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[meme] Transpiling Rust to Lua via WASM

Status
Not open for further replies.

~El

Level 17
Joined
Jun 13, 2016
Messages
556
so we all love using anything except Lua itself to make maps these days, hence the absolute zoo of transpilers targeting JASS, vJASS, TypeScript, C#, Python, whatever

i just realized we can add one more language to this list (actually far more than one, more on that later): Rust

Rust can easily compile into WASM via the wasm32-unknown-unknown target, and being a Rust shill i can go on forever about how great it is.

there's also at least two tools for transpiling WASM into Lua: wasm2lua and Wasynth. the former uses node, the latter is written in Rust itself, so Wasynth is of more interest to me as a portable runtimeless solution

that means we can do Rust -> WASM -> Lua

admittedly the generated Lua code is quite shite, mainly because it has to emulate WASM's linear memory, so it'll probably run like ass, but hey, who cares, its not like we're trying to solve a massive performance problem here, most WC3 logic is just a bunch of function calls and some collection management

other than that all we need is a bunch of simple shims on the Lua side and a supporting lib for Rust that'll use those shims and we should be good to go.

im now lowkey considering doing a POC map in Rust. i know y'all nerds probably couldn't care less for Rust, but hey, whatever, this is fun

...

yeah okay this isn't just limited to Rust either, we could in fact use any language that has WASM as a compilation target. like AssemblyScript, im just bringing up Rust because it would be an insanely powerful language to bring into the fold

pros and cons:
  • + pro: using linear memory for storage means we put much less pressure on the GC and can avoid weird GC leak scenarios
  • - con: using linear memory means a lot of weird bit twiddling and working with integers which lua can be a bit tricky with. also the current codegen in Wasynth emulates integers in software, yikes. 32-bit int types (and smaller) can probably use lua's builtin number type tho with some tweaks to the codegen, because it still has 53 bits of integer precision when the exponent is set to 0
  • + pro: Rust has one of the most powerful type systems among modern languages
  • - con: the codegen relies a lot on table lookups and helper functions to do anything
  • - con: needs extra scaffolding (and maybe a fork of the codegen) to actually be useful in WC3
  • + pro: can use almost any no-std crate in the Rust ecosystem for shit like math, crypto, memes, utility. dont need to reinvent the bicycle
  • + pro: massive meme
 
Level 19
Joined
Jan 3, 2022
Messages
320
Lua >5.3 has an integer type. But Warcraft has Lua compiled with 32-bit everything (tested float) to have the same behavior as Jass.
Lua:
-- lua 5.3 console
for k,v in pairs({1,2^63, 1<<63}) do print(math.type(v), v) end
integer 1
float   9.2233720368548e+18
integer -9223372036854775808
 

~El

Level 17
Joined
Jun 13, 2016
Messages
556
Lua >5.3 has an integer type. But Warcraft has Lua compiled with 32-bit everything (tested float) to have the same behavior as Jass.
Lua:
-- lua 5.3 console
for k,v in pairs({1,2^63, 1<<63}) do print(math.type(v), v) end
integer 1
float   9.2233720368548e+18
integer -9223372036854775808
yeah that unfortunately significantly complicates the codegen, because wasm has native support for 64-bit arithmetic. means polyfilling it and having to split it into two locals wherever a 64-bit int is involved. or just forbidding 64-bit ints entirely, cus implementing 64-bit division with 32-bit math fucking sucks
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Lua >5.3 has an integer type. But Warcraft has Lua compiled with 32-bit everything (tested float) to have the same behavior as Jass.
Lua:
-- lua 5.3 console
for k,v in pairs({1,2^63, 1<<63}) do print(math.type(v), v) end
integer 1
float   9.2233720368548e+18
integer -9223372036854775808
Yes math.type will return "float" or "integer" in newer Lua versions.

Interestingly, I found goto syntax is actually possible in Lua. Doubtful it's particularly useful thanks to loop versatility, but it could be important for simultaneously getting out of nested loops without exiting the function.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
556
Interestingly, I found goto syntax is actually possible in Lua. Doubtful it's particularly useful thanks to loop versatility, but it could be important for simultaneously getting out of nested loops without exiting the function.
yeah! limited gotos became a thing in 5.3. their only restriction is that they can't enter the scope a local variable, but i imagine them being very useful for implementing some of wasm's control flow constructs
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
so we all love using anything except Lua itself to make maps these days, hence the absolute zoo of transpilers targeting JASS, vJASS, TypeScript, C#, Python, whatever
I have to say, I found this comment to be completely hiarious. There really are a lot of options out there, it's like the Wild West.

TypeScript has TypeScript2Lua (a very well-maintained, heavily supported program, probably the most stable of all the options).

I think Drake53 made that C-sharp transpiler.

InFrane made the Python2Lua transpiler.

For cJass, there is cJass2Lua.

For JASS, we have good old World Editor's "hidden" Jass2Lua transpiler, Drake53's manual Jass2Lua transpiler, cJass2Lua and vJass2Lua.

For vJass, we only have vJass2Lua (although Drake53 is working on doing their own variant).

For Zinc, I am secretly (shhh, don't tell anyone) working on building this into the vJass2Lua transpiler. I don't want to jynx anything, but it's about 2/3rds done.

One of the things that sets vJass2Lua apart from the others is that it is not doing ANY syntax checking. It assumes that the syntax is correctly pre-evaluated by something like World Editor, JassHelper or pJass, prior to being converted. Therefore, it is not useful for "getting away with coding in vJass" like the other options, but rather takes the approach "ok, you have this vJass code, let's turn it into Lua so that it's compatible", but the end result is that I want to encourage people actually coding in Lua and not sticking with vJass, by enabling them to have an easier time with switching their maps while sticking (as closely as possible) to the API that they know.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
556
I have to say, I found this comment to be completely hiarious. There really are a lot of options out there, it's like the Wild West.

TypeScript has TypeScript2Lua (a very well-maintained, heavily supported program, probably the most stable of all the options).

I think Drake53 made that C-sharp transpiler.

InFrane made the Python2Lua transpiler.

For cJass, there is cJass2Lua.

For JASS, we have good old World Editor's "hidden" Jass2Lua transpiler, Drake53's manual Jass2Lua transpiler, cJass2Lua and vJass2Lua.

For vJass, we only have vJass2Lua (although Drake53 is working on doing their own variant).

For Zinc, I am secretly (shhh, don't tell anyone) working on building this into the vJass2Lua transpiler. I don't want to jynx anything, but it's about 2/3rds done.

One of the things that sets vJass2Lua apart from the others is that it is not doing ANY syntax checking. It assumes that the syntax is correctly pre-evaluated by something like World Editor, JassHelper or pJass, prior to being converted. Therefore, it is not useful for "getting away with coding in vJass" like the other options, but rather takes the approach "ok, you have this vJass code, let's turn it into Lua so that it's compatible", but the end result is that I want to encourage people actually coding in Lua and not sticking with vJass, by enabling them to have an easier time with switching their maps while sticking (as closely as possible) to the API that they know.
it makes sense i think. lua is a pretty old (and weird) language itself, and people wanna use languages that are either familiar to them, more modern, or both.

and yeah, as far as actual utility goes, a vjass to lua transpiler is probably much useful than anything else out there, the other projects are pretty niche to say the least

and as far as this rust endeavour, i dont think anyone else besides me would be actually interested in using it
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
lua is a pretty old (and weird) language itself,
Considering that Lua is the most widely-used game modding language, I don't see an issue. What makes Lua "weird":

Array indices starting at 1
Almost everything is a table (including globals)
Metatables
Dynamically-typed (with Emmy annotation being one of the only proactive support models for people trying to review type problems in their code without asserting them in run-time)
An incomplete implementation of string pattern searching (a poor man's Regex)
Invisible _ENV behavior
Functions as dynamically-created containers

All of those can be learned to acquire their benefits, and worked around where things are unnecessarily awkward. A lot of these quirks can even be used to bolster the capability of GUI triggers via stuff like Precice Wait and Global Variable Remapper.

What can't be worked around is that Blizzard disabled access to the debug API, the garbage collector API, and the "load" method's "bytecode" implementation. This also can't be solved by any third-party tool, unless that said tool is replacing WarCraft 3 altogether (e.g. WarSmash).
 
Last edited:

~El

Level 17
Joined
Jun 13, 2016
Messages
556
Considering that Lua is the most widely-used game modding language, I don't see an issue. What makes Lua "weird":
the problem is that Lua's ecosystem is very splintered. there's several major axis that these splits have happened:
  • the versions and forks - 5.1, 5.2, 5.3, 5.4, luau, luajit, etc.
  • the environments - roblox, wow, gmod, luarocks, etc.

this means that a lot of lua code isnt easily and readily reusable between ecosystems without modifications, which is a pain in the ass. in practice this means that, unless you're working in an existing ecosystem, you have to reinvent the wheel a lot. this is something i stumbled into a lot when trying to find libs for lua - especially general-purpose stuff like data formats, cryptography, etc

this is especially painful considering most existing ecosystems out there target 5.1, 5.2 or luajit.

not to mention that a lot of the libs written for those specific environments sometimes make extensive use of environment-specific APIs that aren't present in vanilla lua, so you often have to polyfill the missing bits

What can't be worked around is that Blizzard disabled access to the debug API, the garbage collector API, and the "load" method's "bytecode" implementation. This also can't be solved by any third-party tool, unless that said tool is replacing WarCraft 3 altogether (e.g. WarSmash).
well, in particular the bytecode stuff got disabled because its a major security hole in lua's design. the lua vm isnt sophisticated enough to detect invalid bytecode, and lua's "safety" relies mainly on the assumption that all executed bytecode is generated by luac from valid lua source code. that means that by loading bytecode directly you can break out of the sandbox pretty quickly if you know what you're doing, and then just execute arbitrary code

not sure if this applies to the debug lib too, but i guess they wanted to err on the side of caution. though not being able to get a stacktrace is a huge pain in the ass.

Array indices starting at 1
Almost everything is a table (including globals)
Metatables
Dynamically-typed (with Emmy annotation being one of the only proactive support models for people trying to review type problems in their code without asserting them in run-time)
An incomplete implementation of string pattern searching (a poor man's Regex)
Invisible _ENV behavior
Functions as dynamically-created containers
well, we live in a world where strongly-typed, statically-checked languages are on the rise again, so a lot of these are actually pretty major issues IMO. sure you can work around them but its a pain in the ass if you're coming from a more powerful language like TypeScript or C#, hence all the transpilers :)
 

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
if you're coming from a more powerful language like TypeScript or C#, hence all the transpilers :)
powerful language like TypeScript or C#
powerful (...) TypeScript
Am I reading this right? TypeScript and powerful in the same sentence?
TypeScript is literally hocus pocus garbage JavaScript with a new layer to bloat things up.
Coding and catching errors in it might feel nice, but it's conceptually dumb.
Ewww, I might puke on my screen while typing this, and I'll blame you :p
 

~El

Level 17
Joined
Jun 13, 2016
Messages
556
Am I reading this right? TypeScript and powerful in the same sentence?
TypeScript is literally hocus pocus garbage JavaScript with a new layer to bloat things up.
Coding and catching errors in it might feel nice, but it's conceptually dumb.
Ewww, I might puke on my screen while typing this, and I'll blame you :p
despite being a monstrous hodge-podge of features and afterthoughts, you can't really deny typescript its place in the market, nor can you deny the fact that its type system is disproportionately well-developed, considering what it is

the level of typelevel magic achievable in typescript is comparable in its absurdity and versatility to c++ templates, just without the monomorphization part. still, the stuff i've seen out there still gives me shivers

that is besides the point anyway, typescript is still a much more extensive language than lua
 
Last edited:

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
despite being a monstrous hodge-podge of features and afterthoughts, you can't really deny typescript its place in the market, nor can you deny the fact that its type system is disproportionately well-developed, considering what it is

the level of typelevel magic achievable in typescript is comparable in its absurdity and versatility to c++ templates, just without the monomorphization part. still, the stuff i've seen out there still gives me shivers

that is besides the point anyway, typescript is still a much more extensive language than lua
I was already aware of that to a certain extent, I was just trying say that i'm not a fan of it in a humoristic way :D
A wc3 friend asked me to help him on coding some parts of his map, I felt like I was reading hieroglyphics for a good amount of time.
 
Status
Not open for further replies.
Top