bd19fee673
Small empirical iter confirming the 14e tail-call story works dogfood-practical. New fixture std_list_stress.ailx builds a 1000-element List<Int> via recursive build, folds it with both fold_left (tail-marked in std_list) and fold_right (constructor- blocked, unmarked), prints both sums (500500 each). IR evidence at the monomorphised fold-recursion sites: fold_left__I_I: musttail call i64 @ail_std_list_fold_left__I_I(...) fold_right__I_I: plain call i64 @ail_std_list_fold_right__I_I(...) The tail: true marker on std_list.fold_left's recursive call survives monomorphisation through the __I_I specialisation. fold_right correctly emits a plain call (recursive call is second arg to f, not tail position). Empirical findings at N=1000: - fold_left runs in constant stack (musttail). - fold_right runs in ~1000 frames. No segfault; default 8MB Linux stack absorbs it comfortably. - build (recursive, unmarked) likewise fits. - End-to-end ~40ms wall (build + clang link); program <1ms. - Boehm GC handles 2 × 1000 Cons allocations without symptom. Tests 87 -> 88. Cumulative 30 e2e tests. cargo doc 0 warnings. Cumulative state, post-15c: 2 stdlib modules (std_maybe, std_list), 14 combinators, cross-module recursive ADTs working, TCO surviving monomorphisation, GC at 1000-element scale. Four compiler bugs surfaced + fixed in dogfood since 14a. Natural pause point. Queue for future iters: 15d (std_either), 15e (std_pair), 16a (nested patterns), 16b (local rec let), 17a (per-fn arena, Decision 9 future-iter). None block further stdlib work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1.4 KiB
Plaintext
42 lines
1.4 KiB
Plaintext
; Iter 15c — empirical stress test for std_list's folds.
|
|
; Builds a 1000-element list [1000, 999, ..., 1] and folds it with
|
|
; both fold_left (tail-marked, should run in constant stack via
|
|
; `musttail call` lowering) and fold_right (constructor-blocked,
|
|
; runs at ~1000-deep stack — well within an 8MB Linux stack budget).
|
|
; Expected stdout: two lines, each `500500` (sum 1..1000 = 500500).
|
|
|
|
(module std_list_stress
|
|
|
|
(import std_list)
|
|
|
|
(fn build
|
|
(doc "Build [n, n-1, ..., 1] :: std_list.List Int via Cons recursion. Constructor-blocked; not tail.")
|
|
(type
|
|
(fn-type
|
|
(params (con Int))
|
|
(ret (con std_list.List (con Int)))))
|
|
(params n)
|
|
(body
|
|
(if (app == n 0)
|
|
(term-ctor std_list.List Nil)
|
|
(term-ctor std_list.List Cons
|
|
n
|
|
(app build (app - n 1))))))
|
|
|
|
(fn add
|
|
(doc "Binary +. Used as the fold accumulator op for both fold_left and fold_right.")
|
|
(type
|
|
(fn-type
|
|
(params (con Int) (con Int))
|
|
(ret (con Int))))
|
|
(params a b)
|
|
(body (app + a b)))
|
|
|
|
(fn main
|
|
(doc "Build a 1000-element list, fold it both ways, print both sums (each 500500).")
|
|
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
|
(params)
|
|
(body
|
|
(seq (do io/print_int (app std_list.fold_left add 0 (app build 1000)))
|
|
(do io/print_int (app std_list.fold_right add 0 (app build 1000)))))))
|