-
-
Notifications
You must be signed in to change notification settings - Fork 180
Fix #588: lexer_CaptureMacroBody can read nested MACRO/ENDM
#594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
49b58e5 to
5f20629
Compare
This alters the result of the line-continuation-macro test; I've argued that that the new result is a logical one.
|
No problem with the modified test case, given the altered requirements for an |
|
|
||
| /* Function to read identifiers & keywords for macros within macros */ | ||
|
|
||
| static bool startsMacroWithinMacro(int c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There must be a similar check elsewhere, and should be merged with this. Preferably, the factored-out function should be placed close to the function that actually performs identifier lexing, so that the character sets are kept in sync during future modifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
startsMacroWithinMacro was based on startsIdentifier. They both allow A-Za-z_, but startsIdentifier also allows . for local labels, whereas startsMacroWithinMacro also allows \\ for macro arguments or line continuations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest having a startsIdentifier and startsScopedIdentifier, perhaps? The latter would accept ., but not the former.
| return (c <= 'Z' && c >= 'A') || (c <= 'z' && c >= 'a') || c == '_' || c == '\\'; | ||
| } | ||
|
|
||
| static int readMacroWithinMacro(char firstChar) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this name, because it seems to imply that the function reads the entire macro, when it only checks for a macro boundary. Maybe readMacroBoundary? Though I'm not satisfied with that one...
|
After reviewing the code, the part that I really don't like is having to manually handle macro arguments. The entire point of the new lexer is to flatten them in a single place, and this would begin introducing the old lexer's pattern of handling macro args explicitly in each place—which led to a bunch of idiosyncrasies. As @AntonioND pointed out, the other problem with nested macros is that there is no clear distinction between the two "macro" passes, i.e. whether an argument should be expanded when evaluating the outer macro, or the inner one. The old lexer behavior was to expand nothing inside the inner when processing the outer, which is fine. The key insight here, is that there isn't much incentive to define a macro within a macro if you can't "pre-expand" anything into it. @Rangi42 instead suggested sticking the macro definition in an Another problem with defining a macro in a macro is the lifetime of the underlying buffer: to help speed up macro definition, they are stored as views into buffers as much as possible, instead of creating additional copies. Allowing macros to be defined from within macros would require adding more lifetime logic (ref counting, sure, but that implies a pointer both to the buffer start and the ref-counted buffer, which starts sounding like madness). Worse still, the computations required to check for a macro definition start require a lexer-in-lexer (to expand any macro args), and a parser-in-lexer (to ensure consistent behavior with the parser), which is more madness that the new lexer is supposed to fix away, and that I don't want to have to maintain either. I guess the best way to prohibit nested macros would be for the capture function to stop checking for macro definitions (or any kind of depth, for that matter), and have the parser check if inside a macro when reaching a macro definition line. |
|
If #590 can be fixed to allow using If Basically if we can take care of #590 I can modify this to be "Remove the partial |
Beginning a macro definition would have to be checked for anyways, to avoid calling the macro capture function incorrectly. One could argue that nested macros should be checked during macro definition instead of invocation, but 1. macro args make that impossible to predict, and 2. it would lead back to the parser-in-lexer problem we're trying to avoid anyways. |
|
#388 is relevant to this issue. |
|
Yes, and really, considering the interaction that that could have with macro args, I have since changed my mind, and don't want it anymore. What I was intending it for was a big hack, anyways... |
(This PR replaces #592; I'm keeping unrelated fixes in their own branches.)
I expect there will be discussion over whether this is an appropriate fix, and whether nested
MACROs should be explicitly disallowed; but at least they're technically possible.rgbasmnow handles this asm the same way as 0.4.1 and outputs the ROM11 ff 99 99 ee:I went ahead and altered the
line-continuation-macrotest to be passed. Rationale in the previous PR: #592 (comment)