Compiler: fix 16 of 18 compile errors — 32/72 tests passing

Fixes:
- Include graphics.h/virmem.h in gwrt.h (5 programs: draw_commands,
  get_put, graphics_stubs, peek_gfx, view_window)
- RND(n): discard argument to buffer instead of emitting it inline
- Float constant 0: emit "0.0f" not "0f" (invalid C suffix)
- MID$ function: proper 3-argument emission with optional length
- FOR/NEXT: use static variables instead of block scope for limit/step
  (fixes FOR inside IF/THEN and unmatched brace issues)
- RESUME/RESUME NEXT: handle as statements (not misparse as FOR/NEXT)
- ON TIMER/KEY/COM: skip event trap setup (not misparse as ON n GOTO)
- MID$ assignment: recognize and skip (don't misparse as variable)
- ERROR statement: emit gw_error() call
- ERASE: stub handler

Only 2 compile errors remain: bubble_sort (SWAP with arrays),
misc_stmts (ENVIRON$ variable name clash).

32 of 72 tests pass. New: datetime, luhn, peek_poke, error_handler,
on_timer, timer_stop, monte_carlo, number_guess.
This commit is contained in:
Eremey Valetov
2026-03-29 13:31:17 -04:00
parent 4f4a8df412
commit 0e0052f9cf
2 changed files with 76 additions and 13 deletions
+2
View File
@@ -14,6 +14,8 @@
#include "strpool.h"
#include "portio.h"
#include "sound.h"
#include "graphics.h"
#include "virmem.h"
#include <setjmp.h>
/* Initialization / shutdown */
+74 -13
View File
@@ -198,7 +198,12 @@ static void emit_atom(void)
float v;
memcpy(&v, tp + 1, 4);
tp += 5;
EMIT("%.9gf", v);
{ char nbuf[32]; snprintf(nbuf, sizeof(nbuf), "%.9g", v);
if (!strchr(nbuf, '.') && !strchr(nbuf, 'e'))
EMIT("%s.0f", nbuf); /* 0 → 0.0f */
else
EMIT("%sf", nbuf); /* 3.14 → 3.14f */
}
return;
}
if (tok == TOK_CONST_DBL) {
@@ -272,9 +277,12 @@ static void emit_atom(void)
return;
}
case FUNC_RND: {
/* RND may or may not have parens */
/* RND([n]) — argument is ignored (controls seed behavior) */
if (cur() == '(') {
advance(); emit_num_expr();
advance();
/* Consume but discard the argument */
char *discard = emit_to_buf(emit_prec_wrapper, 0);
free(discard);
if (cur() == ')') advance();
}
EMIT("((float)rand() / RAND_MAX)");
@@ -630,10 +638,17 @@ static void emit_str_expr(void)
EMIT("gw_fn_mid(&(gw_value_t){.type=VT_STR,.sval=");
advance(); emit_str_expr();
if (cur() == ',') advance();
EMIT("}, ");
EMIT("}, (int)(");
emit_num_expr();
EMIT(", 255");
if (cur() == ',') { advance(); EMIT("); /* mid with len */ "); }
EMIT("), ");
if (cur() == ',') {
advance();
EMIT("(int)(");
emit_num_expr();
EMIT(")");
} else {
EMIT("255");
}
if (cur() == ')') advance();
EMIT(").sval");
return;
@@ -1033,12 +1048,13 @@ static void emit_stmt(void)
EMIT(");\n");
skip_spaces();
if (cur() == TOK_TO) advance();
/* Store limit in a temp */
EMIT(" { %s _for_limit_%d = (%s)(", c_type(type), for_label_counter, c_type(type));
/* Store limit and step at function scope (no {} block — FOR may span IF THEN) */
EMIT(" static %s _for_limit_%d; _for_limit_%d = (%s)(",
c_type(type), for_label_counter, for_label_counter, c_type(type));
emit_num_expr();
EMIT(");\n");
/* Step (default 1) */
EMIT(" %s _for_step_%d = 1;\n", c_type(type), for_label_counter);
EMIT(" static %s _for_step_%d; _for_step_%d = 1;\n",
c_type(type), for_label_counter, for_label_counter);
skip_spaces();
if (cur() == TOK_STEP) {
advance();
@@ -1096,9 +1112,8 @@ static void emit_stmt(void)
fc = for_label_counter > 0 ? for_label_counter - 1 : 0;
}
}
EMIT(" goto for_top_%d;\n", fc);
EMIT(" for_done_%d: ;\n", fc);
EMIT(" }\n");
EMIT(" goto for_top_%d;\n", fc);
EMIT(" for_done_%d: ;\n", fc);
return;
}
@@ -1148,6 +1163,12 @@ static void emit_stmt(void)
}
return;
}
/* ON TIMER / ON KEY / ON COM — event trapping, skip */
if (cur() == TOK_PREFIX_FE || cur() == TOK_KEY) {
EMIT(" /* ON event trap — not compiled */\n");
while (cur() && cur() != ':' && cur() != 0) tp++;
return;
}
EMIT(" { int _on_val = (int)(");
emit_num_expr();
EMIT(");\n");
@@ -1347,6 +1368,39 @@ static void emit_stmt(void)
return;
}
/* RESUME / RESUME NEXT / RESUME n */
if (tok == TOK_RESUME) {
advance();
skip_spaces();
if (cur() == TOK_NEXT) {
advance();
EMIT(" /* RESUME NEXT — not fully compiled */\n");
} else if (is_const(cur())) {
uint16_t target = read_int();
EMIT(" goto L_%u; /* RESUME n */\n", target);
} else {
EMIT(" /* RESUME — not fully compiled */\n");
}
return;
}
/* ERROR n */
if (tok == TOK_ERROR) {
advance();
EMIT(" gw_error((int)(");
emit_num_expr();
EMIT("));\n");
return;
}
/* ERASE */
if (tok == TOK_ERASE) {
advance();
EMIT(" /* ERASE — not yet compiled */\n");
while (cur() && cur() != ':' && cur() != 0) tp++;
return;
}
/* TRON/TROFF */
if (tok == TOK_TRON) { advance(); return; }
if (tok == TOK_TROFF) { advance(); return; }
@@ -1590,6 +1644,13 @@ static void emit_stmt(void)
return;
}
/* MID$ assignment: MID$(var$, start [,len]) = expr */
if (tok == TOK_PREFIX_FF && tp[1] == FUNC_MID) {
EMIT(" /* MID$ assignment — not yet compiled */\n");
while (cur() && cur() != ':' && cur() != 0) tp++;
return;
}
/* Implicit assignment (variable at start of statement) */
if (is_letter(tok)) {
emit_assignment();