So it turns out that LuLPeg's differences to regular LPeg are enough to break MoonScript in some common use cases, but not others. For example, extending a class from another module is broken, but extending a class in the same module works.
This is what I get for not running MoonScript's test suite in LÖVE initially!
The errors I saw at first were bizarre: An "unable to parse" error for the first
line of an imported module, regardless of the line's contents.
These errors only appeared when calling require
on a MoonScript
module containing a class that extended another class in a different module.
First, I ran moonc on the project and ran that in LÖVE, and all was well, confirming that the issue was not my MoonScript code itself.
Then, I manually compiled the offending file inside LÖVE (using the splatted MoonScript and LuLPeg), and used VS Code to diff the versions:
-- try manually loading this and check the generated code...
readFile = (path) ->
file = assert io.open(path, "rb")
content = file\read '*all'
file\close!
content
writeFile = (path, contents) ->
file = assert io.open(path, "w")
file\write contents
file\close!
do
parse = require 'moonscript.parse'
compile = require 'moonscript.compile'
moon_code = readFile './LiveTest.moon'
print "----- Moon Code ------"
print moon_code
print "----- Lua Code ------"
tree, err = parse.string moon_code
unless tree then error "Parse error: " .. err
lua_code, err, pos = compile.tree tree
unless lua_code then error compile.format_error err, pos, moon_code
print lua_code
writeFile "LiveTest_2.lua", lua_code
love.event.quit!
return
Hm, that doesn't look right!
At this point, I still wasn't sure what was responsible for the bad code generation. After all: My local Lua installation is Lua 5.4, I installed MoonScript with Luarocks, I had to manually update MoonScript's dependencies for Lua 5.4, and LÖVE is using LuaJIT, based on Lua 5.1, not vanilla Lua. There are a lot of moving parts! :)
So, first, I went to get the LPeg source code, but the site was down at the time, so I instead decided to try running my LÖVE project with the version of MoonScript installed on my system, in case it was an older version than what I grabbed from GitHub. This made no difference to the generated code.
I then tried to install Lua 5.1 through homebrew
, so that I could then install Luarocks against that, then install LPeg with Luarocks, then get the build artifact for LPeg, specifically built against a Lua 5.1 install, to test with LÖVE.
The homebrew formula for Lua 5.1 was disabled. I tried to manually edit it, but it wasn't on my local disk, so I couldn't. I then went to check LPeg's webpage again, and this time, eventually, it loaded, and I was able to get the source code.
Do you feel productive yet? I sure do. :)
Once I had the LPeg source, I needed a Lua to build it against, so I grabbed LuaJIT since that's what LÖVE is using on dev platforms. Building each required reading and minorly editing their makefiles, which is fine, whatever.
I finally had an lpeg.so built for Apple Silicon that I could dump in my project directory and load in LÖVE instead of LuLPeg, so I re-ran my code gen experiment, and lo and behold, the output was correct.
So the issue was confirmed to be LuLPeg's divergence from LPeg. Crud.
My goal with this project was to make MoonScript more accessible to people who are already interested in LÖVE but maybe lack the technical "dealing with bullshit" skills necessary to successfully install Luarocks and MoonScript on say, Windows 10.
My hope was to give people a ZIP archive they could unpack on any machine where LÖVE would run, and just write MoonScript for it. MoonScript, and Lua in general, are a wee bit of a "Linux Club" where users without a certain level of skill and knowledge aren't able to try things out. I want Lua to be more mainstream for beginners. I want MoonScript to be more mainstram, too.
I don't dislike small, insular communities; in fact I prefer them! But I do dislike when communities are small or insular entirely because of unnecessary tech friction.
The real solution would be to fork LuLPeg and make it into a 1:1 replacement for LPeg, where every unit test passes. Alternatively, one could maybe patch MoonScript to work with whatever LuLPeg currently does, but this would be less ideal from a maintenance standpoint.
At the moment, I don't have the time to do either of those things.
For now, I have attempted to keep the "turnkey" spirit of the project template by providing native LPeg for Mac (ARM and x64) and Windows (x64), and still falling back to LuLPeg on other platforms but printing a warning.
I did it this way to try to cover the most common set of machines people will be using the template on. This way, in the most common cases, it's still a setup that should work out of the box.
I wasn't sure what range of architectures I would need to include for Linux users, for example, since we all love putting Linux on every machine ever to be manufactured. Linux users are also more easily positioned to install LPeg on the cli and just grab the artifact afterwards.
Adding platforms|architectures to the template is a matter of building LuaJIT and then LPeg for that platform and adding it into the require path hoodoo in main.lua
, and I welcome any additions folks would like to contribute.
You can get the project template here: