mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Refactor the lexer to not use the lookupExpansion X macro
This macro was only used twice, in `beginExpansion` and `lexer_DumpStringExpansions`, with `getExpansionAtDistance` already containing an inlined and slightly modified version of `lookupExpansion` (retaining the `LOOKUP_PRE_NEST` and `LOOKUP_POST_NEST` macros, but with both of them doing nothing). Not using an X macro here makes the actual control flow in both places more obvious, and I think the repeated code is acceptable for the same reasons as the similar-but-distinct implementations of `readString`, `appendStringLiteral`, `yylex_NORMAL`, and `yylex_RAW`.
This commit is contained in:
119
src/asm/lexer.c
119
src/asm/lexer.c
@@ -671,61 +671,18 @@ static void reallocCaptureBuf(void)
|
|||||||
fatalerror("realloc error while resizing capture buffer: %s\n", strerror(errno));
|
fatalerror("realloc error while resizing capture buffer: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The multiple evaluations of `retvar` causing side effects is INTENTIONAL, and
|
|
||||||
* required for example by `lexer_dumpStringExpansions`. It is however only
|
|
||||||
* evaluated once per level, and only then.
|
|
||||||
*
|
|
||||||
* This uses the concept of "X macros": you must #define LOOKUP_PRE_NEST and
|
|
||||||
* LOOKUP_POST_NEST before invoking this (and #undef them right after), and
|
|
||||||
* those macros will be expanded at the corresponding points in the loop.
|
|
||||||
* This is necessary because there are at least 3 places which need to iterate
|
|
||||||
* through iterations while performing custom actions
|
|
||||||
*/
|
|
||||||
#define lookupExpansion(retvar, dist) do { \
|
|
||||||
struct Expansion *exp = lexerState->expansions; \
|
|
||||||
\
|
|
||||||
for (;;) { \
|
|
||||||
/* Find the closest expansion whose end is after the target */ \
|
|
||||||
while (exp && exp->totalLen + exp->distance <= (dist)) { \
|
|
||||||
(dist) -= exp->totalLen + exp->skip; \
|
|
||||||
exp = exp->next; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* If there is none, or it begins after the target, return the previous level */ \
|
|
||||||
if (!exp || exp->distance > (dist)) \
|
|
||||||
break; \
|
|
||||||
\
|
|
||||||
/* We know we are inside of that expansion */ \
|
|
||||||
(dist) -= exp->distance; /* Distances are relative to their parent */ \
|
|
||||||
\
|
|
||||||
/* Otherwise, register this expansion and repeat the process */ \
|
|
||||||
LOOKUP_PRE_NEST(exp); \
|
|
||||||
(retvar) = exp; \
|
|
||||||
if (!exp->firstChild) /* If there are no children, this is it */ \
|
|
||||||
break; \
|
|
||||||
exp = exp->firstChild; \
|
|
||||||
\
|
|
||||||
LOOKUP_POST_NEST(exp); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static struct Expansion *getExpansionAtDistance(size_t *distance)
|
static struct Expansion *getExpansionAtDistance(size_t *distance)
|
||||||
{
|
{
|
||||||
struct Expansion *expansion = NULL; /* Top level has no "previous" level */
|
struct Expansion *expansion = NULL; /* Top level has no "previous" level */
|
||||||
|
|
||||||
#define LOOKUP_PRE_NEST(exp)
|
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
|
||||||
#define LOOKUP_POST_NEST(exp)
|
|
||||||
struct Expansion *exp = lexerState->expansions;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
/* Find the closest expansion whose end is after the target */
|
/* Find the closest expansion whose end is after the target */
|
||||||
while (exp && exp->totalLen + exp->distance <= *distance) {
|
while (exp && exp->totalLen + exp->distance <= *distance) {
|
||||||
*distance -= exp->totalLen - exp->skip;
|
*distance -= exp->totalLen - exp->skip;
|
||||||
exp = exp->next;
|
exp = exp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is none, or it begins after the target, return the previous level */
|
/* If there is none, or it begins after the target, stop at previous level */
|
||||||
if (!exp || exp->distance > *distance)
|
if (!exp || exp->distance > *distance)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -733,16 +690,8 @@ static struct Expansion *getExpansionAtDistance(size_t *distance)
|
|||||||
*distance -= exp->distance; /* Distances are relative to their parent */
|
*distance -= exp->distance; /* Distances are relative to their parent */
|
||||||
|
|
||||||
/* Otherwise, register this expansion and repeat the process */
|
/* Otherwise, register this expansion and repeat the process */
|
||||||
LOOKUP_PRE_NEST(exp);
|
|
||||||
expansion = exp;
|
expansion = exp;
|
||||||
if (!exp->firstChild) /* If there are no children, this is it */
|
|
||||||
break;
|
|
||||||
exp = exp->firstChild;
|
|
||||||
|
|
||||||
LOOKUP_POST_NEST(exp);
|
|
||||||
}
|
}
|
||||||
#undef LOOKUP_PRE_NEST
|
|
||||||
#undef LOOKUP_POST_NEST
|
|
||||||
|
|
||||||
return expansion;
|
return expansion;
|
||||||
}
|
}
|
||||||
@@ -757,21 +706,34 @@ static void beginExpansion(size_t distance, uint8_t skip, char const *str, bool
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
distance += lexerState->expansionOfs; /* Distance argument is relative to read offset! */
|
distance += lexerState->expansionOfs; /* Distance argument is relative to read offset! */
|
||||||
|
|
||||||
/* Increase the total length of all parents, and return the topmost one */
|
/* Increase the total length of all parents, and return the topmost one */
|
||||||
struct Expansion *parent = NULL;
|
struct Expansion *parent = NULL;
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
|
|
||||||
#define LOOKUP_PRE_NEST(exp) do { \
|
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
|
||||||
assert((exp)->totalLen <= SIZE_MAX - (size - skip)); \
|
/* Find the closest expansion whose end is after the target */
|
||||||
(exp)->totalLen += size - skip; \
|
while (exp && exp->totalLen + exp->distance <= distance) {
|
||||||
} while (0)
|
distance -= exp->totalLen + exp->skip;
|
||||||
#define LOOKUP_POST_NEST(exp) do { \
|
exp = exp->next;
|
||||||
if (name && ++depth >= nMaxRecursionDepth) \
|
}
|
||||||
fatalerror("Recursion limit (%zu) exceeded\n", nMaxRecursionDepth); \
|
|
||||||
} while (0)
|
/* If there is none, or it begins after the target, stop at the previous level */
|
||||||
lookupExpansion(parent, distance);
|
if (!exp || exp->distance > distance)
|
||||||
#undef LOOKUP_PRE_NEST
|
break;
|
||||||
#undef LOOKUP_POST_NEST
|
|
||||||
|
/* We know we are inside of that expansion */
|
||||||
|
distance -= exp->distance; /* Distances are relative to their parent */
|
||||||
|
|
||||||
|
/* Otherwise, register this expansion and repeat the process */
|
||||||
|
assert(exp->totalLen <= SIZE_MAX - (size - skip));
|
||||||
|
exp->totalLen += size - skip;
|
||||||
|
parent = exp;
|
||||||
|
|
||||||
|
if (name && depth++ >= nMaxRecursionDepth)
|
||||||
|
fatalerror("Recursion limit (%zu) exceeded\n", nMaxRecursionDepth);
|
||||||
|
}
|
||||||
|
|
||||||
struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
|
struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
|
||||||
|
|
||||||
/* We know we are in none of the children expansions: add ourselves, keeping it sorted */
|
/* We know we are in none of the children expansions: add ourselves, keeping it sorted */
|
||||||
@@ -1069,23 +1031,30 @@ void lexer_DumpStringExpansions(void)
|
|||||||
if (!lexerState)
|
if (!lexerState)
|
||||||
return;
|
return;
|
||||||
struct Expansion **stack = malloc(sizeof(*stack) * (nMaxRecursionDepth + 1));
|
struct Expansion **stack = malloc(sizeof(*stack) * (nMaxRecursionDepth + 1));
|
||||||
struct Expansion *expansion; /* Temp var for `lookupExpansion` */
|
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
size_t distance = lexerState->expansionOfs;
|
size_t distance = lexerState->expansionOfs;
|
||||||
|
|
||||||
if (!stack)
|
if (!stack)
|
||||||
fatalerror("Failed to alloc string expansion stack: %s\n", strerror(errno));
|
fatalerror("Failed to alloc string expansion stack: %s\n", strerror(errno));
|
||||||
|
|
||||||
#define LOOKUP_PRE_NEST(exp) do { \
|
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
|
||||||
/* Only register EQUS expansions, not string args */ \
|
/* Find the closest expansion whose end is after the target */
|
||||||
if ((exp)->name) \
|
while (exp && exp->totalLen + exp->distance <= distance) {
|
||||||
stack[depth++] = (exp); \
|
distance -= exp->totalLen + exp->skip;
|
||||||
} while (0)
|
exp = exp->next;
|
||||||
#define LOOKUP_POST_NEST(exp)
|
}
|
||||||
lookupExpansion(expansion, distance);
|
|
||||||
(void)expansion;
|
/* If there is none, or it begins after the target, stop at the previous level */
|
||||||
#undef LOOKUP_PRE_NEST
|
if (!exp || exp->distance > distance)
|
||||||
#undef LOOKUP_POST_NEST
|
break;
|
||||||
|
|
||||||
|
/* We know we are inside of that expansion */
|
||||||
|
distance -= exp->distance; /* Distances are relative to their parent */
|
||||||
|
|
||||||
|
/* Only register EQUS expansions, not string args */
|
||||||
|
if (exp->name)
|
||||||
|
stack[depth++] = exp;
|
||||||
|
}
|
||||||
|
|
||||||
while (depth--)
|
while (depth--)
|
||||||
fprintf(stderr, "while expanding symbol \"%s\"\n", stack[depth]->name);
|
fprintf(stderr, "while expanding symbol \"%s\"\n", stack[depth]->name);
|
||||||
|
|||||||
Reference in New Issue
Block a user