Prohibit nested macros

After discussion (starting there:
https://github.com/gbdev/rgbds/pull/594#issuecomment-706437458
), it was decided that plain nested macros should not be
allowed.
Since #590 is fixed, EQUS can be used as a workaround;
multiline strings (#589) will make that easier on the
user when implemented.
Fixes #588, supersedes and closes #594.
Additionally, closes #388.
This commit is contained in:
ISSOtm
2020-12-09 10:44:39 +01:00
parent f16e34b804
commit 462fd7539c
5 changed files with 67 additions and 35 deletions

View File

@@ -2045,7 +2045,6 @@ finish:
void lexer_CaptureMacroBody(char **capture, size_t *size) void lexer_CaptureMacroBody(char **capture, size_t *size)
{ {
char *captureStart = startCapture(); char *captureStart = startCapture();
unsigned int level = 0;
int c = peek(0); int c = peek(0);
/* If the file is `mmap`ed, we need not to unmap it to keep access to the macro */ /* If the file is `mmap`ed, we need not to unmap it to keep access to the macro */
@@ -2082,27 +2081,7 @@ void lexer_CaptureMacroBody(char **capture, size_t *size)
} while (isWhitespace(c)); } while (isWhitespace(c));
/* Now, try to match either `REPT` or `ENDR` as a **whole** identifier */ /* Now, try to match either `REPT` or `ENDR` as a **whole** identifier */
if (startsIdentifier(c)) { if (startsIdentifier(c)) {
switch (readIdentifier(c)) { if (readIdentifier(c) == T_POP_ENDM) {
case T_ID:
/* We have an initial label, look for a single colon */
do {
c = nextChar();
} while (isWhitespace(c));
if (c != ':') /* If not a colon, give up */
break;
/* And finally, a `MACRO` token */
do {
c = nextChar();
} while (isWhitespace(c));
if (!startsIdentifier(c))
break;
if (readIdentifier(c) != T_POP_MACRO)
break;
level++;
break;
case T_POP_ENDM:
if (!level) {
/* Read (but don't capture) until EOL or EOF */ /* Read (but don't capture) until EOL or EOF */
lexerState->capturing = false; lexerState->capturing = false;
do { do {
@@ -2116,8 +2095,6 @@ void lexer_CaptureMacroBody(char **capture, size_t *size)
shiftChars(1); shiftChars(1);
goto finish; goto finish;
} }
level--;
}
} }
lexerState->lineNo++; lexerState->lineNo++;
} }

View File

@@ -923,6 +923,26 @@ Note that a single colon
.Ql \&: .Ql \&:
following the macro's name is required. following the macro's name is required.
Macros can't be exported or imported. Macros can't be exported or imported.
.Pp
Plainly nesting macro definitions is not allowed, but this can be worked around using
.Ic EQUS .
This won't work:
.Bd -literal -offset indent
outer: MACRO
inner: MACRO
PRINTT "Hello!\[rs]n"
ENDM
ENDM
.Ed
.Pp
But this will:
.Bd -literal -offset indent
outer: MACRO
definition equs "inner: MACRO\[rs]nPRINTT \[rs]"Hello!\[rs]\[rs]n\[rs]"\[rs]nENDM"
definition
PURGE definition
ENDM
.Ed
.El .El
.Ss Exporting and importing symbols .Ss Exporting and importing symbols
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file. Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.

View File

@@ -0,0 +1,27 @@
outer_ok: MACRO
definition equs "inner_ok: MACRO\nPRINTT \"Hello!\\n\"\nENDM"
definition
PURGE definition
ENDM
outer_ok
inner_ok
outer_arg: MACRO
definition equs "inner_arg: MACRO\nPRINTT \"outer: \1\\ninner: \\1\\n\"\nENDM"
definition
PURGE definition
ENDM
outer_arg outside
inner_arg inside
outer: MACRO
WARN "Nested macros shouldn't work, whose argument would be \\1?"
inner: MACRO
ENDM
outer
inner

View File

@@ -0,0 +1,5 @@
warning: nested-macrodef.asm(26) -> nested-macrodef.asm::outer(22): [-Wuser]
Nested macros shouldn't work, whose argument would be \1?
ERROR: nested-macrodef.asm(26) -> nested-macrodef.asm::outer(25):
Unterminated macro definition
error: Assembly aborted (1 errors)!

View File

@@ -0,0 +1,3 @@
Hello!
outer: outside
inner: inside