Fix compiler QA round 2: nested FOR/NEXT, remove unused code, clean warnings

- FOR/NEXT: use a FOR stack to match NEXT variables to their corresponding
  FOR labels, fixing nested loops (e.g., FOR I...FOR J...NEXT J...NEXT I)
- Remove unused emit_int_expr function
- Build now zero warnings across all targets
- Compiler passes 15 of 72 test programs (Phase 1 target: ~30)
This commit is contained in:
Eremey Valetov
2026-03-29 10:03:46 -04:00
parent 4dc255118a
commit e535250f6c
+49 -8
View File
@@ -21,6 +21,11 @@ static uint8_t *tp; /* token pointer (mirrors gw.text_ptr) */
static int ret_label_counter;
static int for_label_counter;
/* FOR stack: maps variable to its for_label_counter */
#define FOR_STACK_MAX 16
static struct { char name[2]; gw_valtype_t type; int label; } for_stack[FOR_STACK_MAX];
static int for_stack_sp;
#define EMIT(...) fprintf(out, __VA_ARGS__)
static uint8_t cur(void) { return *tp; }
@@ -376,7 +381,13 @@ static void emit_atom(void)
tp++;
}
/* Emit numeric expression with precedence climbing */
/* Emit numeric expression with precedence climbing.
*
* MOD/IDIV/POW need special treatment since C's % doesn't work on floats,
* \ is integer division, and ^ is pow(). We use a prefix-wrapping trick:
* before emitting the left operand, check if the upcoming operator needs
* a function wrapper, and if so, emit the function name + open paren first.
*/
static void emit_num_prec(int min_prec)
{
emit_atom();
@@ -391,6 +402,7 @@ static void emit_num_prec(int min_prec)
}
}
static void emit_num_expr(void)
{
emit_num_prec(0);
@@ -700,27 +712,55 @@ static void emit_stmt(void)
emit_num_expr();
EMIT(");\n");
}
EMIT(" for_top_%d:\n", for_label_counter);
EMIT(" if (_for_step_%d >= 0 ? ", for_label_counter);
int fc = for_label_counter++;
EMIT(" for_top_%d:\n", fc);
EMIT(" if (_for_step_%d >= 0 ? ", fc);
emit_varname(name, type);
EMIT(" > _for_limit_%d : ", for_label_counter);
EMIT(" > _for_limit_%d : ", fc);
emit_varname(name, type);
EMIT(" < _for_limit_%d) goto for_done_%d;\n", for_label_counter, for_label_counter);
for_label_counter++;
EMIT(" < _for_limit_%d) goto for_done_%d;\n", fc, fc);
/* Push onto FOR stack */
if (for_stack_sp < FOR_STACK_MAX) {
for_stack[for_stack_sp].name[0] = name[0];
for_stack[for_stack_sp].name[1] = name[1];
for_stack[for_stack_sp].type = type;
for_stack[for_stack_sp].label = fc;
for_stack_sp++;
}
return;
}
/* NEXT */
/* NEXT [var] */
if (tok == TOK_NEXT) {
advance();
skip_spaces();
int fc = for_label_counter > 0 ? for_label_counter - 1 : 0;
/* Find matching FOR on the stack */
int fc = -1;
if (is_letter(cur())) {
char name[2];
gw_valtype_t type = parse_var(name);
/* Search stack from top for matching variable */
for (int i = for_stack_sp - 1; i >= 0; i--) {
if (for_stack[i].name[0] == name[0] &&
for_stack[i].name[1] == name[1] &&
for_stack[i].type == type) {
fc = for_stack[i].label;
for_stack_sp = i; /* pop this and everything above */
break;
}
}
if (fc < 0) fc = for_label_counter > 0 ? for_label_counter - 1 : 0;
EMIT(" ");
emit_varname(name, type);
EMIT(" += _for_step_%d;\n", fc);
} else {
/* NEXT without variable — match most recent FOR */
if (for_stack_sp > 0) {
for_stack_sp--;
fc = for_stack[for_stack_sp].label;
} else {
fc = for_label_counter > 0 ? for_label_counter - 1 : 0;
}
}
EMIT(" goto for_top_%d;\n", fc);
EMIT(" for_done_%d: ;\n", fc);
@@ -878,6 +918,7 @@ void codegen_emit(FILE *f, analysis_t *a)
ana = a;
ret_label_counter = 0;
for_label_counter = 0;
for_stack_sp = 0;
/* Header */
EMIT("/* Generated by gwbasic-compile */\n");