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>
1 line
1.9 KiB
JSON
1 line
1.9 KiB
JSON
{"defs":[{"body":{"cond":{"args":[{"name":"n","t":"var"},{"lit":{"kind":"int","value":0},"t":"lit"}],"fn":{"name":"==","t":"var"},"t":"app"},"else":{"args":[{"name":"n","t":"var"},{"args":[{"args":[{"name":"n","t":"var"},{"lit":{"kind":"int","value":1},"t":"lit"}],"fn":{"name":"-","t":"var"},"t":"app"}],"fn":{"name":"build","t":"var"},"t":"app"}],"ctor":"Cons","t":"ctor","type":"std_list.List"},"t":"if","then":{"args":[],"ctor":"Nil","t":"ctor","type":"std_list.List"}},"doc":"Build [n, n-1, ..., 1] :: std_list.List Int via Cons recursion. Constructor-blocked; not tail.","kind":"fn","name":"build","params":["n"],"type":{"effects":[],"k":"fn","params":[{"k":"con","name":"Int"}],"ret":{"args":[{"k":"con","name":"Int"}],"k":"con","name":"std_list.List"}}},{"body":{"args":[{"name":"a","t":"var"},{"name":"b","t":"var"}],"fn":{"name":"+","t":"var"},"t":"app"},"doc":"Binary +. Used as the fold accumulator op for both fold_left and fold_right.","kind":"fn","name":"add","params":["a","b"],"type":{"effects":[],"k":"fn","params":[{"k":"con","name":"Int"},{"k":"con","name":"Int"}],"ret":{"k":"con","name":"Int"}}},{"body":{"lhs":{"args":[{"args":[{"name":"add","t":"var"},{"lit":{"kind":"int","value":0},"t":"lit"},{"args":[{"lit":{"kind":"int","value":1000},"t":"lit"}],"fn":{"name":"build","t":"var"},"t":"app"}],"fn":{"name":"std_list.fold_left","t":"var"},"t":"app"}],"op":"io/print_int","t":"do"},"rhs":{"args":[{"args":[{"name":"add","t":"var"},{"lit":{"kind":"int","value":0},"t":"lit"},{"args":[{"lit":{"kind":"int","value":1000},"t":"lit"}],"fn":{"name":"build","t":"var"},"t":"app"}],"fn":{"name":"std_list.fold_right","t":"var"},"t":"app"}],"op":"io/print_int","t":"do"},"t":"seq"},"doc":"Build a 1000-element list, fold it both ways, print both sums (each 500500).","kind":"fn","name":"main","params":[],"type":{"effects":["IO"],"k":"fn","params":[],"ret":{"k":"con","name":"Unit"}}}],"imports":[{"module":"std_list"}],"name":"std_list_stress","schema":"ailang/v0"} |