codegen fixes, --no-gc-check / --fast-math, raise caps, DATE$/TIME$ shift
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).
This commit is contained in:
+23
-7
@@ -113,16 +113,32 @@ line numbers are preserved. Direct-mode scratchpad scripts and classic
|
||||
```
|
||||
Usage: gwbasic-compile [options] input.bas
|
||||
Options:
|
||||
-o FILE Output C source file (default: stdout)
|
||||
-c Compile to executable (invoke gcc)
|
||||
-O LEVEL GCC optimization level (default: 2)
|
||||
--keep-c Keep generated C file (with -c)
|
||||
--runtime DIR Path to runtime headers/library
|
||||
--warn Static analysis warnings
|
||||
--safe Runtime safety checks (implies --warn)
|
||||
-o FILE Output C source file (default: stdout)
|
||||
-c Compile to executable (invoke gcc)
|
||||
-O LEVEL GCC optimization level (default: 2)
|
||||
--keep-c Keep generated C file (with -c)
|
||||
--runtime DIR Path to runtime headers/library
|
||||
--warn Static analysis warnings
|
||||
--safe Runtime safety checks (implies --warn)
|
||||
--safe=sanitize Above + address/UB sanitizers (with -c)
|
||||
--no-gc-check Skip per-line gwrt_check_line() (no GC, no Break)
|
||||
--fast-math Skip division-by-zero checks
|
||||
```
|
||||
|
||||
### Performance Flags (`--no-gc-check` / `--fast-math`)
|
||||
|
||||
`--no-gc-check` skips the `gwrt_check_line()` call emitted at the start of
|
||||
every non-REM line. That call drives the string-pool compacting GC and
|
||||
the Ctrl+Break trap. Removing it gives a small per-line speedup for
|
||||
programs that don't allocate strings or need responsive interruption.
|
||||
String reassignment can still trigger compaction lazily, but the
|
||||
guaranteed periodic check is gone.
|
||||
|
||||
`--fast-math` removes the explicit divide-by-zero check around the `/`
|
||||
operator. The result of `X = 10 / 0` becomes `inf` rather than raising
|
||||
"Division by zero". Useful for compute-bound code that already validates
|
||||
inputs.
|
||||
|
||||
### Memory Safety (`--warn` / `--safe`)
|
||||
|
||||
The `--warn` flag enables compile-time static analysis warnings:
|
||||
|
||||
+7
-3
@@ -112,8 +112,12 @@ Tested on FreeDOS 1.4 via QEMU.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- Maximum 256 variables, 64 arrays, 16 FOR nesting, 24 GOSUB nesting,
|
||||
16 WHILE nesting
|
||||
- Static caps -- 32-bit / Linux builds: 1024 variables, 256 arrays,
|
||||
64 FOR nesting, 128 GOSUB nesting, 64 WHILE nesting. 16-bit real-mode
|
||||
DOS keeps the original modest caps (256 / 64 / 16 / 24 / 16) because
|
||||
the MEDIUM model has a single 64KB DGROUP for all static data.
|
||||
- `CALL`/`CALLS` (machine code execution) raises Illegal function call
|
||||
- `DATE$`/`TIME$` assignment accepted but does not modify the system clock
|
||||
- `DATE$`/`TIME$` assignment shifts the program's view of the clock via
|
||||
a process-local offset; the OS time is unaffected (setting the OS
|
||||
clock would require root)
|
||||
- Device stubs (`ERDEV`, `IOCTL`, `COM`, `LCOPY`) return defaults
|
||||
|
||||
Reference in New Issue
Block a user