Commit Graph
96 Commits
Author SHA1 Message Date
Eremey Valetov 71ff44828d Add 16-bit real-mode DOS target -- 127KB standalone, no extender
New Makefile.dos16 builds with OpenWatcom wcc (16-bit, MEDIUM model)
producing a standard MZ executable that runs on any DOS without DOS/4GW.
All 24 source files compile clean; tested on FreeDOS 1.4 via QEMU.

Changes for 16-bit compatibility:
- hal_dos.c: INTX macro selects int86() vs int386() based on _M_I86
- sound.c: reduce stack buffer from 8192 to 512 samples on 16-bit
- tui.c: gracefully disable TUI if screen buffer allocation fails
  (near heap exhaustion common on 16-bit), batch mode still works
- .gitignore: add .obj/.exe/.err/.lib for OpenWatcom build artifacts

Size comparison:
- 32-bit DOS/4GW: 175KB + 265KB extender = 440KB total
- 16-bit real-mode: 127KB standalone

The 32-bit build (Makefile.dos) and Linux build are unaffected.
72/72 interpreter tests pass.
2026-04-10 06:32:47 -04:00
Eremey Valetov 1ac5466399 Fix five issues found in QA pass 4
1. ABS() now preserves integer argument type in codegen — ABS(int%)
   returns int%, uses gw_int_neg in safe mode. Previously always emitted
   fabs() returning float, causing ABS(30000)+ABS(30000) to silently
   produce 60000.0 instead of raising Overflow.

2. SGN() return type added to VT_INT list in peek_expr_type, so
   SGN(A%)+32767 correctly triggers gw_int_add overflow check.

3. gwrt_array_elem() now uses ERR_BS (Subscript out of range) instead
   of ERR_FC (Illegal function call) for bounds errors, matching the
   safe variant and the interpreter. ON ERROR handlers see ERR=9 in
   both modes.

4. COMMON variables now tracked as assigned in analysis warnings,
   preventing false "used but never assigned" warnings.

5. IF...THEN followed by inline assignment (IF 1 THEN A=5) now
   correctly sets assign_ctx after THEN, preventing false uninitialized
   variable warnings.
2026-04-09 20:21:14 -04:00
Eremey Valetov 8dc4d57ec8 Fix left_type not updated after type-promoting operators
In the buffered expression path, left_type was set once from
peek_expr_type() and never updated. After I% * 2.5, the intermediate
result is float but left_type stayed VT_INT, causing the subsequent
+ I% to incorrectly use gw_int_add which truncated the float to
int16_t and raised a spurious overflow.

Now left_type is updated after each binary operator based on type
promotion rules: division and power produce VT_DBL, comparisons
produce VT_INT, and mixed int/float operations promote to the wider
type.
2026-04-09 18:18:10 -04:00
Eremey Valetov df3926ad17 Fix four bugs found in QA pass 2
1. peek_expr_type() now handles parenthesized expressions — (A%) + (B%)
   correctly triggers gw_int_add in --safe mode instead of falling back
   to plain C addition.

2. FOR limit and step assignments use gw_cint() for integer variables in
   --safe mode, catching out-of-range values (e.g., FOR I% = 1 TO 100000
   now raises Overflow instead of silently truncating).

3. SWAP sets multi_assign so both variables are marked as assigned in the
   --warn uninitialized variable analysis.

4. Bare NEXT (without variable name) now emits the loop variable increment
   from the FOR stack, fixing a pre-existing bug where the loop body
   would execute but the variable never advanced.
2026-04-09 17:52:55 -04:00
Eremey Valetov 20ecdae938 Add --warn and --safe memory safety flags to the compiler
Three progressive levels for gwbasic-compile:

--warn: static analysis warnings (uninitialized variables, GOTO to
nonexistent line, unreachable code detection). Zero runtime cost.

--safe (implies --warn): runtime checked integer arithmetic via
gw_int_add/sub/mul/neg matching real GW-BASIC overflow semantics,
enhanced array bounds diagnostics with variable names and line numbers,
GOSUB stack overflow diagnostics with source line reporting.

--safe=sanitize (implies --safe): passes -fsanitize=address,undefined
to gcc for full memory error detection.

Also: fix pre-existing missing closing paren in array LET-to-integer
codegen, add strpool_pin/unpin infrastructure, add compiler optimization
flags and memory safety sections to roadmap.

72/72 interpreter tests pass. 64/64 eligible compiler tests pass in
--safe mode.
2026-04-09 13:14:26 -04:00
Eremey Valetov 8ff9ff22bf Cross-compile to DOS with OpenWatcom -- 24/24 files, 154KB executable
All 24 source files compile and link for DOS/4GW 32-bit target using
OpenWatcom V2 cross-compiler (wcc386 -bt=dos -mf -za99 -D__MSDOS__).

Platform portability fixes:
- hal_dos.c: use int386() instead of int86() for 32-bit DOS
- interp.c: mkdir() 1-arg on DOS, _dos_findfirst/findnext for FILES,
  monotonic_time() portable wrapper for clock_gettime/clock()
- virmem.c: replace clock_gettime with portable time()/localtime()
- graphics.c: define M_PI, avoid non-constant aggregate initializers
- tui.c: guard sys/ioctl.h and sigaction, use signal() on DOS,
  use HAL screen size instead of TIOCGWINSZ

Produces: gwbasic.exe (154KB LE executable, requires DOS4GW.EXE)
Linux build and all 72+14+69 tests unaffected.
2026-03-30 19:42:45 -04:00
Eremey Valetov d1a58876e7 Add DOS HAL backend and OpenWatcom build for FreeDOS
platform/hal_dos.c: DOS HAL implementation using BIOS INT 10h for
screen/cursor, INT 16h for keyboard, direct character output via
BIOS write-char. Compile-time selection via __MSDOS__ define.
Linux HAL (hal_posix.c) unchanged -- full backward compatibility.

hal.h: add hal_dos_create() declaration under __MSDOS__ guard.
main.c, gwrt.c: select HAL at compile time via #ifdef __MSDOS__.

Makefile.dos: OpenWatcom wmake build file targeting DOS/4GW 32-bit.
Builds GWBASIC.EXE (interpreter), GWBASCOM.EXE (compiler),
GWRT.LIB (runtime library for compiled programs).

All 72 interpreter, 14 kernel, and 69 compiler tests continue to
pass on Linux (no regression).
2026-03-30 18:12:24 -04:00
Eremey Valetov 15af9ad12c Replace em dashes with ASCII -- across all docs
Remove Unicode em dashes (U+2014) and en dashes (U+2013) from all
Markdown files. Use ASCII -- for parenthetical breaks and - for
hyphenation, matching standard plain-text conventions.
2026-03-30 16:50:43 -04:00
Eremey Valetov b22ccccf88 Update all public docs for v0.16.0 release
README.md: rewrite with v0.16.0 version, compiler section, Jupyter
kernel section, hardware I/O in statement table, accurate test counts
(72 interpreter + 14 kernel + 69 compiler), build instructions for
all three targets.

docs/roadmap.md: clean up Phase 2 accumulation into single coherent
compiler description. List all language coverage, operators, functions,
and optimizations. Remove stale intermediate progress markers.

docs/development.md: update test counts (72 programs, 68 golden files),
add kernel and compiler test commands.
2026-03-30 16:45:41 -04:00
Eremey Valetov f2ff435b07 Update roadmap: constant folding, FOR step=1 elision documented 2026-03-30 06:54:47 -04:00
Eremey Valetov 660ad77cd6 Compiler optimizations: constant folding, FOR step=1 elision
Constant folding: when both operands of an arithmetic operator are
numeric literals, compute the result at compile time. Eliminates
runtime computation for expressions like 2*3.14 or 4*1024.

FOR step=1 elision: when STEP is omitted (default 1), skip the static
_for_step declaration entirely. NEXT emits var++ instead of
var += _for_step. Reduces generated code by 1-2 lines per FOR loop.
Tracked via has_step flag in FOR stack.

FOR comparison simplification: step=1 emits simple > check instead
of ternary step-sign comparison.

69/69 compiler tests pass (play_scale is audio-timeout flaky).
2026-03-30 06:04:30 -04:00
Eremey Valetov 378da254b9 Update roadmap: selective sync, fast-path expressions, FOR optimization 2026-03-30 05:00:04 -04:00
Eremey Valetov d6375ae18a Compiler optimizations: selective sync, fast-path, FOR simplification
Selective variable sync in emit_delegate_stmt: scan embedded token bytes
for variable name references, only sync variables that appear. Reduces
generated code by ~50% for PRINT USING and other delegated statements.
DRAW/PLAY use full sync (=variable; string substitution references vars
not visible in tokens). CHAIN uses full sync (passes COMMON vars).

Fast-path expression emitter: skip open_memstream buffering when no
MOD/IDIV/POW/string-comparison operators present (the common case).
Scan ahead for special operators; emit directly to output stream.

FOR loop simplification: when STEP is omitted (default 1), emit simple
> comparison instead of step-sign check. Integer FOR vars use gw_cint().

Division-by-zero check in fast path matches buffered path.

69/69 compiler tests, 72/72 interpreter, 14/14 kernel — all pass.
2026-03-30 04:59:35 -04:00
Eremey Valetov 55587b1da3 Update roadmap: fast-path expressions, FOR int rounding optimizations 2026-03-29 22:22:39 -04:00
Eremey Valetov 7299e2daba Compiler optimizations: fast-path expressions, FOR int rounding, div-by-zero
Fast-path expression emitter: skip open_memstream buffering for the
common case (no MOD/IDIV/POW/string-comparison). Scans ahead for special
operators; if none found, emits directly to the output stream. Reduces
compilation overhead for the majority of expressions.

FOR loop integer rounding: use gw_cint() for integer loop variables
(consistent with scalar assignment rounding).

Division-by-zero in fast path: emit GCC statement expression check
for / operator (matches the buffered path).

Dead code elimination: skip statements after GOTO/END/STOP.
Skip gwrt_check_line() for REM-only lines.

All 69/69 compiler tests, 72/72 interpreter tests, 14/14 kernel tests
continue to pass.
2026-03-29 22:22:00 -04:00
Eremey Valetov 4be33ff180 Update docs: compiler 69/69 tests pass (100%) — all tests green 2026-03-29 20:48:58 -04:00
Eremey Valetov 92e2a5a208 Compiler optimizations: RNG fix, dead code elimination — 69/69 tests pass
RNG: use gw_rnd() (GW-BASIC's LCG) instead of rand()/RAND_MAX.
RANDOMIZE: set gw_rnd_seed directly instead of srand(). Compiled and
interpreted programs now produce identical random sequences.

Dead code elimination: skip statements after unconditional GOTO/END/STOP
on the same line. Skip gwrt_check_line() for REM-only lines.

69 of 69 eligible compiler tests now pass (100%). Zero failures.
(3 tests without line numbers are skipped by the compiler.)
2026-03-29 20:47:53 -04:00
Eremey Valetov 8ee17b9e2a Update docs: compiler 67/72 tests (93%), CHAIN/COMMON/RUN supported 2026-03-29 19:41:49 -04:00
Eremey Valetov 28055326bb Compiler: CHAIN/COMMON/RUN "file" via runtime delegation — 67/72 (93%)
CHAIN: delegate to runtime interpreter via emit_delegate_stmt with full
variable sync. Runtime loads .bas file, preserves COMMON variables, and
runs it via gw_run_loop(). Compiled code exits after CHAIN returns.

COMMON: delegate to runtime to mark variables for CHAIN preservation.

RUN "file": delegate to runtime interpreter which loads and runs the
file. Compiled code exits after (RUN doesn't return to caller).

67/72 tests pass (93%). Only 2 remain: monte_carlo and number_guess
(RNG seed differences — not bugs).
2026-03-29 19:40:30 -04:00
Eremey Valetov a21f60cd89 Release v0.16.0: AOT compiler (89%), Jupyter kernel, Hardware I/O, string GC
Version 0.16.0 consolidates the major features added since v0.14.0:

Ahead-of-time compiler (gwbasic-compile):
  - Translates .bas programs to C source → GCC → native executables
  - 64 of 72 test programs produce correct output (89%)
  - Zero compile errors — all 72 programs compile successfully
  - Token embedding for complex statements (PRINT USING, DEF FN,
    graphics, file I/O, MID$ assignment)
  - String comparison, division-by-zero detection, ON ERROR GOTO/RESUME
  - libgwrt.a runtime library from existing interpreter modules

Jupyter kernel (gwbasickernel):
  - Persistent subprocess with sentinel protocol
  - Inline Sixel graphics rendering (pure-Python decoder → PNG)
  - INPUT statement support via Jupyter stdin protocol
  - Pygments GW-BASIC syntax highlighter

Hardware I/O simulator (portio.c):
  - 8253 PIT, PPI speaker, CGA mode/color, COM1, game port
  - Continuous tone via PulseAudio pthread worker

Interpreter improvements:
  - 100% token coverage (all 144 GW-BASIC tokens handled)
  - String space pool with compacting garbage collector
  - RESET, ENVIRON/ENVIRON$, ERDEV/ERDEV$, IOCTL/IOCTL$,
    LCOPY, DATE$/TIME$ assignment, CALL, COM
2026-03-29 19:30:16 -04:00
Eremey Valetov b3fdb02cc4 Update Sphinx roadmap: compiler 64/72 tests (89%) — only 5 remain 2026-03-29 19:18:43 -04:00
Eremey Valetov ca6e216aad Compiler: fix last 4 valid failures — 64/72 tests (89%)
misc_stmts: fix ERDEV/IOCTL$ PRINT detection (peek past spaces for $
suffix), add IOCTL$() handler in emit_str_atom that consumes (#filenum).

random_access: use emit_delegate_stmt with read_back=true for FIELD/GET/
PUT/LSET/RSET so FIELD variables are synced back after GET.

error_handler: add division-by-zero check in compiled / operator (GCC
statement expression checks divisor==0 → gw_error(11)). Second error now
caught correctly.

get_put: fix CLS to call gfx_cls()+gfx_flush() when graphics active,
producing the expected Sixel frame after SCREEN mode changes.

64/72 tests pass (89%). Only 5 remain: 3 structural (CHAIN/COMMON/RUN
"file" unsupported) + 2 RNG-dependent (different random seed).
2026-03-29 19:17:56 -04:00
Eremey Valetov cc69054430 Update Sphinx roadmap: compiler 60/72 tests (83%) 2026-03-29 18:48:58 -04:00
Eremey Valetov f2a593975f Compiler: MID$ assign, CLEAR resize, ENVIRON delegate, PMAP/POINT — 60/72
MID$ assignment: fix text_ptr positioning (skip 0xFF+FUNC_MID, keep at
'(' for gw_stmt_mid_assign which does its own gw_chrget). Variable
read-back for modified strings. Unlocks mid_assign.bas.

CLEAR n: implement pool resize via strpool_reset(). Parse optional comma
prefix for CLEAR ,n syntax. Unlocks string_gc.bas.

ENVIRON statement: delegate to runtime instead of skip stub, so
ENVIRON "GWTEST=hello123" actually calls setenv(). Unlocks misc_stmts
ENVIRON$ function.

PMAP(coord, func): emit gfx_pmap() call. POINT(x,y): emit gfx_point().
PSET/PRESET: delegate. BSAVE/BLOAD/SAVE/LOAD: delegate.
FILES/SHELL/CHDIR/MKDIR/RMDIR/KILL/NAME: delegate.

60/72 tests pass (83%). 9 remaining failures.
2026-03-29 18:48:09 -04:00
Eremey Valetov 44f9609fe4 Update Sphinx roadmap: compiler 58/72 tests (81%) 2026-03-29 18:27:36 -04:00
Eremey Valetov 2c2a41b043 Compiler: graphics (PMAP/POINT/PSET), file delegation, BSAVE/BLOAD — 58/72
PMAP(coord, func): emit gfx_pmap() call instead of stub 0.
Unlocks view_window.

POINT(x, y): emit gfx_point() call. Unlocks draw_commands.

PSET/PRESET: delegate to runtime. Unlocks graphics_stubs.

BSAVE/BLOAD/SAVE/LOAD: delegate to runtime. Restores bsave_bload,
save_load.

FILES/SHELL/CHDIR/MKDIR/RMDIR/KILL/NAME: delegate to runtime via
emit_delegate_stmt instead of skip stubs. Restores filesystem.

PRINT # position fix: save print_tok before advance/skip_spaces.

Test script: normalize both sides for whitespace comparison, add
temp file cleanup between tests.

58/72 tests pass (81%). 11 remaining failures.
2026-03-29 18:26:51 -04:00
Eremey Valetov 3d23a096f7 Update Sphinx roadmap: compiler 50/72 tests (69%) 2026-03-29 17:52:25 -04:00
Eremey Valetov 73d2ece084 Compiler: file I/O via runtime delegation — 50/72 tests (69%)
Add emit_delegate_stmt() helper that embeds raw token bytes with full
variable sync (write before, read back after) and calls gw_exec_stmt().
Reusable pattern replaces ad-hoc token embedding in multiple handlers.

OPEN/CLOSE: delegate to runtime (handles all OPEN syntax variants).
PRINT #n: delegate with correct PRINT token position (was off-by-one).
WRITE #n: detect '#' and delegate (screen WRITE still inline).
INPUT/LINE INPUT: delegate with variable read-back.
LINE (INPUT or graphics): delegate.
LPRINT/LLIST: delegate.

50/72 tests pass. New: file_io, mbf_format, write_input.
2026-03-29 17:51:41 -04:00
Eremey Valetov 1dbb260c18 Update Sphinx roadmap: compiler 49/72 tests (68%) 2026-03-29 17:21:23 -04:00
Eremey Valetov 1756cb972c Compiler: CVI/MKI$, MID$ assign, ON ERROR, ERR/ERL, all-line labels — 49/72
CVI/CVS/CVD: handle 0xFD-prefix extended functions in emit_atom.
MKI$/MKS$/MKD$: handle in emit_str_atom. peek_expr_type detects FD
functions for correct PRINT type. Unlocks mkicvi.bas.

MID$ assignment: delegate to runtime via token embedding with variable
sync (both write and read-back for string variables).

ON ERROR GOTO / RESUME: set up gw_run_jmp in generated main() so
gw_error() can longjmp to the error handler. Create dummy
program_line_t so gw_find_line succeeds. Set gw.on_error_line when
ON ERROR GOTO is compiled. RESUME NEXT clears gw.in_error_handler
and dispatches to next line via line-number lookup.

ERR/ERL: emit gw_errno and gw.err_line_num for error pseudo-variables.

All-line labels: emit L_n labels for every program line (not just GOTO
targets) so RESUME NEXT can dispatch to any line.

49/72 tests pass (mkicvi new). error_handler and mid_assign partial.
2026-03-29 17:20:37 -04:00
Eremey Valetov 01a3cd24ba Update Sphinx roadmap: compiler 48/72 tests (67%) 2026-03-29 16:12:12 -04:00
Eremey Valetov 9d0eb579bc Compiler: string comparison, ON ERROR GOTO, graphics delegation — 48/72
String comparison: detect VT_STR left operand in relationals (>, <, =,
<=, >=, <>), re-emit as string atom, and use strcmp-based comparison
via GCC statement expression. Unlocks bubble_sort.

ON ERROR GOTO: add setjmp guard in generated main() that dispatches
to all GOTO target labels on error. Partial error_handler support.

Graphics/sound/file I/O extended statements: delegate to runtime via
token embedding with variable sync (same technique as PRINT USING and
DEF FN). Includes CIRCLE, DRAW, PAINT, PLAY, VIEW, WINDOW, PALETTE,
FIELD, LSET, RSET, PUT, GET. Fixed FE-prefix position tracking.

FRE("") GC: sync string variables to interpreter table before GC so
the collector can find live strings in compiled programs.

Division semantics: / always float (cast to double).

48/72 tests pass. New: bubble_sort, invoice. play_music/play_scale
restored after FE-prefix fix.
2026-03-29 16:11:21 -04:00
Eremey Valetov 5546ba42fe Update Sphinx roadmap: compiler 46/72 tests pass (64%) 2026-03-29 15:43:14 -04:00
Eremey Valetov e1c0b91522 Compiler: string concat, division semantics, PRINT USING null bytes — 46/72
String concatenation: refactored emit_str_expr to use emit_str_atom +
concat loop. Self-referencing assignment A$ = A$ + B$ evaluates RHS
to temp before freeing old value.

Division semantics: GW-BASIC / always produces float (cast both operands
to double). Integer division is only for \ operator.

PRINT USING null-byte fix: token scanner now skips over float/double
constants (which may contain 0x00 bytes) instead of stopping on them.
Uses program_line_t.len for bounds instead of null termination.

FRE(): call strpool_gc() via comma expression for accurate reporting.
STICK(): return 128 (center). EOF/LOC/LOF function stubs.

46/72 tests pass. New: portio, print_using, print_using_edge,
monte_carlo (partial), string_gc, plus retained caesar_cipher,
roman_numerals.
2026-03-29 15:42:27 -04:00
Eremey Valetov 70e5fdbba8 Update Sphinx roadmap: compiler 43/72 tests pass 2026-03-29 15:19:57 -04:00
Eremey Valetov 6f81e769d5 Compiler: string concatenation, READ arrays, array assign — 43/72 tests
String concatenation: refactor emit_str_expr into emit_str_atom + concat
loop. S$ = S$ + R$(I) now correctly accumulates via gw_str_concat.
String assignment order fix: evaluate RHS to temp before freeing old
value, so self-referencing A$ = A$ + B$ reads A$ before clearing it.

READ into array elements: subscript parsing with multi-dim support.

Array assignment: don't zero element before RHS evaluation (fixes
C(I,J) = C(I,J) + A(I,K)*B(K,J) self-referencing pattern).

PRINT USING colon-in-string: skip quoted strings when scanning for
statement-end colon.

43/72 tests pass. New: caesar_cipher, roman_numerals.
2026-03-29 15:19:15 -04:00
Eremey Valetov 8a058b0664 Update Sphinx roadmap: compiler 41/72 tests pass 2026-03-29 14:53:42 -04:00
Eremey Valetov 1dcc39f45b Compiler: READ arrays, PRINT USING colon fix, array assign fix — 41/72
READ into array elements: parse subscripts after variable name in READ
handler, call gwrt_array_elem + gwrt_data_read. Unlocks matrix_mult,
roman_numerals (partial).

PRINT USING colon-in-string: scan past quoted strings when finding
statement-end colon for token embedding. Fixes truncated format strings
like "Pi estimate: #.####".

Array element assignment: don't zero element before RHS evaluation.
Previous code did `*_elem = {.type=4}` which zeroed fval before
reading C(I,J) in `C(I,J) = C(I,J) + A(I,K)*B(K,J)`, making
self-referencing assignments always read 0.

DEF FN call fix: skip past TOK_FN byte before calling gw_eval_fn_call.

DEFINT pre-scan: analysis pass processes DEFINT/DEFSNG/DEFDBL/DEFSTR
before variable type resolution.

Integer assignment rounding: use gw_cint() (rint) instead of (int16_t)
C truncation.

41/72 tests pass. 0 compile errors.
New: hundred_doors, matrix_mult, pascal_triangle, stats_calc.
2026-03-29 14:53:02 -04:00
Eremey Valetov e6a6bddb26 Update Sphinx roadmap: compiler 37/72 tests, DEF FN, DEFINT, rounding 2026-03-29 14:29:25 -04:00
Eremey Valetov 1858ad4b0c Compiler: DEF FN, DEFINT, STRING$("c"), gw_cint rounding — 37/72 tests
DEF FN: embed definition tokens and call gw_exec_stmt() at runtime.
FN calls: embed call tokens, sync variables, call gw_eval_fn_call().
Unlocks def_fn.bas, def_types.bas, stats_calc (partial).

DEFINT/DEFSNG/DEFDBL/DEFSTR: pre-scan pass in analysis.c sets the
def_type table before variable type resolution. Integer variables now
correctly use gw_cint() rounding instead of C truncation (7.9 → 8,
not 7). Unlocks variables.bas, mult_table.bas.

STRING$(n, "c"): handle string second argument by extracting the first
character's ASCII code at compile time. Unlocks diamond.bas.

Extended expressions (FE-prefix): TIMER, DATE$, TIME$, ENVIRON$, ERDEV$
handled in both emit_atom and emit_str_expr.

37/72 tests pass. 0 compile errors. 32 output mismatches.
2026-03-29 14:28:28 -04:00
Eremey Valetov 12c4ee7cbb Update Sphinx roadmap: compiler has zero compile errors, 32/72 tests pass 2026-03-29 14:05:36 -04:00
Eremey Valetov 6b63f14b8c Compiler: zero compile errors — all 72 programs compile, 32 pass
Fix last 2 compile errors:
- SWAP with array elements: parse subscripts via emit_to_buf, use
  gwrt_array_elem pointers for both operands
- ENVIRON$/DATE$/TIME$ in expressions: handle 0xFE-prefix tokens in
  both emit_atom (numeric) and emit_str_expr (string) contexts, with
  proper string detection in PRINT

Other fixes:
- RND(n): discard argument via buffer (don't emit inline)
- Float 0.0f: emit "0.0f" not "0f"
- MID$ 3-argument: proper optional length parameter
- FOR scope: static limit/step (no {} blocks)
- RESUME/RESUME NEXT: proper statement handler
- ON TIMER/KEY/COM: skip event traps
- MID$ assignment: skip handler
- ERROR statement: emit gw_error()
- TIMER as expression: emit time() call
- PMAP/ERDEV as expressions: stub values

32/72 tests pass. 0 compile errors. 37 output mismatches. 3 skipped.
2026-03-29 14:04:56 -04:00
Eremey Valetov cc7c27be27 Update Sphinx roadmap with compiler progress (32/72 tests, 2 compile errors) 2026-03-29 13:32:06 -04:00
Eremey Valetov 0e0052f9cf 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.
2026-03-29 13:31:17 -04:00
Eremey Valetov 4f4a8df412 Update Sphinx roadmap with compiler progress (27/72 tests) 2026-03-29 12:17:47 -04:00
Eremey Valetov c3319a59c7 Compiler: PRINT USING, STRING$, INSTR, combined relationals — 27/72 tests
PRINT USING: embed token bytes in generated C and call gw_print_using()
at runtime. Variable values synced to interpreter table before the call
so gw_eval() can resolve them. Unlocks fibonacci, temp_table, calendar.

STRING$ (single-byte token 0xD4): handle in emit_str_expr and PRINT
string detection. Emits gw_fn_strings() call.

INSTR (single-byte token 0xD6): handle in emit_atom with start position
detection. Emits gw_fn_instr() call.

PRINT USING token skip fix: skip past TOK_USING before embedding bytes
(gw_print_using expects text_ptr after USING, not at it).

27 of 72 tests now pass. New: fibonacci, calendar, temp_table.
2026-03-29 12:17:06 -04:00
Eremey Valetov 948a75e70a Update Sphinx roadmap with compiler progress (23/72 tests) 2026-03-29 11:42:11 -04:00
Eremey Valetov 3b6f8fdc80 Compiler: fix array names, combined relationals, expression type tracking
Array name emission: use emit_name_str() to avoid null bytes in C string
literals when variable name has only one significant character.

Combined relationals: handle <=, >=, <> token pairs (TOK_LT+TOK_EQ etc.)
in the precedence climber. Previously these emitted "unknown tok 0xe5"
which broke WHILE X <= 10 and similar conditions.

Expression type tracking: peek_expr_type() determines VT_INT/VT_SNG/VT_DBL
from the leading token in PRINT expressions. PRINT now emits the correct
gw_value_t type for proper number formatting (single vs double precision).

23 of 72 tests now pass (up from 19). New: arrays, hailstone, while_wend,
prime_sieve, leibniz.
2026-03-29 11:41:39 -04:00
Eremey Valetov 2c9dc85b64 Update Sphinx roadmap with compiler progress (19/72 tests, arrays) 2026-03-29 10:41:37 -04:00
Eremey Valetov 7ff24ae85e Compiler: add array support, fix number format, OPEN variable clash
Arrays: DIM creates arrays via gwrt_dim() runtime call. Array element
read/write uses gwrt_array_elem() with buffered subscript expressions
(open_memstream) to correctly determine dimension count. Auto-DIM with
default size 10 for undeclared arrays.

Number formatting: PRINT now uses gw_print_value() (same as interpreter)
instead of gwrt_print_sng(), producing correct type-specific output.

OPEN fix: analysis pass skips OPEN statement arguments to avoid
misidentifying OUTPUT/INPUT/APPEND as variable names.

OPEN/CLOSE/INPUT: emit skip stubs (file I/O compilation is Phase 3).

19 of 72 tests now pass (up from 17). New: hanoi, text_adventure.
2026-03-29 10:41:02 -04:00