Port the README from the Go version and document embedding
Carries the reference README across, adjusted where C changes the answer: cmake instead of make, the ak* libraries instead of the go-sdl2 bindings, and the limits table now includes the three ceilings the Go version did not need because it called make(). The new "Embedding the interpreter" section is the point of the rewrite, so it states the four rules the library holds to -- nothing terminates the process, nothing calls malloc, no file-scope mutable state, the host owns the loop -- and each was checked against the tree rather than asserted. Adds akbasic_runtime_load(). Writing the section turned up a real gap: a host usually already holds its script as a string and wants the sink reserved for output, and the only path that existed was AKBASIC_MODE_RUNSTREAM reading the program through the sink's readline, which forces a game to point its output device at its source text. The alternative was reaching into the header's "internal API" block for store_line. Neither is something to put in a README. Adds examples/embed.c, which is the code the README quotes -- a custom sink, a bounded per-frame run, and the PASS-not-CATCH rule for a loop inside an ATTEMPT. It is built by every build and registered as a CTest case, so a signature change breaks the build instead of rotting the document. The README's own snippet is compiled separately as a check; both were run before committing. The "What Isn't Implemented / Isn't Working" section leads with the eleven inherited defects rather than burying them, because five of them were found by this port and a reader deserves to know that 1 - 2 - 3 computes 1 - 2 before they hit it. Corrected two claims while verifying: the runtime is 10.1MB rather than the ~8MB first written, and its largest single cost is the environment pool at 4.1MB, not the source table. ctest 60/60; ASan+UBSan 60/60; no warnings under -Wall -Wextra. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -149,6 +149,28 @@ akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_run(akbasic_Runtime *obj, int
|
||||
/** @brief Point the runtime at an input stream and choose a starting mode. */
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_start(akbasic_Runtime *obj, int mode);
|
||||
|
||||
/**
|
||||
* @brief Load a whole program from memory, filing each line under its line number.
|
||||
*
|
||||
* The entry point for an embedding host, which usually already holds its script
|
||||
* as a string and wants the sink reserved for output. The alternative --
|
||||
* AKBASIC_MODE_RUNSTREAM -- reads the program through the sink's readline, which
|
||||
* works for a file-backed driver but forces a game to point its output device at
|
||||
* its source text.
|
||||
*
|
||||
* Lines are separated by `\n`; a `\r` before it is tolerated. Blank lines are
|
||||
* skipped. A line with no line number is filed under the last one seen, matching
|
||||
* what the scanner does in RUNSTREAM mode. This does not run anything: follow it
|
||||
* with akbasic_runtime_start(obj, AKBASIC_MODE_RUN).
|
||||
*
|
||||
* @param obj Object to initialize, inspect, or modify.
|
||||
* @param source Whole program text; must not be NULL.
|
||||
* @return `NULL` on success, otherwise an error context owned by the caller.
|
||||
* @throws AKERR_NULLPOINTER When `obj` or `source` is NULL.
|
||||
* @throws AKBASIC_ERR_BOUNDS When a line is longer than AKBASIC_MAX_LINE_LENGTH or its number is out of range.
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_load(akbasic_Runtime *obj, const char *source);
|
||||
|
||||
/* --- Internal API: exposed for the scanner, parser and verb handlers only. --- */
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_variable(akbasic_Runtime *obj, akbasic_Variable **dest);
|
||||
|
||||
Reference in New Issue
Block a user