Files
Brummel 6b7ee45e49 test(series): RED pin for the SMA worked example (#61 headline)
The headline acceptance of #61: the simple-moving-average worked
example from design/models/0007-kernel-extensions.md must build via
`ail build --alloc=rc`, run, and print the correct moving averages.
Green ⇒ the kernel-tier `Series` library extension works end to end
(ring-buffer push, financial-style indexing at index 0 = newest,
count/total bookkeeping).

The fixture is the 0007 worked example with two corrections applied,
both verified against the live tool this session:

- `>=` is not a surface symbol; the polymorphic Ord helper is `ge`
  (here on Int operands: total_count vs window size).
- `print` on Float emits no trailing newline, so the four averages
  would concatenate into an unreadable blob. The emit branch now
  prints the average followed by `io/print_str "\n"`, so each
  average lands on its own line and the output is deterministic and
  assertable. (This legibility fix is also queued to be carried back
  into model 0007.)

RED reason (right-for-the-right-reason): `ail check` rejects with
[bare-cross-module-type-ref] on `Series` — the kernel-tier module
does not exist yet. The fixture itself parses and is otherwise valid.

Expected stdout was derived by probing the live %g float formatter
independently (the SMA averages are 9/3, 16/3, 17/3, 16/3 over the
stream 1,5,3,8,6,2 with window 3): `3.0\n5.33333\n5.66667\n5.33333`.

GREEN side (the `series` kernel module + the five ops) is the next
mini-mode iteration.
2026-06-02 12:59:34 +02:00

59 lines
1.7 KiB
Plaintext

(module series_sma
(data FloatList
(ctor FNil)
(ctor FCons (con Float) (con FloatList)))
(fn sum_window_step
(type (fn-type
(params (borrow (con Series (con Float))) (own (con Int)) (own (con Int)) (own (con Float)))
(ret (own (con Float)))))
(params s n i acc)
(body
(if (app eq i n)
acc
(tail-app sum_window_step s n
(app + i 1)
(app + acc (app Series.at s i))))))
(fn emit_if_full
(type (fn-type
(params (borrow (con Series (con Float))) (own (con Int)))
(ret (own (con Unit))) (effects IO)))
(params s n)
(body
(if (app ge (app Series.total_count s) n)
(seq
(app print (app /
(app sum_window_step s n 0 0.0)
(app int_to_float n)))
(do io/print_str "\n"))
(do io/print_str ""))))
(fn run_stream
(type (fn-type
(params (own (con Series (con Float))) (own (con Int)) (own (con FloatList)))
(ret (own (con Unit))) (effects IO)))
(params s n input)
(body
(match input
(case (pat-ctor FNil) (do io/print_str ""))
(case (pat-ctor FCons v rest)
(let s_new (app Series.push s v)
(seq (app emit_if_full s_new n)
(tail-app run_stream s_new n rest)))))))
(fn main
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let s (new Series (con Float) 3)
(app run_stream s 3
(term-ctor FloatList FCons 1.0
(term-ctor FloatList FCons 5.0
(term-ctor FloatList FCons 3.0
(term-ctor FloatList FCons 8.0
(term-ctor FloatList FCons 6.0
(term-ctor FloatList FCons 2.0
(term-ctor FloatList FNil))))))))))))