![]() |
LambLisp 01 Red Fox Alpha
From AI to Actuator
|
Public Member Functions | |
| void | load () |
| bool | apply_key (const char *key, long val) |
Public Attributes | |
| LL_int32 | cell_block_size = 8 * 1024 |
| LL_int32 | extension_block_size = 4 * 1024 |
| LL_int32 | gc_total_marked = 0 |
| LL_int32 | gc_pool_target = 0 |
| LL_int32 | ncg_frame_pool_size = 16 |
| LL_int32 | sint_in_iram = 1 |
| LL_int32 | rootstack_in_iram = 1 |
| LL_int32 | va_list_max = (LL_int32) toString_MAX_LENGTH |
| LL_int32 | boot_pending = 0 |
Read from LAMB_SETTINGS_PATH before any cells exist. Default matches the hardcoded initial cell block size. Silent if file is missing (first-boot safe).
| void LambPreSettings::load | ( | ) |
Reads LAMB_SETTINGS_PATH_RAW via fopen; silent if missing.
| bool LambPreSettings::apply_key | ( | const char * | key, |
| long | val ) |
[B888] Assign one key . value pair. Returns false if the key is not one of ours, which is what lets load() NAME a typo instead of discarding it.
A SEPARATE FUNCTION BECAUSE load() NOW CALLS IT MORE THAN ONCE PER LINE. Before B888 the dispatch was an if/else if chain written inline in the character loop and reached exactly once per line; parsing every pair on the line means calling it in an inner loop, and the alternative to a function was a second copy of a seven-way chain – the hand-maintained second copy that a new key would silently be missing from.
| LL_int32 LambPreSettings::cell_block_size = 8 * 1024 |
Cells in the initial GC block (8K default; perf pushes 16K to match comps).
| LL_int32 LambPreSettings::extension_block_size = 4 * 1024 |
Cells per on-demand expansion block (4K).
| LL_int32 LambPreSettings::gc_total_marked = 0 |
The LIVE SET the GC last measured, persisted across reboots so the heap can come back already sized for the workload. NOT a block size – the initial block is derived from it (round up to an extension_block_size multiple, then double). 0 = nothing persisted yet. Deliberately a separate key from cell_block_size: the old code wrote a multi-block TOTAL into cell_block_size, which means "size of the initial single block", and the units mismatch bricked boards. Keeping the quantities in distinct fields makes that error unrepresentable.
| LL_int32 LambPreSettings::gc_pool_target = 0 |
THE POOL THE COLLECTOR ACTUALLY NEEDED, i.e. yuasa_N at the end of the last run that expanded – not a live set to be multiplied later. gc_total_marked * 2 was a heuristic standing in for a ratio the VM computes exactly: measured on esp32s3-n8r2-01, N/Amax is 1.27, and the matching writer clamp of total_cells()/2 was therefore ~37% more conservative than necessary, persisting a short figure that forced extra settling boots. ZERO MEANS "NOT WRITTEN BY THIS VM", and the consumer falls back to the old 2x path – so a Settings file written before this key existed still boots exactly as it did.
| LL_int32 LambPreSettings::ncg_frame_pool_size = 16 |
NcgFrames pre-allocated into the free-list pool at startup.
| LL_int32 LambPreSettings::sint_in_iram = 1 |
[P285] WHERE THE HOT PERMANENT STRUCTURES LIVE. 1 = internal SRAM (IRAM-capable D/IRAM on an ESP32), 0 = PSRAM. Settings rather than build flags (owner, 2026-10-22) so one image can be reconfigured per boot and a benchmark can be run across placements without a rebuild.
THE DEFAULTS ARE TODAY'S BEHAVIOUR, so a board with no key behaves exactly as before.
ON AN LX6 THESE TRADE AGAINST THE CODE GENERATOR AND THE EXCHANGE RATE IS STEEP. The sint cache is 73,740 B against 46,704 B of exec headroom – it never fitted, and is placed only by evicting the compiler's working room. Measured twice: [B718] on 2026-09-30 (free exec space 46,704 -> 3,696, up to 74% on recursion) and again on 2026-10-21, where qsort(200) NCG went 10,176 -> 44,186 us because ncg_exec_floor refuses every compile below its floor. On a part with LL_NCG_PSRAM_EXEC native code spills to PSRAM and there is no contention at all.
| LL_int32 LambPreSettings::va_list_max = (LL_int32) toString_MAX_LENGTH |
Hard cap on ONE FORMATTED LOG/ERROR MESSAGE (va_list_expand()), beyond which the text is TRUNCATED rather than an error raised – see the note at that function for why this one buffer must truncate instead of throwing. Separate from toString_MAX_LENGTH (which caps a printed DATUM) so a site that wants longer diagnostics does not also loosen the reader's cap. CLAMPED ON LOAD to [1024, 65536]; see ll_va_list_max for why the ceiling is not advisory.
| LL_int32 LambPreSettings::boot_pending = 0 |
BOOT-ATTEMPT SENTINEL. A persisted setting that makes the VM unbootable is self-perpetuating: the value is read before anything can judge it, the boot dies, and the next boot reads the same value. boot_pending is written 1 just before a risky persisted value is USED and rewritten 0 once the VM is up. Finding it still 1 at load means the previous boot did not survive what it read, so the risky value is discarded rather than retried forever. 0 = last boot completed. 1 = a boot was attempted with persisted values and did not finish.