Files
AILang/examples/fieldtest/rawbuf_3_sensor_pair.ail
T
Brummel 8e9f0f06a6 fieldtest: raw-buf — 4 examples, 6 findings (refs #7)
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.
2026-05-30 16:26:48 +02:00

37 lines
1.7 KiB
Plaintext

; Fieldtest raw-buf.3 (Axis 2, the (new T <types> <values>) sugar across
; element types). Task: "store three Float sensor readings and a Bool
; alarm flag in flat buffers, then report the average of the readings,
; doubled if the alarm flag is set." This drives (new RawBuf (con Float) 3)
; and (new RawBuf (con Bool) 1) in one program, so the construction sugar
; and its inference-from-use story are exercised on both the 8-byte
; (Float) and the 1-byte (Bool) element widths.
;
; The element type of each buffer is never written on RawBuf.set/.get; it
; is recovered purely from the values stored (1.5 : Float, true : Bool).
; Straight-line owned `let`-threading (the only shape that currently
; builds for RawBuf — see rawbuf_1/rawbuf_2).
;
; Expected stdout: average (1.5+2.5+3.5)/3 = 2.5, alarm set => doubled
; => 5.0 -> "5.0".
(module rawbuf_3_sensor_pair
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(params)
(body
(let readings (new RawBuf (con Float) 3)
(let readings (app RawBuf.set readings 0 1.5)
(let readings (app RawBuf.set readings 1 2.5)
(let readings (app RawBuf.set readings 2 3.5)
(let alarm (new RawBuf (con Bool) 1)
(let alarm (app RawBuf.set alarm 0 true)
(let avg (app /
(app + (app RawBuf.get readings 0)
(app + (app RawBuf.get readings 1)
(app RawBuf.get readings 2)))
3.0)
(app print
(if (app RawBuf.get alarm 0)
(app * avg 2.0)
avg))))))))))))