LambLisp 01 Red Fox Alpha
From AI to Actuator
Loading...
Searching...
No Matches
LambPreSettings Struct Reference

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

Detailed Description

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).

Member Function Documentation

◆ load()

void LambPreSettings::load ( )

Reads LAMB_SETTINGS_PATH_RAW via fopen; silent if missing.

◆ apply_key()

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.

Member Data Documentation

◆ cell_block_size

LL_int32 LambPreSettings::cell_block_size = 8 * 1024

Cells in the initial GC block (8K default; perf pushes 16K to match comps).

◆ extension_block_size

LL_int32 LambPreSettings::extension_block_size = 4 * 1024

Cells per on-demand expansion block (4K).

◆ gc_total_marked

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.

◆ gc_pool_target

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.

◆ ncg_frame_pool_size

LL_int32 LambPreSettings::ncg_frame_pool_size = 16

NcgFrames pre-allocated into the free-list pool at startup.

◆ sint_in_iram

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.

◆ va_list_max

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.

◆ boot_pending

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.