rgbds
rgbds copied to clipboard
Remove `EQUS` expansion?
EQUS expansion has a few problems.
- Unlike
{interpolation}and macro arguments, it occurs afterpeeking and reading a complete identifier. This means that the lexer reacts to the identifier's presence before it gets expanded. For example, ifEMPTY EQUS "", thenld a, \ EMPTYgives an error "Begun line continuation, but encountered character 'E'" whereasld a, \ {EMPTY}does not. - Like
{interpolation}and macro arguments, the expanded contents can be anything, even multiple lines, but nothing makes the bare identifier stand out as being so potentially disruptive. For example, inld a, 2 plus 2, ifplus EQUS ";"then it gets treated as a comment. It can also interact weirdly with statements that parse their own newlines (REPT,FOR,MACRO, etc).
If EQUS expansion were eliminated, then string identifiers could work just like numeric ones: evaluate to their literal contents. This would let people write STRING instead of "{STRING}", which I think is a big improvement, especially in longer expressions like STRIN(HAYSTACK, NEEDLE).
On the other hand, this would be a very backwards-incompatible change: people rely on EQUS expansion for certain use cases that other features don't yet cover. We would need to at least have acceptable substitutes. The use cases I'm familiar with:
- Indirect assignment. For example,
CUR_THING EQUS "X"and thenCUR_THING EQU 42will act likeX EQU 42. This can already be done with interpolation like{CUR_THING} EQU 42, and that's required for the newDEF {CUR_THING} EQU 42syntax. (Expansion inCUR_THING EQU 42was confusing anyway.) - Inline expression pieces. For example,
tiles EQUS "* 16"lets you dold a, 7 tiles, orN EQU ($30 + 6) tiles - 1. Macros have to be a complete line so you need different macros for each situation, and interpolation makes the user-defined pieces stand out too much (ld a, 7 {tiles}isn't as plainly readable). This will eventually be doable with user-defined functions (see #201), likeld a, tiles(7), although such functions will ideally support variable arguments to match everythingEQUScan do. - Small one-line macros. The documentation even recommends this with the example
DEF pusha EQUS "push af\npush bc\npush de\npush hl\n". For short cases liketext EQUS db 0,, it's simpler to write and to read than a three-lineMACRO text / db 0, \# / ENDM. This could be done with a combination of single-lineDEF mac MACRO ...syntax (see #902) and allowing multiple instructions on one line with a statement separator (see #805). However the discussion for those feature requests brought up some valid objections, and unlike user-defined functions, they aren't really useful except as a substitute forEQUS.
If anyone's relying on EQUS expansion for something more idiosyncratic or complicated, then at least interpolation can fill all its use cases. On the one hand, {STRING} is less user-friendly than STRING; on the other hand, STRING is more user-friendly than "{STRING}", and I think the latter is a lot more common than the former (after making use of user-defined functions and macros when possible).
I'm not fundamentally opposed to this, but current use cases for EQUS should be more thoroughly surveyed. My experience mostly comes from Pokémon ROM hacks, and I believe yours does as well; on custom test ROMs I've never had much need for complex EQUS expansions that don't match the simple patterns listed above. This would become a compatibility nightmare, so it's important to supply alternatives to all current use cases, and to make sure that those alternatives will be maintained and not treated as temporary crutches to be removed two versions later.
All in all, it's a pretty reasonable proposal, particularly considering that there's the braced identifier fallback for complex metaprogramming cases. But at the same time, alternatives need to be in place before this becomes a possibility.
Another argument for obsoleting EQUS for inline macros is the lack of priority: ld a, NB_PLAYER_TILES + NB_FOLLOWER_TILES tiles may or may not make sense, but will produce a wrong result.
As for inline macros, they would be a new feature, so we could design a terser, less line-reliant syntax for their definitions. Making them token-based (which is also motivated by other factors) would greatly help with this.
I'm not fundamentally opposed to this, but current use cases for
EQUSshould be more thoroughly surveyed.
But at the same time, alternatives need to be in place before this becomes a possibility.
I agree; fortunately 0.6.0 with user-defined functions is a pretty long way away, so there's plenty of time to gather more examples of how projects use EQUS, and see whether 0.5.x's less brittle macros, user-defined functions, or just {interpolation} are sufficient to replace them. (I did check µCity, LADX, and gb-open-world for other use cases.)
As for inline macros, they would be a new feature, so we could design a terser, less line-reliant syntax for their definitions. Making them token-based (which is also motivated by other factors) would greatly help with this.
My first thought is "do we really need a fourth way to do content replacement", but I'll wait and see.
