Change FOREACH to FOR (#680)

This commit is contained in:
Rangi
2021-01-01 18:46:26 -05:00
committed by GitHub
parent 10e3f1a02b
commit 7bb6f71f0b
9 changed files with 63 additions and 63 deletions

View File

@@ -73,7 +73,7 @@ bool yywrap(void);
void fstk_RunInclude(char const *path);
void fstk_RunMacro(char const *macroName, struct MacroArgs *args);
void fstk_RunRept(uint32_t count, int32_t nReptLineNo, char *body, size_t size);
void fstk_RunForeach(char const *symName, int32_t start, int32_t stop, int32_t step,
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size);
void fstk_Init(char const *mainPath, size_t maxRecursionDepth);

View File

@@ -34,9 +34,9 @@ struct Context {
uint32_t uniqueID;
struct MacroArgs *macroArgs; /* Macro args are *saved* here */
uint32_t nbReptIters;
int32_t foreachValue;
int32_t foreachStep;
char *foreachName;
int32_t forValue;
int32_t forStep;
char *forName;
};
static struct Context *contextStack;
@@ -220,14 +220,14 @@ bool yywrap(void)
}
fileInfo->iters[0]++;
/* If this is a FOREACH, update the symbol value */
if (contextStack->foreachName) {
contextStack->foreachValue += contextStack->foreachStep;
struct Symbol *sym = sym_AddSet(contextStack->foreachName,
contextStack->foreachValue);
/* If this is a FOR, update the symbol value */
if (contextStack->forName) {
contextStack->forValue += contextStack->forStep;
struct Symbol *sym = sym_AddSet(contextStack->forName,
contextStack->forValue);
if (sym->type != SYM_SET)
fatalerror("Failed to update FOREACH symbol value\n");
fatalerror("Failed to update FOR symbol value\n");
}
/* If this wasn't the last iteration, wrap instead of popping */
if (fileInfo->iters[0] <= contextStack->nbReptIters) {
@@ -254,8 +254,8 @@ bool yywrap(void)
/* Free the file stack node */
if (!context->fileInfo->referenced)
free(context->fileInfo);
/* Free the FOREACH symbol name */
free(context->foreachName);
/* Free the FOR symbol name */
free(context->forName);
/* Free the entry and make its parent the current entry */
free(context);
@@ -281,7 +281,7 @@ static void newContext(struct FileStackNode *fileInfo)
fileInfo->referenced = false;
fileInfo->lineNo = lexer_GetLineNo();
context->fileInfo = fileInfo;
context->foreachName = NULL;
context->forName = NULL;
/*
* Link new entry to its parent so it's reachable later
* ERRORS SHOULD NOT OCCUR AFTER THIS!!
@@ -443,13 +443,13 @@ void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size)
return;
contextStack->nbReptIters = count;
contextStack->foreachName = NULL;
contextStack->forName = NULL;
}
void fstk_RunForeach(char const *symName, int32_t start, int32_t stop, int32_t step,
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size)
{
dbgPrint("Running FOREACH(\"%s\", %" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
dbgPrint("Running FOR(\"%s\", %" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
symName, start, stop, step);
struct Symbol *sym = sym_AddSet(symName, start);
@@ -464,7 +464,7 @@ void fstk_RunForeach(char const *symName, int32_t start, int32_t stop, int32_t s
else if (step < 0 && stop < start)
count = (start - stop - 1) / -step + 1;
else if (step == 0)
error("FOREACH cannot have a step value of 0\n");
error("FOR cannot have a step value of 0\n");
if (count == 0)
return;
@@ -472,11 +472,11 @@ void fstk_RunForeach(char const *symName, int32_t start, int32_t stop, int32_t s
return;
contextStack->nbReptIters = count;
contextStack->foreachValue = start;
contextStack->foreachStep = step;
contextStack->foreachName = strdup(symName);
if (!contextStack->foreachName)
fatalerror("Not enough memory for FOREACH name: %s\n", strerror(errno));
contextStack->forValue = start;
contextStack->forStep = step;
contextStack->forName = strdup(symName);
if (!contextStack->forName)
fatalerror("Not enough memory for FOR symbol name: %s\n", strerror(errno));
}
void fstk_Init(char const *mainPath, size_t maxRecursionDepth)
@@ -508,9 +508,9 @@ void fstk_Init(char const *mainPath, size_t maxRecursionDepth)
context->uniqueID = 0;
macro_SetUniqueID(0);
context->nbReptIters = 0;
context->foreachValue = 0;
context->foreachStep = 0;
context->foreachName = NULL;
context->forValue = 0;
context->forStep = 0;
context->forName = NULL;
/* Now that it's set up properly, register the context */
contextStack = context;

View File

@@ -240,7 +240,7 @@ static struct KeywordMapping {
{"SHIFT", T_POP_SHIFT},
{"REPT", T_POP_REPT},
{"FOREACH", T_POP_FOREACH},
{"FOR", T_POP_FOR},
{"ENDR", T_POP_ENDR},
{"LOAD", T_POP_LOAD},
@@ -462,7 +462,7 @@ struct LexerState *lexer_OpenFileView(char *buf, size_t size, uint32_t lineNo)
void lexer_RestartRept(uint32_t lineNo)
{
dbgPrint("Restarting REPT/FOREACH\n");
dbgPrint("Restarting REPT/FOR\n");
lexerState->offset = 0;
initState(lexerState);
lexerState->lineNo = lineNo;
@@ -2123,11 +2123,11 @@ void lexer_CaptureRept(char **capture, size_t *size)
do { /* Discard initial whitespace */
c = nextChar();
} while (isWhitespace(c));
/* Now, try to match `REPT`, `FOREACH` or `ENDR` as a **whole** identifier */
/* Now, try to match `REPT`, `FOR` or `ENDR` as a **whole** identifier */
if (startsIdentifier(c)) {
switch (readIdentifier(c)) {
case T_POP_REPT:
case T_POP_FOREACH:
case T_POP_FOR:
level++;
/* Ignore the rest of that line */
break;
@@ -2156,7 +2156,7 @@ void lexer_CaptureRept(char **capture, size_t *size)
/* Just consume characters until EOL or EOF */
for (;;) {
if (c == EOF) {
error("Unterminated REPT/FOREACH block\n");
error("Unterminated REPT/FOR block\n");
lexerState->capturing = false;
goto finish;
} else if (c == '\n' || c == '\r') {

View File

@@ -310,7 +310,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
int32_t start;
int32_t stop;
int32_t step;
} foreachArgs;
} forArgs;
struct StrFmtArgList strfmtArgs;
}
@@ -406,7 +406,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
%token T_POP_ENDM
%token T_POP_RSRESET T_POP_RSSET
%token T_POP_UNION T_POP_NEXTU T_POP_ENDU
%token T_POP_INCBIN T_POP_REPT T_POP_FOREACH
%token T_POP_INCBIN T_POP_REPT T_POP_FOR
%token T_POP_CHARMAP
%token T_POP_NEWCHARMAP
%token T_POP_SETCHARMAP
@@ -431,7 +431,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
%type <sectMod> sectmod
%type <macroArg> macroargs
%type <foreachArgs> foreach_args
%type <forArgs> for_args
%token T_Z80_ADC T_Z80_ADD T_Z80_AND
%token T_Z80_BIT
@@ -634,7 +634,7 @@ simple_pseudoop : include
| popc
| load
| rept
| foreach
| for
| shift
| fail
| warn
@@ -758,15 +758,15 @@ rept : T_POP_REPT uconst {
}
;
foreach : T_POP_FOREACH T_ID T_COMMA foreach_args {
for : T_POP_FOR T_ID T_COMMA for_args {
uint32_t nDefinitionLineNo = lexer_GetLineNo();
char *body;
size_t size;
lexer_CaptureRept(&body, &size);
fstk_RunForeach($2, $4.start, $4.stop, $4.step, nDefinitionLineNo, body, size);
fstk_RunFor($2, $4.start, $4.stop, $4.step, nDefinitionLineNo, body, size);
}
foreach_args : const {
for_args : const {
$$.start = 0;
$$.stop = $1;
$$.step = 1;

View File

@@ -1533,18 +1533,18 @@ As in macros, you can also use the escape sequence
blocks can be nested.
.Pp
A common pattern is to repeat a block for each value in some range.
.Ic FOREACH
.Ic FOR
is simpler than
.Ic REPT
for that purpose.
Everything between
.Ic FOREACH
.Ic FOR
and the matching
.Ic ENDR
will be repeated for each value of a given symbol.
For example, this code will produce a table of squared values from 0 to 255:
.Bd -literal -offset indent
FOREACH N, 256
FOR N, 256
dw N * N
ENDR
.Ed
@@ -1564,24 +1564,24 @@ N = 256
.Ed
.Pp
You can customize the range of
.Ic FOREACH
.Ic FOR
values:
.Bl -column "FOREACH V, start, stop, step"
.Bl -column "FOR V, start, stop, step"
.It Sy Code Ta Sy Range
.It Ic FOREACH Ar V , stop Ta Ar V No increments from 0 to Ar stop No
.It Ic FOREACH Ar V , start , stop Ta Ar V No increments from Ar start No to Ar stop No
.It Ic FOREACH Ar V , start , stop , step Ta Ar V No goes from Ar start No to Ar stop No by Ar step No
.It Ic FOR Ar V , stop Ta Ar V No increments from 0 to Ar stop No
.It Ic FOR Ar V , start , stop Ta Ar V No increments from Ar start No to Ar stop No
.It Ic FOR Ar V , start , stop , step Ta Ar V No goes from Ar start No to Ar stop No by Ar step No
.El
.Pp
The
.Ic FOREACH
.Ic FOR
value will be updated by
.Ar step
until it reaches or exceeds
.Ar stop.
For example:
.Bd -literal -offset indent
FOREACH V, 4, 25, 5
FOR V, 4, 25, 5
PRINTT "{d:V} "
ENDR
PRINTT "done {d:V}\n"
@@ -1596,7 +1596,7 @@ Just like with
blocks, you can use the escape sequence
.Ic \[rs]@
inside of
.Ic FOREACH
.Ic FOR
blocks, and they can be nested.
.Ss Aborting the assembly process
.Ic FAIL

View File

@@ -1,44 +1,44 @@
foreach n, 10
for n, 10
printt "{d:n} "
endr
printt "-> {d:n}\n"
foreach v, 0
for v, 0
printt "unreached"
endr
foreach v, 2, 1
for v, 2, 1
printt "unreached"
endr
foreach v, 1, 2, 0
for v, 1, 2, 0
printt "unreached"
endr
foreach x, 1, 5+1
for x, 1, 5+1
printt "{d:x} "
endr
printt "-> {d:x}\n"
foreach v, 10, -1, -1
for v, 10, -1, -1
printt "{d:v} "
v = 42
endr
printt "-> {d:v}\n"
foreach q, 5, 21, 5
for q, 5, 21, 5
printt "{d:q} "
purge q
endr
printt "-> {d:q}\n"
s EQUS "x"
foreach s, 3, 30, 3
for s, 3, 30, 3
printt "{d:x} "
endr
printt "-> {d:x}\n"
foreach v, 10
for v, 10
printt "{d:v}\n"
if v == 3
purge v

6
test/asm/for.err Normal file
View File

@@ -0,0 +1,6 @@
ERROR: for.asm(16):
FOR cannot have a step value of 0
ERROR: for.asm(41) -> for.asm::REPT~5(47):
'v' already defined as constant at for.asm(41) -> for.asm::REPT~4(45)
FATAL: for.asm(41) -> for.asm::REPT~5(47):
Failed to update FOR symbol value

View File

@@ -1,6 +0,0 @@
ERROR: foreach.asm(16):
FOREACH cannot have a step value of 0
ERROR: foreach.asm(41) -> foreach.asm::REPT~5(47):
'v' already defined as constant at foreach.asm(41) -> foreach.asm::REPT~4(45)
FATAL: foreach.asm(41) -> foreach.asm::REPT~5(47):
Failed to update FOREACH symbol value