It seems to have been introduced in commit 46889593da back in Jan, and I
was using it to summarize multiple failing tests. However, it's not used
in that scenario anymore (and anyway it seems wasteful to compute the
stack for each failing test and then throw it all away).
This is much easier to explain, and it also avoids errors like
forgetting to delete the save dir after editing sources in source dir.
One drawback: there's a little more risk of accidental data loss, either
because of bugs here or programmer mistakes. To mitigate this risk, put
your apps in a git repo and periodically `git commit`.
To find the first word we currently strip _all_ Lua comments. This is
really wasteful for large definitions. At least avoid all these
allocations if the first word is not a comment.
A comment is now in a better place.
Inlining an unnecessary function boundary removes ambiguity between the
similar names load_all and load_files_so_far. It also shrinks call
stacks on error.
Returning errors can feel warm and fuzzy, but it does no good if the
caller doesn't actually check the return value.
Scenario:
define a new function B
call it when initializing global variable A
everything works fine
restart
Before this commit you get a weird error because we silently stopped
loading, and now lots of functions are missing.
After this commit you get a better error message.
There's a protocol invariant to preserve here: If a live command sends a
response in any situation, it needs to send a response in all
situations. Otherwise the driver can't decide whether to wait or not.
Second issue introduced in commit a2451aa26. It's worth checking error
recovery in the simpler test, even though it's technically caught in the
next one. A little redundancy seems good here.
- I often find that opening up driver.love and sending any message gets
my app unwedged. Retrying should be easy. Just press a key.
- There's really no reason for the app to become unresponsive while
waiting for code changes.
This approach tries to address both. Press any key to retry, or show the
error right on the window while I whip out driver.love. You can also
copy the message to the clipboard by hitting 'c'.
Drawbacks of this approach:
- nobody's going to read the message. I myself didn't notice the
default support for copying the error message for _months_.
- more complexity for anyone reading the code to parse. More stuff
that can go wrong. Any errors within the handler will crash the app
hard. (Though now there's less code in the handler, so maybe this is
an improvement on that score.)
The best plan is still to not rely on this too much. Don't ship bugs.
1. No more version history, now we have just the contents of the current
version.
2. Editing a definition no longer changes the order in which definitions
load.
This should make repos easier to browse, and more amenable to modify.
You don't need driver.love anymore. And a stable order eliminates some
gotchas. For example:
using driver.love, define `Foo = 3` in a definition
define `Bar = Foo + 1`
edit and redefine `Foo = 4`
Before this commit, you'd get an error when you restart the app.
Definitions used to be loaded in version order, and editing a definition
would move it to the end of the load order, potentially after
definitions using it. I mostly avoided this by keeping top-level
definitions independent. It's fine to refer to any definition inside a
function body, we only need to be careful with initializers for global
variables which run immediately while loading.
After this commit you can still end up in a weird state if you modify a
definition that other later definitions use. In the above example, you
will now see Foo = 4 and Bar = 4. But when you restart, Foo = 4 and Bar
= 5. But that's no more confusing than Emacs's C-x C-e. It's still
a good idea to keep top-level definitions order-independent. It's just
confusing in a similar way to existing tools if you fail to do so. And
your tools won't tend to break as badly.
Why did I ever do my weird version history thing? I think it's my deep
aversion to risking losing any data entered. (Even though the app
currently will seem to lose data in those situations. You'd need to
leave your tools to find the data.) Now I rely on driver.love's undo to
avoid data loss, but once you shut it down you're stuck with what you
have on disk. Or in git.
I also wasn't aware for a long time of any primitives for deleting
files. This might have colored my choices a lot.
Functions can refer to each other, but global variable initializers
shouldn't.
But this doesn't work. That comment keeps growing to capture more corner
cases.
Step back. What am I trying to achieve?
I'm not trying to create a better abstraction for programming with. I'm
trying to use an existing abstraction (LÖVE) without needing additional
tools.
I'm not supporting end-user programming, only end-programmer
programming. What happens in a regular LÖVE program if you use a global
before it's defined? You get an error, and you're on the hook to fix it.
But it's obvious what's going on because a file has an obvious sequence
of definitions. But what if you have multiple files? It's easy to lose
track of order and we mostly don't care.
The important property existing dev environments care about: merely
editing a definition doesn't _change_ the order of top-level
definitions. Let's just provide this guarantee.
We'll no longer load definitions in order of their version. Just load
definitions in the order they were created. Editing a definition doesn't
change this order. Deleting and recreating a definition puts it at the
end.
The first time you connect to an app with driver.love, it'll request and
obtain any available default_map to show you. That should make for a
better initial experience. Past that point you're free to move
definitions around, and the default map will stop getting in your way.
Is it possible this will work?
If so, the programmer's responsibility is to ensure App.initialize_globals()
has no side-effects besides initializing global bindings.
I just tried my freewheeling apps on Windows and noticed filenames
conflicting and failing to show up in the working tree on the
case-insensensitive file system.