8e9f0f06a6
Downstream field test of the raw-buf surface as a consumer with only the public interface (design ledger + `ail` CLI; no crate source). Four fixtures under examples/fieldtest/, spec at docs/specs/0058-fieldtest-raw-buf.md. Every recorded outcome reproduced independently before commit. Findings (3 bug, 1 spec_gap, 2 working): - B1 [bug] `borrow (RawBuf a)` receiver is unusable. A fn taking `borrow (RawBuf Int)` that calls RawBuf.get/.size on the parameter even once is rejected `consume-while-borrowed` — the diagnostic names the wrong cause (the receiver is not consumed). The ledger advertises get/size as borrow-receiver ops, so the documented use is unreachable from any helper-function decomposition. This blocks Series (#8) — the milestone's own downstream raison d'être — whose at/total_count read through a `borrow (Series a)`. - B2 [bug] An owned RawBuf threaded through a `loop` binder passes check but panics codegen `unknown variable: b` at build. A plain Int loop binder builds fine, so the fault is specific to an owned RawBuf loop binder. Breaks the check↔codegen agreement. - B3 [bug] `param-not-in-restricted-set` omits the allowed set. design/models/0007 §4 promises the diagnostic "names the offending type and the allowed set"; the shipped message names the type, the type-var, and the home type but not `{Int, Float, Bool}`. A downstream author is told what is wrong but not what is right. - B4 [spec_gap] RawBuf.set receiver double-consume is not enforced; two set calls on the same owned buffer silently alias the slab. Not raw-buf-specific (owned Str/ADT behave identically) — a pre-existing linearity-non-enforcement property. Recorded because RawBuf's own→own mutation is the first place a silent alias yields a mutated-in-place surprise. Ratify in the ledger or open a backlog item for full linear enforcement. - W1 [working] `(new …)` sugar + inference-from-use across Int/Float/Bool builds and runs first try (sensor_pair prints 5.0); the Bool i1/i8 packing edge round-trips. The milestone's cleanest win. - W2 [working] param-in reject fires for both Str and a user TypeDef. Net: B1+B2 mean the only RawBuf programs that build today are straight-line owned let-threading with literal indices — the shipped-fixture shape. Helper decomposition (B1) and runtime-length loop fill (B2) both fail. fieldtest does not self-resolve; routing is the orchestrator's call.
36 lines
1.8 KiB
Plaintext
36 lines
1.8 KiB
Plaintext
; Fieldtest raw-buf.4 (Axis 3, param-in element-type restriction).
|
|
; Task: an LLM author models a small "tick" record and reaches for a
|
|
; RawBuf to hold a batch of them — the obvious move for batch storage.
|
|
; RawBuf's element type is restricted to {Int, Float, Bool} via param-in,
|
|
; so a user TypeDef element must be rejected at `ail check` with a
|
|
; diagnostic that tells the author *why* and *what is allowed*.
|
|
;
|
|
; This probes the user-TypeDef path (distinct from the Str path the
|
|
; shipped raw_buf_reject_str.ail covers): does param-in fire for a type
|
|
; the author defined themselves, and does the message name the allowed
|
|
; set so the author can self-correct (e.g. switch to a Float field)?
|
|
;
|
|
; Expected: `ail check` exits non-zero with param-not-in-restricted-set
|
|
; naming `Tick` and the allowed set {Int, Float, Bool}.
|
|
;
|
|
; OUTCOME: rejects as expected (exit 1). Verbatim:
|
|
; [param-not-in-restricted-set] first_price: type-arg `Tick` is not in
|
|
; the restricted set for type-variable `a` of `raw_buf.RawBuf`
|
|
; The reject fires (good) and names the offending type, the type-var, and
|
|
; the home type. BUT it does NOT name the allowed set {Int, Float, Bool},
|
|
; which design/models/0007 §4 explicitly promises ("ParamNotInRestrictedSet
|
|
; names the offending type AND the allowed set"). A downstream author who
|
|
; reaches for RawBuf<Tick> is told `Tick` is wrong but not what would be
|
|
; right; they cannot self-correct without reading the kernel source.
|
|
|
|
(module rawbuf_4_paramin_reject
|
|
|
|
(data Tick
|
|
(ctor MkTick (con Float) (con Int)))
|
|
|
|
(fn first_price
|
|
(doc "Read the first Tick out of a batch buffer. Should never check: RawBuf cannot hold a user ADT.")
|
|
(type (fn-type (params (borrow (con RawBuf (con Tick)))) (ret (con Tick))))
|
|
(params batch)
|
|
(body (app RawBuf.get batch 0))))
|