Skip to content

Commit

Permalink
Implement order-independent purge (gbdev#1173)
Browse files Browse the repository at this point in the history
Each symbol passed to purge is collected in a list before mass removal.
Fixes the issue described in gbdev/rgbds issue gbdev#1152.

---------

Co-authored-by: Rangi42 <[email protected]>
  • Loading branch information
quinnyo and Rangi42 authored Oct 25, 2023
1 parent 7a39e9e commit 944c5f0
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 6 deletions.
7 changes: 7 additions & 0 deletions include/asm/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,11 @@ struct DsArgList {
struct Expression *args;
};

#define INITIAL_PURGE_ARG_SIZE 2
struct PurgeArgList {
size_t nbArgs;
size_t capacity;
char **args;
};

#endif // RGBDS_ASM_LEXER_H
50 changes: 44 additions & 6 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,35 @@ static void freeDsArgList(struct DsArgList *args)
free(args->args);
}

static void initPurgeArgList(struct PurgeArgList *args)
{
args->nbArgs = 0;
args->capacity = INITIAL_PURGE_ARG_SIZE;
args->args = malloc(args->capacity * sizeof(*args->args));
if (!args->args)
fatalerror("Failed to allocate memory for purge arg list: %s\n",
strerror(errno));
}

static void appendPurgeArgList(struct PurgeArgList *args, char *arg)
{
if (args->nbArgs == args->capacity) {
args->capacity = (args->capacity + 1) * 2;
args->args = realloc(args->args, args->capacity * sizeof(*args->args));
if (!args->args)
fatalerror("realloc error while resizing purge arg list: %s\n",
strerror(errno));
}
args->args[args->nbArgs++] = arg;
}

static void freePurgeArgList(struct PurgeArgList *args)
{
for (size_t i = 0; i < args->nbArgs; i++)
free(args->args[i]);
free(args->args);
}

static void failAssert(enum AssertionType type)
{
switch (type) {
Expand Down Expand Up @@ -481,6 +510,7 @@ enum {
struct MacroArgs *macroArg;
enum AssertionType assertType;
struct DsArgList dsArgs;
struct PurgeArgList purgeArgs;
struct {
int32_t start;
int32_t stop;
Expand Down Expand Up @@ -636,6 +666,8 @@ enum {

%type <dsArgs> ds_args

%type <purgeArgs> purge_args

%type <forArgs> for_args

%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
Expand Down Expand Up @@ -1199,16 +1231,22 @@ redef_equs : redef_id T_POP_EQUS string { sym_RedefString($1, $3); }

purge : T_POP_PURGE {
lexer_ToggleStringExpansion(false);
} purge_list trailing_comma {
} purge_args trailing_comma {
for (uint32_t i = 0; i < $3.nbArgs; i++)
sym_Purge($3.args[i]);
freePurgeArgList(&$3);
lexer_ToggleStringExpansion(true);
}
;

purge_list : purge_list_entry
| purge_list T_COMMA purge_list_entry
;

purge_list_entry : scoped_id { sym_Purge($1); }
purge_args : scoped_id {
initPurgeArgList(&$$);
appendPurgeArgList(&$$, strdup($1));
}
| purge_args T_COMMA scoped_id {
appendPurgeArgList(&$1, strdup($3));
$$ = $1;
}
;

export : T_POP_EXPORT export_list trailing_comma
Expand Down
11 changes: 11 additions & 0 deletions test/asm/purge-deferred.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
DEF prefix EQUS "cool"
DEF {prefix}banana EQU 1

ASSERT DEF(prefix)
ASSERT DEF(coolbanana)

; purging `prefix` should not prevent expanding it to purge `coolbanana`
PURGE prefix, {prefix}banana

ASSERT !DEF(prefix)
ASSERT !DEF(coolbanana)
Empty file added test/asm/purge-deferred.err
Empty file.
Empty file added test/asm/purge-deferred.out
Empty file.

0 comments on commit 944c5f0

Please sign in to comment.