Four roadmap items:
- codegen: fix parenthesized string comparison. emit_atom didn't
consume the body of a string-literal token (`"`), so for
PRINT (A$+B$ < "ZZZ") it emitted a 0 placeholder, advanced one byte,
and left "ZZZ" to be reparsed as a variable + extra trailing tokens
-- the binary then failed to link with `var_ZZ_sng` undeclared.
emit_atom now skips to the closing quote. Separately, the
left_type tracking in emit_num_prec dropped VT_STR after a string +
string concat (becoming VT_SNG), so the string-comparison codepath
skipped when the relational operator arrived. Preserve VT_STR
through TOK_PLUS when both operands are strings. Verified: paren
string-cmp now compiles and produces the same -1 / 0 result as the
interpreter.
- compiler: --no-gc-check and --fast-math optimization flags.
--no-gc-check skips the per-line gwrt_check_line() (no string-pool
GC, no Ctrl+Break trap). --fast-math drops the divide-by-zero
guard on `/`; the divisor still goes through (double) so 10/0
produces inf rather than SIGFPE. Both threaded through
codegen_opts_t and exposed in --help. --inline-arrays from the
roadmap deferred -- larger refactor.
- interp: raise static caps on 32-bit / Linux builds. vars 256
-> 1024, arrays 64 -> 256, MAX_FOR_DEPTH 16 -> 64, MAX_GOSUB_DEPTH
24 -> 128, MAX_WHILE_DEPTH 16 -> 64. Codegen FOR_STACK_MAX 16
-> 64. Analysis-pass caps: MAX_LINES 4096 -> 8192, MAX_VARS 256
-> 1024, MAX_GOTOS 256 -> 1024, MAX_DATA 1024 -> 4096,
MAX_GOSUB_RET 256 -> 1024. 16-bit DOS keeps the original modest
caps via #ifdef _M_I86 -- the MEDIUM model has a single 64KB
DGROUP for all static data and the bumped sizes broke runtime
startup under DOSBox-X. 16-bit binary grew from 128KB to 132KB
from the offset_secs field plus DATE$/TIME$ shift code, well
within the FreeDOS budget.
- interp + codegen: DATE$ / TIME$ assignment via process-local
clock offset. Was a no-op accept-and-ignore. Now sets
gw.time_offset_secs (long), and DATE$ / TIME$ / TIMER readers
apply it to time(NULL) before formatting. The OS clock is
unaffected (would need root). Compiled-binary readers also
reference gw.time_offset_secs since libgwrt shares the gw
struct. Verified: PRINT DATE$; DATE$="12-31-1999"; PRINT DATE$
shows the expected before/after in both interpreter and AOT
paths.
After these changes: 72/72 interpreter tests, 68/68 compat, 63/63
compiler tests, DOS smoke under DOSBox-X all pass. Build clean on
both Linux (cmake) and 16-bit DOS (build_dos.sh 16).
Add event-driven programming: ON TIMER(n) GOSUB with TIMER ON/OFF/STOP,
ON KEY(n) GOSUB with KEY(n) ON/OFF/STOP for F1-F10. Fix F-key escape
sequence parser (F9/F10 detection, push back consumed bytes on unmatched
sequences). Add EDIT statement for TUI line editing. Guard key trap
polling so keystrokes aren't consumed when no traps are configured.
AUTO generates line numbers during interactive editing, RENUM
renumbers program lines and patches all GOTO/GOSUB/ON references,
DELETE removes line ranges. COMMON declares variables preserved
across CHAIN. Also fixed LIST/DELETE range parsing (was broken by
expression evaluator consuming the dash as subtraction).
Bump to v0.7.0, 53 tests.
Add OPEN/CLOSE with both modern (OPEN "f" FOR OUTPUT AS #n) and compact
(OPEN "O",#n,"f") syntaxes. PRINT#, WRITE#, INPUT#, LINE INPUT# for
sequential file access. EOF() now returns real file status with peek-ahead.
LOC/LOF return approximate values.
PRINT USING with numeric (#, ., +, -, $$, **, ^^^^, comma grouping) and
string (!, &, \ \) format specifiers. Shared by PRINT USING and PRINT# USING.
SAVE (ASCII), LOAD (with ,R auto-run), and MERGE for program persistence.
MID$ assignment (MID$(var$, start [,len]) = expr) for in-place string
modification. Works with both scalar variables and array elements.
Graphics stubs for SCREEN, PSET, PRESET, LINE, CIRCLE, DRAW, PAINT,
VIEW, WINDOW, PALETTE - parse and discard arguments so graphics-heavy
programs don't crash.
SYSTEM and NEW/CLEAR now close all open files. Version bumped to 0.3.0.
22 tests pass (16 existing + 6 new).
Add variable storage (scalar and array), program line storage with
RUN/LIST/NEW, and full control flow: FOR/NEXT, GOTO, GOSUB/RETURN,
IF/THEN/ELSE, WHILE/WEND, ON GOTO/GOSUB, DATA/READ/RESTORE.
New modules: interp.c (1445 lines - execution loop and statement
dispatcher), vars.c, arrays.c, input.c. Version bumped to 0.2.0.
16 test programs pass including Leibniz pi and prime sieve.
GW-BASIC reimplementation in C11, using Microsoft's open-sourced 8088
assembly as the authoritative reference.
Tokenizer (CRUNCH/LIST), expression evaluator with operator precedence,
all math functions (SIN, COS, TAN, ATN, SQR, LOG, EXP, RND, etc.),
string functions (LEFT$, RIGHT$, MID$, CHR$, ASC, VAL, STR$, etc.),
PRINT statement with comma/semicolon zones, TAB(), SPC().
Handles integer/single/double types with correct promotion, D exponent
for double-precision literals, type suffixes (%, !, #), &H hex/&O octal
literals, MBF conversion routines, and GW-BASIC-compatible number
formatting.
Platform-independent via HAL vtable; POSIX backend included.