This is a bug in 0.2.1b, and possibly earlier, causing crashes in BBS carts like Pieces of Cake. After the new add() functionality was added, complex or token-optimized code causes a hard crash with this error:
As per @Felice, the bug is from an implied nil return from a function, which is apparently different than an explicit "return nil". add(t,nil) works, as should this (since it gets converted to a true nil through assignment):
function fn() end local f=fn() add(rs,f) |
This fails:
add(rs,fn()) |
It’s a runtime error, so it’s likely not related to the parser. My guess is that it’s a bug in the new C implementation of add().
My thought was that since the manual states add(t,v) is equivalent to t[#t+1] = v, it might be a macro replacement internally. The runtime error would then be because it's extracting the wrong values for t and v.
Also, I swear it fixed the runtime error once when I only adjusted whitespace around all of the add statements, though I can't reproduce that. That kind of weirdness outside of the function itself makes me think it's a parser bug.
It’s a runtime error :-) The 0.2.1 changelog states that add() is no longer implemented in Lua; it is only conceptually equivalent to t[#t+1]=v but internally it has always done more (such as handle type error) and since 0.2.1 does even more (it can now use a third argument).
Just because it states 'runtime error' doesn't guarantee that the issue happens there, only that it compiles something that eventually crashes on run. I'd like to hear your explanation of how outside whitespace and pulling function calls out of the passed arguments would affect the add function itself, regardless of where it's implemented. It could be double-executing fn() calls or extracting the wrong t v values (that just happen to still compile). Due to the solutions I've found for the crash, it's much more likely that something is going wrong pre-runtime.
@zep et al
It's failing because fn(...) is returning nil in this case (or maybe the special-case empty value for functions that don't explicitly return anything, which gets coerced to nil on assignment).
I think the original lua-mode add() allowed you to add nil. I imagine it behaved as a no-op. Probably the C-mode version ought to do the same.
Ah, yup, the empty value is the problem.
Works fine if the function returns nil:
But fails if the function doesn't return anything:
The C-mode code just needs to handle the special empty value as if it were nil.
@zep, you probably want to check any other C-ified functions for similar issues.
@shy because we know what exact transformations the PICO-8 parser operates on a given chunk of code (to replace != with ~=, for instance), and add() is not affected by these. The fact that it suddenly worked when you changed whitespace but never worked again can be better explained by some randomness in the code that prevented the runtime error, or by user error.
Thanks @Felice, I updated the top post and title to be more specific, so @zep can see what really went wrong here. More info here, I had no idea that lua treated "return nil" and "return" as different. Apparently it takes advantage of the fact that assignments with a mismatched # of arguments on LHS and RHS assign nil in the rest, so it doesn't actually return anything or push a value to the stack, even when a value is expected. That's quite a bizarre edge case.
@samhocevar: The whitespace fix probably was user error, I likely pulled the function call out just so it was visible in pico8's code editor, and then forgot when I tried to reproduce. However, the bug here was more about what got passed to add than about the add function's implementation itself, so I'd still say it was important to make that distinction.
Thanks everyone -- fixed for 0.2.1c, and also in the current BBS player (0.2.1c dev)
This was indeed caused by re-implementing add() in C, and was supposed to match the existing behaviour. Calling add() with no second parameter now does nothing, and returns nothing -- same as earlier versions.
[Please log in to post a comment]