Document optional line numbers
Chapter 2 gets the rule and the refusal, chapter 4 gets the payoff for LABEL, chapter 9 says DSAVE writes the numbers it handed out and to RENUMBER first if you want gaps, chapter 10 shows a host loading numberless source, chapter 13 gets the QuickBASIC-shaped divergence, and chapter 14's source[] passage gets its second half. Chapter 14 said "two prescans" and listed two; there were three before this and there are four now, so it lists all four and says which of them reports against the right line. TODO.md section 6 records four things found on the way and deliberately not fixed: set_label() filing into the active scope rather than the root, three prescans reporting the wrong line number, duplicate written line numbers still replacing silently, and renumber.c's file-scope scratch arrays. examples/embed.c runs the same program twice, numbered and not, so the example compiles the feature rather than describing it. Its header pointed at ./build/examples/embed, which is not where the binary lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* This is the code in README.md's "Embedding the interpreter" section, kept here
|
||||
* so it is compiled by every build rather than rotting in a document. Build it
|
||||
* with -DAKBASIC_BUILD_EXAMPLES=ON and run `./build/examples/embed`.
|
||||
* with -DAKBASIC_BUILD_EXAMPLES=ON and run `./build/akbasic_example_embed`.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -114,6 +114,24 @@ static const char *PROGRAM =
|
||||
"40 NEXT I#\n"
|
||||
"50 PRINT \"DONE\"\n";
|
||||
|
||||
/*
|
||||
* The same thing with no line numbers, which is what a game script actually
|
||||
* looks like: written in a text editor, branching by LABEL, with nothing to
|
||||
* renumber. A loaded line that arrives without a number is given the slot after
|
||||
* the last one filed, so the two spellings load and run identically. Only the
|
||||
* prompt still needs numbers, because there a number is the one thing separating
|
||||
* program text from a statement to run now.
|
||||
*/
|
||||
static const char *UNNUMBERED_PROGRAM =
|
||||
"PRINT \"COUNTING:\"\n"
|
||||
"FOR I# = 1 TO 5\n"
|
||||
" PRINT I# * I#\n"
|
||||
"NEXT I#\n"
|
||||
"GOTO DONE\n"
|
||||
"PRINT \"NOT REACHED\"\n"
|
||||
"LABEL DONE\n"
|
||||
"PRINT \"DONE\"\n";
|
||||
|
||||
/*
|
||||
* One frame's worth of script. The interpreter never surrenders control: it runs
|
||||
* at most `budget` source lines and returns, so a host game keeps its frame rate
|
||||
@@ -173,6 +191,18 @@ int main(void)
|
||||
* is what the reference does too.
|
||||
*/
|
||||
CATCH(errctx, game_loop(AKBASIC_MAX_SOURCE_LINES, 8, &frames));
|
||||
printf("--- run to completion ---\n%s", CONSOLE.buffer);
|
||||
|
||||
/*
|
||||
* Then the same program again with no line numbers on it. A fresh runtime
|
||||
* rather than a second load into this one, because load() adds to whatever
|
||||
* is already filed rather than replacing it.
|
||||
*/
|
||||
CATCH(errctx, console_sink_init());
|
||||
CATCH(errctx, akbasic_runtime_init(&SCRIPT, &CONSOLE_SINK));
|
||||
CATCH(errctx, akbasic_runtime_load(&SCRIPT, UNNUMBERED_PROGRAM));
|
||||
CATCH(errctx, akbasic_runtime_start(&SCRIPT, AKBASIC_MODE_RUN));
|
||||
CATCH(errctx, game_loop(AKBASIC_MAX_SOURCE_LINES, 8, &frames));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE_DEFAULT(errctx) {
|
||||
@@ -180,6 +210,6 @@ int main(void)
|
||||
rc = 1;
|
||||
} FINISH_NORETURN(errctx);
|
||||
|
||||
printf("--- run to completion ---\n%s", CONSOLE.buffer);
|
||||
printf("--- the same program with no line numbers ---\n%s", CONSOLE.buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user