Files
gw-basic-2026/include/analysis.h
Eremey Valetov f207d74aec 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).
2026-05-04 18:56:58 -04:00

63 lines
1.6 KiB
C

#ifndef ANALYSIS_H
#define ANALYSIS_H
#include "types.h"
#include <stdbool.h>
#include <stdint.h>
#define MAX_LINES 8192
#define MAX_VARS 1024
#define MAX_GOTOS 1024
#define MAX_DATA 4096
#define MAX_GOSUB_RET 1024
typedef struct {
uint16_t line_num;
bool is_target; /* referenced by GOTO/GOSUB/etc. */
bool has_data; /* contains DATA statement */
int data_start; /* index into data pool */
} line_info_t;
typedef struct {
char name[2];
gw_valtype_t type;
uint16_t first_assign_line; /* 0 = never assigned */
uint16_t first_use_line; /* 0 = never used */
} var_info_t;
typedef struct {
line_info_t lines[MAX_LINES];
int line_count;
var_info_t vars[MAX_VARS];
int var_count;
uint16_t goto_targets[MAX_GOTOS];
int goto_count;
char *data_pool[MAX_DATA]; /* collected DATA literals */
int data_count;
int data_line_map[MAX_LINES][2]; /* [line_num, data_start_index] */
int data_line_count;
gw_valtype_t def_type[26]; /* from DEFINT/DEFSNG/DEFDBL/DEFSTR */
} analysis_t;
/* Run analysis pass over the loaded program */
void analysis_run(analysis_t *a);
/* Find a variable in the census, return index or -1 */
int analysis_find_var(analysis_t *a, const char name[2], gw_valtype_t type);
/* Add a variable to the census if not already present */
int analysis_add_var(analysis_t *a, const char name[2], gw_valtype_t type);
/* Check if a line number is a jump target */
bool analysis_is_target(analysis_t *a, uint16_t line_num);
/* Emit static analysis warnings to stderr */
void analysis_warnings(analysis_t *a);
#endif