Document host/script variable exchange, and file the scope hazard it exposes
The host can expose variables to a BASIC program, in both directions and for every type, with no marshalling layer -- akbasic_environment_get() finds or creates by name, the type comes from the suffix as it does for BASIC code, and host and script share the same akbasic_Value. Nothing new was needed to make that work. Testing it before writing it up turned up a hazard worth stating plainly, so the README documents the pattern and section 6 item 17 records the gap. Seeding before akbasic_runtime_start() and reading after the script stops is safe, and so is updating an existing global at any time, because the parent chain is searched. Creating one mid-run is not, in two ways, and both are silent. A script suspended part-way through a bounded run() is usually inside a FOR or GOSUB scope, so a variable created through obj->environment lands in that scope and dies when it pops -- the script reads it correctly inside the loop and gets 0 immediately after. And reaching for the root explicitly does not help: akbasic_environment_get only auto-creates when the environment it is given is the active one, so with a child active it returns NULL through dest without raising, and an unchecked host dereferences it. This one is ours rather than inherited. It falls out of the environment pool meeting the bounded run(), a combination the reference never had because its run() never returned. examples/hostvars.c demonstrates both hazards rather than describing them, and prints what it observes, so the day this is fixed that output changes and the example needs revisiting. Like examples/embed.c it is built and run by every build. Both README snippets were extracted and compiled as a check. Not fixed here: akbasic_runtime_global() would close it in about fifteen lines, but what it should do when the script is suspended inside a user function's scope is a design question worth settling deliberately rather than discovering. Filed with the proposed signature and the tests it wants. ctest 61/61; ASan+UBSan 61/61; no warnings under -Wall -Wextra. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,11 +157,13 @@ akbasic_instrument(basic)
|
||||
# The embedding example. It is built by default and registered as a test so the
|
||||
# code README.md quotes cannot rot: a signature change breaks the build.
|
||||
if(AKBASIC_BUILD_EXAMPLES)
|
||||
add_executable(akbasic_example_embed examples/embed.c)
|
||||
target_compile_options(akbasic_example_embed PRIVATE -Wall -Wextra)
|
||||
target_link_libraries(akbasic_example_embed PRIVATE akbasic)
|
||||
akbasic_instrument(akbasic_example_embed)
|
||||
_add_test(NAME example_embed COMMAND akbasic_example_embed)
|
||||
foreach(_example IN ITEMS embed hostvars)
|
||||
add_executable(akbasic_example_${_example} examples/${_example}.c)
|
||||
target_compile_options(akbasic_example_${_example} PRIVATE -Wall -Wextra)
|
||||
target_link_libraries(akbasic_example_${_example} PRIVATE akbasic)
|
||||
akbasic_instrument(akbasic_example_${_example})
|
||||
_add_test(NAME example_${_example} COMMAND akbasic_example_${_example})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user