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:
+49
-8
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user