File the scanned line in RUNSTREAM, not the raw one
process_line_runstream() chose between the stripped line and the raw buffer on obj->mode == AKBASIC_MODE_REPL, but nothing reaches that function except the RUNSTREAM arm of step(). The stripped branch was dead, so every program the driver ran from a file was stored with its own line number inside source[]: LIST printed "10 10 PRINT", and DSAVE and HELP would have echoed it the same way. No .bas in either corpus calls LIST, and runtime_verbs.c's load() helper -- which claims to load "the way RUNSTREAM would" -- already stored the scanned line, so it encoded the correct contract and could not catch the wrong one. The new test drives the real sink path instead. Keep the step-over-a-leading-number allowance in scan_line_labels() and skip_lineno(): no path inside the library stores a raw line now, but akbasic_runtime_store_line() is public and a host may hand it one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,32 @@ static void clear_output(void)
|
||||
rewind(HARNESS_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A program read through RUNSTREAM is stored without its line numbers.
|
||||
*
|
||||
* The load() helper above files what the scanner stripped, which is what every
|
||||
* caller inside the library does -- but RUNSTREAM used to file the raw buffer,
|
||||
* so a program run from a file held "10 PRINT" under slot 10 and LIST, DSAVE
|
||||
* and HELP would each have printed the number twice. This drives the real sink
|
||||
* path rather than the helper, because the helper is exactly what was not
|
||||
* happening.
|
||||
*/
|
||||
static void test_runstream_strips_line_numbers(void)
|
||||
{
|
||||
TEST_REQUIRE_OK(harness_start("10 PRINT \"ONE\"\n20 PRINT \"TWO\"\n"));
|
||||
TEST_REQUIRE_OK(akbasic_runtime_start(&HARNESS_RUNTIME, AKBASIC_MODE_RUNSTREAM));
|
||||
TEST_REQUIRE_OK(akbasic_runtime_run(&HARNESS_RUNTIME, 0));
|
||||
|
||||
TEST_REQUIRE_STR(HARNESS_RUNTIME.source[10].code, "PRINT \"ONE\"");
|
||||
TEST_REQUIRE_STR(HARNESS_RUNTIME.source[20].code, "PRINT \"TWO\"");
|
||||
|
||||
/* And LIST therefore prints each number once. */
|
||||
clear_output();
|
||||
TEST_REQUIRE_OK(run_line("LIST"));
|
||||
TEST_REQUIRE_STR(HARNESS_OUTPUT, "10 PRINT \"ONE\"\n20 PRINT \"TWO\"\n");
|
||||
harness_stop();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static const char *PROGRAM[] = {
|
||||
@@ -241,5 +267,7 @@ int main(void)
|
||||
TEST_REQUIRE_STATUS(run_line("Y# = PEEK(Z#)"), AKBASIC_ERR_VALUE);
|
||||
|
||||
harness_stop();
|
||||
|
||||
test_runstream_strips_line_numbers();
|
||||
return akbasic_test_failures;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user