From 0e0052f9cfe9bc91c692d2c8c1be5dfc0cd6b6ac Mon Sep 17 00:00:00 2001 From: Eremey Valetov Date: Sun, 29 Mar 2026 13:31:17 -0400 Subject: [PATCH] =?UTF-8?q?Compiler:=20fix=2016=20of=2018=20compile=20erro?= =?UTF-8?q?rs=20=E2=80=94=2032/72=20tests=20passing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- include/gwrt.h | 2 ++ src/codegen.c | 87 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/include/gwrt.h b/include/gwrt.h index 2b4d930..92ebc76 100644 --- a/include/gwrt.h +++ b/include/gwrt.h @@ -14,6 +14,8 @@ #include "strpool.h" #include "portio.h" #include "sound.h" +#include "graphics.h" +#include "virmem.h" #include /* Initialization / shutdown */ diff --git a/src/codegen.c b/src/codegen.c index 68476a7..244c26d 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -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();