Stop pointer parameters leaking value-pool slots
All checks were successful
akbasic CI Build / cmake_build (push) Successful in 3m54s
akbasic CI Build / coverage (push) Successful in 4m10s
akbasic CI Build / sanitizers (push) Successful in 5m16s
akbasic CI Build / akgl_build (push) Successful in 9m43s
akbasic CI Build / mutation_test (push) Successful in 24m33s
All checks were successful
akbasic CI Build / cmake_build (push) Successful in 3m54s
akbasic CI Build / coverage (push) Successful in 4m10s
akbasic CI Build / sanitizers (push) Successful in 5m16s
akbasic CI Build / akgl_build (push) Successful in 9m43s
akbasic CI Build / mutation_test (push) Successful in 24m33s
Create structure parameters before allocating their representation, then keep pointer references in the call variable's inline slot. Add an 8,000-call regression and document the remaining by-value structure escape limitation. Co-authored-by: andrew <andrew@aklabs.net> Co-authored-by: OpenAI Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
@@ -380,8 +380,10 @@ no free, so anything drawn from it is spent for the life of the run — and scop
|
||||
returns a variable's *slot* without returning its storage. A scalar therefore does not
|
||||
draw from it at all: `akbasic_variable_init()` points a one-element non-`@` variable at
|
||||
its own `inlinevalue`, which is what makes a local, a `FOR` counter and a `DEF` parameter
|
||||
free. Arrays and structures still spend, deliberately, because a pointer into a record is
|
||||
allowed to outlive the scope that DIMmed it.
|
||||
free. A pointer parameter is also free: it owns only its one-slot reference, so its
|
||||
`inlinevalue` dies with the call while the target remains in the caller's storage. Arrays,
|
||||
structures and by-value structure parameters still spend, deliberately, because a pointer
|
||||
into a record is allowed to outlive the scope that DIMmed it.
|
||||
[Chapter 13](13-differences.md) states the same budget from a BASIC programmer's side.
|
||||
|
||||
The per-environment three are reset at the top of every line, which is what makes
|
||||
|
||||
@@ -266,6 +266,13 @@ The function saw 99; the caller still has 5. To change a caller's record on purp
|
||||
a pointer — `DEF POKEIT(P@ AS PTR TO CRATE)` — and reach through it with `->`. Neither is
|
||||
a special rule: both fall out of the parameter being assigned like any other variable.
|
||||
|
||||
A pointer parameter's own reference is kept in the call variable's inline slot, so repeated
|
||||
calls do not spend the value pool. Its target remains the caller's structure. A by-value
|
||||
structure parameter is different: its copied slots remain in the value pool because
|
||||
`POINT Q@ AT B@` may retain a pointer to that copy after the function returns. Until escape
|
||||
analysis can distinguish that case, **do not call a by-value structure-parameter function in
|
||||
a loop**; bind a host global and rebind it per instance instead.
|
||||
|
||||
## What is checked, and what is not
|
||||
|
||||
A field name is checked against the set the type declared, and the refusal lists the
|
||||
|
||||
Reference in New Issue
Block a user