Skip to content

Commit 19ce720

Browse files
committed
Runtime error reporting Phase 2: file provenance, LASTERROR$, #OPTION DIAGNOSTICS
Proposal: docs/runtime-error-source-line-proposal.md (both phases now shipped). 2a — per-line source-file provenance: - struct line gains src_file (interned path; NULL = top-level program). - #INCLUDEd lines stamped with their origin during load via a g_load_src_file global set/restored around the recursive include call. - runtime_diagnostic builds an "at <file>:N" location for included lines, keeps "on line N" for top-level (no change for single-file programs). - Paths interned in a bounded table (MAX_SRC_FILES=128); overflow degrades to line-only. 2b — LASTERROR$() builtin + basic_get_lasterror() ccall export: - runtime_diagnostic records its formatted header line into g_last_error. - New FN_LASTERROR no-arg string builtin returns it ("" if none). - Export added to all four WASM EXPORTED_FUNCTIONS lists. 2c — #OPTION DIAGNOSTICS / -diagnostics flag (default off): - New diagnostics_mode global, directive + CLI flag in both arg parsers, reset in basic_apply_arg_string. - diag_http() helper emits a non-halting Warning (status 0 or >=400) at HTTP$ / HTTPFETCH / BUFFERFETCH return sites when the mode is on; the breadcrumb also populates LASTERROR$(). JSON parse-fail breadcrumbs left for a later follow-up under the same directive. Tests: include_error (at file:line), diagnostics_http (breadcrumb), and lasterror_capture (stdout) added to tests/runtime_errors/ + a stdout-substring check mode in the driver. Usage strings gain [-diagnostics]. Verified native + basic-wasm node harness; full `make check` green.
1 parent f1bde21 commit 19ce720

10 files changed

Lines changed: 211 additions & 20 deletions

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
## Changelog
22

3+
### Runtime error source-line reporting — Phase 2 (2026-05-23)
4+
5+
Wishlist §3d Phase 2 (proposal: `docs/runtime-error-source-line-proposal.md`).
6+
Builds on Phase 1's `runtime_diagnostic` infrastructure.
7+
8+
**2a — per-line source-file provenance.** `struct line` gains a `src_file`
9+
field (interned path, `NULL` = top-level program). `#INCLUDE`d lines are
10+
stamped with their origin file during load. Runtime diagnostics now report
11+
`Error at lib/helpers.bas:110` for included lines while top-level lines keep
12+
`Error on line 110` (no change for single-file programs). This is the literal
13+
"`DICTLOAD at script.bas:17`" form from the original wishlist ask. Paths are
14+
interned in a bounded table (`MAX_SRC_FILES = 128`); overflow degrades to the
15+
line-only form.
16+
17+
**2b — `LASTERROR$()` builtin + `basic_get_lasterror()` ccall export.** Returns
18+
the formatted text of the last runtime diagnostic (same as the printed header
19+
line), or `""` if none. Pull-mode companion to `JSONSTATUS()` / `HTTPSTATUS()`:
20+
tool scripts read it directly, JS hosts read it without modifying the script.
21+
Exposed from all four WASM targets.
22+
23+
**2c — `#OPTION DIAGNOSTICS` / `-diagnostics` flag.** Default off. When set,
24+
fail-soft HTTP sites (`HTTP$`, `HTTPFETCH`, `BUFFERFETCH`) that previously set
25+
a status code silently now emit a non-halting `Warning` breadcrumb with line
26+
context on transport failure (status 0) or HTTP error (status >= 400). The
27+
breadcrumb also populates `LASTERROR$()`. Treats `.invalid` / DNS failures and
28+
4xx/5xx as failures. (JSON parse-fail breadcrumbs can join the same umbrella
29+
later; HTTP was the highest-value silent-failure case for tool authors.)
30+
31+
New test cases in `tests/runtime_errors/` (`include_error`, `diagnostics_http`,
32+
`lasterror_capture`) + a stdout-substring check mode in the driver. Verified
33+
native + `basic-wasm` node harness.
34+
335
### Runtime error source-line reporting — Phase 1 (2026-05-23)
436

537
Wishlist §3d, Phase 1 (proposal: `docs/runtime-error-source-line-proposal.md`).

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ EMCC ?= emcc
119119
basic-wasm:
120120
@mkdir -p web
121121
$(EMCC) -w -O2 $(VERSION_DEFINES) -s WASM=1 \
122-
-s EXPORTED_FUNCTIONS='["_basic_load","_basic_run","_basic_halted","_basic_load_and_run","_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_wasm_push_key","_malloc","_free"]' \
122+
-s EXPORTED_FUNCTIONS='["_basic_load","_basic_run","_basic_halted","_basic_load_and_run","_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_get_lasterror","_wasm_push_key","_malloc","_free"]' \
123123
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap","FS","HEAPU8","HEAP16","wasmMemory","getValue"]' \
124124
-s FORCE_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 \
125125
-s INITIAL_MEMORY=33554432 \
@@ -133,7 +133,7 @@ basic-wasm:
133133
basic-wasm-modular:
134134
@mkdir -p web
135135
$(EMCC) -w -O2 $(VERSION_DEFINES) -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME=createBasicModular \
136-
-s EXPORTED_FUNCTIONS='["_basic_load","_basic_run","_basic_halted","_basic_load_and_run","_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_wasm_push_key","_malloc","_free"]' \
136+
-s EXPORTED_FUNCTIONS='["_basic_load","_basic_run","_basic_halted","_basic_load_and_run","_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_get_lasterror","_wasm_push_key","_malloc","_free"]' \
137137
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap","FS","HEAPU8","HEAP16","wasmMemory","getValue"]' \
138138
-s FORCE_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 \
139139
-s INITIAL_MEMORY=33554432 \
@@ -146,7 +146,7 @@ basic-wasm-modular:
146146
basic-wasm-canvas:
147147
@mkdir -p web
148148
$(EMCC) -w -O2 $(VERSION_DEFINES) -s WASM=1 -DGFX_VIDEO -Igfx \
149-
-s EXPORTED_FUNCTIONS='["_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_load_and_run_gfx","_basic_load_and_run_gfx_argline","_wasm_push_key","_wasm_gfx_rgba_ptr","_wasm_gfx_rgba_version_read","_wasm_gfx_bitmap_pixel_at","_wasm_gfx_screen_screencode_at","_wasm_gfx_key_state_set","_wasm_gfx_key_state_clear","_wasm_gfx_key_state_ptr","_wasm_gamepad_buttons_ptr","_wasm_gamepad_axes_ptr","_wasm_mouse_js_frame","_wasm_canvas_build_stamp","_wasm_canvas_set_debug","_wasm_canvas_set_debug_trace_for","_wasm_debug_log_stacks","_wasm_gfx_set_js_sprite_backend","_wasm_gfx_get_js_sprite_backend","_wasm_gfx_sprite_rgba_ptr","_wasm_gfx_sprite_w","_wasm_gfx_sprite_h","_wasm_gfx_sprite_version","_wasm_gfx_sprite_draw_params","_malloc","_free"]' \
149+
-s EXPORTED_FUNCTIONS='["_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_get_lasterror","_basic_load_and_run_gfx","_basic_load_and_run_gfx_argline","_wasm_push_key","_wasm_gfx_rgba_ptr","_wasm_gfx_rgba_version_read","_wasm_gfx_bitmap_pixel_at","_wasm_gfx_screen_screencode_at","_wasm_gfx_key_state_set","_wasm_gfx_key_state_clear","_wasm_gfx_key_state_ptr","_wasm_gamepad_buttons_ptr","_wasm_gamepad_axes_ptr","_wasm_mouse_js_frame","_wasm_canvas_build_stamp","_wasm_canvas_set_debug","_wasm_canvas_set_debug_trace_for","_wasm_debug_log_stacks","_wasm_gfx_set_js_sprite_backend","_wasm_gfx_get_js_sprite_backend","_wasm_gfx_sprite_rgba_ptr","_wasm_gfx_sprite_w","_wasm_gfx_sprite_h","_wasm_gfx_sprite_version","_wasm_gfx_sprite_draw_params","_malloc","_free"]' \
150150
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap","FS","HEAPU8","HEAP16","wasmMemory","getValue"]' \
151151
-s FORCE_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 \
152152
-s INITIAL_MEMORY=67108864 \
@@ -171,7 +171,7 @@ basic-wasm-raylib: $(RAYLIB_WEB_LIB)
171171
@mkdir -p web
172172
$(EMCC) -w -O2 $(VERSION_DEFINES) -s WASM=1 -DGFX_VIDEO -DGFX_USE_RAYLIB -Igfx -I$(RAYLIB_WEB_SRC) \
173173
-s USE_GLFW=3 -s FULL_ES2=1 -s ALLOW_MEMORY_GROWTH=1 \
174-
-s EXPORTED_FUNCTIONS='["_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_load_and_run_gfx","_basic_load_and_run_gfx_argline","_wasm_push_key","_wasm_gfx_key_state_set","_wasm_gfx_key_state_clear","_wasm_gfx_key_state_ptr","_wasm_gamepad_buttons_ptr","_wasm_gamepad_axes_ptr","_malloc"]' \
174+
-s EXPORTED_FUNCTIONS='["_basic_apply_arg_string","_basic_get_jsonstatus","_basic_get_httpstatus","_basic_get_version","_basic_get_lasterror","_basic_load_and_run_gfx","_basic_load_and_run_gfx_argline","_wasm_push_key","_wasm_gfx_key_state_set","_wasm_gfx_key_state_clear","_wasm_gfx_key_state_ptr","_wasm_gamepad_buttons_ptr","_wasm_gamepad_axes_ptr","_malloc"]' \
175175
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap","FS","HEAPU8","HEAP16","HEAPF32","wasmMemory","getValue"]' \
176176
-s FORCE_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 \
177177
-s INITIAL_MEMORY=67108864 \

0 commit comments

Comments
 (0)